spec: disclosed gaps in a receipt chain, and the receipt_gap_disclosed outcome (#117) - #260
Open
lywinged wants to merge 1 commit into
Open
spec: disclosed gaps in a receipt chain, and the receipt_gap_disclosed outcome (#117)#260lywinged wants to merge 1 commit into
lywinged wants to merge 1 commit into
Conversation
…d outcome (agentrust-io#117) Under a profile requiring action receipts, a specification that offers only complete and broken rewards concealment: an operator who backfills a lost receipt scores better than one who reports the loss. A GapDisclosure is a signed chain element stating that receipts which would have occupied its position were never emitted. Coverage is structural, never asserted. The disclosure links back to the element before the gap and the next element links back to the disclosure, so verification is two link checks a verifier already performs on every ordinary element. No range fields exist: a hash chain cannot express a range, and an emitter cannot know its successor's hash at write time. The outcome receipt_missing_required is narrowed to silent absence and receipt_gap_disclosed is added beside it, with acceptance a verifier policy input that never satisfies a profile requiring independently proven completeness. A disclosure at the live tail, where no successor exists to seal it, is unverified rather than disclosed or invalid: a chain truncated immediately after a disclosure is indistinguishable from an honest tail, so whatever the tail is granted, truncation is granted too. That case is pinned by its own test over byte-identical disclosures whose only difference is the seal. Twenty conformance vectors, two per rule, from a generator that reproduces them byte for byte; the verifier consumes a named-rule registry in the shape of agentrust-io#124. Two cross-references that predate the renumbering which introduced section 3.3.1 are updated to name section 3.3.2, where the text they cite now lives. Refs agentrust-io#117 Signed-off-by: Louielunz <48041247+lywinged@users.noreply.github.com>
Contributor
|
❔ Contributor Check: UNKNOWN
Automated check by AgenTrust Contributor Check. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #117.
Opened per the maintainer-carry note there; all three asks from that comment are in,
each named below. Authorship per CONTRIBUTING step 3: carried by a maintainer, proposer credited
in the CHANGELOG entry.
What
Section 3.3.4, normative, marked
<!-- CHANGED: #117 -->: aGapDisclosureis a signed chainelement stating that receipts which would have occupied its position were never emitted. Coverage
is structural rather than asserted: the disclosure links back to the element before the gap, the
next element emitted links back to the disclosure, and verification is two link checks a verifier
already performs on every ordinary element. There are no range fields. A hash chain cannot express
a range, and an emitter cannot know its successor's hash at write time; the design discussion in
#117 walks through why the issue's original field list does not survive that.
The action-receipt outcome
receipt_missing_requiredis narrowed to silent absence, andreceipt_gap_disclosedis added beside it. Acceptance is a verifier policy input, with onenon-negotiable bound: it never satisfies a profile requiring independently proven completeness.
The tail case, as a test
A disclosure at the live tail, after the failure and before resumption, has no successor to seal
it. The spec text forbids granting it
receipt_gap_disclosedand forbidsreceipt_invalidequally: inability to check is not evidence of a defect, section 3.3.2's principle for unknown
issuer keys. It is surfaced unverified with a distinct advisory and upgraded on re-verification
once the chain resumes.
test_the_live_tail_is_not_granted_what_the_seal_earnspins it: fixtures 01 and 17 carrybyte-identical disclosures whose only difference is whether a successor exists, and the test
asserts the sealed one earns the outcome and the tail one does not. The adversarial reading is in
the test's docstring: a chain truncated immediately after a disclosure is byte-for-byte an honest
live tail, so this is also the assertion that truncation buys an advisory, never an outcome.
Fixtures 16 and 18 carry the two near misses: a contradiction standing at the tail still fails,
and a stale successor-link field with no successor is still a tail.
What a disclosed gap does not establish
That the missing receipts ever existed, how many were lost, or that the emitter did not omit them
selectively. What the splice proves is where the gap sits in the chain, and nothing else. The
section states this in its own text, and
causeandreceipts_lost_estimateare constrained todescriptive self-reports a verifier MUST NOT condition any outcome on. The failure mode this
guards is a reader treating disclosure as though it restored what was lost; the text is written so
that no requirement can be read as making a disclosed gap benign.
The interaction with the undecidable state
receipt_gap_disclosedand the tail's unverified state are two more instances of the patternbeing unified across #246, #190, trace-tests#82 and agent-manifest#348: "this was not established"
as a first-class outcome rather than a silent pass. Both names this PR introduces,
receipt_gap_disclosedand the tail'sgap_disclosure_unverified, are candidates for thatvocabulary. Each is held in one constant in the generator and one in the test; outside those, the
disclosed name appears in one spec section and one docs table row. A rename is those sites and one
regeneration. Not blocked on it, per the carry note.
Evidence
examples/action-receipts/gap-disclosure/, two independentvectors per rule, enforced by a margin test rather than remembered. The second vector of each
pair sits against an implementation shortcut the first cannot detect: case-normalised key and
session lookups, digest comparisons truncated to a prefix, sealed-ness derived from a link field
rather than from the chain, a contradiction check gated on the sealed path, and a type check
that only tests presence.
RULES) in the shape test(conformance): single-vector coverage has no margin — define and enforce independence #124 settled next door, so anunregistered check is a check that never runs.
tests/test_generators_reproduce_fixtures.pydiscovery.it; the one survivor widens an exception catch that no JSON-expressible fixture can distinguish,
recorded here rather than left to be found.
typeequality checkthe draft recorded as unimplemented now has a rule and two vectors (19, 20), and the Reporting
obligations are echoed in every fixture's expected result rather than left unpinned.
Housekeeping
Two cross-references that predate the renumbering which introduced section 3.3.1 are updated to
name section 3.3.2, where the text they cite now lives: one in section 3.3.3's profile paragraph,
one in the
receipt_unverifiedrow ofdocs/verification.md.Backward compatibility
Non-breaking. The section binds under a profile requiring action receipts; no current profile
does, and section 3.3.3 already contemplates such profiles as future work. Existing verifiers and
records are untouched; the outcome addition follows #114's decision shape, widening under opt-in
rather than in place. No schema change in this PR: per CONTRIBUTING, the schema PR tracks the
merged spec change.
Checklist
satisfied
<!-- CHANGED: #117 -->CHANGELOG.mdupdatedProduction origin, for the record: the mechanism is operated in a per-action receipt emitter whose
crash recovery writes a functionally equivalent disclosure; relying parties treat a disclosed gap
differently from a silent one, which is the distinction this section makes portable.
Tool-assisted: drafting, the mutant battery and the fixture regeneration. The derivation is in
the section text, the commit message and the test docstrings, where the next reader can find it.