Seal Rotation Log
Append-only log of every ed25519 keypair rotation on the SongForgeAI reproducibility seal infrastructure.
Why this log exists
The deep audit on 2026-05-04 (second pass) caught an unexplained operational pattern: the public key file at /.well-known/songforgeai-pubkey.json showed 4 rotations in 5 days, including one that lasted only 13 minutes (5/1 16:20 → 5/1 16:33).
That pattern is either:
- Deliberate (operator testing the rotation procedure), or
- Accidental (operator ran the script twice, or
misread the runbook), or
- A security event (key suspected compromised, rotated
defensively, then rotated again because the first rotation itself was compromised somehow)
Without a reason log, future readers — including the operator themselves 6 months from now — cannot tell which is which. Cryptographic integrity infrastructure should not have unexplained churn; this log forces a one-line reason on every rotation so the history is auditable.
Rotation contract
Every rotation must add one entry to this log within 24 hours of the rotation timestamp. Failure to log is itself a trust-decay finding.
The companion runbook lives at docs/SEAL-KEY-ROTATION-RUNBOOK.md (B1979). When rotating, the runbook walks the procedure; this log captures the WHY for posterity.
Format
## YYYY-MM-DD HH:MM (UTC) — <reason category>
- **Outgoing key fingerprint:** last 8 hex chars of the previous public key
- **Incoming key fingerprint:** last 8 hex chars of the new public key
- **Reason:** one paragraph explaining WHY this rotation happened
- **Operator:** torgin-dev (or other)
- **Rotation duration:** how long the new key has been current
before the next rotation (filled in retroactively when
the next rotation lands)Reason categories
- scheduled — quarterly hygiene rotation per runbook §1
- compromise — actual or suspected key compromise
- runbook-test — operator exercising the rotation procedure
- accidental — script ran when not intended
- migration — first-time generation, environment migration,
algorithm upgrade
Entries (newest first)
---
2026-05-01 16:33 (UTC) — compromise [retroactive entry]
- Outgoing key fingerprint:
2db8 8902(rotated 2026-04-26) - Incoming key fingerprint:
bf66 7667(current) - Reason: *Retroactive entry created 2026-05-04 (B2035) per
the new logging discipline. The original reason for this rotation was not recorded in the moment; based on file timestamps, the operator rotated keys twice within 13 minutes on 5/1 (16:20 → 16:33). Most likely interpretation: an operator-side runbook test that hit a gotcha (the first rotation was itself replaced 13 min later, suggesting the operator caught something post-rotation). If operator has a different recollection, edit this entry with the actual reason.*
- Operator: torgin-dev
- Rotation duration: current as of 2026-05-04 (3 days)
2026-05-01 16:20 (UTC) — runbook-test [retroactive entry, inferred]
- Outgoing key fingerprint:
e18b f3(rotated 2026-04-26) - Incoming key fingerprint:
8902(retired 13 min later) - Reason: *Retroactive entry created 2026-05-04 (B2035).
Inference: this rotation was almost certainly a runbook test that the operator immediately superseded — the 13-minute retention is too short for any other reason. If the operator recalls the actual reason, edit this entry.*
- Operator: torgin-dev
- Rotation duration: 13 minutes (very short — see audit
finding 2026-05-04 deep audit Section 4 #1)
2026-04-26 23:53 (UTC) — migration [retroactive entry]
- Outgoing key fingerprint:
00000000(the placeholder
zero-key from initial generation)
- Incoming key fingerprint:
e18b f3 - Reason: *Retroactive entry. The first real rotation —
replaces the zero-fingerprint placeholder from initial generation with the first production keypair.*
- Operator: torgin-dev
- Rotation duration: 5 days (rotated again 2026-05-01)
2026-04-26 (initial generation, undated UTC time) — migration [retroactive entry]
- Outgoing key fingerprint: N/A (first generation)
- Incoming key fingerprint:
00000000(zero-key
placeholder; immediately replaced same day)
- Reason: *Retroactive entry. Initial seal-keypair
infrastructure landed B1431. The zero-fingerprint placeholder in historical[] is the artifact of how scripts/generate-seal-keypair.ts records the first generation — there's no "previous key" to log, so the slot is filled with zeros. Same-day rotation to the first real key is normal initialization behavior.*
- Operator: torgin-dev
- Rotation duration: ~24 hours
---
Operator notes
- The first 4 entries above are retroactive — added
2026-05-04 (B2035) when this log file was created. Future rotations should be logged at the time of rotation, not reconstructed afterward.
- If a retroactive entry's "Reason" paragraph is incorrect
(operator has a different recollection of why a particular rotation happened), edit the entry directly. Source-of-truth is what the operator remembers; this log is the externally-readable record of what they remember.
- The next Trust Decay Audit (next due 2026-05-17) checks
this log against /.well-known/songforgeai-pubkey.json — if any rotation timestamp in the JSON is missing from this log, it's a ratchet failure.