Lineage v2 (two-layer storage)¶
Audience: compliance / SRE operators who need detached child bodies for large lineage payloads and a join-pointer (child_sha) that survives parent-timeline truncation.
Overview¶
Lineage v2 stores lineage in two HMAC-chained layers:
.sdd/lineage/v2/
parent.jsonl # task_id, child_run_id, parent_call_id,
# summary, child_sha, hmac
children/<sha>.jsonl # full ChildBody payloads, hmac-chained per file
child_sha is the sha256 of the canonical first body line and acts as the content-addressed join pointer. Append order is: write+fsync the child file, then append the parent ref under flock(LOCK_EX).
Source:
src/bernstein/core/lineage/v2_store.py-LineageV2Store- the
lineage v2group insrc/bernstein/cli/commands/lineage_cmd.py
v1 remains the default. v2 is opt-in.
Enabling v2¶
Either:
BERNSTEIN_LINEAGE_V2=1in the environment, orbernstein.yamlwithlineage.version: 2.
When v2 is active the writer dual-writes through the v2 store; v1 readers keep working until the operator migrates out.
CLI¶
bernstein lineage v2 show TASK_ID [--root PATH] [--output-json]
bernstein lineage v2 verify [--root PATH] [--output-json]
bernstein lineage v2 export TASK_ID [--format jsonl|sigstore]
[--root PATH] [--output FILE]
--root defaults to .sdd/lineage/v2/.
show¶
Reconstructs and prints the full timeline for TASK_ID. Use --output-json for scripting; the table form prints run id, parent call id, summary, body count, and the first 24 chars of child_sha.
verify¶
Validates the HMAC chains across both layers. Exits 1 on failure; the failure list names the offending file plus the broken record.
export¶
Emits the timeline for TASK_ID as:
--format jsonl(default) - dump of parent refs + bodies.--format sigstore- SLSA v0.3 in-toto Statement per child, suitable for sigstore attestations.
Layout¶
| File | Contents |
|---|---|
parent.jsonl | One line per parent ref. Fields: task_id, child_run_id, parent_call_id, summary, child_sha, hmac. |
children/<sha>.jsonl | Full ChildBody payloads for the run named by child_sha. Each file is hmac-chained independently. |
Properties enforced by the store (and proved by 22 Hypothesis tests):
- HMAC unforgeability across both layers
- Replay determinism (same store + same task -> identical timeline)
- Append commutativity per task across concurrent writers
- Verify-after-truncate detects every truncation
- Orphan detection: a parent ref pointing to a missing child fails verify
Examples¶
Force v2 for a single run and verify on completion:
Export attestations for an audit pack:
Troubleshooting¶
Lineage v2: FAIL after a hard kill. The parent ref is appended after the child file is fsynced. A crash between those steps leaves a child file without a parent ref. Run verify to see which sha is orphaned; remove children/<sha>.jsonl to clear, or replay the run.
No v2 records for task. The writer is still on v1. Confirm BERNSTEIN_LINEAGE_V2=1 is set in the orchestrator's environment, not just the CLI shell; bernstein run inherits the env from where it was launched.