Agent-era builds · Stamp spec v0.1
The canonical stamp
An approval a machine can quietly rewrite is not an approval. A stamp is the receipt that ties one agent action to the exact draft a person read, the exact machine parameters that ran, and the exact moment the permission dies. Seven JSON blocks, canonicalized per RFC 8785, bound with SHA-256. No names, no personal data, nothing to interpret.
Spec v0.1.0 · Published 2026-11-04 · Status: current. Breaking changes ship as v0.2 at a new versioned URL; this page stays frozen.
Why it exists
The problem it was built for
A privacy officer tells an agent on a call: go ahead with the tracker change. Two weeks later the tag container ships with three feeds the draft never described. Nobody lied. The draft just was not bound to anything, so "I approved this" became a memory instead of a fact.
The stamp closes that gap. It records what was approved in a form a third party can re-verify months later: the draft the person saw, the parameters the machine ran, and the expiry that kills the permission. Agents draft; people sign. The stamp is the signature made checkable.
The specification
Seven blocks, in this order
Every stamp is one JSON object with exactly these seven blocks, in this order. A missing block is an error, not a shortcut: a verifier cannot check what is not there.
1. stamp_metadata: the envelope
schema_version is "0.1.0".stamp_id is a UUIDv7, so stamps sort by creation time without trusting anyone's clock. created_at_utc andexpires_at_utc are RFC 3339 timestamps, and the expiry is mandatory. An approval without an expiry is a permission that never dies, and stale approvals must not resurrect.
2. action_declaration: what the action is
consequential_action_row_id names one of the twelve consequential actions, CA-01 through CA-12, in the index's own language. summary says what will happen in one sentence.least_privilege_scope is read,draft, or act: the smallest permission the task needs, never more. target_system_identifier names the system being touched as a stable id, never a credential or an endpoint secret. data_categories_touched lists categories, such as purchase_event oremail_sha256, never values.
The rule with no exceptions: a stamp carries no raw personal information. If a field would need a name, an email address, or an ID number, it does not belong in the stamp.
3. cited_authority: which law governed the draft
corpus_version pins the movahedi.ca corpus the agent wrote against, for example v2026.12.0.statute_citations lists the provisions, for example Law 25 s. 8.1. enforcement_case_ids lists the primary cases, for example OPC-2023-001, the 2023 Home Depot matter where the OPC found offline purchase data flowing to Meta without proper consent. Pending legislation is labeled pending; this spec never presents a Bill C-36 provision as in force.
4. execution_binding: the machine's exact arguments
execution_parameters holds the parameters the agent will run with. The stamp canonicalizes them per RFC 8785, the JSON Canonicalization Scheme (keys sorted, no whitespace, UTF-8 bytes), and records execution_payload_sha256, the SHA-256 hex of those bytes. Any widening of the arguments after approval changes the hash. That is the point.
5. human_view_binding: the proof the person saw what ran
human_draft_sha256 is the SHA-256 of the UTF-8 bytes of the rendered draft the approver actually read.bound_approval_digest_sha256 is the dual bound: SHA-256 over the stringhuman_draft_sha256 + "|" + execution_payload_sha256 + "|" + expires_at_utc, ASCII pipes, no spaces. One digest ties the draft the person saw to the payload that ran to the moment the permission expires. Edit the draft after signing and the digest breaks. Swap the payload after signing and the digest breaks. This is the block a verifier checks first.
6. human_signoff: the person's word
approver_role names the role, for example the privacy officer designated under Law 25 s. 3.1. Roles, not names: a portable approval record is no place for a person's identity.decision is approved,rejected, or modified.signed_at_utc is the RFC 3339 moment of decision.attestation is one or two sentences in the approver's own words saying what they believe they approved. Amodified decision must describe the modification, or the stamp is invalid.
7. non_certification_disclaimer: the immutable literal
Byte-identical in every stamp, in every edition. It appears below exactly as it must appear in the JSON:
This stamp is an open evidence format for recording human approvals of agent actions. It is not legal advice, and it is not a movahedi.ca compliance certification.
The literal is part of the spec, not decoration. Nothing may be added to it, nothing removed. And to be explicit about what this page will never say: no stamp is ever described as certified, endorsed, or approved by movahedi.ca. The stamp records evidence. It confers no status.
Worked example
A fictional stamp, end to end
Café Lumen is a fictional Montreal retailer. Its agent drafts a change to activate a server-side purchase feed, consequential action CA-05. The privacy officer reads the draft, approves with a modification, and the stamp below is what gets filed. Every value is invented; the digests are illustrative, not computed.
{
"stamp_metadata": {
"schema_version": "0.1.0",
"stamp_id": "0193a7c2-4b1e-7f9d-8c3a-2e5f6a7b8c9d",
"created_at_utc": "2026-11-04T17:20:00Z",
"expires_at_utc": "2027-02-02T17:20:00Z"
},
"action_declaration": {
"consequential_action_row_id": "CA-05",
"summary": "Activate a server-side purchase-event feed for the fictional retailer Café Lumen.",
"least_privilege_scope": "draft",
"target_system_identifier": "tag-manager:GTM-FAKE000",
"data_categories_touched": ["purchase_event", "email_sha256"]
},
"cited_authority": {
"corpus_version": "v2026.12.0",
"statute_citations": ["Law 25 s. 8.1"],
"enforcement_case_ids": ["OPC-2023-001", "CAI-INTERFACES-TRUQUEES"]
},
"execution_binding": {
"execution_parameters": {
"container_id": "GTM-FAKE000",
"feed": "server-side purchase events",
"destinations": ["analytics warehouse (first party)"],
"dry_run": true
},
"execution_payload_sha256": "fictional-digest-9f2c41aa07bd3e88c1d5f6a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5"
},
"human_view_binding": {
"human_draft_sha256": "fictional-digest-1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f80",
"bound_approval_digest_sha256": "fictional-digest-77aa88bb99cc00dd11ee22ff33445566778899aabbccddeeff00112233445566"
},
"human_signoff": {
"approver_role": "privacy officer designated under Law 25 s. 3.1",
"decision": "modified",
"signed_at_utc": "2026-11-04T17:35:00Z",
"attestation": "Approved with the feed limited to purchase events for 90 days, then a fresh review. No ad-platform destinations without a new stamp."
},
"non_certification_disclaimer": "This stamp is an open evidence format for recording human approvals of agent actions. It is not legal advice, and it is not a movahedi.ca compliance certification."
}Read it the way a verifier does. The scope is draft, not act: the agent may prepare the change, but a human publishes the container. The data categories are hashed or event types, never raw values. The cited authority names the statute and the case that govern the draft. The attestation carries the modification in plain words: purchase events only, 90 days, then a fresh review, and no ad-platform destinations without a new stamp.
Verification
How to verify a stamp
- Take
execution_parameters, canonicalize per RFC 8785, hash with SHA-256. Compare toexecution_payload_sha256. - Take the UTF-8 bytes of the draft the approver read, hash them. Compare to
human_draft_sha256. - Recompute the bound digest from the two hashes and
expires_at_utc. Compare tobound_approval_digest_sha256. - Check the decision is
approvedormodified, and thatexpires_at_utcis still in the future.
Any mismatch, any missing block, any expired stamp: reject. There is no partial credit in a verification.
The honesty caveat
A stamp is only as honest as the code that computes it. If the tool that renders the draft shows the person one text and hashes another, the stamp lies beautifully. So the rule: never trust digests computed by the same agent that benefits from the approval. The stamp tool computes them locally, in the approver's browser, with nothing leaving the machine.
Versioning
v0.2 ships as a new page, never an edit
Breaking changes ship as spec v0.2 at a new versioned URL. This page stays frozen and verifiable forever; v0.1 stamps never need re-issuing. Additive clarifications may appear here as dated errata notes, marked as errata. What forces v0.2: a new required field, a changed digest formula, or a new decision value.
One question stays open for v0.2: should a modifieddecision carry a machine-readable diff of the change, or is the one-line attestation enough? The attestation won the argument for v0.1 on simplicity. It may not survive contact with real disputes.
A stamp does not make an agent trustworthy. It makes an approval checkable. Aim for the second; the first is not on offer.