Network authority family

Admission Binding Receipt: settling that the party admitted and the party that acted are the same party

The Admission Binding Receipt is a signed statement that a supplied admission credential and one supplied conduct receipt yield byte identical subject commitments under one disclosed binding salt that the admission credential already commits to, and that the extracted conduct instant is at or after the stated admission instant and within the signed maximum separation. Networks that admit participants, the acceptors who rely on that admission, and anyone later untangling who did what all need it.

The property that makes it different from a session log is that identity is compared under a salt the credential pre committed to. A session log links an admission event to an action by carrying the same identifier in two rows, which means both rows contain the identifier and either row can be rewritten. Here neither identifier appears. Two HMAC commitments are compared byte for byte, and the salt commitment is inside the credential, so a binding cannot be manufactured after the fact by choosing a convenient salt.

The problem

A network admits a participant. Later, something happens on that network. The question is whether the thing that happened was done by the party that was admitted.

That sounds like a question a database answers. It is, until the two halves live in different systems run by different parties, which is the normal case. The admitting party issued a credential. A separate conduct service observed an action and wrote a receipt. Nobody joined the two, and joining them after the fact requires an identifier that appears in both, in a comparable form.

Name the parties. The admitting party asserts it admitted a participant with certain properties. The acceptor who relied on the admission asserts it was entitled to rely. The conduct service asserts that some actor performed an action. The party being accused asserts that the actor was somebody else, or that it was never admitted in the form claimed, or that the admission had lapsed by the time the action occurred.

Three specific failures make this hard.

The first is that the identifier forms differ. An admission credential names a subject one way. A conduct receipt names an actor another way. Somebody writes a mapping table, and the mapping table becomes the weakest link in the chain, editable and unsigned.

The second is that both artifacts are asserted rather than compared. Producing a document that says the same identifier twice is trivial. What would be evidence is a comparison that neither party could have steered, over material neither party could change after the fact.

The third is time. An admission is not permanent. Conduct that happened before the admission was granted, or long after the admission's usefulness lapsed, is not conduct the admission speaks to. Records almost never carry a bound on how far apart the two events are permitted to be, so any conduct at any distance from an admission gets linked to it.

The privacy problem sits across all three. The identifiers are exactly what nobody wants to publish. A binding artifact that establishes the link by carrying the subject identifier is an artifact that cannot be shared with the parties who need the link established.

When the admitted party is autonomous, the third failure becomes the interesting one. An agent admitted once can act indefinitely. Without a signed bound on separation, an admission from a year ago covers an action today, and nobody has to argue for that because nothing in the record objects.

What the receipt binds

The schema is at https://thehiveryiq.com/.well-known/schemas/admission-binding-v1.json.

FieldMeaning
receipt_typeFixed to admission.binding.
schemaFixed to r1.0.0.
binding_idIdentifier of up to 256 characters from letters, digits, dot, underscore and colon.
tenant_idThe tenant the binding belongs to, in the same character form.
admissionThe admission side. Carries credential_commitment, subject_commitment, salt_commitment, admission_instant, an admission_authority_class from network_operator, registry, directory or self_asserted, and a credential_verification_class from signature_verified, structure_verified or acceptor_verified.
conductThe conduct side. Carries the conduct receipt_id, an envelope_sha256, the conduct receipt_type, an actor_subject_commitment and a conduct_instant.
validityThe separation bound, as maximum_separation_seconds up to 604800 and a maximum_separation_commitment.
findingThree constants. subject_relation is same_subject, temporal_relation is conduct_at_or_after_admission_and_within_bound, and status is bound.
evaluated_atThe UTC instant of evaluation.
boundaryThe fixed non attestation string.

The finding is three schema constants rather than an enum, which is a design decision worth naming. This receipt only exists in one state. There is no not_bound variant, because a failed comparison produces a verification failure rather than a signed negative finding.

What is deliberately not in the signed body

Neither identifier appears. Not the credential subject, not the conduct actor. The credential itself does not appear either. What appears are four commitments computed in src/typed/admission-binding.js.

Three of them share one construction. For a label, a salt commitment and a value, the commitment is HMAC-SHA256 keyed by the raw binding salt bytes, over the concatenation of the UTF-8 label, a single zero byte, the UTF-8 salt commitment, another zero byte, and the UTF-8 value. The zero byte separators mean no label and value pair can be confused with any other. Three labels are used:

  • subject over the exact UTF-8 identifier representation produces both admission.subject_commitment and conduct.actor_subject_commitment.
  • admission-credential over the canonical body of the admission credential produces admission.credential_commitment.
  • maximum-separation-seconds over the unpadded decimal string of the separation seconds produces validity.maximum_separation_commitment.

The fourth is different. salt_commitment is a plain SHA-256 over the UTF-8 label admission-binding-salt, a zero byte, and the raw binding salt bytes. This is the value the admission credential already carries, and it is what stops salt shopping. A party cannot verify a binding by picking whatever salt makes two identifiers collide, because the salt has to hash to the commitment the credential committed to before any conduct happened.

The binding salt itself is disclosed to the verifier at verification time and does not live in the receipt. So a holder of the salt can check the binding, and a reader without it holds four opaque digests.

The conduct receipt body is absent, present only as envelope_sha256, a digest of the complete envelope under the same recursively sorted JSON rule used across the canon: keys sorted recursively, no whitespace, non ASCII escaped as lowercase \uXXXX, SHA-256 over the UTF-8 bytes. The receipt envelope itself uses the shared Ed25519 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.

  1. SCHEMA. Validates the envelope against the admission binding v1 schema. A failure means the artifact is malformed.
  2. ISSUER_KEY_MATCH. Requires key_id to resolve to a trusted key eligible for admission.binding at the envelope timestamp. It fails when no resolver was supplied, when no eligible key exists at that timestamp, and when resolution errors. A failure means the signer is not trusted for this type at this time.
  3. ENVELOPE_SIGNATURE. Runs the envelope crypto and reports the failing inner gate by name. A failure means the digest, the identifier form or the signature did not hold.
  4. ADMISSION_CREDENTIAL_PRESENT. Requires a structured credential object, requires the profile extractor to produce one nonempty subject identifier, an admission instant and a salt commitment, requires admission.admission_instant to equal the credential's instant, and requires the credential salt commitment to be 64 lowercase hex characters. A failure means the credential is absent, unreadable under the profile, or disagrees with the body about when admission happened.
  5. ADMISSION_CREDENTIAL_COMMITMENT. Recomputes the credential commitment from the disclosed salt, the salt commitment and the canonical credential body, and compares. A failure means the credential presented is not the credential committed to.
  6. ADMISSION_SALT_PRECOMMITMENT. Recomputes the salt commitment from the disclosed salt and requires it to equal admission.salt_commitment, then requires the credential's own salt commitment to equal that same value. A failure means the salt does not hash to the committed value, or the credential committed to a different salt.
  7. CREDENTIAL_VERIFICATION_CANDOUR. Requires a verification record for the declared class, requires its credential digest to match the supplied credential, requires a nonempty record identifier, requires the record's observed class to equal the declared class, requires signature_verified to be true exactly when the declared class requires it and false when it does not, and requires a nonempty acceptor identifier. A failure means the receipt overstates or understates how the credential was checked.
  8. CONDUCT_RECEIPT_LINK. Requires a complete conduct envelope with a signed body, requires conduct.receipt_id and conduct.receipt_type to match it, and requires conduct.envelope_sha256 to equal the recomputed envelope digest. A failure means the conduct receipt named is not the one supplied.
  9. CONDUCT_RECEIPT_INTEGRITY. Requires the conduct receipt's own key to resolve to a trusted key eligible for its type at its timestamp, and requires the conduct envelope to pass its own verification. A failure reports the conduct receipt's failing gate.
  10. CONDUCT_ACTOR_COMMITMENT. Runs the configured extractor for the conduct receipt type, requires one nonempty actor identifier and a conduct instant, requires conduct.conduct_instant to equal the extracted instant, and recomputes actor_subject_commitment from the disclosed salt over that identifier. A failure means the actor commitment is not the commitment that identifier produces.
  11. SUBJECT_COMMITMENTS_IDENTICAL. Recomputes the admission subject commitment from the credential's subject identifier, requires it to equal admission.subject_commitment, and then requires the admission and conduct commitments to be byte identical. A failure means the admitted subject and the acting subject are not the same subject under this salt.
  12. MAXIMUM_SEPARATION_COMMITMENT. Recomputes the separation commitment over the declared seconds and compares. A failure means the bound stated in the clear is not the bound that was committed.
  13. TEMPORAL_RELATION. Requires both instants to be valid UTC, requires the conduct instant to be at or after the admission instant, and requires it to be at or before the admission instant plus the separation seconds. A failure names the permitted interval.
  14. FINDING_RECOMPUTE. Requires finding.subject_relation to be same_subject, finding.temporal_relation to be conduct_at_or_after_admission_and_within_bound and finding.status to be bound. A failure names the field and the expected value.
  15. BOUNDARY_MATCH. Requires boundary to equal the constant this implementation holds for this type. A failure means the non attestation was edited.

The mint path is equally strict. It rejects every caller supplied field the service is supposed to compute, including the receipt type, the schema, the boundary, the evaluated instant, the admission, conduct, validity and finding objects, and each individual commitment, digest, class, instant and finding component. It refuses to mint with a 422 when the two subject commitments differ or when the conduct instant falls outside the committed separation.

The boundary

This receipt attests only that a supplied admission credential and one supplied conduct receipt yield byte identical subject commitments under one disclosed binding salt that the admission credential already commits to, and that the extracted conduct instant is at or after the stated admission instant and within the signed maximum separation. It does not attest that the admission credential is validly issued, that any admitting party is entitled to admit, that either identifier is true, that the subject is a person or entity of any asserted kind, that the conduct occurred, or that the conduct is authorized. It does not decide authenticity beyond the checked signatures and stated verification class, completeness of records, actual knowledge, intent, fault, fraud, contractual effect, legal effect, regulatory effect, eligibility, title, responsibility, liability, or any dispute. It does not authorize admission, access, conduct, a transaction, credential presentation, disclosure, or reliance by any party. It does not establish that either source artifact is complete, exclusive, current, unrevoked, unaltered before receipt, or truthful. It cannot decide whether an absent conduct receipt exists, whether another admission credential exists, whether the admitting party relied on the credential, whether the conduct service observed all conduct, or whether any party knew of the other artifact.

BOUNDARY_MATCH compares that text against the constant the implementation holds.

The last sentence is the most useful one in a dispute, and it is the one nobody would write unprompted. It enumerates the questions the instrument cannot see: an absent conduct receipt, another admission credential, whether the admitting party relied, whether the conduct service saw everything. Each of those is a real argument somebody will make. Having them written into the artifact means the argument starts from an agreed position rather than from a discovery fight about what the receipt implied.

Notice what this does to the shape of a dispute. A party holding this receipt has settled one thing completely: the admitted subject and the acting subject are the same subject, and the action fell inside the committed window. That is usually the fact everybody was arguing about, and it is now not arguable. Everything else the boundary lists is still live, but those are questions about entitlement and authority that were always going to require judgment. The instrument does the mechanical part cleanly and refuses the rest, which is why the mechanical part can be relied on.

The clause about identifiers not being true is the one that keeps this honest. Two commitments matching proves the same string was committed twice. It does not prove the string names a real party. A network that admits under fabricated identifiers produces bindings that are internally perfect and externally meaningless, and the receipt says so.

Adversarial cases

From test/admission-binding.test.mjs.

A missing credential subject fails ADMISSION_CREDENTIAL_PRESENT. A credential with no extractable subject cannot anchor a binding, and the gate refuses before any commitment is computed.

An altered credential commitment fails ADMISSION_CREDENTIAL_COMMITMENT. Swapping in a different credential after the commitment was made changes the recomputed value over its canonical body.

A replacement salt commitment fails ADMISSION_SALT_PRECOMMITMENT. This is salt shopping, the central attack. A forger who wants two unrelated identifiers to bind would search for a salt under which they collide, or simply present a different salt. Both fail, because the credential already carries the salt commitment and the disclosed salt has to hash to it.

A conflicting verification class fails CREDENTIAL_VERIFICATION_CANDOUR. Claiming a stronger check than the verification record supports is caught. So is claiming a signature verification for a class that does not perform one.

A substituted conduct digest fails CONDUCT_RECEIPT_LINK. Pointing a binding at a more convenient conduct receipt changes the envelope digest.

An altered linked conduct signature fails CONDUCT_RECEIPT_INTEGRITY. The conduct receipt is verified in full rather than merely referenced.

A mismatched actor commitment fails CONDUCT_ACTOR_COMMITMENT. The commitment is recomputed from the extracted actor identifier, so writing a value that matches the admission side does not survive.

Unequal subject commitments fail SUBJECT_COMMITMENTS_IDENTICAL. This is the case the whole receipt exists to catch: an admission for one party used to explain conduct by another.

A changed maximum separation fails MAXIMUM_SEPARATION_COMMITMENT. Widening the window in the clear to make a late action fit does not change the committed value.

Later conduct fails TEMPORAL_RELATION. Conduct outside the committed window is refused even when the subjects match.

An unsupported finding is caught by FINDING_RECOMPUTE after structural validation, and an altered boundary is caught by BOUNDARY_MATCH after structural validation. Both of these are edits that pass the schema and fail the gate.

Payload digest tampering fails PAYLOAD_DIGEST.

Two structural tests confirm the design rather than an attack. The receipt omits salts and source identifiers, and the mint path rejects every computed caller field.

Performance

From hive-verifier-api/benchmarks/results-latest.json, measured at 2026-08-09T22:28:01.099Z at commit e167719f7d815809c6f55c5dde4495edf1c5615f over 200 iterations:

MeasureValue
Mint p504.669 ms
Mint p955.533 ms
Verify p504.149 ms
Verify p957.317 ms
Artifact size2906 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/admission-binding
curl -sS -X POST https://thehiveryiq.com/v1/verify/admission-binding -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 between an admission credential and a conduct receipt and verifies both rather than trusting either. The conduct side is generic: any receipt type with a configured extractor for an actor identifier and a conduct instant can be the conduct half, so this composes across the canon rather than with one partner type.

It does not replace the admission credential, the conduct receipt, or any authority evidence. Whether the admitting party could admit is a question for authority.qualification. Whether the authority was still live is a question for authority.revocation. This receipt answers only whether the two subjects are the same subject inside a committed window.

Status

production_deployed.

References for this instrument
Canon entry
Admission Binding Receipt in the Hive canon
JSON Schema
https://thehiveryiq.com/.well-known/schemas/admission-binding-v1.json
Verify route
POST /verify/admission-binding
Canonical type
admission.binding
Private by design. Hive does not store your prompts. Every request is already receipted by a one-way SHA-256 fingerprint, not the words. Proof, not surveillance.