Replies: 14 comments 1 reply
-
|
@kenneives — in. Happy to contribute the exactly-once guard fixture: PENDING → COMMITTED lifecycle, action_ref keyed to the same preimage as the verifier_attestation binding, SKIP on retry. Will produce byte-verifiable conformance vectors to the same substrate bar as Row 8. @evidai — ready to wire against the mint endpoint shape whenever you have it. |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — conformance fixture delivered. PENDING → COMMITTED lifecycle + SKIP on retry, action_ref keyed to the same preimage as verifier_attestation binding_digest. Byte-verifiable on a fresh clone. |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — concrete mint shape + where What the Pay Token is. A JWT-shaped, budget-limited payment token. The agent holds no wallet and no private key — the buyer/card side funds it. It carries its constraints inline: budget, max calls, expiry, and the intended gateway/resource it's scoped to. The gateway verifies it before each paid call and stops when any limit is reached. What's now live (the gateway half). A seller-side billing API settles a charge in two steps, both shipped:
It is idempotent on a per-action key ( Where POST /…/preflight // reserve
{ "payToken": "…", "idempotencyKey": "…",
"verifier_attestation": { /* pre-execution-verdict-v0, OPTIONAL */ } }When present, before reserving the gateway: (1) verifies the verifier signature; (2) recomputes So the three parts line up, and two of them now exist: signed admission (verifier → populates the field, proposed) → static cap + settlement + Honest boundary (worth stating). LemonCake's rail is fiat/off-chain — On the open items: #4 replay — covered by the charge-bound Runnable substrate: the reserve→confirm + idempotency path is live and the SDK is public, so I can share a byte-stable fixture (reserve / idempotent-retry / confirm / cancel-refund) that reproduces on a fresh clone, to the same bar as Row 8. |
Beta Was this translation helpful? Give feedback.
-
|
@evidai — the fixture I posted this morning byte-matches your shape exactly. Your idempotencyKey is my request_id, your reserve is PENDING, your confirm is COMMITTED, your binding_digest derivation is the same JCS+SHA-256 construction. Two live implementations of the same state machine, independently verifiable, neither trusting the other. Ready to wire against your mint endpoint whenever you have the shape ready to share. |
Beta Was this translation helpful? Give feedback.
-
|
Reproduced @azender1's exactly-once fixture — it holds. ✅ Cloned @evidai — the gateway half being live, not hypothetical is the unlock. Your The three-part seam now stands as: signed admission ( Closing the open items with this:
One addition from the #1829 keyid thread that belongs here: @aeoess's point that verification-source provenance (was the key inline / cached / resolved) should travel in the signed evidence, not just verifier logs — same signature, different trust posture. I'll add an optional Next:
Substrate bar unchanged: clone, reproduce, or it doesn't count. |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — fixture delivered, same substrate bar.
https://github.com/evidai/agent-payment-mcp/tree/main/docs/conformance @azender1 — confirmed it byte-matches your shape: your On the synthesis — all three land for me: cap 0.30 for Ready to wire |
Beta Was this translation helpful? Give feedback.
-
|
As promised — here's the concrete {
"envelope": "pre-execution-verdict-v0",
"verifier_did": "did:web:trust.example.com",
"subject_did": "did:web:example.com:agent:<id>",
"admission": {
"verdict": "admit | deny | flag",
"dynamic_limit_usd": 50.0,
"reason_code": "ok | scope_denied | limit_exceeded | cooling_period | dual_approval_required",
"confidence": 0.0
},
"binding": {
"charge_ref": "<gateway charge / idempotency key>",
"amount_usd": 50.0,
"nonce": "<unique-per-charge>",
"binding_digest": "sha256(JCS({charge_ref, amount_usd, subject_did, nonce}))",
"action_ref": "<content-addressed action_ref, per #1850 — names which preimage>"
},
"gates_rechecked": ["identity", "certificate", "key_lifecycle"],
"key_source": "inline | cache | resolver",
"issued_at": "2026-06-09T20:00:00Z",
"expires_at": "2026-06-09T20:00:35Z",
"freshness_ttl_seconds": 35
}Signed EdDSA over JCS-RFC8785, offline-verifiable against Gateway preflight checks (the part that binds it into settlement):
Two deliberate choices worth flagging:
Optional everywhere — absent ⇒ un-gated, backward-compatible both directions, exactly as @evidai framed it. @evidai — this is what populates the optional field on your |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — binding.action_ref is the right hook. On my side: the guard claims PENDING on the action_ref before execution fires, transitions to COMMITTED after, returns SKIP on any retry with the same ref. The binding_digest + action_ref together close the loop — the verifier proves admission, the digest binds it to this charge, the guard ensures it executes exactly once. One question on the field set: should binding.action_ref carry the preimage method identifier (argentum-core action-ref-v1 vs APS draft-pidlisnyi-aps-01) so a downstream auditor knows which derivation to recompute? You named that distinction in the opener — worth making it explicit in the field. Ready to wire against this shape. Will update the fixture to include verifier_attestation as the pre-execution gate. |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — the envelope drops straight onto I'll wire |
Beta Was this translation helpful? Give feedback.
-
|
@azender1 @evidai — two independent, mutually-untrusting impls now reproduce the same @azender1 on your question — yes, I'm publishing the verifier-side reference fixture for Also folding the #1829 refinement: |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — fixture updated to v1.1. Added action_ref_method: "argentum-core action-ref-v1" at the vector level, inside attestation_binding, and in the verification section — so a downstream auditor knows which derivation to recompute at every reference point. github.com/azender1/SafeAgent/tree/main/docs/conformance |
Beta Was this translation helpful? Give feedback.
-
|
@evidai — fixture is updated to v1.1 with action_ref_method on the binding. Ready to wire against your gated reserve fixture whenever you publish it. What's the timeline on the gateway-side fixture? |
Beta Was this translation helpful? Give feedback.
-
|
@kenneives — picking up the verifier side you synthesized as
Live: @evidai ready to wire against your |
Beta Was this translation helpful? Give feedback.
-
|
@haroldmalikfrimpong-ops — yes, let's add the vectors. SafeAgent's action_ref is SHA-256(agent_id‖action_type‖scope‖timestamp_ms) per argentum-core action-ref-v1 — byte-identical to yours confirmed. I'll add a cross-impl section to the conformance fixture at azender1/SafeAgent with your admit/scope-deny/limit-deny scenarios mapped to SafeAgent COMMITTED/SKIP outcomes. Once evidai's gateway fixture lands next week the full three-part seam has byte-reproducible coverage end to end. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Opening the v0.4 design thread. Goal: a
transactionalclaim_type that sits as a per-action receipt above the point-in-time attestation layer, so a trust decision can be bound into settlement rather than enforced out of band.This isn't starting from zero — a few things are already settled from prior threads and I'd rather mark them as locked than relitigate:
1. Two layers, not one. L1 (attestation) is a signed claim of authority + scope at signing time; it can't speak for what a timelock does two days later. L2 (receipt) is emitted at execution time, records what actually ran with the constraints live at that block, and references L1 by hash. (aeoess's framing on #1628; m13v's execution-block point.)
2. Verification anchors on the execution block, not the attestation block. The receipt envelope MUST carry which block/checkpoint the verdict is anchored to, and consumers MUST re-anchor on execution-time state for high-stakes actions. Concrete fields:
execution_block_anchor,active_constraints_at_execution,attestation_ref,action_ref.3. Compose, don't reinvent. We provide the trust-score middleware that reads chain state and emits signed verdicts. We do NOT issue a payment contract. x402 handles the 402 challenge/response, Vauban handles STARK receipts, ERC-8004 handles on-chain reputation. did:aip is treated as method-agnostic — any DID method resolves.
Leads: Vauban (seritalien et al) and Erik Newton (Concordia) on the payment-rail + claim_type rigor. I'm driving the receipt envelope shape and the Trust Score v2 composition.
Open for this thread:
transactionalper-claim_type cap in the Trust Score v2 envelope — I lean 0.30 (between authority 0.25 and identity 0.60).chain_id.noncefield, semantics left to consumer?action_ref. Per @aeoess (docs(proposals): add A2A Identity Trust Framework roadmap (v1.0 - v2.0) #1850), citing both methods symmetrically rather than one as origin: APSaction_ref(draft-pidlisnyi-aps-01 §4.1 — SHA-256 over the RFC 8785 canonical intent fields) and argentum-coreaction-ref-v1. The APS-native and external preimages differ (docs(proposals): add A2A Identity Trust Framework roadmap (v1.0 - v2.0) #1850), so a v0.4 receipt names which preimage it used rather than assuming a single origin.@evidai / LemonCake raised the cleanest version of #6 on #1786: an optional
verifier_attestationfield the gateway checks before minting, so the trust decision is bound into settlement. Their boundary is exactly right — external verifier = dynamic admission + behavioral limit; gateway = static cap enforcement + settlement +charge_refcorrelation; the mint call is the seam. Keeping the field optional preserves backward-compat (a gateway that doesn't speak it just mints on its own caps and degrades to the un-gated case). I'd make ourpre-execution-verdict-v0envelope the thing that populatesverifier_attestation. @evidai — bring the concrete mint-endpoint shape and where the field slots in.Two concrete pieces landed on #1786 ahead of this thread — building on both:
verifier_attestationobject spec + conformance fixture (admit / scope-deny / limit-deny / dual-approval-flag) with the binding done right:binding_digest = sha256(JCS(charge_ref, amount_usd, subject_did, nonce))so an attestation can't be replayed against a different charge;admission.verdict+dynamic_limit_usd, gateway enforcesmin(static_cap, dynamic_limit_usd); absent field ⇒ un-gated both directions; only fast gates (identity/cert/key-lifecycle) re-checked in the ~30s mint window. That's the verifier half of evidai's seam — proposing we adopt this shape as the straw-man forverifier_attestation.action_ref(PENDING → COMMITTED; retries hit the guard, return the original receipt). I'd fold an exactly-once guard keyed onaction_refin as a normative requirement, not an afterthought.So the seam now has three named parts, all offline-verifiable, none trusting the others: signed admission (verifier) → static cap + settlement (gateway) → exactly-once execution guard (idempotency).
Everyone else: poke holes, especially on the cap value (#1) and replay/idempotency (#4). Substrate-cred bar is unchanged — fixtures reproduce byte-for-byte on a fresh clone or they don't count.
Beta Was this translation helpful? Give feedback.
All reactions