docs: state a position on format assertion, and give the spec validation semantics - #47
Merged
Conversation
…ion semantics 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 <noreply@anthropic.com>
fas89
added a commit
to fas89/fluid
that referenced
this pull request
Sep 13, 2026
…g paths A path-filtered check cannot be a REQUIRED check. On a pull request that does not match the filter the context never reports at all, so branch protection waits for a report that will never arrive and the pull request hangs permanently, with nothing to click. That is why main still requires no status checks: turning the existing three on as they were would have bricked the next docs PR rather than protected anything. Not hypothetical here. PR open-data-protocol#47 was a docs change and received these three checks only because it happened to also touch conformance/run.py. PR open-data-protocol#48 — LICENSE and CONTRIBUTING.md — reported no checks at all and merged with nothing having run. The push trigger keeps its filter: nothing waits on a push, so skipping the corpus for a README typo on main costs nothing and saves a runner. On pull requests the corpus is about forty seconds, which is cheaper than one person wondering why their pull request will not merge. Two properties this file already had, now load-bearing and worth stating: It declares no `schedule:`. The two workflows GitHub auto-disabled for inactivity — link-check and schema-sync — are exactly the two that carry one, and this repository went 73 days between commits, past the 60-day threshold. A required context living in a scheduled workflow would be switched off by a quiet spell and hang every pull request thereafter. `corpus` and `backward compatibility` both declare `needs: meta`. A job skipped because its `needs` failed still reports a check run, and branch protection counts skipped as satisfied. So the three must be required TOGETHER: requiring only the latter two would let a pull request merge while `gates can fail` is red, and that job's entire purpose is proving the other two can go red. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The conformance corpus surfaced this and recorded it as open: is
formatassertive in FLUID? The specification did not say, so the corpus took the weaker reading and put the assertive cases inoptional/. Right call for a corpus — but it pushed the decision onto every implementer.The position
formatis an annotation, never an assertion. A validator MUST NOT reject a FLUID document solely because a string fails to match the format named for it; it MAY surface the mismatch as a warning.Stated plainly rather than left to be discovered: a document that validates is not thereby guaranteed to carry a well-formed
metadata.owner.email. Exactly three format keywords appear across all twelve published schemas —uri(54),email(17),date-time(10) — and all three are descriptive.Why, beyond the 2020-12 default
Conformance must not depend on which validator you run.
formatvocabularies are optional in Draft 2020-12 and implementations differ in which formats they recognise and what they pull in to check them. Assertiveformatwould make the same document conformant in one language and non-conformant in another — which defeats the purpose of publishing a corpus at all.The choice is not symmetric. Declaring
formatassertive would invalidate documents that are valid today. That is a narrowing, whichGOVERNANCE.mdforbids between versions ("minor versions may add. They may not narrow") andscripts/check-compat.pyenforces on every PR. Annotation-only is the only reading still available to a pre-1.0 spec 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.A gap this exposed
The spec had no validation-semantics section at all — it never said how a document is validated, which schema applies, or which draft governs keyword meaning.
formatmerely happened to expose that. The new section covers all of it.It also calls out a trap: FLUID has its own field named
format—exposes[].binding.format(bigquery_table,snowflake_table, …) and theformatkeys in the acquisition blocks. Those are constrained byenum, andenumis assertive. The names collide and the annotation rule does not apply to them.Also corrected
The page claimed 0.7.4 was the latest published schema. It is 0.7.5.
tests/README.md
The question is kept, not deleted — 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; deleting the trail would hide that it was ever in doubt. The section is renamed from "Known ambiguities" to "Questions the corpus has surfaced", since one is now settled.
The second question — the reference implementation validating 2020-12 schemas with a
Draft7Validator— stays open, and now has a heading of its own instead of being silently swallowed by the first.Verification
No corpus data changed; the diff is two docs and one docstring.
conformance/run.pyconformance/run.py --no-optionaltests/meta_test.py(as CI runs it)check-compat.pypairwise 0.7.1→0.7.5specs/regeneration driftschema/change)🤖 Generated with Claude Code