Skip to content
↑↓Navigate↵SelectescClose

0022 - Registry state from signed per-provider artifacts

Registry state decision using signed, reviewable, per-provider pricing artifacts

  • Status: Accepted
  • Date: 2026-07-29
  • Deciders: nexus core team
  • Tags: registry, pricing, provenance, audit, cli

The model registry decides which models exist, what each endpoint can do, and what every metered unit costs. Registry state was established by an in-service sync: the control plane extracted catalogs and prices from provider sources, wrote sync plans, price bands, and price versions, and notified gateways over a NATS subject.

That mechanism cannot answer the questions an operator and an auditor need answered. There is no single document that states what a provider serves, so registry state cannot be reviewed before it applies, reproduced afterwards, or signed. A sync that fails partway leaves a catalog whose completeness is unknown, and a model that disappears from a source is removed implicitly rather than as a decision someone approved. Several providers publish no machine-readable catalog or price list at all — Azure AI Foundry and AWS Bedrock among them — so an extraction-driven sync could never be the only path to registry state.

  • Registry state must be reproducible from an artifact that can be digested, signed, and retained as release evidence.
  • An operator must see what an import changes, including retirements, before it applies.
  • An approval must bind to the exact content it approved, so approved content cannot be swapped afterwards.
  • Pricing must be validated offline, without a database, because an unpriced or mispriced endpoint bills real money.
  • Providers with no published catalog must use the same import path as providers with one.
  • In-service sync with review hooks — Keep extraction in the service and add an approval step. Retains the scraping dependency in the running system and still produces no artifact to sign, archive, or diff.
  • Signed per-provider artifacts imported by the CLI — One document per provider is the complete statement of that provider’s registry state; import validates, plans, and applies it.
  • Per-model incremental patches — Smaller diffs, but no point at which the catalog is a complete verifiable statement, and retirement returns to being implicit.

Chosen option: signed per-provider artifacts imported by the CLI.

Registry state comes from one artifact per provider source, carrying a catalog table (one row per model, with capabilities and aliases) and a rates table (per-meter prices in USD per million tokens, with context bands and effective intervals). Each artifact is the complete state for its provider: applying it replaces that provider’s registry state, and a model the artifact no longer carries is planned as an explicit retirement rather than removed silently.

nexus registry import <artifact.json> (cli/src/commands/registry/import.rs in the source repository) is one command with three stops. It validates the artifact against the contract, prints a plan summarizing N to add, M to change, K to retire with per-record findings, and applies on confirmation. --check validates without touching a database, --dry-run stops at the plan, and --yes skips the prompt for unattended local use.

Every apply records an import change set carrying the artifact’s identity and the approval material. approval_binding_check, added by the control-plane migration for registry artifact import change sets, requires each recorded approval column to equal its source column for any change set that carries an approval hash, so an approval cannot be rebound to different content.

Artifacts are produced by tools/registry-generator/ in the source repository: from published sources where they exist, and from an operator-maintained catalog and rates CSV pair where they do not.

Gateways converge to committed changes by polling Postgres rather than by notification; see 0010 - NATS JetStream as the internal async event bus.

  • Registry state is reproducible from a document that can be digested and signed, and release automation can retain the artifact with its manifest, digest, signature, and provenance as release evidence.
  • Retirement is explicit and approval-gated. Re-importing an artifact without a model retires that endpoint, so the artifact must always be the provider’s complete state rather than a partial update.
  • Pricing is validated before it can bill: --check runs with no database, and an endpoint whose usage cannot be priced is excluded from routing rather than served at a guessed rate.
  • Three surfaces that existed only because the registry had no authoritative source are removed: the per-endpoint wallet flag, endpoint support classification, and the support manifest. What a provider serves is now stated by its artifact.
  • The sync-era schema is gone. model_registry_sync_plans becomes model_registry_import_change_sets, and the sync runs, document extraction, price band, price version, and support classification tables are dropped. These migrations drop tables and columns, so reverting to an earlier binary is not possible; recovery from a bad import is a database restore.
  • just models-sync no longer exists. Re-establishing registry state uses nexus registry import.
  • Applied state reaches gateways within GATEWAY_REGISTRY_POLL_SECONDS rather than immediately, and a gateway keeps its previous snapshot when a poll fails.
  • A provider without a published catalog requires a maintained CSV pair. The generator leaves unprovable fields blank and names them on exit rather than guessing, and --skip-unpriced drops a model it cannot price instead of holding back the rest.

See Provider Pricing Operations for the operator-facing generate/review/import workflow.