# Offline and Air-Gap Technical Reference **Source Advisories**: - 01-Dec-2025 - DSSE‑Signed Offline Scanner Updates - 07-Dec-2025 - Reliable Air‑Gap Verification Workflows **Last Updated**: 2025-12-14 --- ## 1. OFFLINE UPDATE BUNDLE STRUCTURE ### 1.1 Directory Layout ``` /bundle-2025-12-14/ manifest.json # version, created_at, entries[], sha256s payload.tar.zst # actual DB/indices/feeds payload.tar.zst.sha256 statement.dsse.json # DSSE-wrapped statement over payload hash rekor-receipt.json # Rekor v2 inclusion/verification material ``` ### 1.2 Manifest Schema **manifest.json**: ```json { "version": "string", "created_at": "UTC ISO-8601", "entries": [{"name": "string", "sha256": "string", "size": int}], "payload_sha256": "string" } ``` ### 1.3 DSSE Predicate Schema **statement.dsse.json payload**: ```json { "payloadType": "application/vnd.in-toto+json", "payload": { "subject": { "name": "stella-ops-offline-kit-.tgz", "digest": {"sha256": "string"} }, "predicateType": "https://stella-ops.org/attestations/offline-update/1", "predicate": { "offline_manifest_sha256": "string", "feeds": [{"name": "string", "snapshot_date": "UTC ISO-8601", "archive_digest": "string"}], "builder": "string", "created_at": "UTC ISO-8601", "oukit_channel": "edge|stable|fips-profile" } } } ``` ### 1.4 Rekor Receipt Schema **rekor-receipt.json**: ```json { "uuid": "string", "logIndex": int, "rootHash": "string", "hashes": ["string"], "checkpoint": "string" } ``` ## 2. VERIFICATION SEQUENCE ### 2.1 Offline Kit Import Steps ``` 1. Validate Cosign signature of tarball 2. Validate offline-manifest.json with JWS signature 3. Verify file digests for all entries (including /attestations/*) 4. Verify DSSE: - Call StellaOps.Attestor.Verify with: - offline-update.dsse.json - offline-update.rekor.json - local Rekor log snapshot/segment - Ensure payload digest matches kit tarball + manifest digests 5. Only after all checks pass: - Swap Scanner's feed pointer to new snapshot - Emit audit event (kit filename, tarball digest, DSSE digest, Rekor UUID + log index) ``` ### 2.2 Activation Acceptance Rules - Trust root: pinned publisher public keys (out-of-band rotation) - Monotonicity: only activate if `manifest.version > current.version` - Atomic switch: unpack → validate → symlink flip (`db/staging/` → `db/active/`) - Quarantine on failure: move to `updates/quarantine/` with reason code ## 3. OFFLINE DIRECTORY LAYOUT ``` /evidence/ keys/ roots/ # root/intermediate certs, PGP pubkeys identities/ # per-vendor public keys tlog-root/ # hashed/pinned tlog root(s) policy/ verify-policy.yaml lattice-rules.yaml sboms/ # *.cdx.json, *.spdx.json attestations/ # *.intoto.jsonl.dsig (DSSE) tlog/ checkpoint.sig # signed tree head entries/ # *.jsonl (Merkle leaves) + proofs tools/ cosign- (sha256) oras- (sha256) jq- (sha256) scanner- (sha256) ``` ## 4. OFFLINE VERIFICATION POLICY SCHEMA ```yaml keys: - ./evidence/keys/identities/vendor_A.pub - ./evidence/keys/identities/your_authority.pub tlog: mode: "offline" checkpoint: "./evidence/tlog/checkpoint.sig" entry_pack: "./evidence/tlog/entries" attestations: required: - type: slsa-provenance - type: cyclonedx-sbom optional: - type: vex constraints: subjects: alg: "sha256" certs: allowed_issuers: - "https://fulcio.offline" allow_expired_if_timepinned: true ``` ## 5. DETERMINISTIC EVIDENCE RECONCILIATION ALGORITHM ``` 1. Index artifacts by immutable digest 2. For each artifact digest: - Collect SBOM nodes from canonical SBOM files - Collect attestations (provenance, VEX, SLSA, signatures) - Validate each attestation (sig + tlog inclusion proof) 3. Normalize all docs (stable sort, strip non-essential timestamps, lowercase URIs) 4. Apply lattice rules (precedence: vendor > maintainer > 3rd-party) 5. Emit `evidence-graph.json` (stable node/edge order) + `evidence-graph.sha256` + DSSE signature ``` ## 6. OFFLINE FLOW OPERATIONAL STEPS ``` 1. Import bundle (mount WORM media read-only) 2. Verify tools (hash + signature) before execution 3. Verify tlog checkpoint 4. Verify each inclusion proof 5. Verify attestations (keyring + policy) 6. Ingest SBOMs (canonicalize + hash) 7. Reconcile (apply lattice rules → evidence graph) 8. Record run: write `run.manifest` with input/policy/tool/output hashes; DSSE-sign with Authority key ``` ## 7. SCANNER CONFIG SURFACE ### 7.1 Offline Kit Configuration ```yaml scanner: offlineKit: requireDsse: true # fail import if DSSE/Rekor verification fails rekorOfflineMode: true # use local snapshots only attestationVerifier: https://attestor.internal trustAnchors: - anchorId: "UUID" purlPattern: "pkg:npm/*" allowedKeyids: ["key1", "key2"] ``` ### 7.2 DSSE/Rekor Failure Handling **DSSE/Rekor fail, Cosign + manifest OK**: - Keep old feeds active - Mark import as failed; surface ProblemDetails error via API/UI - Log structured fields: `rekorUuid`, `attestationDigest`, `offlineKitHash`, `failureReason` **Config flag to soften during rollout**: - When `requireDsse=false`: treat DSSE/Rekor failure as warning; allow import with alerts ## 8. SBOM INGESTION DETERMINISTIC FLOW ```bash # 1. Normalize SBOMs to canonical form jq -S . sboms/app.cdx.json > sboms/_canon/app.cdx.json # 2. Validate schemas (vendored validators) # 3. Hash-pin canonical files and record in manifest.lock sha256sum sboms/_canon/*.json > manifest.lock # 4. Import to DB with idempotent keys: (artifactDigest, sbomHash) ``` ## 9. OFFLINE REKOR MIRROR VERIFICATION ### 9.1 File-Ledger Pattern - Keep `tlog/checkpoint.sig` (signed tree head) + `tlog/entries/*.jsonl` (leaves + proofs) ### 9.2 Verification Steps ``` 1. Recompute Merkle root from entries 2. Check matches `checkpoint.sig` (after verifying signature with tlog root key) 3. For each attestation: - Verify UUID/digest appears in entry pack - Verify inclusion proof resolves ``` ## 10. METRICS & OBSERVABILITY ### 10.1 Offline Kit Metrics (Prometheus) ``` offlinekit_import_total{status="success|failed_dsse|failed_rekor|failed_cosign"} offlinekit_attestation_verify_latency_seconds (histogram) attestor_rekor_success_total attestor_rekor_retry_total rekor_inclusion_latency ``` ### 10.2 Structured Logging Fields ``` rekorUuid attestationDigest offlineKitHash failureReason kitFilename tarballDigest dsseStatementDigest rekorLogIndex ``` ## 11. ERROR HANDLING ### 11.1 Import Failure Modes | Failure Type | Action | Audit Event | |--------------|--------|-------------| | Cosign signature invalid | Reject, quarantine | `IMPORT_FAILED_COSIGN` | | Manifest signature invalid | Reject, quarantine | `IMPORT_FAILED_MANIFEST` | | DSSE verification failed | Reject (if requireDsse=true) | `IMPORT_FAILED_DSSE` | | Rekor inclusion failed | Reject (if requireDsse=true) | `IMPORT_FAILED_REKOR` | | Digest mismatch | Reject, quarantine | `IMPORT_FAILED_DIGEST` | | Version not monotonic | Reject | `IMPORT_FAILED_VERSION` | ### 11.2 Quarantine Structure ``` /updates/quarantine/-/ bundle.tar.zst manifest.json verification.log failure-reason.txt ``` ## 12. CLI COMMANDS ### 12.1 Offline Kit Import ```bash stellaops offline import \ --bundle ./bundle-2025-12-14.tar.zst \ --verify-dsse \ --verify-rekor \ --trust-root /evidence/keys/roots/stella-root.pub ``` ### 12.2 Offline Kit Status ```bash stellaops offline status # Output: # Active kit: bundle-2025-12-14 # Kit digest: sha256:abc123... # Activated at: 2025-12-14T10:00:00Z # DSSE verified: true # Rekor verified: true ``` ### 12.3 Offline Verification ```bash stellaops verify offline \ --evidence-dir /evidence \ --artifact sha256:def456... \ --policy verify-policy.yaml ``` ## 13. AUDIT TRAIL ### 13.1 Audit Event Schema ```json { "eventId": "uuid", "eventType": "OFFLINE_KIT_IMPORTED", "timestamp": "2025-12-14T10:00:00Z", "actor": "system", "details": { "kitFilename": "bundle-2025-12-14.tar.zst", "tarballDigest": "sha256:...", "dsseStatementDigest": "sha256:...", "rekorUuid": "...", "rekorLogIndex": 12345, "previousKitVersion": "bundle-2025-12-07", "newKitVersion": "bundle-2025-12-14" }, "result": "success" } ``` ### 13.2 Audit Log Storage ```sql CREATE TABLE offline_kit_audit ( event_id UUID PRIMARY KEY, event_type TEXT NOT NULL, timestamp TIMESTAMPTZ NOT NULL, actor TEXT NOT NULL, details JSONB NOT NULL, result TEXT NOT NULL ); CREATE INDEX idx_offline_kit_audit_ts ON offline_kit_audit(timestamp DESC); CREATE INDEX idx_offline_kit_audit_type ON offline_kit_audit(event_type); ``` ## 14. SECURITY CONSIDERATIONS ### 14.1 Key Management - Trust roots: pinned via out-of-band distribution - Key rotation: maintain version history in trust store - Revocation: maintain revoked_keys list in trust anchors ### 14.2 Integrity Guarantees - All bundles content-addressed - Manifest integrity via signature - DSSE envelope integrity via signature - Rekor inclusion proof integrity via Merkle tree ### 14.3 Air-Gap Boundaries **Allowed**: - Local file system reads (read-only mount) - Local tool execution (verified binaries) - Local database writes (staged) **Forbidden**: - Network egress - DNS lookups - NTP synchronization (use frozen clock) - External API calls --- **Document Version**: 1.0 **Target Platform**: .NET 10, PostgreSQL ≥16, Angular v17