docs(specs): add S16 container remote repositories spec

Summary

Adds docs/specs/S16-container-remote.md — the S16 spec for container remote repositories (kind=2): a proxy-and-cache of a single external container registry, layered on the S13 virtual/remote foundation and the S12 hosted OCI spec.

Scoped to the remote kind only, per the remote/virtual split in !900 (merged). This MR extracts the remote half of the pre-split combined draft; the container virtual slice is S32 (#239), specified separately.

What the spec covers

  • The container remote database schema (container_remote_*), owned here since S13 defers per-format schema ownership to the format slices. It follows ADR-007 and names its divergences from it: the container_remote_blobs columns, the index refinements, and container_remote_repositories.auth_status with its CHECK, all reconciled by a follow-up handbook MR
  • OCI auth-challenge discovery and token-exchange against upstreams requiring a Bearer token: the memoized discovery verdict on auth_status, auth_url caching, an in-process bearer-token cache, retry-on-401, timing isolation from S13's probe_timeout, and single-flight coalescing on concurrent cold requests
  • Manifest and blob proxy dispatch on top of S13's Lookup/Probe/Fetch, reusing S12's content-negotiation contract
  • Cache freshness: stale-tag revalidation (If-None-Match, 304 bump, 200 manifest upsert plus tag re-point) — tags are the only container cache row with a freshness window — and client HEAD semantics, where a miss fills like a GET
  • Digest verification on cache-fill (S16 owns the digest check S13 delegates to the owning slice)
  • Tag listing and referrers, live-proxied to the single upstream
  • ContainerRemoteConfig (token-exchange timeout, token cache TTL bounds)
  • Error mapping onto S12's OCI error envelope, including the UNAUTHORIZED/DENIED codes for propagating upstream auth decisions

Key decisions

  • New remote tables use UUIDv7 ids, extending work item #185 (closed)'s scope rather than ADR-007-as-published's stale bigint+sequence text for these tables
  • Token cache TTL honors the upstream's expires_in (clamped), not a flat TTL
  • Config message named ContainerRemoteConfig/container_remote (renamed from ContainerVirtualConfig — these are remote-repository settings)
  • A client HEAD on a cache miss fills like a GET, following S14's discipline, so no upstream HEAD is issued for an artifact
  • A proxied manifest takes the same two-phase session path as a blob, not S12's StoreBlob. A raw S13 Fetch offers only the session, the verification it needs already exists on the S06 Commit seam, and both siblings leave the storage path to Fetch without naming an S06 call. Reversible with no migration if the extra object-store operations prove to matter
  • The challenge-discovery verdict is memoized on a three-state auth_status rather than re-derived from a nullable auth_url, whose NULL meant both "not discovered" and "no token needed" — which made every request against an anonymous upstream re-run the discovery HEAD. Follows last_health_status's shape on the same table. Container-only: neither sibling negotiates upstream auth

S13-side dependencies recorded, not assumed

Four S13 changes this spec needs are gated in Follow-ups rather than treated as present: the no-transparent-decode switch, the Content-Length allowlist exemption, an expected digest reaching the existing cache-fill Commit argument, and Docker-Content-Digest made readable with a pre-commit comparison. Plus an S13 spec-text amendment: its behavioral-columns table and clear-on-url-change rule both name auth_url explicitly and need auth_status alongside it. The criteria that depend on unlanded pieces are marked gated.

Re-baselined against !909 (merged) (merged)

Aligns with the S13 corrections from !909 (merged), now in main: digest-verification-on-fill ownership, single-flight follower-model naming, and cross-origin redirect credential stripping (S13 cover 8, which resolves the W6 thread). Branch is merged up to date with main.

Related to #283 (closed)

Edited by Radamanthus Batnag

Merge request reports

Loading
Loading