Skip to content

[Impl] A schema can't be derived from the tables yet: seven authoring rules and a CI lint would fix that #121

Open

Description

@KonstantinMirin

What did you build?

A validator or schema

What you tried to express, and what happened

Postindustria (IAB Tech Lab member) generated its own schemas from the specification, with a deterministic parser and no model calls. Outputs: JSON Schema 2020-12, rules with test vectors, and TypeScript, Python, and Go types. Inputs: main at 44dfaaf, alone and with the 14 PRs open on 2026-10-26. The run shows what the schema README asks implementers to report:

  • Decisions: 44. In 39, the text leaves a point open, and 37 of these ask the specification to state something. The other 5 are changes we proposed.
  • Example failures: 55 places on main and 85 with the open PRs. Most follow the text but not a change we proposed. On main, 5 disagree with the text, and 10 with the open PRs.
  • Lint findings, by kind. No authoring rule removes a MUST statement that names no field or key: it binds a party, or needs conformance test vectors.
Finding main With the open PRs
1. Presence 4 5
2. Objects 7 7
3. Options 6 5
4. Value lists 5 9
5. Markers 1 1
6. Paths 4 6
7. Names that resolve to no row or key 6 13
MUST statements naming no field or key 13 26
Other 0 1

Every item: What generating the schemas had to decide.

What you did instead

We recorded each decision, since two implementers could decide them differently. Our shared types PR closes this issue. It adds the shared types to § 2.2. Its § 2.6 and § 3 state an authoring rule for each of rows 1 to 6, with the option forms from our buyer writes PR. Our PRs give each name in row 7 a row or a term. The gist gives each rule, with examples.

In validate.yml, scripts/check_appendix.py lints the § 2.6 table grammar, and a new scripts/check_examples.py checks every example against the tables.

Our PRs settle 34 of the 37 asks, four differently from what we asked. They adopt 4 of our 5 changes, one in part, and we withdraw UUIDs for minted IDs.

Open questions for the working group, as suggestions:

  1. Answered in our pricing PR. Should money be { amount, currency }, so that an amount never appears without its currency? No. An Amount carries no currency. A rate reads in its own pricing[] entry's REQUIRED currency. The commitment, and every other Amount on the line item, reads in the committed entry's currency, and OpenProposal never converts.
  2. Answered in our shared types PR and #123. Should each zoned value carry its IANA zone, as { instant, time_zone } or an RFC 9557 string, beyond the line item time_zone that § 5.5 — Daypart clock: a line-item time zone and the window shape (#111) #123 adds? No. An Instant is UTC and ends in Z, so one instant has one written form. Only repeating civil time needs a zone. The line item time_zone, a ZoneName, is the clock for daypart and a calendar frequency_cap.period.

Fields involved

Every field and key table, and prose, mostly in § 2 and § 3.

How blocking was it?

Workaround required, but it works

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 — no real rate cards, deal terms, client names or inventory data.

Revised 2026-11-03: Our shared types and buyer writes PRs carry the authoring rules, and our shared types PR adds the lint. Both open questions are answered, and we withdraw UUIDs for minted IDs.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions