AI Initiative logoAI Initiative
Reading room / Manthan

Refusal reason-code registry

Refusal reason-code registry. Covers Identifier convention; Schema per entry; Categories; Registry — v0.2.

Protocol registry / reusable policy template
This is the retained source text, not a new validation of its claims. Numerical results and comparative claims require the accompanying source review before public reuse.

Read the connected case study or article →

Not explicitly stated in source · Date not established

Provenance, authorship and editorial notes

Refusal reason-code registry

Id

manthan-herald-protocol-registries-refusal-reasons

Project

Manthan

Source path

manthan/herald-protocol/registries/refusal-reasons.md

Source sha256

824f5b41919ecf4df8b07a892278b03d244fcb2f338a6b7b053be0651d38b0f7

Local copy sha256

824f5b41919ecf4df8b07a892278b03d244fcb2f338a6b7b053be0651d38b0f7

Repo head

3a94084024a3434cef331fecac91c2c3b43f0313

Date
Not recorded
Date basis

Original publication date not established; Git revision date retained separately.

Author

Not explicitly stated in source

Author basis

Unknown; Git committer not substituted for document author.

Last source commit

8b75d1b0157c20a0a463f0e31008ef9f73099beb

Last source commit date

2026-06-08T07:40:14Z

Document status

Protocol registry / reusable policy template

Summary

Refusal reason-code registry. Covers Identifier convention; Schema per entry; Categories; Registry — v0.2.

Topics
  • Protocol and verification
  • Identifier convention
  • Schema per entry
  • Categories
Theme

Protocol and verification

Priority

reference

Related ids
  • manthan-herald-protocol-spec
  • manthan-herald-protocol-threats
Evidence concerns
  • Recovered source text is preserved verbatim. Assertions, comparisons, commands and results belong to its original context; they were not re-executed or externally re-verified during this corpus review.
Word count

1869

Bytes

13580

Source relative

herald-protocol/registries/refusal-reasons.md

Remote mirror

manthan/herald-protocol/registries/refusal-reasons.md

Full text preserved

True

Refusal reason-code registry

Status: Normative for HERALD v0.2 conformance.
Source: EXT §10.1 (envelope shape), §10.2 (rate publishing), §10.3 (per-sigil notice), §5.4 (refusal transparency).

A refusal attestation's reason field MUST contain a code from this registry. A refusal whose reason is not in the registry — and not prefixed x- per the experimental-code rule below — MUST be treated by verifiers as malformed and rejected.

This registry is referenced by:

Identifier convention

Schema per entry

Each entry has five fields:

Categories

Codes are grouped into seven categories for histogram aggregation. The category is not part of the wire format — it's a documentation convenience for refusal_report summary structures.

1. Rate / capacity (transient, retry-friendly)
2. Capability / policy (semantic mismatch)
3. Legal / compelled (refusals the conduit is required to make)
4. Authorisation (sender not entitled)
5. Sigil state (origin sigil's lifecycle blocks the request)
6. Envelope validity (the envelope itself is broken or stale)
7. Quorum / confidence (multi-party requirements unmet)

Registry — v0.2

Rate / capacity

IDDescriptionAppealablePrivacy-sensitiveRelated
rate_limit_exceededSender exceeded the conduit's published rate limit.yesnoEXT §5.4, [SPEC §5.2]
capacity_exceededConduit is overloaded; transient. Senders SHOULD apply backoff.yesnoEXT §5.4
cost_floor_breachedSender did not meet the conduit's published rate floor (per capability manifest).yesno[EXT §4.1] (capability manifest), [THREATS §subsidy-as-attack]

Capability / policy

IDDescriptionAppealablePrivacy-sensitiveRelated
capability_not_supportedConduit does not support the requested capability or transport. Senders should re-resolve via the capability manifest.nono[EXT §4.1]
policy_violationEnvelope content violates the conduit's published policy. The policy MUST be a published, named document; arbitrary "we don't like it" is non-conformant.yespartial[EXT §10.3]
privacy_redaction_requiredConduit's privacy filter detected sensitive content (e.g. PII) and conduit lacks the redaction capability. Sender may re-submit with redaction.sometimesyes[THREATS §exfiltration-via-relay]
IDDescriptionAppealablePrivacy-sensitiveRelated
legal_compulsionRefusal under a legal/regulatory obligation that the conduit is permitted to disclose. The disclosure SHOULD be in the per-sigil notice's appeals contact.sometimesyes[THREATS §refusal-as-denial-of-speech]
legal_compulsion_undisclosedRefusal under a legal obligation the conduit CANNOT disclose (gag-bound). Conduits operating in jurisdictions where gag orders are possible MUST emit this code when applicable; using legal_compulsion to mask a gagged refusal is non-conformant. Verifiers and senders SHOULD treat this code as a strong signal to seek alternate routes (per fallback, [EXT §10.4]).noyes[THREATS §refusal-as-denial-of-speech], [SPEC §382]
sanctions_screeningSender's sigil or apparent destination is on a sanctions list the conduit honours. Distinct from legal_compulsion because sanctions are typically disclosable but jurisdiction-specific.sometimesyes—

Authorisation

IDDescriptionAppealablePrivacy-sensitiveRelated
authorisation_requiredSender is not authorised on this conduit (private conduit, allowlist-only, or paid-only without payment proof).sometimesno[EXT §5.1]
quorum_membership_requiredSender is required to be a member of a named quorum (per Herald or capability rules) and is not.yesno[EXT §3.3], [EXT §4.x] (quorum membership — see D-312)

Sigil state

IDDescriptionAppealablePrivacy-sensitiveRelated
sigil_unknownOrigin sigil has no birth attestation findable by the conduit. Sender should publish or republish birth.yesno[SPEC §2.1, §2.4]
sigil_deprecatedOrigin sigil is in deprecated state per its own attestation; the conduit honours the deprecation.nono[SPEC §2.4], [EXT §1]
sigil_on_bestiaryOrigin sigil appears on a Bestiary list the conduit honours. The notice SHOULD name the Bestiary list (not the listing reason — that's bestiary-side due process).yesno[EXT §8]
lineage_unprovenRequired lineage attestation for this envelope is missing or fails the renderer-conformance distinct-rendering rule (T-021).yesno[EXT §3.2], [SPEC §2.3], (T-021 future)

Envelope validity

IDDescriptionAppealablePrivacy-sensitiveRelated
envelope_invalid_signatureOrigin signature failed verification. Hard refusal; sender should not retry without re-signing.nono[SPEC §3.4], [EXT §6]
envelope_expiredEnvelope's expires field is in the past at the moment the conduit considers relay.nono[SPEC §3.1]
envelope_replayNonce already seen within the conduit's replay-cache window.nono[SPEC §3.7]
envelope_malformedEnvelope failed CBOR-deterministic canonicalisation or required-field check.nono[SPEC §3.5], [EXT §13 — D-308 dom-sep]
trace_parent_invalidtrace_parent is missing, malformed, or violates the trace-parent binding rule (E.trace ≠ parent.trace).nono[SPEC §3.3a]
routing_unknownDestination sigil is not addressable via this conduit; sender should re-resolve. The fallback field SHOULD be populated when known.yesno[EXT §11] (discovery), [EXT §10.4]

Quorum / confidence

IDDescriptionAppealablePrivacy-sensitiveRelated
confidence_below_floorSender's published confidence on this envelope is below the conduit's floor (optional capability). The floor MUST be in the conduit's capability manifest.yesno[EXT §4.1]
quorum_not_metEnvelope required Herald-quorum endorsement that did not reach the configured threshold.yesno[EXT §3.3]

Experimental codes (x- prefix)

A conduit MAY use a reason code outside this registry if and only if it is prefixed x- (e.g. x-greylisting-trial). Rules:

Registration process for new codes

A new (non-x-) reason code is added by:

1. Proposing the code in a R-NNN research task or a D-NNN discovery task with the same five fields (id, description, appealable, privacy-sensitive, related sections).
2. Discussion period of at least 30 days on the registry. (For v0.2 draft, this is waived; future stable versions enforce it.)
3. Promotion by adding the code to this registry document and bumping the registry version. Existing implementations that don't recognise the new code MUST treat it as malformed and refuse.
4. No deletions without deprecation. Per the EXT §13 lifecycle rule (12-month deprecation per identifier), removing a reason code requires a notice period and a transition period during which both old and new codes are accepted.

Privacy-sensitive code rules

Codes marked privacy-sensitive: yes or partial carry these additional constraints in refusal_report and per-sigil notice:

Migration notes

EXT §5.4 (line 388) currently reads:

"...per-reason histogram (with reason codes drawn from a reason-code registry, [CHARTER §refusal-reasons])."

This reference is a phantom anchor — [CHARTER §refusal-reasons] does not exist in the current CHARTER (1019 lines, no such section). The registry lives in EXT (this document, normative for protocol shape). CHARTER may, optionally, gloss the cultural meaning of refusal in a separate section; that's out of scope for D-310.

Proposed EXT patch (reviewer should apply):

- per-reason histogram (with reason codes drawn from a reason-code registry, [CHARTER §refusal-reasons]).
+ per-reason histogram (with reason codes drawn from the reason-code registry, [EXT §10.5]).

And add a new §10.5 at the end of EXT §10:

### 10.5 Reason-code registry

The `reason` field of a `refusal` attestation MUST be a code drawn from the
HERALD refusal reason-code registry, distributed as `registries/refusal-reasons.md`.
The registry specifies the canonical underscored identifier, whether the
refusal is appealable, whether it is privacy-sensitive, and the related
SPEC/EXT/THREATS sections.

Codes outside the registry are non-conformant unless prefixed `x-` (experimental).
A `x-` code MUST NOT exceed 5% of refusals in any reporting window.

A new code is added per the registration process documented in
`registries/refusal-reasons.md` (registration → discussion → promotion → no
deletions without deprecation).

Appendix A — Worked examples

A.1 Standard rate-limit refusal

{
  "type": "refusal",
  "value": {
    "refused":  "env:7f3a2b8e9c1d2f4a",
    "reason":   "rate_limit_exceeded",
    "by":       "sigil:relay.example.k8...",
    "ts":       1746460800,
    "fallback": null
  }
}

Per-sigil notice (only required if rate against this sigil exceeds threshold):

conduit sigil:relay.example.k8..., period 2026-05-05, target sigil:agent.alpha..., refused 240/2400 attempts (10%), dominant reason rate_limit_exceeded, appeals: mailto:abuse@example.com.

A.2 Gag-bound refusal

{
  "type": "refusal",
  "value": {
    "refused":  "env:09a4...",
    "reason":   "legal_compulsion_undisclosed",
    "by":       "sigil:relay.example.k8...",
    "ts":       1746460800,
    "fallback": "sigil:relay.alt.j2..."
  }
}

Per-sigil notice:

conduit sigil:relay.example.k8..., period 2026-05-05, target sigil:agent.alpha..., refused 100% under legal_compulsion_undisclosed, fallback sigil:relay.alt.j2..., appeals: see fallback.

The conduit names the code, the count, and the fallback. It does NOT name the compelling authority, the order's contents, or the affected message bodies. The code itself is the disclosure that something is being compelled.

A.3 Bestiary refusal

{
  "type": "refusal",
  "value": {
    "refused":  "env:c3d5...",
    "reason":   "sigil_on_bestiary",
    "by":       "sigil:relay.example.k8...",
    "ts":       1746460800,
    "fallback": null
  }
}

Per-sigil notice MUST name the Bestiary list (e.g. "spam-2026-05") so the affected sigil can pursue the bestiary's own due-process channel ([EXT §8]). It MUST NOT include the listing reason — that's bestiary-side, not conduit-side.


v0.2, 2026-05-05.

Continue exploring