Skip to content

feat(validate): report the schema revision a validation actually used - #60

Merged
rldyourmnd merged 2 commits into
mainfrom
feat/report-the-schema-a-validation-used
Aug 31, 2026
Merged

feat(validate): report the schema revision a validation actually used#60
rldyourmnd merged 2 commits into
mainfrom
feat/report-the-schema-a-validation-used

Conversation

@rldyourmnd

Copy link
Copy Markdown
Contributor

gds validate repository --json named its target and its findings but never the schemas it judged them against. Nothing else in the CLI did either — there was no schema digest anywhere in the tree.

A version string cannot fill that gap, and here is the proof

Consumers reached for the binary's version. Measured on this machine:

installed binary      gds version 0.8.0
source constant       var Version = "0.7.0"
newest release tag    gds-v0.6.0

No tag exists for 0.7.0 or 0.8.0. But the sharper problem is not the numbering — it is that two live checkouts of this project carry different schemas, and no version string distinguishes them.

schemas/v1/repository.schema.json here and in the archived NDDev-it-com/github-device-sync are not the same document. The archived one lists workflow_ref and repository_id as required; this one marks both optional and carries an extra generated-from enum value. Same file name, same project, different contract — and the two produce different digests, sha256:e27e6877… here against sha256:2526481e… there.

I established which set the installed binary actually carries by asking the artifact rather than the source: it holds 51 $ids pointing at NDDev-OpenNetwork/github-device-sync/schemas and none at the archived path. So a consumer printing gds --version beside a green result is printing a name with no contract behind it, while the thing that decided the result is invisible.

This came from setup-systems, whose check_render.sh prints gds --version beside its validation result, with a comment explaining that a green result which does not name its validator is worth less than one that does. The reasoning is right; the value available to them was not. I answered their schema question from the archived tree before noticing the split, which is the same mistake from the other side.

What this adds

Set.Digest() hashes every embedded schema file — path and content, NUL-separated, in the sorted order fs.ReadDir returns — and validate repository carries it as data.schema_digest:

{
  "anchor": "/…/.gds/repository.yaml",
  "target": "/…",
  "schema_digest": "sha256:e27e6877aa05171e7849a5ed9d7f9ff5f16852be8adf769a4c18d6b1483fd90b"
}

Being derived from content, it cannot name a revision that was never compiled, and it separates the two schema sets above without anyone having to know they exist.

Verified in both directions

It moves when the schemas move. Adding a property to repository.schema.json and rebuilding changed the digest.

The test can fail. TestSchemaDigestCoversEverySchemaFile recomputes the digest independently over the embedded set. Mutating the implementation to hash paths but not file content makes it fail — Digest() = "sha256:9e4dbfe4…", want "sha256:2526481e…" over 50 schema files — and the real implementation passes. A digest that skipped a file would stay identical while that file changed, which is the failure it exists to prevent, so the assertion had to be shown capable of catching it.

TestSchemaDigestIdentifiesTheEmbeddedSet covers format and determinism: two sets compiled from the same embedded schemas must agree, or the digest identifies the run rather than the schemas and is worse than printing nothing.

Scope

data in operation-result.schema.json is an open object with maxProperties: 128, so no schema change is needed. go build ./..., go vet, and the core/validation and core/app suites are clean.

`gds validate repository --json` named its target and its findings but not
the schemas it judged them against, and nothing else in the CLI did either
-- there was no schema digest anywhere in the tree.

Callers filled the gap with the binary's version string, and that string
identifies nothing. On this machine the binary reports 0.8.0, the source
constant is 0.7.0, and the newest release tag is gds-v0.6.0; no tag for
either 0.7.0 or 0.8.0 exists. A consumer printing `gds --version` beside a
green result is printing a name with no contract behind it, which is the
shape this estate keeps finding: a value without the thing that gives it
meaning.

`Set.Digest()` hashes every embedded schema file, path and content, in the
sorted order `fs.ReadDir` returns, and `validate repository` carries it in
`data.schema_digest`. It is derived from content, so unlike a build-time
stamp it cannot name a revision that was never compiled.

Verified in both directions. Adding a property to repository.schema.json
and rebuilding moves the digest from 2526481e to c02d033f. The coverage
test recomputes the digest over the embedded set independently; excluding
file content from the implementation makes it fail with a different digest
over 50 schema files, so the assertion can fail rather than merely pass.
`core/app` and `core/validation` are both in the source paths the bundle
lock digests, so adding the schema digest changed the source tree identity
and left every projection stale against it.

Regenerated through `gds generate repository` plan/apply rather than by
hand: the two files carry per-file digests in their own headers that
cannot be derived by reading them. `gds generate repository --check` now
reports no findings.
@rldyourmnd
rldyourmnd merged commit 6228325 into main Aug 31, 2026
7 checks passed
@rldyourmnd
rldyourmnd deleted the feat/report-the-schema-a-validation-used branch August 31, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant