The problem
Authority gets delegated onward. A principal grants to an operator, the operator grants to a service, the service grants to an agent. Four parties, three links, and at the end of it an action happens.
Every party in that chain checked the link immediately above it. Nobody checked the chain.
This is the structural weakness of delegated authority. Each credential is signed by its grantor and each is individually valid. What no single credential can express is whether the grantor gave away more than it had. A middle party that received authority to spend one hundred in one category can issue a credential for five hundred across three categories, and that credential is signed, well formed and accepted by anyone who looks only at it.
Name the parties. The root principal asserts it granted narrow authority. The middle party asserts it delegated in good faith within what it understood. The final actor asserts it acted inside the credential it was handed. The acceptor asserts it verified a valid credential, which is true and also beside the point.
Three specific failures.
The first is that nobody holds the whole chain. Each party holds its own credential and possibly its parent. Reassembling the chain after the fact means asking every party for its copy, and the parties with an interest in a particular reading are the parties who supply the evidence.
The second is that the comparisons are not made even when the chain is assembled. Comparing a child ceiling to a parent ceiling is easy. Comparing category sets is fiddly. Comparing expiry dates is easy but gets skipped. Checking that onward delegation depth actually decreases is almost never done, which is how a chain of two becomes a chain of six.
The third is disclosure. Category names are business information. A chain that reveals which categories of action were delegated at each hop tells anybody holding it how the delegating organisation is structured and what it does. So chains do not get shared, and the comparisons do not get made.
When the parties are autonomous, chains grow without anybody deciding they should. An agent that can delegate creates sub agents, which create sub agents. Depth accounting stops being a formality and becomes the only thing standing between a bounded grant and an unbounded one.
What the receipt binds
The schema is at https://thehiveryiq.com/.well-known/schemas/delegation-attenuation-v1.json.
| Field | Meaning |
|---|---|
receipt_type | Fixed to delegation.attenuation. |
schema | Fixed to r1.0.0. |
delegation_chain_id | Identifier of one to 128 characters from letters, digits, dot, underscore and colon. |
root_authority | The top of the chain, as an authority_commitment, a root_class of issuer_resolved_signed_credential, caller_supplied_signed_credential or asserted_without_credential, a root_maximum_onward_delegation_depth from 1 to 15, and a category_commitment_context. |
links | Two to 16 links. Each carries an ordinal, a granting_party_commitment, a receiving_party_commitment, a credential_envelope_sha256, issued_at, expires_at, a per_action_ceiling_minor integer, one to 256 category_commitments, and a maximum_onward_delegation_depth. |
action | The action at the end, as an action_id, an action_record_sha256, an actor_party_commitment, an action_at, an amount_minor and a category_commitment. |
attenuation_finding | One of conforms, does_not_conform or indeterminate. |
boundary | The fixed non attestation string. |
The schema requires at least two links. A chain of one is not a chain, and this instrument is about what happens between links.
What is deliberately not in the signed body
No party is named and no category is named. Parties appear as commitments. Categories appear as commitments computed in src/typed/delegation-attenuation.js from a category context salt of exactly 64 lowercase hex characters.
Two constructions are used, both plain SHA-256 over a domain separated concatenation with zero byte separators.
The category context is SHA-256 over the UTF-8 prefix
delegation.attenuation/category-context/v1
then a zero byte, then the raw salt bytes. This value is root_authority.category_commitment_context, and every link credential must carry the same value.
A category commitment is SHA-256 over the UTF-8 prefix
delegation.attenuation/category/v1
then a zero byte, then the raw salt bytes, then another zero byte, then the UTF-8 category code. The category code must be lowercase and match a fixed form of an alphanumeric first character followed by up to 63 alphanumeric, dot or underscore characters.
The context commitment is what makes subset comparison meaningful without disclosure. Two commitments are comparable only if they were computed under the same salt, and the context value proves they were, without revealing the salt. A forger who wanted to make a child's category appear inside a parent's set would have to compute under a different salt, and the context check catches that.
Category commitment arrays are required to be strictly increasing in unsigned octet order. That gives one canonical representation per set, so subset comparison is deterministic and a set cannot be padded with duplicates.
The link credentials themselves are absent, present only as credential_envelope_sha256, which covers the complete envelope. The action record is absent, present as action_record_sha256. The receipt envelope uses the shared construction over the ASCII string hive-receipt <receipt_id> <payload_sha256> <ts>.
The gates
Verification runs in this order and stops at the first failure.
- ISSUER_KEY_MATCH. Resolves the envelope key through the issuer key resolver. A failure means the signer is not trusted here.
- ENVELOPE_INTEGRITY. Runs the envelope crypto over the payload digest, the receipt identifier form and the Ed25519 signature. A failure means the receipt does not stand on its own.
- SCHEMA. Validates the envelope against the delegation attenuation v1 schema. A failure means the artifact is malformed or carries a field the schema does not permit.
- LINK_ORDINAL_DENSE. Requires each link's
ordinalto equal its array position. A failure means the chain skips or repeats a position, which is the shape of a chain with a link removed. - LINK_EVIDENCE_BINDING. Requires a supplied credential envelope for every declared link, bound by
credential_envelope_sha256. A failure means a link was declared without its evidence. - LINK_CREDENTIAL_INTEGRITY. Runs each supplied credential envelope through its own verification against the credential key resolver. A failure means a credential in the chain is internally broken.
- LINK_CREDENTIAL_FIDELITY. Requires each declared link to restate its credential exactly on
granting_party_commitment,receiving_party_commitment,issued_at,expires_at,per_action_ceiling_minor,category_commitmentsandmaximum_onward_delegation_depth. A failure means the receipt describes a link differently from the credential behind it. - ROOT_AUTHORITY_BINDING. Requires
root_authority.authority_commitmentto equal the first link's granting party, androot_maximum_onward_delegation_depthto equal the first link's depth. A failure means the declared root is not the party that actually granted the first link. - CATEGORY_CONTEXT_MATCH. Requires every supplied credential's
category_commitment_contextto equal the root's. A failure names the index and means categories across the chain were committed under different salts, so no subset comparison would be meaningful. - CHAIN_CONTINUITY. Requires each link's
receiving_party_commitmentto equal the next link'sgranting_party_commitment. A failure names both and means the chain has a party substituted in the middle. - ISSUANCE_WITHIN_PARENT_TERM. Requires each child's
issued_atto be at or after its parent'sissued_atand at or before its parent'sexpires_at. A failure means a delegation was issued before its own authority existed or after it lapsed. - ATTENUATION_CEILING_NONINCREASING. Requires each child's
per_action_ceiling_minornot to exceed its parent's. A failure names both amounts. - ATTENUATION_CATEGORY_SUBSET. Requires both the parent and child category arrays to be strictly increasing in unsigned octet order, then requires the child set to be a subset of the parent set. A failure names the offending array.
- ATTENUATION_EXPIRY_NONEXTENDING. Requires both expiries to be valid instants and requires the child's not to be later than the parent's. A failure means a child outlived its parent.
- ATTENUATION_DEPTH_STRICT_DECREASING. Requires each child's
maximum_onward_delegation_depthto be strictly less than its parent's. A failure means depth was retained across a hop, which would allow an unbounded chain. - ROOT_DEPTH_ACCOUNTING. Requires the number of links not to exceed the root depth, and requires each link's depth to equal exactly the root depth minus its ordinal. A failure means the depth budget was not spent one unit per hop.
- FINAL_ACTOR_BINDING. Requires
action.actor_party_commitmentto equal the final link'sreceiving_party_commitment. A failure means somebody other than the end of the chain performed the action. - ACTION_TIME_WITHIN_FINAL_TERM. Requires
action.action_atto fall between the final link'sissued_atandexpires_at. A failure means the action fell outside the term it relied on. - ACTION_CEILING_WITHIN_FINAL_LINK. Requires
action.amount_minornot to exceed the final link's ceiling. - ACTION_CATEGORY_MEMBER. Requires
action.category_commitmentto appear in the final link's category commitments. - ATTENUATION_FINDING_RECOMPUTE. Recomputes the finding and compares. A failure means the caller asserted a finding the chain does not produce.
The finding computation is stricter than the individual gates in one respect worth noting: it returns indeterminate when the credential verification results are missing or do not number exactly one per link, and it propagates indeterminate from any credential state. It returns does_not_conform when any credential state is that, and otherwise reruns the whole comparison set itself before returning conforms. Nothing about the finding is read from the body.
The mint path refuses caller supplied values the service must derive, including the finding, the root authority object, the links array, credential envelope digests, category commitments in every form, the category commitment context, the root class, and the action's actor party commitment and category commitment. It requires the category context salt to be exactly 64 lowercase hex characters and requires the action category code to match the declared form.
The boundary
This receipt attests only that the supplied delegation links and supplied action assertion satisfy the stated mechanical attenuation comparisons at verification. It does not attest that the root authority is valid, that a grantor is entitled to delegate, that the supplied chain is complete or exclusive, that any linked credential is the one an acceptor uses, that an action occurs, that the action is authorized, lawful, effective, enforceable, paid, settled, or accepted, that any party has knowledge or notice, that a category name is revealed, or that any person bears responsibility, loss, harm, fault, or liability. It cannot decide whether authority exists outside the supplied chain, whether a missing link exists, whether an action is proper, or whether an external rule permits it.
The clause about the chain not being complete or exclusive is the one that matters most, and it is the one that would be quietly dropped by anybody selling this. A conforming chain proves that the links presented narrow properly. It says nothing about whether another chain exists granting the same party wider authority through a different route. Multi rooted authority is normal in real organisations, and an instrument that implied it had seen everything would be wrong most of the time.
Saying it makes the receipt more useful in an argument. A party holding a conforms receipt has closed off every internal objection to the chain: no link widened, no link outlived its parent, depth was accounted, the actor was the right actor, the action fit the final link. Those objections used to take months to work through. What remains open is whether some other authority existed, and that is a question about the world rather than about the chain, so it belongs to the parties.
The clause about entitlement to delegate points at its neighbour. This receipt does not check whether the root had authority in the first place. That is what the Granter Qualification Receipt is for, and the boundary tells you to go get one rather than pretending.
Adversarial cases
From test/delegation-attenuation.test.mjs.
An untrusted issuer fails ISSUER_KEY_MATCH, and a signature alteration fails ENVELOPE_INTEGRITY.
An extra field fails SCHEMA. There is nowhere to add anything.
A sparse ordinal fails LINK_ORDINAL_DENSE. This is the removed link. Delete a hop that widened and the ordinals no longer match their positions.
Missing evidence fails LINK_EVIDENCE_BINDING. Declaring a link without producing its credential is the cheapest forgery.
An altered credential fails LINK_CREDENTIAL_INTEGRITY. Each credential is verified in full.
A mismatched declared ceiling fails LINK_CREDENTIAL_FIDELITY. Here the forger leaves the credentials alone and restates a link's ceiling in the receipt so the chain appears to attenuate. Every one of the seven fidelity fields is compared against the credential.
A wrong root commitment fails ROOT_AUTHORITY_BINDING. Attributing a chain to a different root does not survive the comparison against the first link's grantor.
A context substitution fails CATEGORY_CONTEXT_MATCH. This is the sophisticated attack on the category comparison. Compute a child's categories under a different salt so its commitments happen to sit inside the parent set. The context value catches it, because every credential has to declare the same context.
A substituted middle party fails CHAIN_CONTINUITY. Splicing an unrelated credential into the middle breaks the receiving to granting equality.
An early child issuance fails ISSUANCE_WITHIN_PARENT_TERM. A delegation issued before the authority it derives from is a retroactive grant.
An increased amount ceiling fails ATTENUATION_CEILING_NONINCREASING. The central widening attack.
Amount narrowing while category widening fails ATTENUATION_CATEGORY_SUBSET. This is the interesting one. The forger narrows the ceiling, which looks like good faith attenuation, while adding a category. Narrowing one dimension does not buy widening another, and each dimension is checked independently.
An extended child expiry fails ATTENUATION_EXPIRY_NONEXTENDING. Widening in time is widening.
A retained depth fails ATTENUATION_DEPTH_STRICT_DECREASING, and an irregular root accounting fails ROOT_DEPTH_ACCOUNTING. Both of these block the unbounded chain, one by requiring strict decrease at every hop and one by requiring the depth at each ordinal to be exactly the root depth minus that ordinal.
An action actor substitution fails FINAL_ACTOR_BINDING. A chain ending at one party cannot explain an action by another.
An action after expiry fails ACTION_TIME_WITHIN_FINAL_TERM. An amount above the final ceiling fails ACTION_CEILING_WITHIN_FINAL_LINK. A category outside the final set fails ACTION_CATEGORY_MEMBER.
A stated finding fails ATTENUATION_FINDING_RECOMPUTE, and a payload digest tamper is caught by PAYLOAD_DIGEST.
Three structural tests confirm the design rather than an attack: minting keeps the category salt and the raw category out of the envelope, the minter refuses every caller supplied computed field, and the credential envelope digest covers the complete envelope rather than only the signed body.
Performance
From hive-verifier-api/benchmarks/results-latest.json, measured at 2026-08-09T22:28:01.099Z at commit e167719f7d815809c6f55c5dde4495edf1c5615f over 200 iterations:
| Measure | Value |
|---|---|
| Mint p50 | 6.885 ms |
| Mint p95 | 7.582 ms |
| Verify p50 | 6.205 ms |
| Verify p95 | 7.29 ms |
| Artifact size | 3108 bytes |
Local harness measurement on one machine and one Node version, recorded on Node v20.20.1, linux/x64, two Intel Xeon cores at 2.90 GHz. It is a reproducible measurement of this code, not a production latency guarantee.
How to run it
This type has no mint route. It is produced as an export by another route and only verified here, so there is nothing to authenticate against. The verify route takes no credentials.
- Host:
https://thehiveryiq.com/v1 - Verify route:
/verify/delegation-attenuation
curl -sS -X POST https://thehiveryiq.com/v1/verify/delegation-attenuation -H 'content-type: application/json' -d '{"receipt": <a receipt of this type>}'
Where it sits in the canon
Family: network authority. Category: typed receipt contract.
It sits over a set of delegation credentials and verifies each one rather than trusting the chain's own description of them. Its natural partners are authority.qualification, which asks whether the root was ever entitled, and authority.revocation, which asks where an action fell relative to a withdrawal. This receipt asks only whether the chain narrowed at every step and whether the action fit the end of it.
It does not replace the credentials, an acceptor's own checks, or any determination that the action was proper. The boundary rules all of that out in the signed bytes.
Status
production_deployed.