Skip to content

[Change] §2.2, §3.1 — Freeze the buyer's selected[] into the committed artifact when a line item reaches agreed #160

Open

Description

@peterduhon

What kind of change?

Change a normative requirement (MUST / SHOULD / MAY)

Which section?

2.2 — Catalog references

Current text

§ 2.2: "When a proposal reaches status `agreed`, every `catalog_ref` MUST be replaced by its resolved value in the stored record, so the committed artifact is self-contained and immutable."

§ 3.1 as drafted in #22 carries no agreed-state rule for `selected[]`.

Proposed text

Add after the § 2.2 resolution sentence:

"When a line item reaches status `agreed`:

(a) Each `selectable` field's `selected[]` is part of the committed artifact and is frozen. 

(b) selected[] MUST satisfy the same § 2.2 self-containment guarantee as a resolved `catalog_ref` value. 

(c) The frozen record MUST remain immutable and MUST be sufficient to derive pricing[].agreed_rate (per #30) without a round trip. 

(d) Where an option in `available[]` is given as a `catalog_ref`, the `selected[]` entry MUST carry the version-pinned reference, and the frozen record preserves the version in effect when the selection was made. 

(e) Where `selected[]` is absent, the `included[]` default composition is the frozen composition and MUST be recorded as such."

Why

#22 gives the buyer's selection a key; #30 gives agreed_rate a derivation. Neither states what the committed artifact contains. The seller's half of composition self-contains at agreement — § 2.2 resolves every catalog_ref so the stored record depends on no live catalog. The buyer's half currently has no stated fate: nothing says selected[] survives into the stored record, is immutable once agreed, or pins the option version in effect.

Line items have a status independent of the proposal (§ 5.1); the rule therefore keys off line-item status, as § 5.6.1 already does for commitment — "Populated during composition. Frozen when status becomes agreed." This filing extends that precedent from the buyer's commercial commitment to the buyer's composition.

Without the freeze, four things break after agreement: a disputed invoice cannot be decomposed into base plus deltas from the record (#30 writes the formula; its inputs must be in the artifact); activation_route is operationally, not just commercially, significant — publisher_side, clean_room and id_partner are different executions, and a price does not encode the chosen route; addressable_scale and availability are recomputed against the selection (§ 3.3) but the selection they were computed against is not preserved; and a catalog that versions forward after agreement leaves the stored record's meaning dependent on live state — the exact hazard § 2.2's version pinning exists to prevent.

This also answers open question 4 of #91: how selected[] should name an option given only as a catalog_ref. Answer: by its version-pinned reference, with the version preserved in the frozen record.

#32 (VJAlkimi, Oct 8) — format validation at submission. Already consumes this concept, quoting "the line item's resolved formats selection (selected[] when present, otherwise included[])" verbatim. It validates against that resolution but never defines the field or freezes its value. This change does both.

#14 (fgranata, Sep 28) — geo becomes selectable. Accepted, with Sirajmx preparing a PR covering §5.6 and §3. The selectable surface keeps expanding — properties, audiences, now geo, and formats per #32 — and every expansion widens the composition gap this change closes.

The queue is converging on this concept; this is the change that defines it and its freeze semantics. That's a stronger position than being first — the concept already has consumers in the queue, and none of them define it or freeze it. Filing before the §3 PR solidifies puts the definition ahead of its consumers instead of chasing them.

Knock-on effects

Would this break an implementation already built to this draft?

No — additive or editorial

Alternatives you considered and rejected

  1. Leave the freeze to [Change] § 4.1 — Define record_digest and assent[]; defer signer identity to the AAMP profile #63's record_digest. A digest binds assent to content at signing; it does not state what the stored record contains, that selections are immutable after agreement, or how catalog-versioned options pin. The mechanisms compose; they are not substitutes.

  2. Rely on negotiation_history[]. An append-only event log of field names is a process record, not a state record; reconstructing the agreed composition by replay is the burden the object model exists to absorb.

  3. Infer the composition from agreed_rate. Distinct compositions can yield the same rate, zero-delta selections are price-invisible, and activation routing cannot be inferred from price at all.

You are commenting as

Individual, no organisational position

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.

Activity

  1. KonstantinMirin commented on Nov 12, 2026

    @KonstantinMirin

    Thanks, @peterduhon. Our PRs already cover (a), (b), (c), and (e), and (d) doesn't arise:

    On your first alternative: the freeze isn't left to the digest. In #140, agreed is terminal, and every selectable value of the line item MUST remain as in the version assent[] names (§ 4.1.2).

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

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

    change-requestProposes specific normative wordingnormativeChanges what the spec requires

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions