Skip to main content

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

  1. Take execution_parameters, canonicalize per RFC 8785, hash with SHA-256. Compare toexecution_payload_sha256.
  2. Take the UTF-8 bytes of the draft the approver read, hash them. Compare to human_draft_sha256.
  3. Recompute the bound digest from the two hashes andexpires_at_utc. Compare tobound_approval_digest_sha256.
  4. Check the decision is approved ormodified, and that expires_at_utc is 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.