4.7 KiB
4.7 KiB
Export AirGap Prep — PREP-EXPORT-AIRGAP-57-001
Status: Ready for implementation (2025-11-20) Owners: Exporter Service Guild · Evidence Locker Guild Scope: Portable evidence export mode (air-gap) that reuses EvidenceLocker sealed/portable bundles and packages them for ExportCenter delivery.
Dependencies (must remain green before coding)
- EvidenceLocker packaging contract (sealed + portable):
docs/modules/evidence-locker/bundle-packaging.md,docs/airgap/portable-evidence.md. - Upstream sealed bundle export readiness (56-001) and bootstrap pack alignment (56-002) — inputs are reused verbatim, no re-signing.
- Orchestrator/Notifications envelopes for emission events remain pending; not required to start packaging but block notification wiring.
Contract for EXPORT-AIRGAP-57-001
-
Input: bundle id (
bundleId) that is already sealed. Export service fetches the portable archiveportable-bundle-v1.tgzvia the EvidenceLocker portable endpoint (write-once cache). -
Packaging: create deterministic gzip/tar (
export-portable-bundle-v1.tgz) with fixed mtime2025-01-01T00:00:00Z, PAX headers, and sorted entries:export-portable-bundle-v1.tgz ├── export.json # Export job metadata (bundleId, exportId, tenant, createdAtUtc, rootHash, sourceUri, portableVersion) ├── portable-bundle-v1.tgz # Bit-for-bit copy from EvidenceLocker (no re-signing) ├── checksums.txt # SHA256 for all files (portable bundle included) + Merkle root ├── verify-export.sh # POSIX script: checksum portable bundle, call `stella evidence verify --bundle portable-bundle-v1.tgz` └── README.md # Operator instructions (ingress/egress steps, expected headers, schema links)- Gzip header mtime and tar mtimes are pinned; permissions
0644; owner/group0. checksums.txtlists files in lexical order; first lineroot <sha256(export-portable-bundle-v1.tgz)>.verify-export.shuses onlytar+sha256sum/shasum; no network calls.
- Gzip header mtime and tar mtimes are pinned; permissions
-
API surface (ExportCenter)
POST /v1/exports/airgap/evidence/{bundleId}: stages the export; responds202 AcceptedwithexportIdand link to poll.GET /v1/exports/airgap/evidence/{exportId}: returns status + download link when ready; includesrootHash,portableVersion,bundleId.GET /v1/exports/airgap/evidence/{exportId}/download:application/gzip, filenameexport-portable-bundle-v1.tgz, ETag = SHA256.- Auth:
export:readfor GET,export:writefor POST; support tenant scoping identical to EvidenceLocker.
-
Determinism & observability
- No wall-clock usage beyond the already fixed
createdAtUtcwritten once per export job. - Emit structured log
{exportId,bundleId,portableVersion,rootHash}on completion. - Metrics: counter
export.airgap.portable.completed, histogramexport.airgap.portable.duration_ms, gaugeexport.airgap.portable.queue_depth.
- No wall-clock usage beyond the already fixed
-
Error handling
- If bundle not sealed →
409 SealedRequiredwithretryAfter. - If portable artefact missing → trigger fetch from EvidenceLocker; return
202withpendingReason=PortableMaterialising. - Verification failures of copied bundle (hash mismatch) → mark export
FAILEDand keep artefact; require operator acknowledgement.
- If bundle not sealed →
Acceptance criteria
- Deterministic archive bytes for a given (
bundleId,exportId) across reruns; gzip/tar timestamps and ordering pinned. - Export archive contains the unmodified EvidenceLocker portable bundle and top-level instructions for offline operators.
- CLI verification path documented in README and script; succeeds with no network access using current
stella evidence verify. - Status/Download endpoints documented and cover
202/404/409/500cases; ETag andLast-Modifiedset.
Implementation notes for developers
- Reuse EvidenceLocker’s
PortableBundleVersionconstant to avoid drift; do not unzip/repack the inner portable archive. - Populate
export.jsonusing UTC ISO-8601; includesourceUrireferencing the original EvidenceLocker portable endpoint used. - Store artefacts under object key
exports/{tenant}/{bundleId}/{exportId}/export-portable-bundle-v1.tgzwith write-once semantics. - Mirror logging/metrics naming with 56-001/56-002 to ease dashboard reuse.
Open items / risks
- Notifications/timeline emission remains pending on Wave 150/140 envelope drop; add once schemas land (tracked separately).
- If portable bundle version bumps to v2, archive filename and
portableVersionmust be updated in tandem.
Handoff
- This prep artefact is ready to implement in
src/ExportCenter/StellaOps.ExportCenter.WebServicejob +StellaOps.ExportCenter.Workerfor queue processing. - Link back to this document from Sprint 0162 Delivery Tracker entry P4.