feat: account files carry priority, latency targets and prices

Merged
HA
2d ago
+1391-104

What

Account files (model_provisioning.account_limits_directory) can now hold one account's whole serving deal, per model and per serving class:

account: acme
priority: 100                     # account default
models:
  example/chat-model:
    priority: 300                 # model override
    tariffs: [...]                # batch prices only
    classes:
      standard:
        realtime_inflight: 200
        tariffs: [...]            # realtime / playground prices
        cache_tariff: {...}
        ttft_ms: 1000
        itl_ms: 30
        priority: 500             # class override
  • The old top-level realtime_inflight shape is still accepted and means classes.standard.realtime_inflight. If both name the same model, the two limits must match.
  • Only standard can be configured until models carry other classes.
  • Limits, realtime prices and cache tariffs live per class. Model-level tariffs take batch prices only.
  • An account/model pair may be configured in its account file or in an organisation overlay, not both. Startup checks this, and so does validate-account-limits --org-overlays.
  • New dwctl-model-provisioning account-schema command.

How

  • Migration (additive): nullable users.scheduling_priority, plus a new account_model_policies table (account, model, optional class: priority, ttft_ms, itl_ms). Both have notify triggers. Older images ignore both.
  • Reconcile: the account files are applied in one transaction under the existing advisory lock.
    • Limits keep their whole-table semantics.
    • Priorities, policies and prices are owned row by row via the account-catalog provisioning source:
      • hand-written prices are adopted only when the pair is declared;
      • omitted prices retire, keeping their history;
      • prices owned by the organisation catalog are refused.
    • The retire-omitted-prices step is shared with the organisation catalog.
  • Gateway: the sync flattens class โ†’ model โ†’ account priority, and the per-class targets, into the onwards overlay and account. Onwards stamps them as nvext.agent_hints.priority / nvext.router.{ttft,itl}_target on realtime requests to dynamo members.
    • These are hints: the request keeps its billed class, unlike legacy overlay targets, which still make it custom.
    • Daemon (batch/flex) traffic keeps its deadline priority.
    • Members that refuse scheduling fields get nothing.

Design choices worth a look

  1. The account-wide toleration preset stays where it is today, set in the console. These files don't touch it; per-model/class toleration overrides come in a follow-up.
  2. The account default priority is written only by the files; there is no console control.
  3. The limits table has no class dimension yet. Changing its key in place would break older pods' upserts mid-rollout, so the class column comes later as expand/contract, when non-standard classes exist.

Rollout

Dormant. Today's files reconcile to exactly what they do now, because they only use the old limits shape. Nothing changes until a file uses the new fields.

Tests

  • just lint rust: green.
  • just test rust: 4236 passed.
  • New tests cover:
    • format validation;
    • the cross-catalogue conflict check;
    • priorities, policies, limits and prices written, re-applied idempotently and cleared;
    • personal accounts;
    • price adoption, and the refusal of prices owned by the organisation catalog;
    • gateway sync of account priority and policy;
    • onwards hint stamping.

๐Ÿค– Generated with Claude Code