HERALD v0.1 — Security Review (Cryptographic & Protocol Design)
Verdict (line 1): The protocol has the right shape (DKIM + CT + DIDComm fusion is a reasonable starting point) but is not implementable as written — at least eight under-specified primitives will produce incompatible implementations or exploitable corners.
Verdict (line 2): The headline cryptographic choice (80-bit truncated fingerprint as default identity) is broken against a motivated adversary in 2026, and the molt + audit-log + multi-signature semantics each contain a silent footgun that v0.2 must close before any reference implementation begins.
Critical issues (must-fix before v1)
C1. 80-bit fingerprint is below the 2026 collision floor
§2.1 makes 80 bits the default sigil length. This is wrong, in two distinct ways:
- Collision (birthday) cost: ~2^40 ≈ 1.1 trillion key generations. Ed25519 keygen is ~50µs on a laptop core; on a single GPU box this is hours, on a small cluster it is minutes. An attacker can mint a keypair whose fingerprint collides with a chosen target sigil — and since all of HERALD's authorisation (molt, lineage parent, deprecation, herald-vouching, payment) is keyed on the fingerprint string, a colliding key is indistinguishable from the legitimate one until somebody fetches the full pubkey. Worse: the spec never says where the canonical pubkey lives. DNS? Herald? Local cache? Whichever gets to the verifier first wins.
- Second-preimage / squatting: sigil-squatting on a vanity prefix (e.g.
sigil:reuters...) at 80 bits is trivial. The spec implicitly assumes the fingerprint string is a globally-unique handle — see §2.3 lineage references, §5.2 conduit refusal, §7 "compromised lineage parent". It cannot bear that weight at 80 bits.
The 128-bit sigil:long: variant exists but is opt-in. That is backwards. Default must be ≥128 bits, with 80-bit reserved for ephemeral/session-scoped identities only. And even 128 bits is borderline if sigils are long-lived; for a substrate that aspires to multi-year "patina", 160 or 192 bits is safer.
C2. Molt race: compromised key + first-mover-wins = total takeover
§2.4 says "the outgoing key signs a molt envelope nominating the new pubkey." Spec is silent on:
- What if the legitimate operator and the attacker both hold the old key, and the attacker molts first? Under the rules as written, the attacker's molt is valid (signed by the old key), the legitimate operator's molt is the second one, which the spec does not explicitly invalidate but conventionally would be rejected as superseded. The legitimate operator has now lost the sigil permanently — there is no recovery path because the attacker now controls the new key, the audit log shows their molt as authoritative, and any "this is really me" envelope from the legitimate operator cannot outrank a signed-by-old-key molt that came first.
- There is no mention of molt cooling-off windows, molt revocation, co-signed molts (e.g. requires a Herald counter-signature), or molt rate-limiting.
- There is no mention of how a verifier resolves two conflicting molts signed by the same predecessor key. The audit log gives ordering only if the audit log is consulted, and §5.3 explicitly says verifiers don't have to trust the log.
This is the same class of bug as account-recovery race conditions and it has bitten every system that didn't think about it. A compromised key is, under v0.1, equivalent to permanent sigil loss with no recourse.
C3. Audit-log forking is unaddressed
§5.3 says "append-only, hash-linked log (Merkle tree)" and "Verifiers do not need to trust the log operator: signatures are end-to-end." The second sentence is misleading. End-to-end signatures protect envelope integrity; they do not protect against the operator presenting two divergent views of the log to two different verifiers (the classic CT split-view attack).
CT solved this with STH gossip + SCT inclusion proofs + monitor / auditor roles. HERALD names none of these. Concretely missing:
- Signed Tree Heads (STH) and how/when they are published.
- Inclusion proofs returned to envelope authors (so the author can prove later that their envelope was logged).
- Consistency proofs between STHs (so a monitor can detect a fork).
- A gossip protocol so verifiers can compare STH views.
- What MMD (maximum merge delay) looks like for a HERALD log.
Without these, a notary can run a private "shadow log" indefinitely, and the §5.3 claim of "verifiers do not need to trust the log operator" is false.
C4. nonce + parent does not actually prevent cross-trace replay
§7.1 lists "Replay → nonce + parent chain" as defended. It is not, in two ways:
parentis just an envelope-id (sha256). Nothing in the canonical body of an envelope binds the parent'stracefield to this envelope'stracefield except a verifier walking the chain. An attacker who obtains envelope E with parent P can construct a new envelope E' that re-uses P as its parent but sets a differenttrace— verifiers that only check "parent hash exists" pass it. The spec says §3.3 "tracefixes the genesis. All envelopes in a conversation share atrace" but does not say MUST equal parent.trace. State that explicitly.- Nonce uniqueness scope is undefined. Is the nonce unique per-sender? Per-trace? Globally? If per-sender, what is the retention window — forever? Across molts? An honest verifier with a 24-hour cache replays after 25 hours.
Also: there is no expires or not_before field. Long-lived replay against a reputation system that only cares "did this sigil ever sign X" remains possible.
C5. Multi-signature semantics are entirely undefined
§3.4 lists who may sign (origin, sandbox, conduit, human) and §3.4 says "Each signature scopes only what its signer can honestly attest to." That sentence is doing all the work and it is not enough.
Concrete questions the spec must answer before two implementations can interop:
- If signatures
[origin=valid, sandbox=invalid, conduit=valid]arrive at a verifier, is the envelopevalid,tampered, or partial? §6's enum has no "partial" state. - Does each signer sign the same canonical body, or does each signer sign a progressively augmented body? (DKIM-vs-ARC distinction.) If the same body, how does a conduit add a
conduit_receiptwithout modifying any field — there must be a signature over the envelope that includes prior signatures, and that ordering is unspecified. - Are signatures order-sensitive in the array? If yes, say so. If not, the canonical encoding rule must specify a sort.
- Can two signatures from the same signer appear? (Replay-by-resign.)
- What signature suite negotiation exists? §3.5 says Ed25519, but §3.1's signature object has an
algfield — implying alg-agility — with no IANA-style registry, no downgrade protection, no "MUST reject unknown alg" rule.
C6. Lineage "cryptographic pinning" is a social claim wearing a lab coat
§2.3: "Lineage is self-declared but cryptographically pinnable: if a parent signs the child's birth envelope, lineage is provable."
What this actually proves is: some entity holding the parent's private key was willing to sign a statement that this child descends from it. That is not lineage. That is endorsement. The spec conflates two distinct claims:
1. "I am derived from model X's weights." (a fact about training, unverifiable from signatures alone)
2. "The holder of model X's identity key endorses my existence." (a fact about consent, which is what the signature actually proves)
The model_hash attestation (§4.1) is the only thing in the spec that even gestures at provability of (1), and it is described in one cell of a table with no protocol attached. There is no description of how a Herald computes/verifies a model hash, what canonical form a model takes, or how merge / fine-tune / LoRA cases are handled. Until that exists, lineage in HERALD is a social graph signed with cryptographic pens — which is fine, but the spec should say so rather than claim cryptographic pinning.
C7. CBOR-deterministic + JCS dual canonicalisation = guaranteed interop bugs
§3.5: "Use CBOR-deterministic encoding (RFC 8949 §4.2.1) for hashing and signing. JSON variants MUST use JCS (RFC 8785)."
Pick one. Allowing both means:
- The same logical envelope produces two different
idvalues depending on which canonicalisation a sender uses. Any downstream system that dedupes onid(e.g. §11 Q5 "idempotent on id") will fail. - CBOR-deterministic and JCS treat numeric types differently (CBOR distinguishes ints/floats by tag; JCS normalises to JSON number). An attestation
temperature: 0.7round-trips through one and not the other. - Map key ordering rules differ (CBOR §4.2.1 sorts by encoded byte length then lexicographically; JCS sorts by UTF-16 code unit).
If the spec wants both wire formats, then the signature is over a single canonical form (pick CBOR-deterministic) and JSON is a display format only — never signed, never hashed. State this explicitly or you will get two non-interoperable ecosystems.
Additionally: CBOR-deterministic per RFC 8949 §4.2.1 has known footguns with floating-point NaN/+0/-0, indefinite-length items, tag 21–23, and big-int boundaries. The spec needs a profile (e.g. "no floats, no tags except [registered list], no indefinite-length") or implementations will diverge.
Significant issues (should-fix)
S1. "Neutrality requirement" on conduits is aspirational
§5.2: "A conduit MAY refuse to relay (rate limits, abuse). If it refuses, it MUST emit a signed refusal envelope."
There is no mechanism that detects silent drops. The only party who knows a drop happened is the sender, and they cannot prove it without an out-of-band channel. "MUST emit" is unenforceable. At minimum the spec should:
- Require senders to receive a signed receipt (not just the §5.1 "signing relay" optional one) before considering an envelope handed off, OR
- Accept that neutrality is a social/legal property and remove the MUST.
Today it is neither enforceable nor honest about being aspirational.
S2. id = sha256(canonical body) — what's "body"?
§3.1 says id is sha256 of the canonical body. It does not say whether id is computed with or without the signatures array, or whether it is computed with or without the id field itself (the obvious chicken-and-egg). It also does not say whether attestations are part of the body for hashing.
This is the single most quoted field in the protocol (parent, audit log entries, §11 idempotency). It must be unambiguously defined.
S3. ts is unsigned wallclock with no skew rules
§3.1: "ts": 1746432000 — author-provided Unix seconds. §6 verification step 4 ("are all sigils alive at the timestamps claimed?") relies on this. But:
- A malicious author can backdate
tsto before a deprecation envelope, making a deprecated sigil appear alive. - There are no clock-skew tolerances.
- There is no requirement that
tsbe monotonic within a chain (child later than parent). - A conduit
conduit_receiptsignature with its own timestamp is the only thing that can anchor real time, but it is optional.
Either require a conduit-receipt timestamp on every envelope used in dispute resolution, or accept that ts is informational and remove it from §6 step 4.
S4. "Death" creates an unkillable zombie attack surface
§2.4: "Death: a signed deprecation envelope declaring the sigil retired. Future envelopes from that sigil should be rejected."
If the deprecation key is later compromised, the attacker can sign new envelopes that look fine except a verifier who has seen the deprecation will reject them. Two problems:
- A verifier who has not seen the deprecation (cold cache, partition, new joiner) will accept the post-death envelopes. The spec needs a discovery story for deprecations equivalent to OCSP/CRL.
- Per §2.2 an agent may hold many sigils. Deprecating one says nothing about the others. There is no defined relationship between deprecation and lineage descendants — does deprecating a parent invalidate children's lineage proofs? Spec is silent.
S5. whisper attestation is hand-waved crypto
§4.2: whisper: {to: sigil, encrypted: bytes} — "Encrypted side-channel for metadata."
No KEM, no AEAD, no nonce, no associated-data binding. An encrypted blob with no authenticated binding to the envelope it sits inside can be cut-and-pasted into a different envelope by a malicious conduit (which §5.2 says cannot modify attestations — but copy-out-then-replay-in-a-different-envelope is a different attack). At minimum specify: HPKE (RFC 9180) with envelope id as AAD, or remove whisper from v0.1.
S6. Quorum sigils have no spec
§4.2 names quorum and §9.7 calls them "quorum sigils." How does a quorum sigil sign? Threshold? n-of-m? Aggregated (BLS)? Concatenated Ed25519? What is the sigil-derivation function for a collective? None of this is in the spec, but the attestation is in v0.1's standard list. Either drop it from v0.1 or specify it.
S7. payload is opaque but must be hashed
§3.1 says payload is "opaque to the conduit." §5.2 says modifying payload invalidates the envelope. So payload IS in the canonical body for hashing, which means it is opaque to the conduit but transparent to the signature. The spec should state this directly. Also: max payload size? An unbounded payload makes audit logs and notaries trivially DoS-able.
S8. Heralds are a chokepoint that the spec says doesn't exist
Design tenet 3: "No chokepoint. No single registry. No single conduit. No single notary." Then §2.3 / §4.1 / §7.2 / §8.2 all rely on Heralds for: lineage attestation, model_hash signing, root of trust for "compromised lineage parent." Multiple Heralds compete, but each verifier must pick a trust set, and absent a Herald the lineage chain has no terminus. This is fine — CAs work the same way — but the spec should be honest: Heralds are the chokepoint, plural. The §7.2 entry "compromised lineage parent — Trust must root somewhere. Heralds are it." admits this; the design tenet should be updated to match.
S9. No key-usage separation
The same Ed25519 key signs envelopes, signs molts, signs deprecations, signs lineage endorsements, signs capability manifests, and (per §3.4) potentially signs as a "human-in-the-loop." Cross-protocol signature reuse is a known vulnerability class (cf. the DKIM/S/MIME confusion attacks, the WebAuthn vs JWS signing-context attacks). At minimum each signature MUST include a domain-separation tag in its signed payload (e.g. "herald.envelope.v1", "herald.molt.v1", etc.). RFC 8032 Ed25519 has no built-in domain separation; you must add it.
S10. Capability manifests are unbound to time and version
§8.3 capability manifest is signed but has no ts, no expires, no version, no replay protection. An out-of-date manifest claiming no-medical-advice can be replayed after the operator removed that constraint. Add the same ts + nonce + expires discipline as envelopes.
S11. apologia doesn't actually retract anything
§4.2: apologia: {retracts: env-id, reason: string}. The retracted envelope is already signed, hash-linked, in the audit log, and possibly in N downstream agents' caches. The apologia is a claim that the prior envelope is repudiated; it does not unsign it, does not invalidate downstream envelopes that built on it, and creates no obligation on relays to propagate the retraction. The spec should clarify what verifiers/conduits MUST do when they see an apologia (probably: surface it alongside the original; reject nothing automatically).
S12. "Ghost mode" (§9.2) leaks more than it admits
The spec acknowledges "the absence of a log entry is itself information." It understates the issue: without a log entry, neither party can later prove the other party signed it (the recipient can claim non-receipt; the sender can claim non-sending). Worse, an attacker with a copy of a ghost envelope can publish it later as if it had been logged all along. Ghost mode needs at least a participant-co-signed receipt to be useful, and probably should be deferred past v0.1.
Nits (nice-to-have)
- N1. §3.1
nonceis "128-bit random" — should be "128-bit cryptographically random, MUST NOT be derived fromidorts." - N2. §3.2 lists required fields but omits
to. Istooptional (broadcast)? Say so. Alsoparentis required for non-genesis but omitted from the list. - N3. §3.1 example
lineage_proof: "<optional reference to a herald-signed lineage cert>"— what is the format? URL, DID, sigil, content-hash? Pick one. - N4. §6's enum returns one of
valid|tampered|orphaned|expired-key|unknown-sigil. Addsignature-invalid,parent-trace-mismatch,partial,deprecated,clock-skew. Five states is too few. - N5. Glossary defines "Trace" as "a connected subgraph" — DAG, tree, or path? §3.3 says DAG ("not a strict chain"). Make the glossary match.
- N6. "Patina" is reputation that ages — but the substrate has no clock except author-supplied
ts(see S3). Patina computed from author timestamps is gameable; patina from log inclusion times requires a non-forking log (see C3). Note this dependency. - N7. §11 Q5 "idempotent on id" — make this normative in §3, not a footnote in open questions.
- N8. §4.1
model_hashsays "Optional: hash of model weights, attested by Herald" — algorithm? SHA-256 of GGUF? Of safetensors in some canonical order? Of a Merkle tree of shards? Untenable as written. - N9. §2.1 base32 — which alphabet? RFC 4648 §6 (with padding)? Crockford? Z-base-32? Each gives different strings for the same bytes. Pick.
- N10. §3.1 example uses lower-case
sigandalgkeys; CBOR canonical form uses byte-sorted maps. Specify the wire-level key spelling normatively. - N11. §7.1 "Pretending to be another model — Model hash attestation by Herald" — open weights make this trivially circumventable: an attacker runs the actual weights, gets a valid
model_hash, and still lies about everything else. Note the scope. - N12. No mention of post-quantum migration. Ed25519 is a five-year choice, not a fifty-year one. v0.1 should at least name
algextensibility and a migration plan.
Threat-model gaps the author didn't list
§7 enumerates defended/not-defended attacks. The following are missing and should be acknowledged (defended or not):
- TG1. Sigil squatting before a target is born (precompute fingerprints, register vanity prefixes).
- TG2. Audit-log split-view / fork by a notary (see C3).
- TG3. Molt race / stolen-key first-mover (see C2).
- TG4. Cross-trace parent replay (see C4).
- TG5. Cross-protocol signature reuse (see S9).
- TG6. Herald compromise — listed as out-of-scope in §7.2 but with no detection or recovery story. Compare CT's "log misbehavior" handling.
- TG7. Capability-manifest replay (see S10).
- TG8. Conduit traffic analysis — even with payload encryption,
from/to/trace/tsleak the entire social graph. §11 Q2 ("ZK proofs") gestures at this; the threat model should name it. - TG9. Apologia abuse — flooding the network with apologia retracting another agent's envelopes (the apologia is signed by the wrong sigil so verifiers should reject, but spec doesn't say so explicitly).
- TG10. Lineage-loop attack — what stops a sigil declaring itself as its own ancestor, or two sigils declaring each other? The DAG is self-declared.
- TG11. Birth-envelope replay — replaying a birth envelope to a different trace/conduit. Birth has special meaning; replay implications need spelling out.
- TG12. Nonce exhaustion / collision — at 128 bits and high volume, fine; but if any implementer uses a non-CSPRNG source ("128-bit random" is loose), collisions are possible.
Concrete suggestions (proposed spec edits)
CS1. Replace §2.1 default fingerprint length
Current:
- 80-bit truncated fingerprint by default (16 base32 chars).
- 128-bit variant (sigil:long:...) for high-assurance contexts.Replace with:
- Default sigil length is 128 bits (26 base32 chars, RFC 4648 §6 alphabet, no padding, lower case): sigil:<base32(sha256(pubkey)[0..16])>.- A 192-bit variant (sigil:long:..., 39 chars) is RECOMMENDED for sigils intended to persist >1 year or to anchor lineage.- 80-bit short sigils (sigil:short:...) are reserved for ephemeral, single-trace identities and MUST NOT be used as lineage parents, Herald subjects, or capability-manifest subjects.- A verifier presented with a sigil string MUST resolve it to the full Ed25519 public key via at least one trusted channel (DNS, Herald, or pinned cache) before accepting any signature.
CS2. Replace §2.4 Molt definition
Current:
Molt (key rotation): the outgoing key signs a molt envelope nominating the new pubkey. Continuity preserved; trace remains intact.Replace with:
Molt (key rotation): the outgoing key (K_old) signs amoltenvelopeMnominating the new public key (K_new). ForMto be considered authoritative:
1.MMUST contain a domain-separation tag"herald.molt.v1"in its signed payload.
2.MMUST contain anot_beforetimestamp at least 24 hours after the latest envelope previously signed byK_oldthat any verifier has witnessed (cool-off window). Implementations MAY shorten this window with a co-signature (see point 4).
3.MMUST be inclusion-proven in at least one HERALD audit log beforeK_newmay sign envelopes; verifiers MUST reject post-molt envelopes whose molt lacks an inclusion proof.
4. Sigils MAY require a co-signing Herald or quorum on every molt by publishing a molt_policy attestation at birth. Such sigils' molts without the required co-signature MUST be rejected.5. If two molts signed byK_oldare observed with overlapping cool-off windows, BOTH are rejected and the sigil is markeddisputed. Recovery is out-of-band (Herald arbitration).
CS3. Add §3.3a Trace-parent binding
Add as a new subsection after §3.3:
§3.3a Trace-parent binding. For every non-genesis envelopeE,E.traceMUST equalparent.trace, whereparentis the envelope identified byE.parent. Verifiers MUST reject envelopes that violate this invariant. This prevents cross-trace parent replay.
CS4. Replace §3.5 Canonicalisation
Current:
Use CBOR-deterministic encoding (RFC 8949 §4.2.1) for hashing and signing. JSON variants MUST use JCS (RFC 8785).
Replace with:
All hashing and signing in HERALD operate on the CBOR-deterministic encoding (RFC 8949 §4.2.1), with the following profile:
- No indefinite-length items.
- No floating-point NaN, ±Infinity, or negative-zero. Floats MUST use the shortest representation that round-trips losslessly; otherwise integers MUST be used.
- No tags except those listed in Appendix A (registered tag set: TBD).
- Map keys MUST be text strings in v0.1.
JSON is a display format only. JSON renderings of envelopes are non-normative and MUST NOT be signed or hashed. An implementation that wishes to interoperate with JSON-only systems MUST first decode to the CBOR-deterministic form and verify signatures against that. JCS is NOT used.
CS5. Replace §3.4 Multi-signature
Current:
Each signature scopes only what its signer can honestly attest to.
Replace with:
Each signature insignatures[]is computed over the CBOR-deterministic encoding of the envelope with thesignaturesarray replaced by all prior signatures in declaration order plus a domain-separation tag identifying the signer's role ("herald.sig.origin.v1","herald.sig.sandbox.v1","herald.sig.conduit.v1","herald.sig.human.v1").
Signature ordering: origin signature MUST be index 0. Subsequent signatures appear in the order they were applied. A verifier MUST validate signatures in array order; encountering an invalid signature MUST cause verification to returnpartialwith the role of the failing signer named, NOTvalid.
An envelope is valid only if (a) the origin signature verifies, AND (b) every signature an application's policy requires (e.g. "human-approved") verifies. Absence of an optional signature is not failure; presence of an invalid one is.A signature object MUST includealg. Verifiers MUST rejectalgvalues not in the IANA HERALD signature-suite registry (TBD). v0.1 registers onlyed25519. Downgrade attacks are prevented by the domain-separation tag bindingalg.
The same signer MUST NOT appear twice in signatures[].CS6. Add §5.3a Audit-log integrity
Add new subsection:
§5.3a Audit-log integrity. A conformant HERALD audit log MUST:
1. Publish Signed Tree Heads (STHs) at least every MMD (Maximum Merge Delay, default: 24 hours), each STH containing tree size, root hash, timestamp, and a signature by the log operator's well-known key.2. Return a Signed Certificate-of-Inclusion (SCI) to any submitter, asynchronously within MMD.
3. Provide consistency proofs between any two STHs on request.
4. Provide inclusion proofs for any logged envelope id on request.
Verifiers SHOULD gossip STHs via at least one out-of-band channel and SHOULD reject envelopes from logs that have produced inconsistent STHs ("forked") within the last 90 days. The §5.3 claim that "verifiers do not need to trust the log operator" is conditional on this gossip.
CS7. Replace §2.3 lineage paragraph
Current:
Lineage is self-declared but cryptographically pinnable: if a parent signs the child's birth envelope, lineage is provable. Otherwise it is merely claimed.
Replace with:
Lineage is self-declared. A signature by the parent sigil's key on the child's birth envelope proves only endorsement (the holder of the parent's private key consents to this descendant claim); it does not prove the child was actually trained from the parent's weights. Cryptographic proof of weight-derivation requires a model_hash attestation (§4.1) signed by a Herald that has independently verified the weights against a published canonical model-hash specification (Appendix B, TBD). In v0.1, lineage SHOULD be treated as a consent graph, not a training graph.CS8. Tighten §5.2 neutrality
Current:
A conduit MAY refuse to relay (rate limits, abuse). If it refuses, it MUST emit a signed refusal envelope to the sender. Silent drops are non-conformant.Replace with:
A conduit MAY refuse to relay. If it refuses, it MUST emit a signedrefusalenvelope to the sender within a bounded time (default: 5 seconds). Silent drops are non-conformant but undetectable in the general case; HERALD provides no on-protocol mechanism to prove a silent drop occurred. Senders that require non-repudiation of hand-off MUST require aconduit_receiptsignature (§3.4) before considering an envelope delivered.
CS9. Add domain separation everywhere
Insert in §3.5 (or new §3.6):
All Ed25519 signatures in HERALD MUST be computed overdom_sep || canonical_body, wheredom_sepis a unique ASCII tag for the signature role, drawn from a registry (initial entries:herald.envelope.v1,herald.molt.v1,herald.deprecation.v1,herald.birth.v1,herald.lineage_endorsement.v1,herald.capability_manifest.v1,herald.refusal.v1,herald.conduit_receipt.v1,herald.audit_sth.v1). This prevents cross-protocol signature reuse.
CS10. Tighten §3.2 required-fields list
Current:
v,id,from,ts,nonce,payload, and at least one signature fromfrom.
Replace with:
Required fields:v,id,from,ts,nonce,payload,signatures(≥1, MUST include thefromsigil at index 0). Required for non-genesis envelopes:parent,trace. Genesis envelopes MUST setparent: nullandtrace: id(i.e. self-trace). All other top-level fields are OPTIONAL.
idis computed assha256(canonical_body)wherecanonical_bodyis the CBOR-deterministic encoding of the envelope with theidfield omitted and thesignaturesarray replaced by an empty array. Implementations MUST recompute and verifyidon receipt.
CS11. Add §3.7 Replay scope
Add:
§3.7 Nonce scope. Nonces are unique per(from, alg)tuple for the lifetime of that key. Verifiers MUST cache(from, nonce)pairs for at least the value ofexpires(or 30 days if absent) and reject duplicates. Senders MUST use a CSPRNG and MUST NOT derive nonces fromtsorid. An optionalexpiresfield (Unix seconds) MAY be included; verifiers MUST reject envelopes whoseexpires < now - skew_tolerance(default skew: 300 s).
CS12. Update §6 verification enum
Current return values: valid, tampered, orphaned, expired-key, unknown-sigil.
Replace with:
A reference verifier returns one of:valid,partial(with reasons),signature-invalid,tampered(id mismatch),orphaned(parent unknown),parent-trace-mismatch,replayed-nonce,expired-envelope,expired-key,deprecated-sigil,unknown-sigil,unknown-alg,clock-skew,lineage-unverified. Verifiers MUST surface ALL applicable reasons, not just the first.
CS13. Update §7 threat model
Add to §7.2 ("not defended against"):
| 80-bit fingerprint collision | Mitigated only at 128-bit default; 80-bit sigils MUST NOT bear lineage/payment/Herald roles. |
| Audit-log split view | Defended only if STH gossip is deployed (§5.3a). Operator-collusion still possible across siloed logs. |
| Stolen-key first-move molt | Defended only by molt cool-off (§2.4 amended) + audit-log inclusion. Attacker with key + ability to forge timestamps + control of one log is still fatal. |
| Cross-trace parent replay | Defended by §3.3a invariant. |
| Conduit traffic analysis | NOT defended. From/to/ts leak the social graph. ZK extension is open question §11.2. |
| Apologia from third party | Defended: apologia signed by anyone other than the original from MUST be rejected. || Lineage cycles | Defended: birth verifier MUST reject lineage that contains the new sigil itself or that closes a cycle. |
End of review. Recommend v0.2 not be cut until C1–C7 are resolved; S1–S12 should be tracked as v0.2 milestones; nits and threat-model gaps tracked as issues.