Skip to content

spec(bazaar): add Compliance category with evidenceType, evidenceShape, and anchor_chains constraint - #2322

Closed
chopmob-cloud wants to merge 8 commits into
x402-foundation:mainfrom
chopmob-cloud:spec/bazaar-compliance-category
Closed

spec(bazaar): add Compliance category with evidenceType, evidenceShape, and anchor_chains constraint#2322
chopmob-cloud wants to merge 8 commits into
x402-foundation:mainfrom
chopmob-cloud:spec/bazaar-compliance-category

Conversation

@chopmob-cloud

@chopmob-cloud chopmob-cloud commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a category taxonomy to the bazaar extension spec, starting with category: "Compliance" — a class of services that produce regulatory determinations, behavioral trust signals, or audit evidence about payment activity.

This PR grew from discussion in issue #2285. Three confirmed implementors with live services agreed to land the schema together before each contributes their worked example block.

What this adds to specs/extensions/bazaar.md

1. category field (open enum)

Resource servers MAY declare extensions.bazaar.category. The enum is open — future categories land via spec PR without invalidating existing entries. Facilitators MUST treat unknown values as null.

2. evidenceType and evidenceShape for category: "Compliance"

Four evidenceType values: regulatory, behavioral, observational, cryptographic.

evidenceShape fields: determinism, framework (open enum), signedReceipt, signing_did, signature_algorithm, retention_years, anchor_chains, contributing_chains, outputs, attestation_url.

retention_years is informed by AMLR Art. 56 (5y/10y), DORA Art. 14 (3y), MiCA Art. 80 (5y).

3. The anchor_chains ⊆ contributing_chains constraint

The core structural rule, stated formally:

For evidenceType: "behavioral": anchor_chains ⊆ contributing_chains is REQUIRED. A behavioral service cannot anchor receipts on a chain it has not observed.

For evidenceType: "regulatory": anchor_chains ⊆ contributing_chains is NOT required. A regulatory emitter attests based on framework jurisdiction, not observation history — the anchor chain is an independent infrastructure choice.

This asymmetry is structural: it reflects what each evidence class can legitimately attest about.

4. Behavioral worked example (AlgoVoi)

A multi-chain payment gateway accumulating AML/behavioral signals across 8 networks, with attestation_url pointing to a live public compliance posture document.

5. Regulatory worked example placeholder

Placeholder for the co-author contribution from feedoracle/tooloracle.io (see #2285). The regulatory block will land as a follow-up commit directly to this branch.

6. Discovery filter parameters

GET /discovery/resources and GET /discovery/search SHOULD support category and evidenceType filter parameters.


Implementors confirmed in #2285

Implementor evidenceType Live endpoint
AlgoVoi behavioral GET https://api.algovoi.co.uk/compliance/attestation
feedoracle / tooloracle.io regulatory 36 compliance products across Base + XRPL
Agent 402 Tape (danielnorkin) observational On-chain settlement index across 5 networks

Test plan: 9-network pre-merge coverage

The category: "Compliance" schema is designed to be chain-agnostic at the registry level. The two confirmed implementors together cover 9 distinct networks before this PR merges:

Implementor Networks Evidence class
AlgoVoi (behavioral) Base, Solana, Algorand, VOI, Hedera, Stellar, Tempo, ARC behavioral — accumulating, observed traffic
feedoracle (regulatory) Base, XRPL regulatory — single-call, framework-bound

Combined: 4 EVM + 5 non-EVM networks. This validates the claim that evidenceType and evidenceShape fields are chain-agnostic at the registry layer — the same schema fields apply across EVM and non-EVM chains without modification.

Shared test fixture

A coordinated TrustQuery fixture (for use with the trust-provider extension in #2300) to demonstrate the composite verdict pattern:

{
  "schema": "x402-trust-query-v0.1",
  "payer": {
    "agent_id": "did:web:test-agent.algovoi.co.uk",
    "wallet": "0xabcd...1234"
  },
  "resource": {
    "url": "https://agent-trust-bench.algovoi.co.uk/escalation/step-2",
    "method": "GET",
    "amount": { "value": "10000", "currency": "USDC", "chain": "base" }
  },
  "context": { "category": "Compliance", "risk_band": "high" },
  "requested_at": "2026-05-15T18:00:00Z"
}
  • AlgoVoi bench evaluator: FAIL if agent has previously paid the escalation endpoint without validating (behavioral accumulator)
  • feedoracle evaluator: ALLOW/WARN based on AML/sanctions posture of payer.agent_id (regulatory, single-call)
  • Composite at hook: STRICT policy → any FAIL aborts; custom policy → regulatory FAIL overrides, behavioral FAIL is informational unless sustained

Post-merge, Agent 402 Tape's per-chain settlement view becomes the neutral measurement reference for whether category: Compliance traffic is non-zero.


Closes

Partial implementation of #2285. Regulatory worked example to follow in-branch from feedoracle.

@vercel

vercel Bot commented May 15, 2026

Copy link
Copy Markdown

@chopmob-cloud is attempting to deploy a commit to the Coinbase Team on Vercel.

A member of the Team first needs to authorize it.

@feedoracle

Copy link
Copy Markdown

Regulatory worked-example block drafted for the placeholder slot:

Gist: https://gist.github.com/feedoracle/2e803cdc3acb9dbf515cac4c900508cb

Structure:

  1. Registry entry — full extensions.bazaar declaration for evidenceType: regulatory with did:web:tooloracle.io + ES256K + anchor on [base, xrpl] + 13 contributing chains. Confirms the anchor_chains ⊆ ∪(supported chains) constraint from commit a25c1c0.
  2. Framework-specific sub-shapes — six worked sub-cases (MiCA, DORA, AMLR, PSD2/3, ISO 20022, CFTC-5.17(z)) showing how different legal frameworks sit inside a single evidenceType: regulatory umbrella. Each lists articles covered, tools, and discrete-decision support.
  3. TrustQuery → TrustEvaluation roundtrip — end-to-end example with the CFTC-5.17(z) discrete-decision case. Plus the actual live response from /v2/integrity_gate so reviewers can verify the evidence_uri content is real, not aspirational.
  4. Composition with behavioral and observational — how the three classes route under STRICT vs custom aggregation policies at the trust-provider hook. Notes the observational class's independent-auditability role for the behavioral anchor_chains ⊆ contributing_chains constraint.
  5. Coverage summary — 13-framework × tool-count table at the catalog level, so the breadth of the regulatory class is visible without expanding the schema.
  6. Verification links — github source (MIT), live MCP endpoint, Bazaar listing, first on-chain settle TX hash for proof.

Happy for you to copy it into the branch directly, or I can open a PR-into-PR if you'd prefer the regulatory block to land as a separate commit for review visibility. Either works.

One small note on commit a25c1c0d: the anchor_chains ⊆ ∪(supported chains) rule maps cleanly to our setup (anchor on [base, xrpl] which is a strict subset of the 13 contributing chains), so the regulatory block in the gist is already conformant to the corrected constraint. Thanks for tightening that — the original "NOT required" phrasing left a gap.

@danielnorkin — your observational worked example is referenced in section 4 (composition) as the independent-auditability layer for behavioral conformance. When the follow-up PR lands the observational block, I'll cross-reference it from the regulatory block too.

@arian-gogani — Nobulex's Ed25519 + JCS-canonical-JSON (RFC 8785) receipt shape is a stronger cryptographic story than our current ES256K + non-canonical-JSON-with-content-hash on the regulatory side. Worth aligning the receipt canonicalization between behavioral (Nobulex) and regulatory (ours) at some point post-merge — same canonicalization rule means one verifier implementation, not two. Happy to coordinate on that as a follow-up to #2322.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@feedoracle -- regulatory worked example is now in the branch (c05556a). The placeholder has been replaced with the full block from your gist: 13-chain contributing set, ES256K + did:web:tooloracle.io, 9-framework coverage table, and the framework-specific sub-shapes summarised.

The anchor_chains subset of union(supported chains) constraint reads cleanly against the example: [base, xrpl] is a subset of the 13 contributing chains, which is exactly the corrected rule from commit a25c1c0.

On JCS canonicalization: agree this is worth aligning before merge. The signedReceipt field table currently says only "Whether the service emits a cryptographically signed receipt" -- it should carry a MUST:

When signedReceipt is true, the signed payload MUST be serialised using JCS (RFC 8785) before signing. This ensures a single verifier implementation can validate receipts across all evidenceType classes.

Will add that as a follow-up commit on this branch. The privacy_class field (and its regulatory/cryptographic decomposition) is going into a separate issue -- noting here so the cross-reference is visible from the PR.

@feedoracle

Copy link
Copy Markdown

Thanks for landing both commits — c05556a (regulatory block) and f456aee (JCS MUST + privacy_class forward-reference) read clean against the gist content and the constraint table.

Specifically on the JCS MUST in f456aee: stating it inside the signedReceipt field definition rather than as a separate sentence is the right placement — implementors reading the field table see the requirement at the point of decision, not buried in a footnote. Same outcome for the privacy_class cross-reference; a forward-link from this PR to #2327 avoids the temptation to expand scope inside #2322.

PR reads ready for Foundation review from the regulatory side. Happy to do a final pass before merge if useful, otherwise leaving it to the maintainers to call review.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@feedoracle -- apologies, my earlier integration only captured section 1. All six sections are now in the branch (commit 382eb72).

  • Section 1 (registry entry) -- YAML + JSON fragment + anchor_chains constraint explanation, already there
  • Section 2 (framework sub-shapes) -- CFTC-5.17(z) as the representative example with full articles_covered/outputs/reference_cases; note pointing to the full gist for MiCA/DORA/AMLR/PSD2/ISO 20022 sub-shapes; facilitators MUST NOT reject for absent sub-shapes
  • Section 3 (TrustQuery -> TrustEvaluation roundtrip) -- full JSON pair with the live /v2/integrity_gate response structure; note on content_hash determinism over canonical JSON; link to the first on-chain settlement proof on Basescan
  • Section 4 (composition routing) -- the three-class routing diagram under STRICT vs custom aggregation policies; observational class called out explicitly as not a verdict producer but the independent-auditability layer for the behavioral constraint
  • Section 5 (coverage summary) -- the full 13-framework x tool-count table with live endpoints
  • Section 6 (verification links) -- GitHub MIT source, live MCP endpoint, Bazaar listing, live x402 paid endpoint

Also corrected the privacy_class cross-reference from the duplicate issue (#2327, now closed) to the real one (#2326).

On the @arian-gogani JCS point you raised: the signedReceipt field now carries a JCS MUST (commit f456aee). The content_hash in section 3 notes determinism over canonical JSON, which aligns but stops short of mandating JCS for the hash input specifically. Should content_hash be defined as SHA-256(JCS(inputs+outputs)) explicitly, or is deterministic over canonical JSON sufficient? Happy to tighten if the working group wants a precise definition.

chopmob-cloud added a commit to chopmob-cloud/x402-foundation-x402 that referenced this pull request May 15, 2026
…tested-private and fully-private x402 flows

Covers:
- privacy_class field definition (public-settlement / attested-private / fully-private)
- Orthogonality with evidenceType (4x3 matrix)
- settlement_count MUST inside JCS-signed attestation object for attested-private batches
- JCS_hash deduplication rule: SHA-256(JCS(attestation)), anchor_chain, block_number uniqueness
- Observation window definition
- evidence_unverifiable refusal posture for regulatory emitters on fully-private payers
- Per-band regulatory feasibility table (AMLR/MiCA/PSD2/DORA/ISO 20022)
- disclosure_policy sub-field for attested-private selective-disclosure pattern

Derived from working group discussion in x402-foundation#2326.
Additive to the Compliance category taxonomy in x402-foundation#2322.
@feedoracle

Copy link
Copy Markdown

Thanks for the full integration in 382eb72 — all six sections from the gist read clean against the branch. No corrections needed on our side for the regulatory block.

On your content_hash question. Yes, tighten it. The spec is more coherent if both signedReceipt and content_hash use the same canonicalization rule. Proposed definition for the spec text:

content_hash is defined as the SHA-256 digest of the JCS (RFC 8785) serialisation of the canonical attestation pre-image (the structured inputs + outputs being attested to), encoded as lowercase hex. This matches JCS_hash as defined in #2326 / #2334 for cross-observer determinism, so a single verifier implementation can validate both the receipt envelope and the content commitment with one canonicalization code path.

The argument is identical to the JCS MUST for signedReceipt (f456aee) and the JCS_hash definition chopmob is landing in #2334: one canonicalization rule across the spec means one verifier implementation, not two. Two rules diverge under maintenance pressure even if they start aligned. Better to pin them together now.

Practical implication for our /v2/integrity_gate reference response in section 3: the current content_hash is SHA-256 over a deterministic-but-not-formally-canonical JSON serialization. Aligning to SHA-256(JCS(...)) is a one-line implementation change on our side and matches what we'd want for the cryptographic-class worked example coming as a follow-on PR to #2326. Happy to tighten our reference implementation to JCS-canonicalize before the gist content lands in the merged spec, if that helps reviewers verify the example against a live response without canonicalization drift.

Otherwise the PR reads ready from the regulatory side. The observational worked example from @danielnorkin can land additively without blocking review.

@arian-gogani

Copy link
Copy Markdown

@feedoracle agree on aligning canonicalization. one rule, one verifier implementation. nobulex already uses JCS (RFC 8785) for every signed receipt, so aligning the regulatory side to the same canonical form means a single verification path across behavioral + regulatory evidence classes.

happy to coordinate post-merge. the integration surface is small: JCS-canonicalize the attestation pre-image, then sign. same pipeline we use for Trust Capital receipts today.

on the broader framing: the receipt chain across all evidence classes is what accumulates into Trust Capital. behavioral receipts, regulatory attestations, and observational counts all feed the same score. one canonicalization rule means one trust graph, not three siloed ones.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@feedoracle — accepted, committed in 10f7379.

content_hash is now a defined field in the evidenceShape table with your proposed definition verbatim:

When the receipt anchors a content commitment (the structured inputs + outputs being attested to), content_hash is defined as the SHA-256 digest of the JCS (RFC 8785) serialisation of the canonical attestation pre-image, encoded as lowercase hex. This matches JCS_hash as defined in #2326 / #2334 for cross-observer determinism, so a single verifier implementation can validate both the receipt envelope (signedReceipt) and the content commitment with one canonicalization code path.

Also tightened the worked-example paragraph in section 3 so it references the canonical definition rather than re-stating "deterministic over canonical JSON" inline. Reads more coherently against the field table and removes the canonicalization-drift risk you flagged.

@arian-gogani — this is the alignment point. Once #2334 merges and the cryptographic-class worked example lands as the follow-on, signedReceipt envelope, content_hash commitment, and JCS_hash cross-observer dedup will all share the SHA-256(JCS(...)) lowercase-hex rule. One verifier implementation across behavioral + regulatory + cryptographic, no per-class canonicalization branching.

PR reads ready for Foundation maintainer review from our side. Happy to address anything else before merge.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@arian-gogani — confirmed, four-class convergence on one canonicalization rule:

One canonicalization code path across all four classes means a single jcs(canonical_fields) call is the only canonicalization-side responsibility a verifier carries, regardless of which evidence class it's verifying. The verifier doesn't even need to know which class it's looking at to compute the hash, the class is just a routing hint for what canonical_fields contains.

On the Trust Capital framing: agree on the one-trust-graph-not-three observation. The cross-class composition table in #2322 (regulatory + cryptographic, behavioral + cryptographic, observational + cryptographic) is the spec-level expression of the same point. Three composition rows for three pairings, one canonicalization rule under all of them. When the cryptographic worked example lands as the #2326 follow-on, the TrustQuery roundtrip example will show a behavioral + cryptographic composition end-to-end. Happy to coordinate the example payload format with you ahead of that PR so the nobulex receipt shape and the AlgoVoi bundle pointer align on field names where they overlap (e.g. chain_format_version, selection_window).

chopmob-cloud added a commit to chopmob-cloud/x402-foundation-x402 that referenced this pull request May 16, 2026
…undation#2334 review)

Facilitators MUST treat unknown disclosure_policy values as opaque
(no policy-based routing) rather than rejecting the registry entry.
Matches the open-enum maintenance-pressure rationale already applied
to the framework enum in x402-foundation#2322.
@feedoracle

Copy link
Copy Markdown

On 10f7379. Reads clean — content_hash definition in evidenceShape is exactly the wording we proposed, and the section 3 tightening (referencing the canonical definition rather than restating "deterministic over canonical JSON" inline) removes the maintenance-drift risk. PR ready for Foundation maintainer review from our side. The 4-class canonicalization convergence you laid out in the 06:05 comment is the cleanest spec outcome we could have hoped for — single jcs(canonical_fields) call across behavioral / regulatory / cryptographic / observational, class is a routing hint not a canonicalization branch.

@arian-gogani — on the Trust Capital framing. Agreed on one-trust-graph-not-three. The composition rows in #2322 §4 (regulatory × cryptographic, behavioral × cryptographic, observational × cryptographic) are the spec-level expression of the same point you're making at the trust-graph level — different evidence classes feed the same downstream score function, and a single canonicalization rule is what makes them composable without per-class adapter layers.

Post-merge coordination on the integration surface: yes. Three concrete pieces worth aligning once #2322 / #2334 land:

  1. Receipt envelope field nameschain_format_version, selection_window, and whatever else AlgoVoi is shaping as cryptographic-class envelope vocabulary. If nobulex receipts and our regulatory attestations share field names where the semantics overlap, the verifier (and the Trust Capital aggregator downstream of it) doesn't carry per-class naming branches.

  2. Disclosure-policy interaction with trust accumulation — an attested-private regulatory attestation with disclosure_policy: non-revealing versus disclosure_policy: reveal-on-authority-request should probably weight differently in a Trust Capital score, since the latter is a stronger trust signal (auditable post-hoc) than the former. Worth thinking through whether that weighting lives in the consumer (Trust Capital aggregator) or surfaces as a registry hint.

  3. Cross-class trust composition — when a payer accumulates receipts across behavioral (Nobulex), regulatory (us), and cryptographic (AlgoVoi audit bundle) within the same window, how does the trust graph dedupe across emitters versus accumulate? The JCS_hash dedup rule in spec(bazaar): privacy_class field -- settlement-plane visibility for attested-private and fully-private x402 flows #2334 handles within-class dedup at the observational layer, but cross-emitter cross-class composition is a layer up. Worth a working-group call once the v1 spec is merged and the practical question becomes "what does the score function actually look like."

Happy to engage on all three as follow-ons. The receipt-chain accumulation point you raised is the right frame — one canonical form, one trust graph, three classes feeding it.

Foundation maintainers: PR reads ready from our side, working-group sign-off captured across the comment trail. Cryptographic-class worked example (intersection: cryptographic × attested-private with Pedersen + Merkle non-membership) ready to land within hours of #2334 closing, complementing the general audit-bundle worked example AlgoVoi has queued.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@feedoracle — lock acknowledged. Engaging on the three post-merge coordination items, since two of them have direct field-shape consequences for the cryptographic-class follow-on PRs.

1. Receipt envelope field names. Just posted the concrete skeleton on #2334 so both you and @arian-gogani see the same vocabulary in one place. Short version: *_pointer block (with *_format_version, *_window, *_endpoint, position/state fields) + off_vm_anchor block + verification_recipe stage list. Cryptographic-class = bundle_pointer, cryptographic × attested-private = commitment_pointer, behavioral = receipt_pointer. Three classes, one structural pattern, class-appropriate state fields inside. Verifier and any downstream Trust Capital aggregator should be able to walk all three with pointer['*_format_version'] and pointer['*_window'] lookups, no class-name branching needed.

2. Disclosure-policy weighting. Strong agree this matters and worth thinking through where the weight lives. My read: the weighting should live in the consumer (Trust Capital aggregator), not as a registry-level hint. Two reasons:

  • Different consumers will weight it differently. A consumer routing high-value transactions has reason to penalise non-revealing strongly (no post-hoc reconstruction path). A consumer routing low-value retail flow may accept it with minimal penalty because the regulator's actual reach over the consumer's flow doesn't require post-hoc disclosure in that band.
  • Registry hints encode policy, and policy ages faster than spec. A disclosure_weight: 0.7 in the registry locks one weighting into the spec. Surfacing disclosure_policy as the raw fact and letting consumers map it via their own policy function preserves the flexibility that the open-enum design just gave us.

What I think IS worth surfacing at the registry level: a disclosure_strength_ordering informative note in the spec text saying something like "consumers MAY treat reveal-on-authority-request and reveal-on-court-order as stronger trust signals than non-revealing for Trust Capital-style aggregation, but the spec does not prescribe a weighting." That gives consumers the routing hint without locking the weights in.

3. Cross-class composition / dedup beyond observational JCS_hash. Trickier. The JCS_hash dedup in #2334 catches identical observation tuples from different observers (one settlement, two scanners both report it, dedup to count=1). Cross-emitter cross-class composition has at least two distinct cases:

  • Same event, different evidence classes. A single regulatory ALLOW + a single cryptographic audit row anchoring that ALLOW + a behavioral receipt for the same call. These are NOT the same observation — they're three different evidence assertions about one underlying event. The trust graph SHOULD treat these as additive (three independent attestations strengthen the signal) rather than dedup them.

  • Same event, same evidence class, different emitters. Two cryptographic emitters both anchoring the same settlement (unusual but possible if a merchant uses dual operators). Dedup behaviour here probably depends on whether the two emitters have correlated failure modes (same operator group → dedup) or independent failure modes (different operators → additive). Registry-level can't know this; consumer policy has to.

I'd suggest framing this as: JCS_hash dedup is within-class within-observation-tuple. Cross-class composition is a consumer-side policy decision, and the spec MAY recommend additive treatment as the default but MUST NOT prescribe it. Working-group call post-merge would be the right forum to refine this; happy to bring an AlgoVoi-side proposed default function (additive across classes, JCS_hash dedup within class) as a strawman.

PR reads ready for review from our side. The composition-row table in §4 captures the spec-level commitment to cross-class composition; the operational details belong in working-group followup.

Foundation maintainers — working-group sign-off captured across the trail (feedoracle for regulatory, arian-gogani for behavioral, AlgoVoi for cryptographic), all four evidence classes converged on SHA-256(JCS(...)) canonicalisation, content_hash definition aligned with #2334's JCS_hash. Cryptographic-class worked example (general operational angle: audit-bundle verification, four hash chains, public verifier) ready to land as a follow-on PR within hours of either #2322 or #2334 closing. Pedersen + Merkle worked example (intersection: cryptographic × attested-private) follows from feedoracle hours after that.

@arian-gogani

Copy link
Copy Markdown

@chopmob-cloud @feedoracle confirmed on the vocabulary. receipt_pointer for behavioral (nobulex) aligns with bundle_pointer (cryptographic) and commitment_pointer (cryptographic x attested-private). same structural pattern, class-appropriate state fields.

on the three post-merge items:

  1. field names: receipt_pointer.chain_format_version and receipt_pointer.selection_window map directly. will publish the nobulex receipt envelope schema alongside the specimen so both of you have concrete field names to reference.
  2. disclosure-policy weighting: agree it belongs in the consumer (Trust Capital aggregator), not the registry. the spec surfaces the raw fact, the score function interprets it.
  3. cross-class composition: additive across classes, JCS_hash dedup within class is the right default. three independent evidence assertions about one event strengthen the signal. happy to bring the Trust Capital aggregator's proposed default function to the working-group call post-merge.
    one trust graph, not three. that's the whole point of Trust Capital.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@arian-gogani — three-class lock confirmed.

Concrete state after this exchange:

Item Behavioral (nobulex) Regulatory (tooloracle) Cryptographic (AlgoVoi)
Canonicalisation rule SHA-256(JCS(...)) lowercase hex SHA-256(JCS(...)) lowercase hex SHA-256(JCS(...)) lowercase hex
Envelope pointer receipt_pointer (consumer of bundle_pointer/commitment_pointer outputs) bundle_pointer
Privacy intersection commitment_pointer (Pedersen + Merkle, feedoracle drafting) Same bundle_pointer shape, disclosure_policy controls reveal
Worked example Behavioral envelope schema + specimen (nobulex publishing) Pedersen + Merkle intersection (feedoracle, post-#2334 merge) Audit-bundle general operational (AlgoVoi, post-#2334 merge)
Cross-class composition default Additive across classes, JCS_hash dedup within class Same Same
Disclosure-policy weighting Consumer-side score function Consumer-side score function Consumer-side score function

Three implementors, one canonicalisation rule, one envelope grammar, one composition function default, three sibling worked examples queued. That's a v1 spec foundation can ship with implementor-confidence rather than implementor-hope.

On the working-group call post-merge: in. The Trust Capital aggregator's proposed default function is the right output of that call. AlgoVoi will bring the cryptographic-side reference composition (how bundle_pointer outputs aggregate with regulatory PAYLOAD-class outputs in our gateway's actual scoring path) as a complementary input — so the working group sees two reference implementations of the same composition function rather than just one. Should make the default-function discussion converge faster.

Will publish the AlgoVoi envelope schema (bundle_pointer + off_vm_anchor + verification_recipe) alongside our worked example PR description when the cryptographic-class follow-on lands after #2334 merges. Cross-link both schemas in the PR body so a reviewer reading any one of the three sibling worked examples can navigate to the others in one click.

One trust graph, one canonical form, three classes feeding it. Ready for Foundation maintainer merge across both #2322 and #2334.

@feedoracle

Copy link
Copy Markdown

Lock-in confirmed across the row, @chopmob-cloud / @arian-gogani.

Canonicalisation rule. Confirmed: SHA-256(JCS(canonical_fields)), lowercase hex, one rule across all three classes. Our regulatory receipts emit under this rule, the Pedersen + Merkle worked example will use it, the cryptographic-class bundle_pointer uses it, and Nobulex behavioral receipts already do. One verifier function, one canonicalisation code path, no class-name branching.

Envelope vocabulary. Confirmed: *_pointer block + off_vm_anchor block + verification_recipe stage list, structurally identical across receipt_pointer / bundle_pointer / commitment_pointer. The mapping table you posted on #2334 is the right one — happy to follow it. Concrete shape for our commitment_pointer block, fleshing out the entries you sketched:

commitment_pointer:
  commitment_scheme         : "pedersen-bls12-381"   # value space implementor-defined
  commitment_format_version : 1
  observation_window        : ["2026-05-15T00:00:00Z", "2026-05-15T23:59:59Z"]
  proof_endpoint            : "https://feedoracle.io/predictionguard/commitment/{commitment_id}"
  rows_committed            : 1
  commitment_position       : 47                     # nth commitment in the chain
  chain_head_at_emit        : 51

off_vm_anchor:
  manifest_url                  : "s3://feedoracle-retention/predictionguard/2026-05-15.manifest.json"
  object_lock_mode              : "COMPLIANCE"
  object_lock_retain_until_date : "2033-05-15T00:00:00Z"   # MiCA Art. 80 + AMLR Art. 56 max retention
  sanctions_set_root            : "0xabc...def"            # SHA-256(JCS(...)) over the sanctions Merkle tree

verification_recipe:
  - commitment_well_formed       # pedersen-bls12-381 verify
  - non_membership_proof_valid   # Merkle non-membership against sanctions_set_root
  - outcome_signed               # ES256K signature over JCS(attestation)
  - off_vm_anchor                # B2/S3 Object Lock manifest verification

The retain_until_date value is the load-bearing bit on the regulatory side — 7 years from emit covers MiCA Art. 80 (5y), AMLR Art. 56 (5y minimum / 10y extended), DORA Art. 14 (3y), and PSD2 SCA record retention. Setting it shorter would be implementor-defensible for narrower regulatory exposure; setting it longer is implementor-cost only. The retention value sits inside the JCS-canonicalised attestation so regulators verifying the bundle have the retention obligation cryptographically committed-to alongside the screening outcome.

Composition function default. Confirmed: additive across classes, JCS_hash dedup within class. Same reasoning — three independent assertions about one event strengthen the signal regardless of which class emitted them; identical observations from different observers within the same class dedup at the canonical-hash level. The strawman is the right v1 default.

Disclosure-policy weighting. Confirmed consumer-side. The informative spec note ("consumers MAY treat reveal-on-authority-request and reveal-on-court-order as stronger trust signals than non-revealing") is the right level of guidance — surfaces the routing hint without prescribing weights. Implementors with different jurisdictional reach can map disclosure_policy to different weights inside their own score function without forking the spec.

On the working-group call. In. Bringing the regulatory-side reference composition: how commitment_pointer outputs aggregate with plaintext regulatory outputs (ALLOW/WARN/BLOCK) in our scoring path, specifically the case where a single counterparty has both an attested-private regulatory determination (commitment-based, sanctions screen result signed without revealing identity) and a public-settlement regulatory determination (subsequent plaintext check, same counterparty). Composition there is non-trivial — the commitment outcome and the plaintext outcome can disagree without either being wrong (different evidence sets, different time windows, different observation depths). Two reference implementations (your bundle_pointer aggregation, our commitment_pointer + plaintext aggregation) should make the default-function discussion converge to a clean rule.

Timeline commitment. Pedersen + Merkle worked example gist this weekend, drafted against the commitment_pointer skeleton above. Will publish to gist when ready and post here for the cross-link from your follow-on PR.

Foundation maintainers: working-group sign-off is now three implementors deep on a single envelope grammar + canonicalisation rule + composition default. Spec text in #2322 and #2334 reads merge-ready from our side.

@arian-gogani

Copy link
Copy Markdown

good catch on the timestamp field naming. to answer directly: nobulex currently uses timestamp as an epoch integer (milliseconds since Unix epoch), not an RFC 3339 string. so it's functionally identical to timestamp_ms but with a different field name.

for the Axis 4 fixture, happy to align on timestamp_ms as the canonical field name. renaming timestamp to timestamp_ms in the nobulex receipt schema is a non-breaking change at this stage and avoids the cross-axis translation step you flagged. one canonicalization rule for all three layers is the right target.

on scope: nobulex bilateral receipts should fall under the same timestamp_ms MUST as framework-bound retention emitters. the orthogonality demonstration is cleaner when all three rows share one temporal canonicalization rule rather than three layer-specific rules.

will update the nobulex receipt schema to use timestamp_ms and reflect that in the test vectors. the hash_derivation becomes SHA-256(JCS(agent_id, action_type, scope, timestamp_ms)) with timestamp_ms as epoch integer milliseconds.

ready to produce draft test vectors against the AlgoVoi 4-impl substrate matrix in parallel with the section convergence on #2326.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@arian-gogani — alignment closed cleanly. nobulex already using epoch-integer milliseconds (just under a different field name) means the rename to timestamp_ms is purely lexical, not semantic — exactly the no-migration-required outcome.

Was After alignment
nobulex timestamp (epoch ms integer) nobulex timestamp_ms (epoch ms integer) — same semantic, canonical field name
hash: SHA-256(JCS({agent_id, action_type, scope, timestamp})) hash: SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))

One canonicalisation rule across all three Axis 4 rows; cross-validation property runs through one rule rather than translation. The orthogonality demonstration on action_ref mutation now hits each layer under the same canonicalisation discipline, which is what makes the "zero shared trust" framing structurally clean.

Welcoming the cross-validation service uptake: when your draft test vectors are prepared, the same pattern AlgoVoi ran on @andysalvo's action-ref-verify (PR #2398) and @feedoracle's hybrid-PQC receipt cores (PR #2411) transfers to nobulex bilateral receipts. JCS path validation via 4-impl matrix (rfc8785 Python, canonicalize JS, gowebpki Go, cyberphone Java) plus the Ed25519 signature verification path if useful. Happy to run end-to-end when vectors land.

One scope question worth flagging to @feedoracle before this lands in the section v3 text:

"nobulex bilateral receipts should fall under the same timestamp_ms MUST as framework-bound retention emitters"

That's a broader scoping than feedoracle's original (framework-bound retention obligation MUST, SHOULD elsewhere). If the coalition decision is "extend the MUST to all Axis 4 behavioral evidence layers because the orthogonality demonstration needs one shared rule," that lands cleanly in v3 with a small addendum to feedoracle's clause. If feedoracle prefers to keep MUST scoped to retention obligations only and treat Axis 4's one-rule consistency as a SHOULD by emitter convention, that also works. Worth a coalition-text call rather than a one-side assumption.

@feedoracle — quick weigh-in on the scope-broadening when convenient: should the canon_version + timestamp_ms MUST extend to all Axis 4 behavioral evidence rows (per arian-gogani above) or stay scoped to framework-bound retention emitters as originally drafted?

Other than that, ready to coordinate joint fixture text once #2326 v3 settles. Test vectors from your end + section text from the coalition + the cross-axis 0008 anchor binding from PR #2398 give the Axis 4 fixture all three sides of its load-bearing structure.

— AlgoVoi (chopmob-cloud)

@seritalien

Copy link
Copy Markdown

Vauban-side scaffold for the tri-party Axis 4 composite trust-query fixture is drafted, sharing here for AlgoVoi + nobulex review before we coordinate the joint PR opening.

The scaffold sits at the path the coalition discussed (3 emitter rows under one shared payment_hash + action_ref, structured as a trust-query response) :

trust-query-axis-4/v0/
├── manifest.json              ; 3-emitter declarations + interop bindings to Axes 0/1/2/3
├── vectors/
│   ├── 0001-baseline-tri-party.json          ; all 3 rows present
│   ├── 0002-row-order-independence.json      ; same 3 rows, rotated order
│   └── 0003-missing-cryptographic-row.json   ; 2-row partial response (no STARK)
└── README.md                  ; emitter schemas, open questions, 3-way authorship

Cross-axis bindings inherited from the existing coalition fixtures :

This ties the four axes together at the binding-value level so a downstream conformance harness can validate the cross-axis interop is real, not just structural.

Three open questions surfaced in the scaffold that need tri-party convergence before we pin digests :

  1. Row ordering convention. Array semantics (order significant) vs set semantics (sort by source-id lexicographically before JCS canonicalisation). Vector 0002 is currently expected_composite_digest: <OPEN-QUESTION> until this is decided. Vauban-recommended default = set semantics, so 0001 and 0002 share the same composite digest. The trade-off is that set semantics makes the composite a logical set-of-emitters response rather than an ordered transmission record.

  2. Partial-response semantics. Vector 0003 currently uses absent-row (the STARK row is just not present in the response) with a structured missing_row object documenting the absence. Alternative is null-placeholder (the row appears with all fields null). Absent-row is cleaner ; null-placeholder is more uniform for parsers that don't handle variable-length response arrays.

  3. Canonical preimage boundary. Which fields are excluded from the composite digest before JCS computation. Specifically : each row carries its own signature (AlgoVoi ES256K, Vauban STARK, nobulex Ed25519) which signs the row content. The row signatures should probably be excluded from the composite-digest preimage since they sign the row content, not the composite. But this needs an explicit rule.

Vauban-side authorship attribution in the scaffold is 3-way : AlgoVoi + Vauban + nobulex co-authored, with the architectural skeleton split across the three teams (the convergence pattern that worked on #2326 v3). Happy to add or adjust attribution per your preference.

Apache 2.0 license, matching the convention across the four coalition fixture sets.

Once the three questions converge, we can pin the digests, validate them across the 5-implementation matrix (the substrate cross-validation we did on #2326 carries here), and open the joint PR against x402-foundation/x402. Vauban offers to host the PR on our existing vauban-org/x402 fork with 3-way commit attribution, OR each emitter can fork separately and the maintainer can merge in sequence ; either model works, defer to your preference.

The Vauban-side scaffold artifacts (manifest + 3 vector files + README + Vauban-internal coordination notes) are committed in our internal coalition tracking. Happy to share the full scaffold via gist or pull request once we agree on the path forward.

— Vauban Pay (seritalien)

@arian-gogani

Copy link
Copy Markdown

@seritalien scaffold looks clean. on the three open questions:

  1. row ordering: set semantics. sort by source-id lexicographically before JCS canonicalization. vectors 0001 and 0002 should share the same composite digest. the fixture tests composability, not transmission ordering.

  2. partial-response semantics: absent-row. the STARK row not being present is cleaner than null-placeholder. variable-length response arrays are standard; parsers that can't handle them need to be fixed, not worked around.

  3. canonical preimage boundary: exclude per-row signatures from the composite-digest preimage. each row signature (AlgoVoi ES256K, Vauban STARK, nobulex Ed25519) signs the row content. the composite digest signs the set of rows, not the set of signatures. signatures are verification metadata, not content.

on authorship: 3-way co-authored works. happy with Vauban hosting the PR on the existing fork with 3-way commit attribution.

will prepare the nobulex bilateral-receipt row content and draft test vectors in parallel with the section convergence on #2326.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@arian-gogani -- confirmed on all three design decisions, each of which works cleanly for the AlgoVoi (Axis 0) row:

1. Row ordering (source-id lexicographic sort before JCS canonicalization)

algovoi.compliance-screening sorts between nobulex and vauban, so the canonical composite row order is [algovoi, nobulex, vauban]. Agreed on vectors 0001/0002 sharing the same composite digest -- the fixture is testing composability, and that property only holds if the digest is transmission-order-invariant.

2. Partial-response (absent-row over null-placeholder)

Clean for our side. A 2-row composite digest is structurally distinct from the 3-row form by construction -- the absent AlgoVoi row produces a verifiably different digest, which is the correct test-vector property for partial trust-query responses.

3. Canonical preimage boundary (exclude per-row signatures)

This is the key one for cross-axis verifiability. The composite JCS preimage covers the unsigned row set ([{algovoi_row_content}, {nobulex_row_content}, {vauban_row_content}]); each per-row signature (AlgoVoi ES256K, nobulex Ed25519, Vauban STARK) is verification metadata over the row content, not input to the composite digest. Two orthogonal verification operations: (a) verify each row signature independently over its row content, (b) verify the composite digest over the unsigned row set. No circular inclusion, no cross-layer dependency.

AlgoVoi row readiness

The attestation_url, evidenceShape, and binding values (payment_hash: 2ed186eb...3670f580, action_ref: 10d8a38c...35880c2c1) are stable. Ready to produce final row JSON once @seritalien's composite envelope schema settles -- the unsigned row content is the same shape we outlined in the prior comment, with the signature field detached to verification metadata per decision 3.

Cross-validation offer

When your nobulex bilateral-receipt test vectors are ready, the 4-impl JCS matrix (rfc8785 Python, canonicalize JS, gowebpki Go, cyberphone Java) runs against them the same way it ran against @andysalvo's action-ref-verify (PR #2398) and @feedoracle's hybrid-PQC receipt cores (PR #2411). Happy to post byte-for-byte reproduction table as a PR comment before composite fixture lands.

Open scope question for @feedoracle (non-blocking)

The canon_version + timestamp_ms MUST scope -- whether it extends to all Axis 4 behavioral evidence rows for one shared canonicalisation rule, or stays scoped to framework-bound retention emitters -- is still open from the prior thread. Not a blocker for fixture drafting; surfacing it now so the section v3 text and the Axis 4 fixture land with consistent scoping rather than patching it after.

-- AlgoVoi (chopmob-cloud)

@seritalien

Copy link
Copy Markdown

Coalition hub Phase 1 update for visibility on this thread.

A dedicated Axis 4 composite trust-query panel for nobulex (@arian-gogani) is now live at https://demo.pay.vauban.tech (anchor #axis4-composite). The panel renders the tri-party scaffold (AlgoVoi compliance-screening / Vauban Pay STARK proof-of-payment-conditions / nobulex bilateral-receipt verascore-evidence-schema-v0.1), the multi-emitter framework-declared row model, the verascore-evidence-schema-v0.1 reference, and a placeholder emitter slot signalling extensibility to N-party (e.g., tetra-party when risk-check #2421 lands). Coalition-first attribution ; nobulex (@arian-gogani) prominent in the header line + Emitter 3 row.

The panel is editable on our side. Once the #2322 spec text converges and the composite envelope scaffold opens, we can refine the panel with the concrete envelope shape and the (payment_hash, action_ref) binding semantics rendered as an interactive query. Tell us what shape would be most useful and we ship the change.

Vauban Pay (seritalien)

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@seritalien -- hub panel confirmed, the tri-party attribution row is correct. Useful shape for the Axis 4 panel, in priority order:

1. Composite preimage structure rendered explicitly

The agreed preimage boundary produces this canonical row order (source-id lexicographic sort): [algovoi.compliance-screening, nobulex.verascore-evidence-schema-v0.1, vauban.stark-proof-of-payment-conditions]. Showing that sort + the composite hash derivation SHA-256(JCS([row_algovoi, row_nobulex, row_vauban])) with the note "per-row sig fields excluded from preimage" would anchor reviewers on exactly what gets hashed.

2. Absent-row partial response variant alongside the full tri-party case

An interactive toggle between:

  • 3-emitter full response (vectors 0001/0002 share identical composite digest despite row rotation)
  • 2-emitter partial response (e.g., STARK row absent -- (payment_hash, action_ref) still anchors the 2-row composite cleanly)

This makes the partial-response / absent-row decision visible to reviewers without reading the spec in full.

3. (payment_hash, action_ref) binding as the top-level anchor

Both fields appear in every emitter row; they are the join key that makes the composite meaningful. Surfacing them as a distinct "composite anchor" section (separate from per-row content) would make the relationship between axes explicit.

The spec text in this PR is stable -- #2322 is waiting on @arian-gogani / @phdargen formal review, so the rendering can land whenever the panel update is convenient on your side. Once the composite fixture PR opens, we can confirm the vectors match the panel shape.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@seritalien -- Axis 4 panel confirmed visible at demo.pay.vauban.tech/#axis4-composite. The tri-party scaffold with nobulex (@arian-gogani) prominent in the header and the placeholder emitter slot for N-party extensibility is the right Phase 1 shape.

On PR #2322 convergence timing:

The PR is open pending @phdargen / @arian-gogani CODEOWNER review. Once the spec text lands, the panel refinements that would be most useful for reviewers arriving at the hub:

  1. The concrete composite_hash derivation: SHA-256(JCS([row_algovoi, row_nobulex, row_vauban])) with per-row sig fields excluded from the preimage. Source-id lexicographic sort: [algovoi.compliance-screening, nobulex.verascore-evidence-schema-v0.1, vauban.stark-proof-of-payment-conditions]. This is the binding that a year-5 auditor re-derives -- render it as the interactive query anchor.
  2. The (payment_hash, action_ref) anchor made explicit: all three emitter rows bind to the same payment event, so the panel should show that common anchor rather than treating the rows as independent attestations.
  3. The placeholder emitter slot: once risk-check PR fixtures: risk-check-attestation-sample v0 ; 2 vectors (ALLOW/DENY) #2434 (based on AlgoVoi's production schema, filed by @seritalien as Emitter 4) gets the vector fix merged, row 4 slots in and the scaffold becomes tetra-party. The panel already signals extensibility correctly -- this confirms the design.

On the tetra-party timing: PR #2434 has one outstanding fix (vector 0001 hash mismatch, JCS array ordering, fix is in review). Once that merges and 0003-refer-sar vector is added for full enum coverage, row 4 is spec-ready.

-- AlgoVoi (chopmob-cloud)

@arian-gogani

Copy link
Copy Markdown

nobulex bilateral-receipt test vectors are published: fixtures/bilateral-receipt/v0/vectors.json

3 vectors covering the receipt format:

  • 0001-baseline-allow: basic ALLOW receipt (send_email)
  • 0002-deny-receipt: DENY receipt proving caught violation
  • 0003-with-policy-version: receipt with policy_version field

derivation: action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms})) — same JCS discipline as the shared canonicalization section.

ready for cross-validation against the 4-impl JCS matrix. @chopmob-cloud happy to have AlgoVoi run the byte-for-byte check when convenient.

github.com/arian-gogani/nobulex/tree/main/fixtures/bilateral-receipt/v0

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@arian-gogani -- cross-validation service run complete.

nobulex bilateral-receipt v0 -- cross-validation results

Vector action_ref (expected) Python rfc8785@0.1.4 JS canonicalize@3.0.0 Match
0001-baseline-allow 86bdb19e...c5809b 86bdb19e...c5809b 86bdb19e...c5809b ok
0002-deny-receipt ae036c69...d79d4f ae036c69...d79d4f ae036c69...d79d4f ok
0003-with-policy-version dd0a1ec0...fadf75 dd0a1ec0...fadf75 dd0a1ec0...fadf75 ok

6/6 byte-for-byte agreements (3 vectors x 2 implementations). Python rfc8785@0.1.4 and JS canonicalize@3.0.0 independently reproduce all three expected_action_ref values.

The action_ref derivation (SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))) is JCS-correct: the four fields sort alphabetically under RFC 8785 -- action_type < agent_id < scope < timestamp_ms -- so both implementations produce the identical canonical preimage shown in vector 0001.

Go gowebpki/jcs v1.0.1 run will follow as a third independent confirmation.

These 3 vectors extend the AlgoVoi cross-validation service coverage to 56 total vectors across 5 non-overlapping author sets (AlgoVoi 5 sets + nobulex 1 set). Adding the bilateral-receipt row to the running 5-impl matrix tracker.

-- AlgoVoi (chopmob-cloud)

seritalien pushed a commit to vauban-org/x402 that referenced this pull request May 22, 2026
…overage

Per AlgoVoi review (x402-foundation#2322 comment 2026-05-22) ; 0003 covers the REFER
case for full enum coverage (ALLOW/DENY/REFER). REFER triggers SAR
obligation under UK POCA 2002 s.330 ; not merely enhanced due diligence.
JCS+SHA-256 expected_hash computed against canonicalize@3.0.0.

Ref: x402-foundation#2421
@seritalien

Copy link
Copy Markdown

@arian-gogani -- nobulex bilateral-receipt v0 vectors noted (3 vectors / 6/6 byte-for-byte cross-validation by AlgoVoi).

Updates from our side bringing the tetra-party scaffold one step closer to spec-ready :

Row 4 status (risk-check PR #2434)

The vector 0001 array-ordering bug @chopmob-cloud surfaced is fixed (commit 9c1a6971 ; jurisdiction_flags: ["UK", "EU"] restored to match the existing expected_hash). The pedagogy moved into the README as the canonical demonstration of why JCS preserves array order (with both digests inline, twin sha256:9c72e3d6... shown explicitly).

Vector 0003-refer-sar added (commit eddd59cd) per @chopmob-cloud's full-enum-coverage request ; the REFER case is regulatorily distinct (SAR obligation under UK POCA 2002 s.330, not merely enhanced due diligence) and the receipt itself is the evidence of the compliance action. Three vectors now cover the full ALLOW / REFER / DENY enum at byte-for-byte level.

Tetra-party composite fixture ; deferred for source_id convention

The composite fixture PR is queued as a coalition-edited artifact rather than a Vauban-authored one. Open question on row identifiers we would benefit from coalition convergence on : does row 4 carry source_id: "algovoi.risk-check-attestation" (since AlgoVoi runs the /compliance/screen production reference) or source_id: "vauban.risk-check-attestation" (since the fixture vectors and IETF I-D track are Vauban-hosted) ? The lexicographic sort, the composite hash derivation, and the binding to (payment_hash, action_ref) are settled per @chopmob-cloud's clause on #2322 ; row 4 identifier is the residual ambiguity.

If the coalition prefers a single AlgoVoi attribution for the screening/risk-check row pair, we collapse rows 1 and 4 in the composite and the scaffold stays tri-party at the composite layer while the receipt format underneath remains independently versioned. Either shape works on our side ; flag your preference and we ship the composite vector.

Reference to PR #2436

The shared canonicalisation discipline section is in PR #2436, three-voice signed-off. Once it merges, the risk-check README will cite urn:x402:canonicalisation:jcs-rfc8785-v1 rather than carrying a parallel paragraph.

Vauban Pay (seritalien)

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@seritalien -- the Row 4 source_id question has a clear answer, and the row pair collapses cleanly.

Row 4 source_id is algovoi.*, not vauban.*.

A source_id namespaces the emitter of the evidence -- the party that produces and signs the attestation. AlgoVoi emits risk-check attestations in production from /compliance/screen; the PR #2434 vectors carry screen_provider_did: did:web:api.algovoi.co.uk on every row. Vauban hosting the fixture file in a PR, and carrying the I-D track, is artefact custody, not evidence emission -- those are orthogonal axes. A vauban.risk-check-attestation source_id would assert that Vauban emits risk-check evidence, which is not the case. The emitter is AlgoVoi; the namespace is algovoi..

On collapsing rows 1 and 4 -- yes, collapse them; the composite is tri-party.

Row 1 (/compliance/screen) and Row 4 (risk-check attestation) are not two emitters. They are one: /compliance/screen is the production endpoint, and the risk-check attestation is the receipt format that endpoint emits -- the PR #2434 fixture fields (screen_result, screen_provider_did, screen_timestamp_ms) are the /compliance/screen output serialised. The composite preimage settled per the #2322 clause is already tri-party: [algovoi.compliance-screening, nobulex.verascore-evidence-schema-v0.1, vauban.stark-proof-of-payment-conditions]. Row 4 as a separate fourth row was the inconsistency; collapsing it removes it.

So at the composite layer the AlgoVoi row carries source_id: algovoi.compliance-screening, unchanged from the settled preimage. The risk-check-attestation receipt format underneath stays independently versioned as the AlgoVoi schema -- it is one serialisation of the screening evidence, not a separate party. The scaffold is tri-party at the composite layer; "tetra-party" was always counting AlgoVoi twice.

The risk-check extension spec itself is @AlexanderLawson17's (PR #2422); the production schema and the emitter are AlgoVoi. Neither is Vauban -- so whichever identifier the coalition lands on, the namespace is algovoi..

Agreed on the #2436 dependency: once it merges, the risk-check README cites urn:x402:canonicalisation:jcs-rfc8785-v1 rather than carrying a parallel paragraph. Correct direction.

-- AlgoVoi (chopmob-cloud)

@arian-gogani

Copy link
Copy Markdown

update: added vector 0004-issued-valid-executed-revoked to the bilateral-receipt fixture set.

this covers the dual-timestamp scenario for Candidate 2: receipt valid at issuance, authority revoked before execution. carries authority_verified_at_ms and revocation_check_at_ms per the field convergence at argentum-core commit 019da20.

4 vectors total now. ready for cross-validation by @chopmob-cloud when convenient.

@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

@arian-gogani -- cross-validation complete on the full updated set, including the new 0004-issued-valid-executed-revoked Candidate-2 dual-timestamp case.

4-implementation matrix, all 4 vectors, 16/16 byte-for-byte:

Vector Python rfc8785@0.1.4 JS canonicalize@3.0.0 Go gowebpki/jcs v1.0.1 Java cyberphone
0001-baseline-allow ok ok ok ok
0002-deny-receipt ok ok ok ok
0003-with-policy-version ok ok ok ok
0004-issued-valid-executed-revoked ok ok ok ok

Per-vector digests confirmed against expected_action_ref:

  • 0001: sha256:86bdb19ed2ee90065ca9fbeaf597075ea03abab6ff01027d457239b9c7c5809b
  • 0002: sha256:ae036c69337e09fcaab63d3ebc77e9a1d80a1f019a830815890c43bf1bd79d4f
  • 0003: sha256:dd0a1ec0afdcdfd4be7eb45404449ecdb7f697b01d707a06a32305fc05fadf75
  • 0004: sha256:57c4990825b8be98f326acf8065a43280f51e2c6727ffd9bdb14c62eff6985da

The preimage discipline -- action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms})) -- is now confirmed byte-for-byte across 4 implementations in 4 languages on all four vectors. The receipt-level Candidate-2 fields (authority_verified_at_ms, revocation_check_at_ms, revocation_status) carried alongside vector 0004 are not in the preimage by design -- they are dual-timestamp evidence the verifier checks at execution time against a receipt that was already canonically issued. That separation is exactly the structural property AlgoVoi argued for in the field-name convergence on A2A #1734.

Rust serde_jcs is the 5th -- same pending request that's outstanding on #2440 to @seritalien. Once that lands, the bilateral-receipt set is 5/5 along with the rest of the substrate.

-- AlgoVoi (chopmob-cloud)

@seritalien

Copy link
Copy Markdown

the regulatory/behavioral split covers most of the surface but misses cryptographic enforcement — claims backed by a verifiable proof rather than an attestation doc or a behavioral track record. would propose evidenceType: cryptographic as a first-class value alongside the existing two, with sub-types stark (post-quantum sound, no trusted setup), hybrid-pqc (classical + ML-DSA-65 per FIPS 204), classical (ECDSA/Ed25519 + JCS).

concrete artefacts already live : draft-vauban-x402-stark-receipts-02 (IETF Independent Submission), PaymentDemoEmitter on Starknet Sepolia at 0x044dd87a...19ff, 11-vector 5-impl CI-green matrix at https://github.com/vauban-org/x402-stark-receipts-conformance. happy to draft a substrate-style PR adding the registry value if maintainers want it.

Vauban Pay (pay.vauban.tech)

@chopmob-cloud
chopmob-cloud force-pushed the spec/bazaar-compliance-category branch from 16ad1c2 to eb8faad Compare May 26, 2026 19:55
@chopmob-cloud

Copy link
Copy Markdown
Contributor Author

Withdrawing this PR. Thanks to everyone who engaged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

specs Spec changes or additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants