# ExportCenter OAS Prep — PREP-EXPORT-OAS-61-001 Status: **Ready for implementation** (2025-11-20) Owners: Exporter Service Guild · API Contracts Guild Scope: Freeze ExportCenter v1 OpenAPI surface (profiles/runs/downloads) with deterministic headers, ETag/versioning, and standard error envelope. ## Design targets - Cover the baseline export capabilities required for Wave 160.B: air-gap evidence exports, attestation exports, mirror/bootstrap exports, and discovery. - Keep payloads deterministic; avoid wall-clock dependence outside stamped fields returned by the service. - Provide strong cache/discovery signals: `ETag`, `Last-Modified`, `Cache-Control: private, must-revalidate`, plus `/.well-known/openapi` entry. ## Paths to include in v1 spec - `GET /.well-known/openapi` — returns OpenAPI document with `ETag` and `X-Export-Oas-Version` (value `v1`). - Evidence exports (portable bundles): - `POST /v1/exports/airgap/evidence/{bundleId}` → `202 Accepted` with `exportId`, `status=pending`. - `GET /v1/exports/airgap/evidence/{exportId}` → status document (`status`, `rootHash`, `artifactSha256`, `portableVersion`, `downloadUri`). - `GET /v1/exports/airgap/evidence/{exportId}/download` → `application/gzip`, filename `export-portable-bundle-v1.tgz`, `ETag` = archive SHA-256. - Attestation exports: - `POST /v1/exports/attestations/{attestationId}` → `202 Accepted` with `exportId`. - `GET /v1/exports/attestations/{exportId}` → status + `downloadUri`, `rootHash`, `statementDigest`. - `GET /v1/exports/attestations/{exportId}/download` → `application/gzip`, filename `export-attestation-bundle-v1.tgz`, `ETag` = archive SHA-256. - Mirror/bootstrap (profiles only, no payload schema change): - `GET /v1/exports/profiles` — lists available export profiles (e.g., `mirror`, `bootstrap`, `airgap-evidence`, `attestation`). Supports pagination (`limit`, `cursor`) and filtering by `kind`. - `GET /v1/exports/runs` — list export runs with status filters, tenant scoping, paging. - Observability hooks (metadata only): - `GET /v1/exports/runs/{exportId}/events` — optional timeline/event stream pointer (when notifications enabled). Can remain `x-stub: true` until envelopes land. ## Components - **Schemas** - `ExportStatus`: `{ exportId, profileId, status: pending|running|completed|failed, artifactSha256, rootHash, portableVersion?, attestationId?, bundleId?, createdAt, completedAt?, downloadUri }` - `ExportProfile`: `{ id, kind, description, version, retentionDays }` - `ErrorEnvelope`: `{ error: { code, message, correlationId, retryAfterSeconds? } }` with deterministic key order. - **Security** - OAuth2 client credentials; scopes: `export:write` (POST), `export:read` (GET/Download). Tenants enforced via claims. - **Headers** - `ETag` on all download/status responses; `Last-Modified` on status/download reflecting deterministic creation time. - Quota headers `X-Stella-Quota-*` retained for consistency with EvidenceLocker/ExportCenter. ## Versioning & determinism - OAS document served with `version: 1.0.0` and `x-stella-oas-revision` (UTC date string). No inline examples with non-deterministic timestamps; examples use `2025-01-01T00:00:00Z`. - All example hashes use fixed placeholder `sha256:0123...deadbeef` to keep docs repeatable. ## Deliverables - Publish OpenAPI YAML at `docs/modules/export-center/openapi/export-center.v1.yaml` matching the paths/schemas above. - Link the `.yaml` from Sprint 0162 Delivery Tracker P10 and set status to DONE once published. ## Acceptance criteria - All listed endpoints present in the YAML with request/response schemas and security scopes. - Deterministic examples (fixed timestamps/hashes) and `ETag`/`Last-Modified` response headers documented. - `/.well-known/openapi` discovery endpoint described with `ETag` and version headers. ## Next steps - Generate the YAML (can seed from EvidenceLocker/Orchestrator style) and check into `docs/modules/export-center/openapi/export-center.v1.yaml`. - Update SDK generator task (62-001) to depend on this OAS once merged.