# Concelier Air-Gap Bundle Deploy Runbook (CONCELIER-AIRGAP-56-003) Status: draft ยท 2025-11-24 Scope: deploy sealed-mode Concelier evidence bundles using deterministic NDJSON + manifest/entry-trace outputs. ## Inputs - Bundle: `concelier-airgap.ndjson` - Manifest: `bundle.manifest.json` - Entry trace: `bundle.entry-trace.json` - Hashes: SHA256 recorded in manifest and entry-trace; verify before import. ## Preconditions - Concelier WebService running with `concelier:features:airgap` enabled. - No external egress; only local file system allowed for bundle path. - Mongo indexes applied (`advisory_observations`, `advisory_linksets`). ## Steps 1) Transfer bundle directory to offline controller host. 2) Verify hashes: ```bash sha256sum concelier-airgap.ndjson | diff - <(jq -r .bundleSha256 bundle.manifest.json) jq -r '.[].sha256' bundle.entry-trace.json | nl | sed 's/\t/:/' > entry.hashes paste -d' ' <(cut -d: -f1 entry.hashes) <(cut -d: -f2 entry.hashes) ``` 3) Import: ```bash curl -sSf -X POST \ -H 'Content-Type: application/x-ndjson' \ --data-binary @concelier-airgap.ndjson \ http://localhost:5000/internal/airgap/import ``` 4) Validate import: ```bash curl -sSf http://localhost:5000/internal/airgap/status | jq ``` 5) Record evidence: - Store manifest + entry-trace alongside TRX/logs in `artifacts/airgap//`. ## Determinism notes - NDJSON ordering is lexicographic; do not re-sort downstream. - Entry-trace hashes must match post-transfer; any mismatch aborts import. ## Rollback - Delete imported batch by `bundleId` from `advisory_observations` and `advisory_linksets` (requires DBA approval); rerun import after fixing hash.