Skip to content

docs(sec-8-11): add action_ref content address, receipt field spec, EU AI Act Article 12 mapping#2217

Open
arian-gogani wants to merge 2 commits into
OWASP:masterfrom
arian-gogani:master
Open

docs(sec-8-11): add action_ref content address, receipt field spec, EU AI Act Article 12 mapping#2217
arian-gogani wants to merge 2 commits into
OWASP:masterfrom
arian-gogani:master

Conversation

@arian-gogani

Copy link
Copy Markdown

Summary

Refinements to Sections 8-11 of the AML and Sanctions Compliance for AI Agent Payments cheat sheet, following up on the co-author offer from @razashariff after PR #2210 merged.

Three additive improvements:

Section 8 — Receipt Canonicalization
Added the action_ref content address pattern: action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms})). This 64-character hex string is a stable, recomputable content address for any agent action, enabling cross-system receipt correlation without replaying the full event log. Complements the existing JCS signing guidance.

Section 10 — Sanctions-List Freshness
Added a concrete JSON receipt structure showing how to bind sanctions screening freshness to the action_ref content address from Section 8. This lets an auditor link a screening result to the specific transaction without relying on log position.

Section 11 — Regulatory Mapping
Added EU AI Act Article 12 as an explicit row in the regulatory mapping table. Article 12 (automatic tamper-evident logging for high-risk AI systems) maps directly to the signed receipt controls in Sections 4 and 8-10. Enforcement begins August 2, 2026. Also added ISO/IEC 42001 Annex A (AI management system records).

All changes are additive. No existing text modified or removed.

@razashariff

Copy link
Copy Markdown
Contributor

Arian —Thanks

One point of framing: this is a contribution to the sheet rather than co-authorship — the document has a single author of record and I'd like to keep it that way. The git history will show your commit and that's the right attribution for what it is. OK for you to be credited though.

@mackowski happy for you to merge if the content passes review.

@mackowski mackowski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! The action_ref pattern and EU AI Act mapping are interesting additions, but before we can merge this we'd need a disclaimer making clear these are proposed patterns rather than established standards — there's no RFC, NIST document, or published audit framework that specifies this construct yet.

@razashariff

Copy link
Copy Markdown
Contributor

Thanks @mackowski. To be clear from my side: the action_ref content-address, the receipt field spec, and the EU AI Act Article 12 mapping here aren't something I authored or verified, and they weren't part of the section I originally contributed. I can't vouch for them as a tested or standardised construct, and as you note, there's no RFC, NIST publication, or published audit framework behind them yet. So please don't read my earlier contribution as backing this one. Happy for you to drop it if it doesn't meet the bar.

- Canonicalize every receipt with RFC 8785 (JCS) before signing, and again before verifying.
- Sign over the hash of the canonical bytes, not raw or pretty-printed JSON.
- Record the canonicalization, hash, and signature algorithm in the receipt (for example `canon: jcs`, `alg: ecdsa-p256-sha256`) so any verifier can reproduce it.
- Derive a stable **content address** (`action_ref`) for each action: `action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))`. This 64-character hex string uniquely and recomputably identifies the action across systems, enabling cross-system receipt correlation without replaying the full event log.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know what we are talking about here in this section (and more generally in the whole cheat sheet?).

Is the process described here an actual implementation requirements or is it more a suggested implementation for some existing functional requirements (from regulation texts)? In other words, could I instead of all that use a JWT and never have to care about JCS at all?

@randomstuff randomstuff Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually based on https://datatracker.ietf.org/doc/draft-marques-asqav-compliance-receipts/05/ ? Is this explained somewhere?

@arian-gogani

Copy link
Copy Markdown
Author

@randomstuff good questions.

on whether this is implementation requirement vs suggested implementation: the cheat sheet is guidance, not a mandate. JCS + Ed25519 is one way to satisfy the underlying requirement (tamper-evident, independently verifiable receipts). you could use a JWT with a deterministic serialization and get the same property. the reason JCS is called out specifically is that JSON serialization is non-deterministic by default (key ordering, whitespace, number formatting), so two parties hashing the same logical object can get different digests. JCS (RFC 8785) closes that gap. if you use JWT with a fixed header and deterministic payload serialization, the verifiability property holds the same way.

on whether this is based on draft-marques-asqav-compliance-receipts: no, this was developed independently. the action_ref content-address pattern (SHA-256 over JCS-canonical fields) predates my awareness of that draft. the convergence is interesting though, it suggests the primitive shape is natural for this problem. the four-field preimage (agent_id, action_type, scope, timestamp_ms) is the minimum set that uniquely identifies an agent action without carrying the full event payload. happy to add a reference to the IETF draft if the reviewers think it adds context.

@razashariff

Copy link
Copy Markdown
Contributor

so the functional requirement here is regulatory: agent payment and sanctions decisions have to produce tamper-evident, attributable, independently verifiable records (AML record-keeping, EU AI Act Art. 12). JCS is one suggested implementation of that, not a mandate.

If a single issuer signs a receipt and one party verifies that exact token, a JWS/JWT is enough and you never touch JCS. Canonicalization only earns its place when different systems must independently re-serialize and re-verify the same record, or derive a stable cross-system content address. So unless cross-system correlation is in scope, the
signed token is fine and you can skip it. Thx

- Canonicalize every receipt with RFC 8785 (JCS) before signing, and again before verifying.
- Sign over the hash of the canonical bytes, not raw or pretty-printed JSON.
- Record the canonicalization, hash, and signature algorithm in the receipt (for example `canon: jcs`, `alg: ecdsa-p256-sha256`) so any verifier can reproduce it.
- Derive a stable **content address** (`action_ref`) for each action: `action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))`. This 64-character hex string uniquely and recomputably identifies the action across systems, enabling cross-system receipt correlation without replaying the full event log.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, maybe action_ref = HEX(SHA-256(JCS({agent_id, action_type, scope, timestamp_ms})))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Also why not base64url?)

- Canonicalize every receipt with RFC 8785 (JCS) before signing, and again before verifying.
- Sign over the hash of the canonical bytes, not raw or pretty-printed JSON.
- Record the canonicalization, hash, and signature algorithm in the receipt (for example `canon: jcs`, `alg: ecdsa-p256-sha256`) so any verifier can reproduce it.
- Derive a stable **content address** (`action_ref`) for each action: `action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))`. This 64-character hex string uniquely and recomputably identifies the action across systems, enabling cross-system receipt correlation without replaying the full event log.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to say:

Derive a stable content address (action_ref) for each action: eg. action_ref = SHA-256(JCS({agent_id, action_type, scope, timestamp_ms}))?

@randomstuff

Copy link
Copy Markdown
Collaborator

(I don't know anything about the topic which makes reviewing quite difficult without quite a bit work.)

@jmanico

jmanico commented Jun 29, 2026

Copy link
Copy Markdown
Member

(I don't know anything about the topic which makes reviewing quite difficult without quite a bit work.)

Just cc me or @mackowski into anything you want our attention on and move on to anything else that interests you. :)

@arian-gogani

Copy link
Copy Markdown
Author

Thanks for the review, @mackowski. An update that changes the context:

Since this PR was opened, the action_ref construct was merged as normative implementation guidance in the OWASP Agentic Skills Top 10 (AST09, PRs #35 and #38, merged by project lead @kenhuangus on June 25). The formula is no longer a proposed pattern. It is referenced OWASP guidance with EU AI Act Article 12 relevance noted in the standard itself.

That said, I am happy to add a note clarifying that the construct originates from AST09 and linking to the canonical source, rather than presenting it as independently derived in this document. That would address the provenance concern without understating the status.

On the review comments from @randomstuff:

  • HEX encoding: agreed, the formula should specify the output encoding. HEX is the convention in the AST09 text and the reference implementation.
  • "content address" framing: yes, that is clearer. Happy to adopt that phrasing.
  • base64url: HEX was chosen for human readability in logs and debuggability. No strong objection to base64url as an alternative, but the AST09 reference uses hex, so consistency argues for keeping it.

Shall I push the updates (disclaimer referencing AST09 as source, HEX explicit, "content address" phrasing)?

Addresses review feedback from mackowski and randomstuff:
- HEX() wrapper explicit in action_ref formula
- Provenance note linking to OWASP AST09 (normative guidance, merged)
- Article 12 enforcement date corrected to December 2, 2027 (Digital Omnibus)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants