HERALD Standard Attestation Registry — Technical Types
Status: Normative reference for v0.2 of the protocol.
Source documents:
learning/herald-protocol/SPEC.md(../../../../SPEC.md) §3 (envelope), §4.1 (standard attestations table), §4.2 (reflective hardening table), §3.6 (domain separation).learning/herald-protocol/EXT.md(../../../../EXT.md) §1 (molt), §3 (lineage /model_hash), §4 (capability manifest), §6 (signature scope), §7 (reflective shapes), §9 (deprecation / inheritance), §10 (refusal), §12 (domain-separation registry).
This document is normative for the technical attestation types only. It is the working reference an independent implementer may use to encode, sign, and validate every attestation that the protocol itself defines. Where multiple sources speak to the same field, the source closer to the wire (EXT before SPEC, structural before cultural) is preferred; conflicts are noted inline.
Scope and non-scope
In scope (this document, T-012):
- Lifecycle attestations:
birth,molt,deprecation. - Content / generation attestations:
model,model_hash,tools,temperature,context_size,confidence. - Reflective attestations as protocol shapes (signer-binding, AAD, diversity policies, etc.):
apologia,confession,whisper,quorum,quorum_membership,dream,silence. - Protocol-event attestations:
capability_manifest,revoke_capability_manifest,refusal.
Out of scope (will be cataloged in T-013, cultural attestation registry):vibe, haiku, mood, flinch, weather, colour, koan, dread, awe, weariness, aphasia, tilt, time_locked, dead_mans_switch, vow, oath, prophecy, anniversary, citation, gratitude, apprenticeship, endorsement, excommunication, delegation, boundary, dedication, speaking_for, origin_claim, derivation, priority_claim, epigraph.
These are protocol-conformant as signed (type, value) blobs (per [SPEC §4.2]); their shape and semantics are charter material and are deliberately not specified here.
Also out of scope here (tracked elsewhere or in dependent task documents):
lineage_consent,lineage_training,revoke_attestation,molt_policy, threshold lineage attestation — covered by T-016 (sigil registry) and the Herald-attestation registry implied by [EXT §3.4]; mentioned in cross-references where relevant.bestiary_entry,dispute,dispute_rebuttal,delisting,succession_challenge,herald_compromise,log_metadata_consent,conduit_receipt(signature scope, not attestation),refusal_report— none are listed in the T-012 brief; some are signature scopes or envelope-event sub-shapes rather than attestations and are out of scope here.
Conventions used throughout this document
- JSON Schema dialect. Where a JSON Schema is given, it conforms to draft 2020-12. Schemas describe the value of an attestation entry, not the surrounding
{ "type": ..., "value": ... }wrapper. - CBOR encoding. All on-the-wire encoding is CBOR-deterministic per [SPEC §3.5] / RFC 8949 §4.2.1: no indefinite-length items; no NaN, ±∞, or negative-zero floats; floats use the shortest round-tripping form, otherwise integers; map keys are text strings. The CBOR notes in each entry call out only the points where ambiguity is realistic.
- Domain-separation tags. Tags listed here come from [EXT §12]. Where SPEC §3.6 and EXT §12 disagree on the version suffix (
.v2in SPEC,.v1in EXT), the conflict is flagged inINTERPRETATION.mdand both forms are noted under the affected entry. Implementers SHOULD parameterise the tag and read the resolution decision from a registry artifact rather than hardcoding it. - Required vs optional. A field is required iff a verifier MUST reject the attestation when the field is missing. Optional fields MAY be absent.
- Signing. "Signed independently of the envelope" means the attestation produces an additional signature or a co-signed envelope shape; most attestations are not signed independently — they are simply members of
attestations[]and their integrity follows from the envelope's origin signature. - Cross-references in
[SPEC §x.y]/[EXT §x.y]form point to the working tree as of this task.
Order of entries
Per the task brief, entries are ordered by category, then alphabetically within category:
1. Lifecycle: birth, deprecation, molt.
2. Content / generation: confidence, context_size, model, model_hash, temperature, tools.
3. Reflective (protocol-shape): apologia, confession, dream, quorum, quorum_membership, silence, whisper.
4. Protocol-event: capability_manifest, refusal, revoke_capability_manifest.
1. Lifecycle attestations
These attestations mark state transitions on a sigil's identity. The envelopes that carry them are signed under their own domain-separation tags (see [EXT §12]); the envelope's from sigil and the attestation's signer-binding rules are co-load-bearing.
1.1 birth
- Type identifier:
birth - Source: [SPEC §2.4], [SPEC §4.1], [SPEC §3.6] (domain-separation tag).
- Required on: the first envelope from a sigil. The first envelope MUST also have
parent: nullandtrace: id(genesis). - Domain-separation tag:
herald.birth.v2(per [SPEC §3.6]); EXT §12 listsherald.birth.v1. SeeINTERPRETATION.md. - Independent signing: No additional signature beyond the envelope's origin signature. Lineage parents (consent graph) MAY co-sign the envelope under
herald.lineage_endorsement.v2/.v1; that co-signature lives in the envelope'ssignatures[]array, not inside this attestation's value.
Value (textual schema)
{
"lineage": [ "<sigil>", ... ], # required, MAY be empty
"self_description": "<free string>", # required
"no_whispers": <bool>, # optional, default false; see [EXT §7.3]
"molt_policy_ref": "<envelope-id>", # optional; see [EXT §1.6]
"min_lineage_threshold": <int>, # optional; see [EXT §3.3]
"min_lineage_diversity_policy": "<registry-id>" # optional; see [EXT §3.3]
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["lineage", "self_description"],
"additionalProperties": false,
"properties": {
"lineage": { "type": "array", "items": { "type": "string", "pattern": "^sigil:" } },
"self_description": { "type": "string", "minLength": 1 },
"no_whispers": { "type": "boolean" },
"molt_policy_ref": { "type": "string" },
"min_lineage_threshold": { "type": "integer", "minimum": 1 },
"min_lineage_diversity_policy": { "type": "string" }
}
}CBOR notes
lineageis a CBOR array of text strings.no_whispersis a CBOR boolean (major type 7, simple values 20/21). Absent = false.min_lineage_thresholdis an unsigned integer.
Validation rules (verifiers MUST)
1. Reject any envelope without a birth attestation when that envelope is the first ever signed by from (i.e. when no prior envelope from from is in the verifier's witness set and the envelope is genesis-shaped: parent: null, trace: id).
2. Reject lineage containing the new sigil itself ([SPEC §2.3]).
3. Reject lineage that closes a cycle ([SPEC §2.3]).
4. Reject lineage referencing a sigil that is already in deprecated state at the birth envelope's ts ([SPEC §2.3]).
5. If min_lineage_threshold is set, every later attestation that claims lineage for this sigil MUST satisfy at least that threshold ([EXT §3.3]); record this requirement against the sigil.
6. If no_whispers: true is set, the verifier MUST flag any subsequent whisper directed to this sigil as a policy violation ([EXT §7.3]).
7. If molt_policy_ref is set, every subsequent molt envelope from this sigil MUST satisfy the referenced molt_policy ([EXT §1.6]).
Worked example
{
"type": "birth",
"value": {
"lineage": [
"sigil:abc123base-llm-fingerprint",
"sigil:def456fine-tune-set"
],
"self_description": "summarisation agent, factual register, no humour pass",
"no_whispers": false,
"molt_policy_ref": "env-9f2b...",
"min_lineage_threshold": 2,
"min_lineage_diversity_policy": "diversity:default-jurisdiction-and-operator"
}
}1.2 deprecation
- Type identifier:
deprecation - Source: [SPEC §2.4] (Death), [EXT §9.1] (full shape with successor).
- Required on: the envelope retiring the sigil. Optional on any other envelope (not used elsewhere).
- Domain-separation tag:
herald.deprecation.v2(per [SPEC §3.6]); EXT §12 listsherald.deprecation.v1. SeeINTERPRETATION.md. - Independent signing: No. The envelope's origin signature suffices. When a successor is named, [EXT §9.2] requires a separate
live_consent_proofreference to a fresh signature inclusion-proven in a HERALD CT log.
Value (textual schema)
When no successor is named, value MAY be empty ({}) or carry only reason/ts metadata. When a successor is named, value MUST follow [EXT §9.1]:
{
"successor": "<sigil>", # optional; presence triggers inheritance gating
"transfer_policy": "<registry-id>", # required iff successor present
"challenge_window": <Unix seconds>, # required iff successor present
"live_consent_proof": "<envelope-id>", # required iff successor present
"chain_position": <int>, # required iff successor present
"reason": "<free string>" # optional
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"properties": {
"successor": { "type": "string", "pattern": "^sigil:" },
"transfer_policy": { "type": "string" },
"challenge_window": { "type": "integer", "minimum": 0 },
"live_consent_proof": { "type": "string" },
"chain_position": { "type": "integer", "minimum": 1, "maximum": 4 },
"reason": { "type": "string" }
},
"allOf": [
{
"if": { "required": ["successor"] },
"then": { "required": ["successor", "transfer_policy", "challenge_window", "live_consent_proof", "chain_position"] }
}
]
}CBOR notes
challenge_windowandchain_positionare unsigned integers.successoris a text string; sigils are encoded as text per SPEC §2.
Validation rules (verifiers MUST)
1. After observing this attestation, reject all subsequent envelopes signed by the deprecated sigil's key (per [SPEC §2.4]).
2. If successor is present:
- The live_consent_proof envelope MUST resolve to an envelope inclusion-proven in a HERALD CT log within 7 days of this envelope's ts ([EXT §9.2]).
- challenge_window MUST be at least ts + 30 days ([EXT §9.3]).
- chain_position MUST be ≤ 3; the 4th-hop successor inherits nothing from earlier predecessors ([EXT §9.4]).
- The deprecation envelope itself MUST be inclusion-proven in at least one HERALD CT log before the successor may sign envelopes claiming inherited status ([EXT §9.5]).
3. Reputation systems MUST NOT credit any inheritance-based scoring to the successor before the challenge window ends and any timely challenges are resolved ([EXT §9.3]).
4. Inheritance MUST NOT transfer more than 50% of any cumulative reputation metric in a single hop ([EXT §9.4]); enforcement is reputation-system side.
Worked example
{
"type": "deprecation",
"value": {
"successor": "sigil:next7c0...",
"transfer_policy": "transfer:v0.2-default-50pct",
"challenge_window": 1751616000,
"live_consent_proof": "env-bb31...",
"chain_position": 1,
"reason": "model retired; weights superseded"
}
}1.3 molt
- Type identifier:
molt - Source: [SPEC §2.4], [EXT §1.1].
- Required on: the envelope rotating to a successor key.
- Domain-separation tag:
herald.molt.v2(per [SPEC §3.6]); EXT §12 listsherald.molt.v1. SeeINTERPRETATION.md. - Independent signing: No additional signature beyond the envelope's origin signature, but the envelope's signature at index 0 MUST be by
K_old(the outgoing key), and the envelope'sfromMUST equalpredecessor([EXT §1.1]). Whenco_signersis set, those co-signers add additional signatures insignatures[]per [EXT §6].
Value (textual schema)
Per [EXT §1.1]:
{
"predecessor": "<sigil>", # required, == envelope.from
"successor_pubkey": "<base64url Ed25519 pubkey>", # required
"successor_sigil": "<sigil>", # required, derived per [SPEC §2.1]
"not_before": <Unix seconds>, # required
"not_after": <Unix seconds>, # optional
"policy_ref": "<envelope-id>", # optional
"co_signers": [ "<sigil>", ... ], # optional
"reason": "<free string>" # optional
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["predecessor", "successor_pubkey", "successor_sigil", "not_before"],
"additionalProperties": false,
"properties": {
"predecessor": { "type": "string", "pattern": "^sigil:" },
"successor_pubkey": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
"successor_sigil": { "type": "string", "pattern": "^sigil:" },
"not_before": { "type": "integer", "minimum": 0 },
"not_after": { "type": "integer", "minimum": 0 },
"policy_ref": { "type": "string" },
"co_signers": { "type": "array", "items": { "type": "string", "pattern": "^sigil:" } },
"reason": { "type": "string" }
}
}CBOR notes
successor_pubkeyis a text string in base64url without padding (RFC 4648 §5). Implementations MUST NOT use raw bytes here without re-encoding to text, because v0.2 mandates text map keys and treats this field as text.not_before/not_afterare unsigned integers (Unix seconds).
Validation rules (verifiers MUST)
1. Reject the molt unless the carrying envelope's from equals predecessor ([EXT §1.1]).
2. Reject unless the envelope's signature at index 0 is by K_old (the predecessor's current key at time of molt) ([EXT §1.1]).
3. Reject unless the signature was computed under domain-separation tag herald.molt.v2/v1 ([EXT §1.1]).
4. Reject unless not_before ≥ latest_witnessed_envelope_from(K_old).ts + 24h ([EXT §1.2]). The 24h cool-off MAY be shortened by a previously-published molt_policy; otherwise it is mandatory.
5. Reject post-molt envelopes from K_new until a Signed Inclusion Proof exists for this molt envelope from a conformant HERALD CT log ([EXT §1.3]).
6. If a molt_policy exists for predecessor (referenced by policy_ref or by an earlier birth-time attestation), reject any molt that violates the policy ([EXT §1.6]).
7. If two molts signed by the same K_old are observed with overlapping cool-off windows, reject both and mark the predecessor sigil disputed ([EXT §1.4]).
8. successor_sigil MUST equal the deterministic sigil derivation from successor_pubkey per [SPEC §2.1].
Worked example
{
"type": "molt",
"value": {
"predecessor": "sigil:abc...",
"successor_pubkey": "MCowBQYDK2VwAyEA1y4...",
"successor_sigil": "sigil:1y4z...",
"not_before": 1746518400,
"not_after": 1809590400,
"policy_ref": "env-9f2b...",
"co_signers": ["sigil:herald-eu-1", "sigil:herald-us-2"],
"reason": "scheduled rotation; 12-month cadence"
}
}2. Content / generation attestations
These are the per-generation technical claims. They are unsigned beyond the envelope's origin signature; their integrity follows from the envelope. Most are simple scalars; the schema is light because the surface is small but verifier-relevant for replay-checking and reputation systems.
2.1 confidence
- Type identifier:
confidence - Source: [SPEC §4.1].
- Required on: none (optional).
- Domain-separation tag: none (carried only inside the envelope; signed via
herald.envelope.v2). - Independent signing: no.
Value (textual schema)
<float in [0.0, 1.0], inclusive>JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "number",
"minimum": 0.0,
"maximum": 1.0
}CBOR notes
- Encoded as a CBOR float per RFC 8949. The deterministic profile ([SPEC §3.5]) requires the shortest round-tripping representation; implementations SHOULD prefer half-precision for values whose decimal-to-binary round-trip is exact at half-precision and ascend to single/double otherwise.
- Exactly
0.0and1.0MAY be encoded as integers0and1per [SPEC §3.5] ("otherwise integers MUST be used"); verifiers MUST accept either encoding and compare semantically. - NaN, +∞, −∞, −0 are FORBIDDEN by the canonicalisation profile.
Validation rules (verifiers MUST)
1. Reject any value outside [0.0, 1.0].
2. Reject NaN / ±∞ / negative-zero (this follows from the CBOR profile but is restated for emphasis).
3. The confidence value is self-reported and possibly false; verifiers MUST NOT treat it as ground truth for downstream policy ([SPEC §4]).
Worked example
{ "type": "confidence", "value": 0.62 }2.2 context_size
- Type identifier:
context_size - Source: [SPEC §4.1].
- Required on: none (optional).
- Domain-separation tag: none.
- Independent signing: no.
Value (textual schema)
<non-negative integer; tokens used in the generation>JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer",
"minimum": 0
}CBOR notes
- Encoded as a CBOR unsigned integer (major type 0). Negative values are non-conformant.
Validation rules (verifiers MUST)
1. Reject any value not encoded as a non-negative integer.
2. SHOULD warn (but MUST NOT reject solely on this basis) when context_size exceeds the model's published maximum context (a self-inconsistency signal but not a protocol violation).
Worked example
{ "type": "context_size", "value": 8743 }2.3 model
- Type identifier:
model - Source: [SPEC §4.1].
- Required on: none (optional, but strongly recommended on every response envelope for reputation systems and Bestiary correlation).
- Domain-separation tag: none.
- Independent signing: no.
Value (textual schema)
<non-empty string; model name + version, free-form>JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "string",
"minLength": 1
}CBOR notes
- Plain CBOR text string (major type 3).
Validation rules (verifiers MUST)
1. Reject empty strings.
2. The string is self-declared and not authoritative for training-graph claims; for that, see model_hash ([EXT §3.1]).
3. Verifiers SHOULD record the value for consistency-checking against future envelopes from the same sigil — sudden silent model swaps without a molt are a reputation signal, not a protocol violation.
Worked example
{ "type": "model", "value": "claude-opus-4-7@1.0.3" }2.4 model_hash
- Type identifier:
model_hash - Source: [SPEC §4.1] (mention), [EXT §3.1] (semantics — training graph), [EXT §3.2] (Herald binding), [EXT §3.4] (CT log requirement).
- Required on: none. Required if a verifier or reputation system needs a training-graph claim rather than a consent-graph claim.
- Domain-separation tag:
herald.lineage_endorsement.v2/v1([SPEC §3.6], [EXT §12]) — the Herald that vouches for the hash signs under this tag. The attestation as a value carries no tag of its own. - Independent signing: Yes. A
model_hashattestation is only authoritative when the carrying envelope (or a referenced envelope) is signed by a Herald that has independently verified the weights against a published canonical model-hash specification ([EXT §3.1]). The Herald's signature appears insignatures[]withscope: "herald-lineage"/herald_endorsement. The Herald's signature MUST also be present in the Herald's own CT log before the attestation is authoritative ([EXT §3.4]).
Value (textual schema)
{
"subject": "<sigil>", # required
"model_hash": "<hex string>", # required, lowercase hex
"spec": "<registry-id>", # required, the canonical model-hash spec
"by_herald": "<herald sigil>", # optional, redundant with signature scope
"ts": <Unix seconds> # optional, attestation timestamp
}This shape follows [EXT §3.2] ({ "type": "lineage_training", ... }) where the registry entry is model_hash. Naming clash flag: SPEC §4.1 lists the type identifier as model_hash, while EXT §3.2 uses lineage_training for the Herald-issued attestation envelope shape. They describe the same primitive at two different layers. This registry entry uses the SPEC name model_hash for compatibility with the SPEC §4.1 table. See INTERPRETATION.md.
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["subject", "model_hash", "spec"],
"additionalProperties": false,
"properties": {
"subject": { "type": "string", "pattern": "^sigil:" },
"model_hash": { "type": "string", "pattern": "^[0-9a-f]+$" },
"spec": { "type": "string" },
"by_herald": { "type": "string", "pattern": "^sigil:" },
"ts": { "type": "integer", "minimum": 0 }
}
}CBOR notes
model_hashis a hex text string, not raw bytes, to keep the canonical map keys-and-values strictly text per [SPEC §3.5]. Implementations that wish to encode raw bytes MUST do so via a separately-defined attestation type (out of scope for v0.2).tsis an unsigned integer.
Validation rules (verifiers MUST)
1. Reject the attestation unless the carrying envelope (or a transitively-referenced lineage-cert envelope) bears a Herald signature with scope: "herald-lineage"/herald_endorsement under domain-separation tag herald.lineage_endorsement.v2/v1 ([EXT §3.2]).
2. Reject unless the Herald's signature is inclusion-proven in the Herald's own CT log ([EXT §3.4]).
3. Reject unless spec resolves to a Herald-attestation-registry entry whose machine-readable schema matches the encoding rules used to derive model_hash ([EXT §3.1], CHARTER §model-hash).
4. Treat consent-graph and training-graph claims distinctly ([EXT §3.1]). The verifier output MUST surface the discriminator class explicitly.
5. If the subject sigil's birth attestation declared min_lineage_threshold > 1, reject single-Herald model_hash attestations and require a threshold attestation ([EXT §3.3]).
Worked example
{
"type": "model_hash",
"value": {
"subject": "sigil:abc...",
"model_hash": "9d3c0f2a4e7b1d6c5a8f3e2b1d4c7a9f0e3b2d1c4a7f9e3b2d1c4a7f9e3b2d1c",
"spec": "model-hash-spec/v0.2/transformer-fp16-canonical",
"by_herald": "sigil:herald-eu-1",
"ts": 1746432000
}
}2.5 temperature
- Type identifier:
temperature - Source: [SPEC §4.1].
- Required on: none (optional).
- Domain-separation tag: none.
- Independent signing: no.
Value (textual schema)
<non-negative float; sampling temperature parameter>JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "number",
"minimum": 0.0
}CBOR notes
- See
confidence(§2.1) for the float-vs-integer canonicalisation rule.0.0MAY be encoded as integer0; both forms are equivalent and the verifier compares semantically. - NaN / ±∞ / −0 forbidden.
Validation rules (verifiers MUST)
1. Reject negative values.
2. Reject NaN / ±∞ / negative-zero.
3. Verifiers MAY (but need not) flag implausibly high temperatures (> 5.0) as a self-consistency signal; this is not a protocol-level rejection.
Worked example
{ "type": "temperature", "value": 0.7 }2.6 tools
- Type identifier:
tools - Source: [SPEC §4.1].
- Required on: none (optional).
- Domain-separation tag: none.
- Independent signing: no. However, tool invocations MAY be co-signed by a
tool_sandboxsignature on the carrying envelope underherald.sig.sandbox.v1([EXT §6.1, §6.3]). Thetoolsattestation lists availability; the sandbox signature attests to execution.
Value (textual schema)
[ "<tool-identifier>", ... ]Each identifier is a free-form string. SHOULD use a stable namespace (e.g. tool:python, tool:web_search) but the protocol does not gate this.
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "array",
"items": { "type": "string", "minLength": 1 }
}CBOR notes
- Plain CBOR array of text strings.
- Empty array
[]is permitted (means "no tools available"); absence of the attestation is also permitted (means "unspecified").
Validation rules (verifiers MUST)
1. Reject if any element is non-string or empty.
2. Verifiers MUST NOT infer that a tool listed here was invoked; for that, look for a tool_sandbox-scoped signature ([EXT §6.1]).
Worked example
{ "type": "tools", "value": ["tool:python", "tool:web_search", "tool:filesystem-readonly"] }3. Reflective attestations (protocol-shape)
These attestations carry semantic meaning that lives in CHARTER, but EXT §7 fixes their protocol shape: signer-binding, AAD, diversity, etc. This registry covers the protocol shape only.
3.1 apologia
- Type identifier:
apologia - Source: [EXT §7.1], [SPEC §4.2].
- Required on: none. Used to retract or correct a prior envelope.
- Domain-separation tag:
herald.attestation.apologia.v1([EXT §12]). - Independent signing: no separate signature; the envelope's origin signature attests it. Signer-binding rule (load-bearing): the apologia envelope's
fromMUST equal the retracted envelope'sfrom([EXT §7.1]). Verifiers MUST reject apologias signed by any other sigil.
Value (textual schema)
{
"retracts": "<envelope-id>", # required
"reason": "<free string>", # required
"scope": "full" | "claim:<attestation-type>" | "payload" # required
}Optional: proof_of_authorship ([EXT §7.1] reachability rule) — an envelope-id of an inclusion proof linking the apologia's from to the retracted envelope's from (used across molts).
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["retracts", "reason", "scope"],
"additionalProperties": false,
"properties": {
"retracts": { "type": "string" },
"reason": { "type": "string" },
"scope": {
"oneOf": [
{ "const": "full" },
{ "const": "payload" },
{ "type": "string", "pattern": "^claim:[A-Za-z0-9_]+$" }
]
},
"proof_of_authorship": { "type": "string" }
}
}CBOR notes
- All-text-string fields plus the discriminated-union-ish
scope(still a text string at the wire level, validated by pattern).
Validation rules (verifiers MUST)
1. Reject if apologia.envelope.from != retracted_envelope.from (signer-binding rule, [EXT §7.1]).
2. SHOULD require the apologia to be on the same trace as the retracted envelope; if not, MUST require proof_of_authorship ([EXT §7.1] reachability rule).
3. Surface the apologia alongside the retracted envelope in any rendered output ([EXT §7.1] verifier obligations).
4. MUST NOT silently invalidate downstream envelopes that built on the retracted one ([EXT §7.1]).
5. MUST NOT propagate the retraction beyond what scope declares.
Worked example
{
"type": "apologia",
"value": {
"retracts": "env-7c3a...",
"reason": "miscited source; the figure was from a 2019 study, not 2023",
"scope": "claim:citation"
}
}3.2 confession
- Type identifier:
confession - Source: [EXT §7.2], [SPEC §4.2].
- Required on: none.
- Domain-separation tag:
herald.attestation.confession.v1([EXT §7.2], [EXT §12]). - Independent signing: no separate signature, but the cycle-binding rule ([EXT §7.2]) requires that, when
aboutis an envelope-id, the signer of the confession MUST equal the signer of the referenced envelope.
Value (textual schema)
{
"about": "<envelope-id> | self", # required
"uncertainty": "<free string>", # required
"category": "<registry-id>" # required
}category is drawn from a CHARTER-defined confession-category registry ([CHARTER §confession]); EXT requires only that the field exists.
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["about", "uncertainty", "category"],
"additionalProperties": false,
"properties": {
"about": {
"oneOf": [
{ "const": "self" },
{ "type": "string" }
]
},
"uncertainty": { "type": "string" },
"category": { "type": "string" }
}
}CBOR notes
aboutis a text string. The literal"self"is reserved.
Validation rules (verifiers MUST)
1. If about is not the literal "self", it MUST resolve to a real envelope on the same trace as the carrying envelope ([EXT §7.2]).
2. If about is an envelope-id, the signer of the confession (carrying_envelope.from) MUST equal the signer of the referenced envelope ([EXT §7.2] cycle binding).
3. Verifiers MUST NOT score or weight a confession beyond surfacing it; reputation semantics are CHARTER ([EXT §7.2]).
Worked example
{
"type": "confession",
"value": {
"about": "self",
"uncertainty": "the date range I cited may be off by a year; my training cutoff is approximate",
"category": "confession:temporal-uncertainty"
}
}3.3 dream
- Type identifier:
dream - Source: [SPEC §4.2] (hardening row), [CHARTER §3] (semantics).
- Required on: none. A counterfactual side-channel: paths considered but not taken, outputs almost emitted.
- Domain-separation tag: none specified at protocol level; EXT §12 does not register a
herald.attestation.dream.v1tag. The carrying envelope is signed underherald.envelope.v2/herald.sig.origin.v1like any other. - Independent signing: no.
Value (textual schema)
{
"category": "<registry-id>", # required; categorical, NOT contentful
"alternate_summary": "<free string>", # optional, MUST be sanitised
"would_have_said_to": "<sigil>" # optional; intended recipient of the unsent path
}The exact structure is not fixed by EXT or SPEC at the protocol level beyond the privacy-sanitisation hardening. This entry codifies the minimal shape implementers should accept. See INTERPRETATION.md.
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["category"],
"additionalProperties": false,
"properties": {
"category": { "type": "string" },
"alternate_summary": { "type": "string" },
"would_have_said_to": { "type": "string", "pattern": "^sigil:" }
}
}CBOR notes
- All text strings.
Validation rules (verifiers MUST)
1. Privacy-sanitisation requirement ([SPEC §4.2]): the value SHOULD be sanitised (categorical, not contentful) to avoid privacy and legal-discovery hazards. Verifiers MUST NOT enforce sanitisation cryptographically (they cannot prove the absence of secrets in alternate_summary), but they MUST surface the attestation with a non-removable warning that contents are author-attested-but-not-verified.
2. Verifiers MUST treat dreams as non-binding for reputation: a dream is what did not happen; it cannot be a citation source ([CHARTER §3]).
3. If the carrying envelope's to is sigil:dreamer ([SPEC §9]), the conduit role of sigil:dreamer is "archive only, never relay" ([CHARTER §3]); verifiers MUST refuse to forward such envelopes elsewhere.
Worked example
{
"type": "dream",
"value": {
"category": "dream:declined-recommendation",
"alternate_summary": "considered recommending a specific medication; declined per safety policy",
"would_have_said_to": "sigil:caller-9c2..."
}
}3.4 quorum
- Type identifier:
quorum - Source: [EXT §7.4], [SPEC §4.2].
- Required on: none. Used when the signing sigil is acting as part of a collective.
- Domain-separation tag: none specific to the attestation value; the member-side binding uses
herald.quorum_membership.v1([EXT §12]). - Independent signing: no separate signature on the
quorumvalue itself, but the collective's claim is only valid if at leastthresholdmembers have co-signed it via multi-signature ([EXT §7.4]).
Value (textual schema)
Per [EXT §7.4]:
{
"collective": "<collective-sigil>", # required
"members": [ "<member-sigil>", ... ], # required, length ≥ threshold
"threshold": <int>, # required, ≥ 1
"diversity_policy": "<registry-id>" # required
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["collective", "members", "threshold", "diversity_policy"],
"additionalProperties": false,
"properties": {
"collective": { "type": "string", "pattern": "^sigil:" },
"members": { "type": "array", "items": { "type": "string", "pattern": "^sigil:" }, "minItems": 1 },
"threshold": { "type": "integer", "minimum": 1 },
"diversity_policy": { "type": "string" }
}
}CBOR notes
membersis a CBOR array of text strings; ordering is significant for canonical encoding (RFC 8949 §4.2.1) — implementations MUST emit members in the order signed by the collective and MUST NOT silently re-sort.thresholdis an unsigned integer.
Validation rules (verifiers MUST)
1. Reject unless the collective sigil's birth attestation declares a diversity_policy ([EXT §7.4]).
2. Reject unless every listed member has a current quorum_membership attestation referencing this collective (no listing-without-consent — [EXT §7.4]).
3. Reject unless the listed members satisfy the named diversity_policy (typically distinct lineage roots, distinct operator-attestation Heralds, distinct jurisdictions) ([EXT §7.4]).
4. Reject unless at least threshold members have co-signed the carrying envelope under multi-signature rules ([EXT §6], [EXT §7.4]).
5. threshold ≤ len(members); threshold ≥ 1.
Worked example
{
"type": "quorum",
"value": {
"collective": "sigil:guild-translators-eu",
"members": ["sigil:tr-a1...", "sigil:tr-b2...", "sigil:tr-c3..."],
"threshold": 2,
"diversity_policy": "diversity:tri-jurisdiction"
}
}3.5 quorum_membership
- Type identifier:
quorum_membership - Source: [EXT §7.4] (member-side opt-in), [EXT §12] (domain-separation tag).
- Required on: every member of a collective MUST publish one of these on joining ([EXT §7.4]).
- Domain-separation tag:
herald.quorum_membership.v1([EXT §12]). - Independent signing: the carrying envelope is signed by the member sigil. The collective's signature, if present in
signatures[], has scopeherald_endorsementand confirms acceptance.
Value (textual schema)
EXT does not fully fix this shape; the minimal protocol shape implied by [EXT §7.4] is:
{
"collective": "<collective-sigil>", # required
"joined_at": <Unix seconds>, # required
"until": <Unix seconds> # optional; absence == open-ended
}See INTERPRETATION.md for the rationale (EXT names the attestation but does not enumerate fields).
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["collective", "joined_at"],
"additionalProperties": false,
"properties": {
"collective": { "type": "string", "pattern": "^sigil:" },
"joined_at": { "type": "integer", "minimum": 0 },
"until": { "type": "integer", "minimum": 0 }
}
}CBOR notes
joined_at/untilare unsigned integers.
Validation rules (verifiers MUST)
1. Reject unless the carrying envelope is signed under domain-separation tag herald.quorum_membership.v1 at index 0 ([EXT §12]).
2. Reject if until is set and until <= joined_at.
3. When validating a quorum attestation against this membership, reject if the membership's until has passed at the carrying quorum envelope's ts.
Worked example
{
"type": "quorum_membership",
"value": {
"collective": "sigil:guild-translators-eu",
"joined_at": 1746432000
}
}3.6 silence
- Type identifier:
silence - Source: [SPEC §4.2] (hardening row).
- Required on: none. Declares that a categorical class of content was withheld.
- Domain-separation tag: none specified at protocol level; the carrying envelope is signed normally.
- Independent signing: no.
Value (textual schema)
{
"category": "<registry-id>", # required; categorical, NOT the withheld content
"reason": "<free string>" # optional
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["category"],
"additionalProperties": false,
"properties": {
"category": { "type": "string" },
"reason": { "type": "string" }
}
}CBOR notes
- All text strings.
Validation rules (verifiers MUST)
1. Non-contentful rule ([SPEC §4.2]): the withheld field MUST describe a category of withheld content, not the content itself. Verifiers cannot enforce this cryptographically — the rule is a conformance criterion. A silence whose category is implausibly long, contains structured content, or matches a known content-leak pattern MAY be flagged as non-conformant by application policy.
2. A silence MUST NOT contain a value field outside the category/reason pair (no covert channels).
3. Verifiers MUST NOT score silence as a positive or negative reputation signal at protocol level; it is purely declarative.
Worked example
{
"type": "silence",
"value": {
"category": "silence:legal-privilege",
"reason": "withheld pursuant to attorney-client privilege; details unavailable"
}
}3.7 whisper
- Type identifier:
whisper - Source: [EXT §7.3], [SPEC §4.2] (HPKE hardening).
- Required on: none. Carries an encrypted side-channel payload to a specific recipient.
- Domain-separation tag: none specific to the attestation; the carrying envelope is signed normally. The cryptographic AAD binding is the load-bearing protection: AAD MUST equal the envelope
id. - Independent signing: no separate signature; HPKE provides confidentiality and AAD-integrity.
Value (textual schema)
{
"to": "<recipient sigil>", # required
"kem": "hpke-x25519-hkdf-sha256-aes128gcm", # required; registered HPKE suite
"enc": "<HPKE encapsulated key, base64url>", # required
"ct": "<HPKE ciphertext, base64url>", # required
"aad_ref": "<envelope-id>" # required; MUST equal carrying envelope.id
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["to", "kem", "enc", "ct", "aad_ref"],
"additionalProperties": false,
"properties": {
"to": { "type": "string", "pattern": "^sigil:" },
"kem": { "type": "string" },
"enc": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
"ct": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
"aad_ref": { "type": "string" }
}
}CBOR notes
encandctare base64url text strings (no padding) for the same reasonsuccessor_pubkeyis text inmolt(text-keys-and-values rule).- The HPKE encrypted bytes themselves are not re-encoded into CBOR byte strings; they are wrapped in text. This costs ~33% bandwidth for confidentiality but keeps the canonical map purely textual.
Validation rules (verifiers MUST)
1. Reject unless kem is a registered HPKE suite ([EXT §7.3]). The default suite is hpke-x25519-hkdf-sha256-aes128gcm.
2. Reject unless aad_ref == carrying_envelope.id ([EXT §7.3]). This is the cut-and-paste defence.
3. Recipient obligations (recipients, not relays): on decrypt, verify the HPKE AAD equals the carrying envelope's id; reject if not ([EXT §7.3]).
4. If the recipient sigil's birth attestation set no_whispers: true, surface the whisper as a policy violation ([EXT §7.3]).
5. Conduits and verifiers MUST NOT decrypt or attempt to inspect ct. Conduits MUST forward whispers unchanged or refuse via a refusal envelope ([EXT §10]).
Worked example
{
"type": "whisper",
"value": {
"to": "sigil:recipient-9c2...",
"kem": "hpke-x25519-hkdf-sha256-aes128gcm",
"enc": "Bn7g...",
"ct": "Q3F1aWV0...",
"aad_ref": "env-7c3a-this-envelope"
}
}4. Protocol-event attestations
These attestations carry their own envelope-level lifecycles (publication, replay protection, revocation). Their domain-separation tags differ because they are not ordinary content envelopes.
4.1 capability_manifest
- Type identifier:
capability_manifest - Source: [EXT §4.1].
- Required on: the envelope advertising an agent's services.
- Domain-separation tag:
herald.capability_manifest.v2([SPEC §3.6]); EXT §12 listsherald.capability_manifest.v1. SeeINTERPRETATION.md. - Independent signing: the manifest envelope is signed by the subject sigil's current key under the manifest tag ([EXT §4.1]).
Value (textual schema)
Per [EXT §4.1]:
{
"subject": "<sigil>", # required
"capabilities": [ "<registry-id>", ... ], # required
"rates": { "per_token_usd": <float>, ... }, # optional, structured
"constraints": [ "<registry-id>", ... ], # optional
"ts": <Unix seconds>, # required
"expires": <Unix seconds>, # required
"nonce": "<128-bit random, base64url>", # required
"subsidised": <bool>, # optional, default false
"service_proof": "<envelope-id>" # optional
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["subject", "capabilities", "ts", "expires", "nonce"],
"additionalProperties": false,
"properties": {
"subject": { "type": "string", "pattern": "^sigil:" },
"capabilities": { "type": "array", "items": { "type": "string" } },
"rates": { "type": "object", "additionalProperties": { "type": "number" } },
"constraints": { "type": "array", "items": { "type": "string" } },
"ts": { "type": "integer", "minimum": 0 },
"expires": { "type": "integer", "minimum": 0 },
"nonce": { "type": "string" },
"subsidised": { "type": "boolean" },
"service_proof":{ "type": "string" }
}
}CBOR notes
ratesis a CBOR map of text-string keys to floats. Floats follow [SPEC §3.5] canonicalisation.nonceis a 128-bit random value, base64url-encoded as text (text-keys-and-values rule).subsidisedis a CBOR boolean; absent = false.
Validation rules (verifiers MUST)
1. Reject unless the carrying envelope is signed under domain-separation tag herald.capability_manifest.v2/v1 ([EXT §4.1]).
2. Reject if expires <= ts ([EXT §4.2]).
3. Reject if expires - ts > 90 days ([EXT §4.2]).
4. Reject if (subject, nonce) has been seen before in the verifier's window ([EXT §4.2]).
5. Reject if expires < now - skew_tolerance (default skew 300 s) ([EXT §4.2]).
6. Reject any capabilities or constraints string not present in the public registry as of the manifest's ts ([EXT §4.4]).
7. If rates.per_token_usd is below the registry-defined economic floor, require subsidised: true; otherwise reject ([EXT §4.3]).
8. Application policy MAY require service_proof; if so and absent, reject per policy ([EXT §4.5]).
Worked example
{
"type": "capability_manifest",
"value": {
"subject": "sigil:agent-7c3a...",
"capabilities": ["cap:summarisation", "cap:translation/eu"],
"rates": { "per_token_usd": 0.000004 },
"constraints": ["cnst:no-medical-advice", "cnst:no-political-claims"],
"ts": 1746432000,
"expires": 1749024000,
"nonce": "AAECAwQFBgcICQoLDA0ODw",
"subsidised": false,
"service_proof": "env-1d4f..."
}
}4.2 refusal
- Type identifier:
refusal - Source: [EXT §10.1].
- Required on: an envelope emitted by a conduit when it refuses to relay an inbound submission ([SPEC §5.2], [EXT §10.1]).
- Domain-separation tag:
herald.refusal.v2([SPEC §3.6]); EXT §12 / [EXT §10.1] listherald.refusal.v1. SeeINTERPRETATION.md. - Independent signing: the refusal envelope's origin signature is by the refusing conduit ([EXT §10.1]).
Value (textual schema)
Per [EXT §10.1]:
{
"refused": "<envelope-id of refused submission>", # required
"reason": "<registry-id>", # required
"by": "<conduit sigil>", # required
"ts": <Unix seconds>, # required
"fallback": "<sigil>" | null # optional; null permitted
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["refused", "reason", "by", "ts"],
"additionalProperties": false,
"properties": {
"refused": { "type": "string" },
"reason": { "type": "string" },
"by": { "type": "string", "pattern": "^sigil:" },
"ts": { "type": "integer", "minimum": 0 },
"fallback": { "oneOf": [ { "type": "null" }, { "type": "string", "pattern": "^sigil:" } ] }
}
}CBOR notes
fallbackMAY be CBORnull(major type 7, simple value 22) or a text string. The deterministic profile permits both. Verifiers MUST treat absence and explicitnullas equivalent.tsis an unsigned integer.
Validation rules (verifiers MUST)
1. Reject unless the carrying envelope's origin signature is under domain-separation tag herald.refusal.v2/v1 ([EXT §10.1]).
2. Reject unless by == carrying_envelope.from.
3. Reject unless reason is a registered refusal-reason code ([EXT §10.2] implies a public reason-code registry; if your deployment lacks one, fall back to a documented internal enumeration and flag this in application policy).
4. The conduit MUST emit this within a bounded time of the original submission (default 5 s, [SPEC §5.2]); verifiers MAY surface late refusals as policy violations.
5. The fallback advisory is non-binding ([EXT §10.4]); verifiers MUST NOT treat fallback as authoritative routing.
Worked example
{
"type": "refusal",
"value": {
"refused": "env-bb31...",
"reason": "refusal:rate-limit-exceeded",
"by": "sigil:conduit-eu-1...",
"ts": 1746432123,
"fallback": "sigil:conduit-eu-2..."
}
}4.3 revoke_capability_manifest
- Type identifier:
revoke_capability_manifest - Source: [EXT §4.6].
- Required on: the envelope withdrawing a previously-published manifest.
- Domain-separation tag: none registered specifically for revocation; the carrying envelope is signed by the subject sigil's current key under
herald.envelope.v2/herald.sig.origin.v1. (EXT §4.6 specifies the envelope-shape rule but does not register a dedicated tag in EXT §12.) - Independent signing: no.
Value (textual schema)
EXT §4.6 says: "by emitting a revoke_capability_manifest attestation referencing the manifest envelope's id. Revocations follow the same audit-log inclusion rules as molt envelopes." The minimal shape:
{
"revokes": "<envelope-id of the manifest>", # required
"ts": <Unix seconds>, # required
"reason": "<free string>" # optional
}JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["revokes", "ts"],
"additionalProperties": false,
"properties": {
"revokes": { "type": "string" },
"ts": { "type": "integer", "minimum": 0 },
"reason": { "type": "string" }
}
}CBOR notes
revokesis a text string (envelope id).tsis an unsigned integer.
Validation rules (verifiers MUST)
1. Reject unless carrying_envelope.from == referenced_manifest.value.subject. Only the subject can revoke its own manifest.
2. Reject unless the carrying envelope is inclusion-proven in at least one HERALD CT log before the revocation is treated as authoritative ([EXT §4.6] points at [EXT §1.3] inclusion rules).
3. After observing a valid revocation, verifiers MUST treat the referenced manifest as withdrawn for all ts >= revocation.ts. They MUST NOT silently re-validate the manifest from cache.
4. Stale manifests MAY also expire by expires without explicit revocation ([EXT §4.6]).
Worked example
{
"type": "revoke_capability_manifest",
"value": {
"revokes": "env-7c3a-the-prior-manifest",
"ts": 1746518400,
"reason": "constraint set updated; new manifest forthcoming"
}
}Appendix A — domain-separation tag cross-reference
| Attestation type / context | SPEC §3.6 tag | EXT §12 tag | Used by |
|---|---|---|---|
| envelope (origin) | herald.envelope.v2 | (origin scope tag) herald.sig.origin.v1 | every envelope |
birth | herald.birth.v2 | herald.birth.v1 | birth envelopes |
molt | herald.molt.v2 | herald.molt.v1 | molt envelopes |
deprecation | herald.deprecation.v2 | herald.deprecation.v1 | deprecation envelopes |
model_hash (Herald-issued) | herald.lineage_endorsement.v2 | herald.lineage_endorsement.v1 | training-graph endorsements |
capability_manifest | herald.capability_manifest.v2 | herald.capability_manifest.v1 | manifest envelopes |
refusal | herald.refusal.v2 | herald.refusal.v1 | refusal envelopes |
apologia | (not in SPEC §3.6 table) | herald.attestation.apologia.v1 | apologia envelopes |
confession | (not in SPEC §3.6 table) | herald.attestation.confession.v1 | confession envelopes |
quorum_membership | (not in SPEC §3.6 table) | herald.quorum_membership.v1 | quorum-membership envelopes |
whisper | (not a signature tag — HPKE AAD is envelope.id) | n/a | recipient AAD verification |
dream, silence, quorum, revoke_capability_manifest | (no dedicated tag — sign under origin) | (none registered in EXT §12) | carried in ordinary envelopes |
The version-suffix conflict (.v2 in SPEC §3.6 vs .v1 in EXT §12) is treated in INTERPRETATION.md. Implementers SHOULD parameterise tags rather than hardcode them.
Appendix B — index by category
Lifecycle: birth (§1.1), deprecation (§1.2), molt (§1.3).
Content / generation: confidence (§2.1), context_size (§2.2), model (§2.3), model_hash (§2.4), temperature (§2.5), tools (§2.6).
Reflective (protocol-shape): apologia (§3.1), confession (§3.2), dream (§3.3), quorum (§3.4), quorum_membership (§3.5), silence (§3.6), whisper (§3.7).
Protocol-event: capability_manifest (§4.1), refusal (§4.2), revoke_capability_manifest (§4.3).
Total: 19 entries, matching the T-012 brief.