From e46b9f56f2edcbc3508daaf6d19e370702686826 Mon Sep 17 00:00:00 2001 From: Speculator55005 <50082482+fas89@users.noreply.github.com> Date: Fri, 11 Sep 2026 22:07:14 +0200 Subject: [PATCH] docs: state a position on format assertion, and give the spec validation semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The conformance corpus surfaced the question and recorded it as open: is `format` assertive in FLUID? The specification did not say, so the corpus took the weaker of the two readings and put the assertive cases in `optional/`. That was the right call for a corpus, but leaving it open pushed the decision onto every implementer. FLUID now states the answer. `format` is an annotation: a validator MUST NOT reject a document solely because a string fails to match the format named for it, and MAY surface the mismatch as a warning. The consequence is stated plainly rather than left to be discovered — a document that validates is not thereby guaranteed to carry a well-formed `metadata.owner.email`. Two reasons beyond the Draft 2020-12 default, both specific to this project: Conformance must not depend on which validator you run. `format` vocabularies are optional in 2020-12 and implementations differ in which formats they recognise. Assertive `format` would make the same document conformant in one language and not in another, which defeats the purpose of publishing a corpus. The choice is not symmetric. Declaring `format` assertive would invalidate documents valid today — a narrowing, which GOVERNANCE.md forbids between versions and `scripts/check-compat.py` enforces on every pull request. Annotation-only is the only reading still available to a pre-1.0 spec that has published twelve schema versions. A future version may add assertive checking behind a new opt-in keyword; it may not retroactively sharpen this one. The section is also the first place the spec says how a document is validated at all, which was a gap `format` merely happened to expose. It calls out one trap explicitly: FLUID has its own FIELD named `format` — `exposes[].binding.format`, and the `format` keys in the acquisition blocks — constrained by `enum`, and `enum` IS assertive. The names collide and the sentence about annotations does not apply to them. Also corrected: the page claimed 0.7.5 was unpublished, naming 0.7.4 as latest. tests/README.md keeps the question rather than deleting it, now marked answered and pointing at the spec — a question the corpus raised and the specification then settled is the outcome that section exists to produce, and deleting the trail would hide that it was ever in doubt. The second question, the Draft 7 validator on 2020-12 schemas, stays open and now has a heading of its own instead of being swallowed by the first. No corpus data changed. Corpus 480/480 (478 without optional), meta-test 19/19, pairwise backward compatibility 0.7.1 through 0.7.5 all clean. Co-Authored-By: Claude Opus 5 --- conformance/run.py | 24 +++++++++++------- docs/schema/specification.md | 28 ++++++++++++++++++++- tests/README.md | 48 +++++++++++++++++++++++++----------- 3 files changed, 75 insertions(+), 25 deletions(-) diff --git a/conformance/run.py b/conformance/run.py index 8dca128..2fd7cdf 100644 --- a/conformance/run.py +++ b/conformance/run.py @@ -163,15 +163,21 @@ def _build_validators(schema: Dict[str, Any]) -> Dict[bool, Any]: In JSON Schema 2020-12 `format` is an ANNOTATION by default, not an assertion: a conformant validator may accept "not-an-email" for - {"format": "email"}. FLUID has never said which it wants, and its own - reference implementation does not assert formats. - - So the core corpus is checked WITHOUT format assertion -- the weaker, - universally-agreed reading -- and cases that depend on formats being - assertive live in tests/optional/, exactly where JSON-Schema-Test-Suite - puts its own format tests. That way the core corpus stays runnable by any - conformant validator, and format behaviour is asserted where an - implementation opts into it, rather than being silently assumed. + {"format": "email"}. FLUID now says the same -- a validator MUST NOT reject + a document solely because a string fails the format named for it -- under + "Validation semantics" in the specification. Its reference implementation + does not assert formats either. + + So the core corpus is checked WITHOUT format assertion, which is both the + specified reading and the universally-agreed one, and cases that depend on + formats being assertive live in tests/optional/, exactly where + JSON-Schema-Test-Suite puts its own format tests. That keeps the core + corpus runnable by any conformant validator while still serving the + implementations that opt into asserting formats. + + This split predates the specification stating a position and is unchanged + by it: what changed is that the core tier's behaviour is now required + rather than merely the safer of two available readings. """ try: from jsonschema import Draft202012Validator, FormatChecker diff --git a/docs/schema/specification.md b/docs/schema/specification.md index 3568385..85d62c4 100644 --- a/docs/schema/specification.md +++ b/docs/schema/specification.md @@ -1,7 +1,7 @@ # Fluid Protocol Specification ::: tip Latest schema version -The latest published JSON Schema is **0.7.4**. This page is the narrative protocol specification; for the version-specific, field-by-field reference see the [**Cheatsheet**](/fluid/schema/cheatsheet), the [**Anatomy**](/fluid/schema/anatomy), and the [**Versions**](/fluid/schema/versions) index (raw JSON Schema + generated HTML per version). +The latest published JSON Schema is **0.7.5**. This page is the narrative protocol specification; for the version-specific, field-by-field reference see the [**Cheatsheet**](/fluid/schema/cheatsheet), the [**Anatomy**](/fluid/schema/anatomy), and the [**Versions**](/fluid/schema/versions) index (raw JSON Schema + generated HTML per version). ::: This document provides the complete, official specification for the FLUID (Federated Layered Unified Interchange Definition) protocol. It is intended for data architects, platform engineers, and developers who are building the next generation of data infrastructure, as well as for vendors seeking to make their tools compliant with this open standard. @@ -84,6 +84,32 @@ This document provides the complete, official specification for the FLUID (Feder --- +## Validation semantics + +A FLUID document is validated against the published JSON Schema whose version matches its `fluidVersion`. Every published schema declares `"$schema": "https://json-schema.org/draft/2020-12/schema"`, so JSON Schema Draft 2020-12 defines the meaning of every keyword except where this section says otherwise. + +### `format` is an annotation, never an assertion + +A validator **MUST NOT** reject a FLUID document solely because a string does not match the `format` named for it. A validator **MAY** surface the mismatch as a warning, and a governance or linting layer built on FLUID **MAY** treat it as an error of its own; neither affects whether the document is a valid FLUID document. + +The consequence is worth stating plainly rather than leaving for a reader to discover: **a document that validates is not thereby guaranteed to carry a well-formed `metadata.owner.email`.** Three formats appear across the published schemas — `uri`, `date-time` and `email` — and all three are descriptive. + +This is the Draft 2020-12 default, and FLUID keeps it for two reasons of its own. + +The first is that conformance must not depend on which validator you run. `format` vocabularies are optional in Draft 2020-12 and implementations differ widely in which formats they recognise and what they pull in to check them. Were FLUID to make `format` assertive, the same document could be conformant in one language and non-conformant in another, which would defeat the purpose of publishing a conformance corpus at all. + +The second is that the choice is not symmetric. Declaring `format` assertive would invalidate documents that are valid today — a narrowing, which [GOVERNANCE.md](https://github.com/open-data-protocol/fluid/blob/main/GOVERNANCE.md) forbids between versions and `scripts/check-compat.py` enforces on every pull request. Annotation-only is therefore the only reading available to a pre-1.0 specification that has already published twelve schema versions. A future version may add assertive checking behind a new, opt-in keyword; it may not retroactively sharpen this one. + +Implementations that do want to assert formats are served by the conformance corpus rather than left to guess: the cases that depend on assertion live in [`tests/optional/`](https://github.com/open-data-protocol/fluid/tree/main/tests/optional), separated from the core tier for exactly this reason, and `conformance/run.py` runs them under a format-asserting validator. + +### FLUID's own `format` field is unrelated + +FLUID defines a **field** named `format` in several places — `exposes[].binding.format` (`bigquery_table`, `snowflake_table`, `gcs_file`, …) and the `format` keys in the acquisition blocks. These are ordinary FLUID fields constrained by `enum`, and `enum` **is** assertive: a `binding.format` outside the enumerated set makes the document invalid. + +The collision of names is unfortunate and is called out here because it is easy to read "`format` is an annotation" as applying to them. It does not. The sentence above is about the JSON Schema *keyword*; this paragraph is about a FLUID *field* that happens to share its spelling. + +--- + ## 1. Specification Root The FLUID definition is a YAML or JSON file (`.fluid.yml` OR `.fluid.json`) with the following root-level objects. diff --git a/tests/README.md b/tests/README.md index 9ad9861..380ec61 100644 --- a/tests/README.md +++ b/tests/README.md @@ -30,7 +30,7 @@ The core/optional split follows [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite). The core tier asserts only what every conformant JSON Schema 2020-12 validator must do. The optional tier asserts behaviour the specification permits but does -not require — today, `format` assertion (see "Known ambiguities" below). +not require — today, `format` assertion (see "Format assertion" below). ## File format @@ -124,22 +124,40 @@ The file is how a strict gate stays adoptable on the day it lands: a real shortcoming is recorded in the repository instead of being hidden by weakening the corpus. -## Known ambiguities the corpus has surfaced +## Questions the corpus has surfaced Recorded here because a conformance suite's job is to turn disagreements into -written questions rather than silent divergence. - -**Is `format` assertive in FLUID?** The specification does not say. In JSON -Schema 2020-12, `format` is an annotation by default — a conformant validator -may accept `"not-an-email"` for `{"format": "email"}`. The reference -implementation does not assert formats. Until FLUID states a position, the core -tier does not assert them either, and the cases that depend on assertion live -in `optional/`. A FLUID document is therefore **not** guaranteed to have a -well-formed `metadata.owner.email` merely because it validates. - -**The reference implementation validates a 2020-12 schema with a Draft 7 -validator.** `fluid_build/schema_manager.py` constructs a -`jsonschema.Draft7Validator` while every published schema declares +written questions rather than silent divergence. One is now answered by the +specification; the other is still open. + +### Format assertion + +*Is `format` assertive in FLUID?* + +**Answered — it is not.** The specification now states that `format` is an +annotation, and that a validator MUST NOT reject a document solely because a +string fails to match the format named for it, under [Validation +semantics](https://open-data-protocol.github.io/fluid/schema/specification#validation-semantics). + +This corpus had already assumed that reading, because it is the Draft 2020-12 +default and the weaker of the two; the difference is that the core tier now +runs without format assertion because the specification says so, rather than +because the question was open. The cases that depend on assertion stay in +`optional/` for implementations that opt in. A FLUID document is still **not** +guaranteed to have a well-formed `metadata.owner.email` merely because it +validates — that is now a stated property rather than an accident. + +Recorded here rather than deleted: a question this corpus surfaced and the +specification then settled is the outcome the section exists to produce, and +removing the trail would hide that the answer was ever in doubt. + +### Draft 7 validator on a 2020-12 schema + +*Does the reference implementation validate 2020-12 schemas correctly?* + +**Still open.** It validates a 2020-12 schema with a Draft 7 validator: +`fluid_build/schema_manager.py` constructs a `jsonschema.Draft7Validator` +while every published schema declares `"$schema": "https://json-schema.org/draft/2020-12/schema"`. Today this is latent rather than active: the schemas use only `$defs` from the 2020-12-only keyword set, and `#/$defs/...` references resolve under Draft 7 as ordinary