Skip to content

[Change] § 4.1 — Define record_digest and assent[]; defer signer identity to the AAMP profile #63

Description

@KonstantinMirin

What kind of change?

Change a field's type or shape

Which section?

4 — Proposal

Current text

| `assent` | Object | derived | Buyer and seller assent records and timestamps for the binding version. Signature scheme is WS1 |

Proposed text

| `assent[]` | Array[AssentEntry] | OPTIONAL | recorded | The parties' acts (§ 4.1.2). Entries MUST NOT be edited or removed |

§ 4.1.1 Binding record and record_digest

The binding record for line items S is the composed record restricted
to S, with these RFC 9535 JSONPaths removed:

$.version, $.status, $.assent, $.negotiation_history,
$.change_requests, $.best_for, $.not_suitable_for, $.seasonality_notes,
$.line_items[*].status, $.line_items[*].availability,
$.line_items[*].addressable_scale, $.line_items[*].assets,
$.line_items[*].hold, $.line_items[*].external_references,
$.line_items[*].commitment.derived_units,
$.line_items[*].pricing[*].min_rate,
$.line_items[*].buyer_supplied.expected_match_rate,
$.line_items[*].buyer_supplied.segments,
$.line_items[*].buyer_supplied.suppression_list

No other path is removed, except that a `buyer_supplied` holding no key
after these removals is removed too.

The composed record is the Full Representation (§ 2.1) of `version` as
the seller published it to this buyer, with the buyer's writes (§ 3.4)
applied. Nothing is filled in, except that `pricing[].agreed_rate` on
the committed entry is set to the § 5.6 result before serializing.

`record_digest` is the `Digest` (§ 2.2) of the binding record's RFC 8785
serialization. It sits only on `assent[]` entries. A receiving party
MUST recompute it before relying on a live `commitment` entry, over the
line items as they stand plus its `commit`'s writes. It recomputes a
matching pair from its agreed record (§ 4.1.2), not from the current
document. The agreed record is the pair's digest input and its two
entries, and each party keeps it.

§ 4.1.2 Assent

`AssentEntry`: `role` (`commitment` | `acceptance` | `withdrawal` |
`decline`), `version`, `record_digest`, `line_item_ids[]`, `at`,
`idempotency_key` on a `commitment`, and a REQUIRED `ground` on a
`decline`.

- Two entries match when their `version`, `record_digest`, and
  `line_item_ids[]` (as sets) are equal.
- The buyer writes `commitment` and `withdrawal`; the seller writes
  `acceptance` and `decline`. An `acceptance` MUST match a live
  `commitment` entry.
- A `commitment` entry is live until a matching `withdrawal` or
  `decline`, its `commit` going stale or void, or `offer_window.end`.
  Nothing ends a matched entry.
- A line item is `agreed` when, and only when, its `commitment` entry
  has a matching `acceptance`. Its `status` does not decide it.
- An entry travels in a message signed under the Web Bot Auth profile
  (§ 2.8), with `Content-Digest` covering the body. The signature
  attributes the entry to the party its `role` implies when the signing
  origin's host is that party's `domain` or a subdomain of it. Each
  party configures which origins it accepts. The signature is OPTIONAL
  evidence; `agreed` does not depend on it.

Our PR on what is signed carries this text. Rules we left out on purpose are in our rules issue.

Why

The draft never says which bytes buyer and seller agree to in assent (§ 4.1), so neither party can prove the agreed terms (#36, #45).

This answers #47 item 3: three questions stay separate. The binding record and assent[] say which bytes were agreed. The Web Bot Auth profile our PR adds (§ 2.8) says which origin sent a message, until the AAMP profile we asked for replaces it. Authorization says who may bind a party, as our reply to @aeoess proposes, and our answers on #57 bind its evidence to record_digest.

Leaving hold out of the record follows @EvgenyAndroid and @premesh, and our holds PR adds that path.

Knock-on effects

  • § 5.8: a commitment entry accepts every terms_refs[] document at the bytes its digest pins (#27).

Would this break an implementation already built to this draft?

Yes — breaking

You are commenting as

Other — IAB Tech Lab member (Postindustria).

Before you submit

  • I have read CONTRIBUTING.md and agree my contribution may be published under this repository's licence.
  • This contains no confidential or commercially sensitive information.

Details and examples: Binding record: full rationale and examples

Revised 2026-11-05: A decline states its ground. Rewritten to match our signing PR: record_digest sits only on entries, role adds withdrawal and decline, and party, signer, and signature are gone. A signed message is optional evidence.

Analyzed and generated with the help of Claude, fully reviewed by me.

Activity

  1. added
    change-requestProposes specific normative wording
    normativeChanges what the spec requires
    breakingWould break an implementation already built to this draft
    on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingWould break an implementation already built to this draftchange-requestProposes specific normative wordingnormativeChanges what the spec requiressection:4-proposal

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions