The frozen API contracts at the arc↔metafactory boundary — what each system promises the other.
The blueprint lifecycle crosses the arc↔metafactory boundary at two critical points: handover (publisher submitting) and install (consumer fetching).
At each crossing, the systems need a frozen contract — an agreed shape for requests, responses, and error conditions.
Once frozen, breaking changes require a major version bump and explicit coordination. Non-breaking additions (new optional fields, new error codes) need only a design-decision amendment.
The seam contracts are the source of truth for both sides. Arc codes against the target shape; metafactory implements it. Neither side guesses.
This is the arc bundle → metafactory boundary. When a publisher runs arc bundle, the CLI produces a signed tarball and submits it via the intake API.
Three endpoints:
| METHOD + PATH | PURPOSE |
|---|---|
POST /intake/v1/submissions | Submit envelope, get submission ID + presigned upload URL |
PUT <presigned-url> | Upload tarball to R2 |
POST /intake/v1/submissions/{id}/finalise | Trigger validation |
The envelope carries: the manifest, the Sigstore attestation, the Rekor entry reference, and a pointer to the tarball. Authentication flows entirely through Sigstore keyless OIDC — no bearer tokens.
Status tracking: Publishers poll or stream submission status via GET /intake/v1/submissions/{id}. Status progresses through: awaiting_upload → integrity_check → attribute_gate → clean_room_l1 → clean_room_l2 → clean_room_l3 → awaiting_sponsor → in_review → approved / rejected / changes_requested.
The full TypeScript interfaces are in the design spec at design/blueprint-lifecycle/seam-contracts.md.
This is the metafactory → arc install boundary. When a consumer runs arc install, the CLI fetches artifacts from the registry and verifies them cryptographically.
Six endpoints, all public, cacheable, read-only:
| METHOD + PATH | PURPOSE | CACHE |
|---|---|---|
GET /registry/v1/{scope}/{name}/manifest | Fetch manifest | 5 min |
GET /registry/v1/{scope}/{name}/{version}/artifact | Fetch artifact tarball | immutable |
GET /registry/v1/{scope}/{name}/{version}/signature | Fetch registry signature | immutable |
GET /registry/v1/{scope}/{name}/{version}/bundle | Fetch Sigstore bundle | immutable |
GET /registry/v1/revocations | Full revocation list | 1 min |
GET /registry/v1/revocations/delta?since={seq} | Revocation delta since sequence | 1 min |
Four verification steps on every install: content-length match, SHA-256 match, Sigstore publisher attestation, metafactory registry signature.
Atomic bundle install: bundles are reference-manifests pointing to already-published blueprints. Arc fetches each reference independently, stages them all in a temp directory, and atomically renames to final location. Any single failure rolls back everything — no partial installs.
Revocation list: stored in Workers KV for fast global propagation. Signed, carries Rekor proofs, uses monotonically increasing sequence numbers. Arc refuses to run blueprints if the revocation list is stale (>15 min without update).
Errors have two faces: what the publisher sees, and what the reviewer sees.
Publisher errors are safe to expose: a stable error code, a human-readable rule description, a docs URL, and an optional fix suggestion. No raw blueprint content is ever leaked back to a potentially malicious publisher.
Reviewer errors carry the full forensic payload: match excerpts (behind MFA re-auth), quarantine snapshot references, observer trace IDs, capability diffs against prior versions.
Every error code that exists in the publisher shape also exists in the reviewer shape with the same string — the reviewer always knows exactly what the publisher sees.
Reviewer-only codes (like narrator_observer_disagreement or counterfactual_divergence) are internal signals the publisher never learns about directly.
The complete TypeScript interfaces, error code enums, and versioning rules are in the design spec.