# Export Center Provenance & Signing > **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. Export Center runs emit deterministic manifests, provenance records, and signatures so operators can prove bundle integrity end-to-end—whether the artefact is downloaded over HTTPS, pulled as an OCI object, or staged through the Offline Kit. This guide captures the canonical artefacts, signing pipeline, verification workflows, and failure handling expectations that backlogs `EXPORT-SVC-35-005` and `EXPORT-SVC-37-002` implement. --- ## 1. Goals & scope - **Authenticity.** Every export manifest and provenance document is signed using Authority-managed KMS keys (cosign-compatible) with optional SLSA Level 3 attestation. - **Traceability.** Provenance links each bundle to the inputs that produced it: tenant, findings ledger queries, policy snapshots, SBOM identifiers, adapter versions, and encryption recipients. - **Determinism.** Canonical JSON (sorted keys, RFC 3339 UTC timestamps, normalized numbers) guarantees byte-for-byte stability across reruns with identical input. - **Portability.** Signatures and attestations travel with filesystem bundles, OCI artefacts, and Offline Kit staging trees. Verification does not require online Authority access when the bundle includes the cosign public key. --- ## 2. Artefact inventory | File | Location | Description | Notes | |------|----------|-------------|-------| | `export.json` | `manifests/export.json` or HTTP `GET /api/export/runs/{id}/manifest` | Canonical manifest describing profile, selectors, counts, SHA-256 digests, compression hints, distribution targets. | Hash of this file is included in provenance `subjects[]`. | | `provenance.json` | `manifests/provenance.json` or `GET /api/export/runs/{id}/provenance` | In-toto provenance record listing subjects, materials, toolchain metadata, encryption recipients, and KMS key identifiers. | Mirrors SLSA Level 2 schema; optionally upgraded to Level 3 with builder attestations. | | `export.json.sig` / `export.json.dsse` | `signatures/export.json.sig` | Cosign signature (and optional DSSE envelope) for manifest. | File naming matches cosign defaults; offline verification scripts expect `.sig`. | | `provenance.json.sig` / `provenance.json.dsse` | `signatures/provenance.json.sig` | Cosign signature (and optional DSSE envelope) for provenance document. | `dsse` present when SLSA Level 3 is enabled. | | `bundle.attestation` | `signatures/bundle.attestation` (optional) | SLSA Level 2/3 attestation binding bundle tarball/OCI digest to the run. | Only produced when `export.attestation.enabled=true`. | | `manifest.yaml` | bundle root | Human-readable summary including digests, sizes, encryption metadata, and verification hints. | Unsigned but redundant; signatures cover the JSON manifests. | All digests use lowercase hex SHA-256 (`sha256:`). When bundle encryption is enabled, `provenance.json` records wrapped data keys and recipient fingerprints under `encryption.recipients[]`. --- ## 3. Signing pipeline 1. **Canonicalisation.** Export worker serialises `export.json` and `provenance.json` using `NotifyCanonicalJsonSerializer` (identical canonical JSON helpers shared across services). Keys are sorted lexicographically, arrays ordered deterministically, timestamps normalised to UTC. 2. **Digest creation.** SHA-256 digests are computed and recorded: - `manifest_hash` and `provenance_hash` stored in the run metadata (Mongo) and exported via `/api/export/runs/{id}`. - Provenance `subjects[]` contains both manifest hash and bundle/archive hash. 3. **Key retrieval.** Worker obtains a short-lived signing token from Authority’s KMS client using tenant-scoped credentials (`export.sign` scope). Keys live in Authority or tenant-specific HSMs depending on deployment. 4. **Signature emission.** Cosign generates detached signatures (`*.sig`). If DSSE is enabled, cosign wraps payload bytes in a DSSE envelope (`*.dsse`). Attestations follow the SLSA Level 2 provenance template; Level 3 requires builder metadata (`EXPORT-SVC-37-002` optional feature flag). 5. **Storage & distribution.** Signatures and attestations are written alongside manifests in object storage, included in filesystem bundles, and attached as OCI artefact layers/annotations. 6. **Audit trail.** Run metadata captures signer identity (`signing_key_id`), cosign certificate serial, signature timestamps, and verification hints. Console/CLI surface these details for downstream automation. > **Key management.** Secrets and key references are configured per tenant via `export.signing`, pointing to Authority clients or external HSM aliases. Offline deployments pre-load cosign public keys into the bundle (`signatures/pubkeys/{tenant}.pem`). --- ## 4. Provenance schema highlights `provenance.json` follows the SLSA provenance (`https://slsa.dev/provenance/v1`) structure with StellaOps-specific extensions. Key fields: | Path | Description | |------|-------------| | `subject[]` | Array of `{name,digest}` pairs. Includes bundle tarball/OCI digest and `export.json` digest. | | `predicateType` | SLSA v1 (default). | | `predicate.builder` | `{id:"stellaops/export-center@"}` identifies the worker instance/cluster. | | `predicate.buildType` | Profile identifier (`mirror:full`, `mirror:delta`, etc.). | | `predicate.invocation.parameters` | Profile selectors, retention flags, encryption mode, base export references. | | `predicate.materials[]` | Source artefacts with digests: findings ledger query snapshots, policy snapshot IDs + hashes, SBOM identifiers, adapter release digests. | | `predicate.metadata.buildFinishedOn` | RFC 3339 timestamp when signing completed. | | `predicate.metadata.reproducible` | Always `true`—workers guarantee determinism. | | `predicate.environment.encryption` | Records encryption recipients, wrapped keys, algorithm (`age` or `aes-gcm`). | | `predicate.environment.kms` | Signing key identifier (`authority://tenant/export-signing-key`) and certificate chain fingerprints. | Sample (abridged): ```json { "subject": [ { "name": "bundle.tar.zst", "digest": { "sha256": "c1fe..." } }, { "name": "manifests/export.json", "digest": { "sha256": "ad42..." } } ], "predicate": { "buildType": "mirror:delta", "invocation": { "parameters": { "tenant": "tenant-01", "baseExportId": "run-20251020-01", "selectors": { "sources": ["concelier","vexer"], "profiles": ["mirror"] } } }, "materials": [ { "uri": "ledger://tenant-01/findings?cursor=rev-42", "digest": { "sha256": "0f9a..." } }, { "uri": "policy://tenant-01/snapshots/rev-17", "digest": { "sha256": "8c3d..." } } ], "environment": { "encryption": { "mode": "age", "recipients": [ { "recipient": "age1qxyz...", "wrappedKey": "BASE64...", "keyId": "tenant-01/notify-age" } ] }, "kms": { "signingKeyId": "authority://tenant-01/export-signing", "certificateChainSha256": "1f5e..." } } } } ``` --- ## 5. Verification workflows | Scenario | Steps | |----------|-------| | **CLI verification** | 1. `stella export manifest --output manifests/export.json --signature manifests/export.json.sig`
2. `stella export provenance --output manifests/provenance.json --signature manifests/provenance.json.sig`
3. `cosign verify-blob --key pubkeys/tenant.pem --signature manifests/export.json.sig manifests/export.json`
4. `cosign verify-blob --key pubkeys/tenant.pem --signature manifests/provenance.json.sig manifests/provenance.json` | | **Bundle verification (offline)** | 1. Extract bundle (or mount OCI artefact).
2. Validate manifest/provenance signatures using bundled public key.
3. Recompute SHA-256 for `data/` files and compare with entries in `export.json`.
4. If encrypted, decrypt with Age/AES-GCM recipient key, then re-run digest comparisons on decrypted content. | | **CI pipeline** | Use `stella export verify --manifest manifests/export.json --provenance manifests/provenance.json --signature manifests/export.json.sig --signature manifests/provenance.json.sig` (task `CLI-EXPORT-37-001`). Failure exits non-zero with reason codes (`ERR_EXPORT_SIG_INVALID`, `ERR_EXPORT_DIGEST_MISMATCH`). | | **Console download** | Console automatically verifies signatures before exposing the bundle; failure surfaces an actionable error referencing the export run ID and required remediation. | Verification guidance (docs/modules/cli/guides/cli-reference.md §export) cross-links here; keep both docs in sync when CLI behaviour changes. --- ## 6. Distribution considerations - **HTTP headers.** `X-Export-Digest` includes bundle digest; `X-Export-Provenance` references `provenance.json` URL; `X-Export-Signature` references `.sig`. Clients use these hints to short-circuit re-downloads. - **OCI annotations.** `org.opencontainers.image.ref.name`, `io.stellaops.export.manifest-digest`, and `io.stellaops.export.provenance-ref` allow registry tooling to locate manifests/signatures quickly. - **Offline Kit staging.** Offline kit assembler copies `manifests/`, `signatures/`, and `pubkeys/` verbatim. Verification scripts (`offline-kits/bin/verify-export.sh`) wrap the cosign commands described above. --- ## 7. Failure handling & observability - Runs surface signature status via `/api/export/runs/{id}` (`signing.status`, `signing.lastError`). Common errors include `ERR_EXPORT_KMS_UNAVAILABLE`, `ERR_EXPORT_ATTESTATION_FAILED`, `ERR_EXPORT_CANONICALIZE`. - Metrics: `exporter_sign_duration_seconds`, `exporter_sign_failures_total{error_code}`, `exporter_provenance_verify_failures_total`. - Logs: `phase=sign`, `error_code`, `signing_key_id`, `cosign_certificate_sn`. - Alerts: DevOps dashboards (task `DEVOPS-EXPORT-37-001`) trigger on consecutive signing failures or verification failures >0. When verification fails downstream, operators should: 1. Confirm signatures using the known-good key. 2. Inspect `provenance.json` materials; rerun the source queries to ensure matching digests. 3. Review run audit logs and retry export with `--resume` to regenerate manifests. --- ## 8. Compliance checklist - [ ] Manifests and provenance documents generated with canonical JSON, deterministic digests, and signatures. - [ ] Cosign public keys published per tenant, rotated through Authority, and distributed to Offline Kit consumers. - [ ] SLSA attestations enabled where supply-chain requirements demand Level 3 evidence. - [ ] CLI/Console verification paths documented and tested (CI pipelines exercise `stella export verify`). - [ ] Encryption metadata (recipients, wrapped keys) recorded in provenance and validated during verification. - [ ] Run audit logs capture signature timestamps, signer identity, and failure reasons. --- > **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.