Consent Docs

How notice campaigns are proven

What a notice campaign commits to in signed roots, what is only reported by your sender, and how one person's evidence is checked.

Concept3 min readFor architects, security reviewers and auditors

A notice campaign commits to who was issued which notice and who answered, in Merkle roots and a signed root for each day. Delivery is what your sender reports, and it is kept apart from every root.

What is committed and what is reported#

Fact How it is kept
Which person was issued a link, on what basis, until when A leaf in the batch's Merkle root
Which notice version a batch carried, and the mode A leaf in the day's campaign root, holding the batch root
Who acknowledged or withdrew, when and in which language A leaf in the day's campaign root
Whether a message was delivered Stored as your sender reported it. In no root.

Each UTC day with answers or issued batches gets one statement, piedap-campaign-anchor/1.0, signed with the deployment's Ed25519 key after 00:30 UTC the next day. Each statement names the hash of the project's previous one, so the days form a chain. Your webhook receives it as campaign.anchored. Keep it: once you hold a day's root, nobody can change that day's answers without the proofs failing against your copy.

The leaves#

Each leaf is text, hashed as in RFC 6962, the same construction as the daily anchors:

notice-link:<link id>:<campaign id>:<batch id>:<recipient id>
  :<subject hash>:<basis>:<expires on>

notice-batch:<batch id>:<campaign id>:<form version id>
  :<notice content hash>:<mode>:<link count>:<batch root>:<issued on>

notice-response:<recipient id>:<link id>:<campaign id>
  :<subject hash>:<notice content hash>:<answer>:<answered on>:<language>

Each leaf is one line; it is wrapped here to fit. Times are ISO 8601 in UTC.

  • The link leaf binds the person's hashed identifier, the basis you stated and the link's expiry to a batch.
  • The batch leaf binds the batch root to the exact notice wording, by its content hash, and to the mode.
  • The answer leaf binds the answer, its time and its language to the person, the link and the wording.

Fields that may change later are in no leaf: delivery reports, your reference, the fingerprint, the address hash and browser of the answer, and the records a withdrawal reached. Erasing a person or uploading a delivery report therefore never breaks a root.

Checking one person's evidence#

Export evidence (JSON) on a person in the campaign gives one file, piedap-campaign-evidence/1.0, signed with the same key. It holds:

  • the campaign and the notice version, with its content hash;
  • the person's hashed identifier, basis and language, and the upload they came from;
  • each link, with an inclusion proof into its batch root, and a proof of the batch into the day's signed statement;
  • the answer, with a proof into its day's statement once that day is anchored.

To check it, recompute each leaf from the fields, then the root from the proof's audit path. Compare the root with the batch root and with the statement you stored from campaign.anchored. Then check the statement's signature against GET /sdk/v1/keys. Delivery appears in the file marked as reported by the sender and not sealed.

What the proof does not show#

  • Who held the link. A link is a bearer link. The proof shows that the link's holder answered, not who that was.
  • That a message arrived. Delivery is what your sender reported.
  • That the person read the notice. I have read this notice records a click.
  • Registration with telecom operators. An answer on a notice page is not consent registered under telecom rules for commercial messages.
  • The wording's legal effect. The page text and the basis you choose are for your counsel.

An acknowledgement is stored on the campaign only. It reads, writes and seals no consent record. A withdrawal goes through the usual path: each record is sealed WITHDRAWN in its own chain and sends consent.withdrawn. The campaign is named only in the unsealed reason of that event. Receipts and the daily anchors of consent records work as before.

↑↓ to move, Enter to open