Files
git.stella-ops.org/docs/api/gateway/export-center.md
2025-12-24 12:38:14 +02:00

4.0 KiB

Export Center Gateway Contract (draft v0.9)

Scope: proxy Export Center APIs through the Web gateway with tenant scoping, deterministic responses, sealed-mode readiness, and offline-friendly signed URL handling.

Security / headers

  • Authorization: DPoP <token>, DPoP: <proof>
  • X-Stella-Tenant: <tenantId> (required; see docs/api/gateway/tenant-auth.md)
  • X-StellaOps-Project: <projectId> (optional)
  • Idempotency-Key: <uuid> (recommended for POST)
  • Accept: application/json (or text/event-stream for SSE)
  • Scopes (proposal): export:read for GET, export:write for POST.

Endpoints

  • GET /export-center/profiles — list export profiles (tenant-scoped).
  • POST /export-center/runs — start an export run.
  • GET /export-center/runs/{runId} — run status + outputs.
  • GET /export-center/runs/{runId}/events — SSE progress stream.
  • GET /export-center/distributions/{id} — signed URLs for OCI/object storage distribution.

POST /export-center/runs (request)

{
  "profileId": "export-profile::tenant-default::daily-vex",
  "targets": ["vex", "advisory", "policy"],
  "formats": ["json", "ndjson"],
  "distribution": {
    "type": "oci",
    "ref": "registry.local/exports/daily",
    "signing": { "enabled": true, "keyRef": "k8s://secrets/eks/oci-signer" }
  },
  "retentionDays": 30,
  "encryption": { "enabled": true, "kmsKey": "kms://tenant-default/key1" },
  "priority": "normal"
}

202 Accepted

{
  "runId": "export-run::tenant-default::2025-12-06::0003",
  "status": "queued",
  "estimateSeconds": 420,
  "links": {
    "status": "/export-center/runs/export-run::tenant-default::2025-12-06::0003",
    "events": "/export-center/runs/export-run::tenant-default::2025-12-06::0003/events"
  },
  "retryAfter": 5
}

GET /export-center/runs/{runId}

{
  "runId": "export-run::tenant-default::2025-12-06::0003",
  "status": "running",
  "profileId": "export-profile::tenant-default::daily-vex",
  "startedAt": "2025-12-06T10:00:00Z",
  "outputs": [
    {
      "type": "manifest",
      "format": "json",
      "url": "https://exports.local/tenant-default/0003/manifest.json?sig=...",
      "sha256": "sha256:c0ffee...",
      "dsseUrl": "https://exports.local/tenant-default/0003/manifest.dsse?sig=...",
      "expiresAt": "2025-12-06T16:00:00Z"
    }
  ],
  "progress": { "percent": 35, "itemsCompleted": 70, "itemsTotal": 200 },
  "errors": []
}

SSE events

  • started: { runId, status }
  • progress: { runId, percent, itemsCompleted, itemsTotal }
  • artifact_ready: { runId, type, id, url, sha256, format }
  • completed: { runId, status: "succeeded", manifestUrl, manifestDsseUrl? }
  • failed: { runId, status: "failed", code, message, retryAfterSeconds? }

Distributions

  • GET /export-center/distributions/{id} returns signed URLs, expiry, checksum, and optional DSSE envelope reference.
  • Response headers: Cache-Control: private, max-age=60, stale-if-error=300; ETag over sorted payload.
  • Signed URL rels: self, alternate (DSSE), bundle when tar/zip produced.

Determinism & limits

  • Max request body 256 KiB; max targets 50; max outputs 1000 assets/export; max bundle size 500 MiB compressed.
  • Default job timeout 60 minutes; idle SSE timeout 60s; client backoff 1s,2s,4s,8s capped at 30s; honor Retry-After.
  • Ordering: manifest items sorted (type asc, id asc, format asc, url asc).
  • Timestamps: ISO-8601 UTC; stable SHA-256 hashes only.

Error codes (proposal)

  • ERR_EXPORT_PROFILE_NOT_FOUND
  • ERR_EXPORT_REQUEST_INVALID
  • ERR_EXPORT_TOO_LARGE
  • ERR_EXPORT_RATE_LIMIT
  • ERR_EXPORT_DISTRIBUTION_FAILED
  • ERR_EXPORT_EXPIRED

Samples

  • Run request/response: see blocks above.
  • Status/manifest/events: reuse Console manifest sample (docs/api/console/samples/console-export-manifest.json) until Export Center publishes dedicated samples.

Outstanding for sign-off

  • Final scope/limit numbers (targets, bundle cap, timeouts).
  • Whether DSSE is mandatory for sealed tenants.
  • Distribution signing rules (key source, validity duration) and retention defaults.