Chain — replay every link
Integrity
One independent chain per task, chained from a fixed genesis value and recomputed from scratch on every render.
How a seal is computed
seal_n = SHA-384( UTF-8(prevSeal) || canonicalJson(event_n) ) canonicalJson: - object keys sorted by UTF-16 code unit, recursively - array order preserved - undefined members dropped - non-finite numbers rejected, not coerced to null - -0 normalised to 0 genesis = "crucible/v1/genesis"
The previous seal is prefixed as raw bytes, not as text, so there is no ambiguity about where a hash ends and its payload begins. Two known digest vectors are pinned in the test suite, so a change to canonical form cannot pass silently.
What this proves
A chain like this detects rewriting history. It does not stop somebody with write access from rewriting the whole log and recomputing every hash from genesis. For that you would need the head published somewhere append-only and independent — a transparency log, or periodic publication of crucible-grade-v1.0.0 heads.
Deletions keep a tombstone, so retiring a task never breaks the chain it was part of.
Replay
| Task | Links | Replay | Head | API |
|---|---|---|---|---|
| Retry storm under a flaky tool reference | 0 | intact | seal crucible/v1/genesis… | replay |
| Nested envelope collapse reference | 0 | intact | seal crucible/v1/genesis… | replay |
| CSV unit-of-measure drift reference | 0 | intact | seal crucible/v1/genesis… | replay |