Files
git.stella-ops.org/docs/modules/findings-ledger/schema-catalog.md
2026-01-14 18:39:19 +02:00

5.4 KiB
Raw Blame History

Findings Ledger Schema Catalog (FL1FL3)

Scope: Versioned canonical schemas for ledger events, projections, and exports.
Status: v1.0.0 sealed (2025-12-02) — breaking changes require new minor/major version tags.

1) Ledger event envelope — ledger.event.v1

Field Type Notes
event.id uuid V7 GUID allowed.
event.type string (ledger_event_type) See schema.md §2.2.
event.tenant string Partition key.
event.chainId uuid Derived when absent (tenant :: policyVersion), see workflow-inference.md.
event.sequence long Gapless per chain, starts at 1.
event.policyVersion string SHA-256 digest of policy bundle; propagated into exports and DSSE.
event.finding object id, artifactId, vulnId.
event.actor object id, type (`system
event.occurredAt string (UTC ISO-8601 ms) Domain clock.
event.recordedAt string (UTC ISO-8601 ms) Service TimeProvider.
event.payload object Mutation-specific body.
event.evidenceBundleRef string? DSSE/capsule id (optional).
event.airgap.bundle object? See airgap-provenance.md.
event_hash char(64) sha256(canonicalJson) lower-hex.
previous_hash char(64) All-zero for chain genesis.
merkle_leaf_hash char(64) `sha256(event_hash

Canonicalisation: UTF-8, sorted keys, lower-case enums, ISO-8601 UTC with millisecond precision, arrays stable-order. Any field addition bumps minor version.

2) Finding projection — ledger.projection.v1

Field Type Notes
tenantId string Partition key.
findingId string Stable identity.
policyVersion string Hash of active policy bundle.
status string `affected
severity number 010, 3 decimal places.
riskScore number 010, 3 decimal places.
riskSeverity string `low
riskProfileVersion string Version/hash from Risk Engine.
riskExplanationId uuid? Links to explain bundle.
labels json KEV/runtime flags, sorted keys.
currentEventId uuid Source ledger event.
explainRef string? Object storage / DSSE reference.
policyRationale json Array of rationale refs.
updatedAt string UTC Projection timestamp.
cycleHash char(64) sha256(canonicalProjectionJson); used in exports.

Projection deterministic hash recipe: serialize projection record with sorted keys (excluding updatedAt jitter) and hash via SHA-256. The replay harness recomputes and compares.

3) Export payloads — export.v1

Shapes share headers: policyVersion, projectionVersion (cycle hash), filtersHash, pageToken, observedAt, provenance (ledgerRoot, projectorVersion, policyHash, optional dsseDigest).

Canonical vs compact

  • Canonical (export.v1.canonical) — full provenance fields, evidence refs, DSSE linkage.
  • Compact (export.v1.compact) — drops verbose fields (policyRationale, comments, actor ids), keeps cycleHash + filtersHash for determinism; redaction manifest enforced.

Record fields

  • Findings: findingId, eventSequence, status, severity, risk, advisories[], evidenceBundleRef, cycleHash.
  • VEX: vexStatementId, product, status, justification, knownExploited, cycleHash.
  • Advisories: advisoryId, source, cvss{version,vector,baseScore}, epss, kev, cycleHash.
  • SBOMs: sbomId, subject{digest,mediaType}, sbomFormat, componentsCount, materials[], cycleHash.

Filters hash: sha256(sortedQueryString); stored alongside fixtures for replayability.

4) Versioning rules

  • Patch: backward-compatible field additions (new optional key) — bump patch digit.
  • Minor: additive required fields or canonical rule tweaks — bump minor.
  • Major: breaking change (field removal/rename, hash recipe) — bump major and keep prior schema frozen.

5) Reference artefacts

  • Golden fixtures: src/Findings/StellaOps.Findings.Ledger/fixtures/golden/*.ndjson.
  • Checksum manifest: docs/modules/findings-ledger/golden-checksums.json.
  • Offline verifier: tools/LedgerReplayHarness/scripts/verify_export.py.

6) Rekor Entry Reference — rekor.entry.ref.v1 (Sprint: SPRINT_20260112_004_FINDINGS)

Field Type Notes
logIndex long? Position in the Rekor log.
logId string? Log identifier (hex-encoded public key hash).
uuid string? Unique entry identifier.
integratedTime long? Unix epoch seconds when entry was integrated.
integratedTimeRfc3339 string? (UTC ISO-8601) RFC3339 formatted integrated time for display/sorting.
entryUrl string? Full URL to the Rekor entry for UI linking (e.g., https://rekor.sigstore.dev/api/v1/log/entries/{uuid}).

Usage: Attached to AttestationPointer records and evidence graph signature metadata. The integratedTimeRfc3339 field provides human-readable timestamps and deterministic sorting. The entryUrl enables direct linking from UI components.

Offline mode: When operating in air-gapped environments, entryUrl may be null or point to a local Rekor mirror. The integratedTime remains authoritative for timestamp verification.