Skip to content

ADR 0004 phase 5: unify pricing resolution and offline-first catalogue refresh #10295

Open

Description

@lpcox

Objective and dependencies

Implement ADR 0004 Gate 5. Parent: #10290. Blocked by Phase 3 (#10293). Can develop alongside Phase 4; refresh-triggered harness re-evaluation must integrate with Phase 4 before this phase closes. Use bounded PRs within this phase for static resolution, runtime/overlay migration, then refresh integration.

Scope

Move accounting to the shared provider/channel/deployment-scoped resolver. Resolve per component/tier using overlay → complete fresh provider observation → validated fresh central snapshot → maintained record → governed import → explicit policy fallback, with field-specific applicability rules. Preserve existing credit calculations unless an intentional correction is separately reviewed.

Represent exact decimal accounting, long-context thresholds, units/currency, cache prices, non-token charges where needed, effective dates, promotions/successors, dynamic-selector ceilings, and unpriceable-model policy. Mixed-source tariffs are assembled, with per-component provenance; fill omissions only when scope, token applicability, units, currency, and effective dates are compatible. Missing is not zero. Provider-advertised discounts stay informational and never lower maxAiCredits accounting.

Implement configurable central feed URL or local snapshot, enabled/offline mode, fetch timeout, refresh interval, maximum age, authenticated/approved transport, atomic validation, and source/schema-partitioned last-known-good cache. Source replacement must not contact the default or another unconfigured endpoint. Assume the default feed is blocked: approved operator/workflow/bundled fallback permits startup; never implicitly allowlist or bypass a denial. Pin each request's tariff/time/revision; refresh never reprices past usage. Integrate fresh harness constraints before subsequent dispatch.

Wire governed provider-qualified models.dev fallback for unsupported/custom pricing providers without requiring native adapters or runtime access to models.dev. Imported pricing does not imply execution, availability, or protocol support.

Entry points: containers/api-proxy/{ai-credits-pricing.js,provider-pricing-overlays.js,runtime-model-catalog.js,models-dev-catalog.js,guards/ai-credits-guard.js}, usage/accounting consumers, Phase 2 source config, and Phase 4 eligibility.

Acceptance criteria

  • Shadow old/new pricing with old authoritative; sanitize diffs and resolve them through fixtures or explicitly approved corrections before switching.
  • Tests cover precedence, incomplete tariffs, incompatible component ranges/dates/units, threshold boundaries, exact arithmetic, expiry/successors, cache estimates, and no discount-driven budget reduction.
  • Cross-provider slug collisions are rejected; custom-provider import fallback and higher-priority overrides retain exact provider provenance.
  • Deterministic tests cover initial fetch, periodic refresh, malformed/schema/auth failures, atomicity, source-partitioned caches, denial/timeouts, stale-age limits, and fallback/fail-closed outcomes.
  • Zero feed requests in offline/local-only mode; blocked-feed startup works with approved bundled prices and no cache; custom-source failure never contacts default.
  • Concurrent/in-flight requests retain tariff/revision consistency; new snapshots apply only to subsequent requests and re-evaluate harness eligibility.
  • Sanitized active source/revision/age/failure/fallback traces are available for Phase 7 exports; credentials never enter logs/cache metadata.
  • Root/proxy accounting and integration regressions preserve policy and budget enforcement.

Non-goals

Do not publish centrally reviewed feeds (Phase 8), infer request-level promotion eligibility, silently use expired data, or add /reflect/v2. Retain legacy adapters until Phase 9's release/parity gates.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions