Problem
The build validates artifact metadata through the Ruby validator
(scripts/validate-metamodel.rb), not through a JSON Schema engine. The schema
in metamodel/artifact.schema.yaml is what consuming projects vendor, so the
two have to reach the same verdict on the same metadata.
#105 added outcome parity for the validity axis: SCHEMA_OUTCOMES in
test/validate_metamodel_test.rb runs fourteen present, empty, and null cases
through the validator and asserts the verdict the schema prescribes. But those
verdicts are written by hand from reading the schema. The test proves that
the validator agrees with a person's reading of the schema, not with the schema.
If the schema changes and the table is not updated, or the reading was wrong in
the first place, the test stays green.
The review of #105 accepted this as a documented limitation rather than a
blocker. This issue is what would remove it.
Why it was not solved in #105
The pinned toolchain (ghcr.io/docs-as-code-toolkit/docs-toolbox:v1.3.1)
declares no JSON Schema engine. It does carry ajv, but as version 6.12.6 at
/usr/share/nodejs/ajv — an incidental Debian package, not something the image
provides on purpose. It does not support Draft 2020-12, which the schema
declares, and it could disappear with any image bump. A guard built on it would
look deterministic while resting on nothing.
Goal
Compute the parity verdicts with a real Draft 2020-12 engine from a deliberately
pinned dependency, so a disagreement between the schema and the Ruby validator
fails the build without anyone having to predict it.
Options
Where the engine comes from
- Add it to the docs-toolbox image (
docs-as-code-toolkit/docs-toolbox), for
example ajv 8 with its Draft 2020-12 entry point and ajv-formats, or the
Ruby gem json_schemer. Keeps the reproducible container as the single
toolchain, but needs a toolbox release and a tag bump here.
- Declare it in this repository, for example a
package.json with a pinned
ajv. This repository currently runs its JS tests with node --test and no
dependencies, so this would introduce the first one.
Consuming projects run the same toolbox image through
templates/scripts/build.sh, so the first option also reaches them; the second
does not.
How far to take it
- Parity only: the engine computes the verdicts for the existing case table
and the test compares them with the Ruby validator.
- Schema as an executed contract:
./build.sh validate also runs every
artifact's front matter through the engine. The Ruby validator would then only
carry what the schema cannot express — retired_on not before created,
risk-specific retirement reasons, relation targets that must exist — and the
parity problem would mostly disappear instead of being tested for. Larger, and
probably its own decision.
Things to decide along the way
format: date. In Draft 2020-12, format is an annotation by default.
An engine only enforces it with format assertion enabled (for ajv, through
ajv-formats). Without that, the engine would accept retired_on: "" while
the Ruby validator rejects it — parity would fail for a reason that is a
configuration choice, not a defect.
- Local mode. With
DOCS_TOOLBOX_LOCAL=1 the host toolchain may not have
the engine. The test must then fail or skip with an explicit message. It must
not silently pass, or it becomes a guard that reads like coverage and checks
nothing.
Acceptance criteria
- A Draft 2020-12 JSON Schema engine is available at a pinned version from a
declared source, not an incidental one.
- The parity test computes each case's verdict by running the engine against
metamodel/artifact.schema.yaml and compares it with the Ruby validator's
verdict. Hand-written expectations are gone, or kept only as readable
documentation next to the computed ones.
- Changing the schema so that a case's verdict flips fails the test without the
test being edited, and changing the validator the same way fails it as well.
Both are demonstrated, not assumed.
- Format assertion for
format: date is enabled, or the resulting mismatch is
documented as a known exception with its reason.
- Local-mode behaviour without the engine is explicit: a clear failure or a
visible skip, never a silent pass.
References
Problem
The build validates artifact metadata through the Ruby validator
(
scripts/validate-metamodel.rb), not through a JSON Schema engine. The schemain
metamodel/artifact.schema.yamlis what consuming projects vendor, so thetwo have to reach the same verdict on the same metadata.
#105 added outcome parity for the validity axis:
SCHEMA_OUTCOMESintest/validate_metamodel_test.rbruns fourteen present, empty, and null casesthrough the validator and asserts the verdict the schema prescribes. But those
verdicts are written by hand from reading the schema. The test proves that
the validator agrees with a person's reading of the schema, not with the schema.
If the schema changes and the table is not updated, or the reading was wrong in
the first place, the test stays green.
The review of #105 accepted this as a documented limitation rather than a
blocker. This issue is what would remove it.
Why it was not solved in #105
The pinned toolchain (
ghcr.io/docs-as-code-toolkit/docs-toolbox:v1.3.1)declares no JSON Schema engine. It does carry
ajv, but as version 6.12.6 at/usr/share/nodejs/ajv— an incidental Debian package, not something the imageprovides on purpose. It does not support Draft 2020-12, which the schema
declares, and it could disappear with any image bump. A guard built on it would
look deterministic while resting on nothing.
Goal
Compute the parity verdicts with a real Draft 2020-12 engine from a deliberately
pinned dependency, so a disagreement between the schema and the Ruby validator
fails the build without anyone having to predict it.
Options
Where the engine comes from
docs-as-code-toolkit/docs-toolbox), forexample
ajv8 with its Draft 2020-12 entry point andajv-formats, or theRuby gem
json_schemer. Keeps the reproducible container as the singletoolchain, but needs a toolbox release and a tag bump here.
package.jsonwith a pinnedajv. This repository currently runs its JS tests withnode --testand nodependencies, so this would introduce the first one.
Consuming projects run the same toolbox image through
templates/scripts/build.sh, so the first option also reaches them; the seconddoes not.
How far to take it
and the test compares them with the Ruby validator.
./build.sh validatealso runs everyartifact's front matter through the engine. The Ruby validator would then only
carry what the schema cannot express —
retired_onnot beforecreated,risk-specific retirement reasons, relation targets that must exist — and the
parity problem would mostly disappear instead of being tested for. Larger, and
probably its own decision.
Things to decide along the way
format: date. In Draft 2020-12,formatis an annotation by default.An engine only enforces it with format assertion enabled (for
ajv, throughajv-formats). Without that, the engine would acceptretired_on: ""whilethe Ruby validator rejects it — parity would fail for a reason that is a
configuration choice, not a defect.
DOCS_TOOLBOX_LOCAL=1the host toolchain may not havethe engine. The test must then fail or skip with an explicit message. It must
not silently pass, or it becomes a guard that reads like coverage and checks
nothing.
Acceptance criteria
declared source, not an incidental one.
metamodel/artifact.schema.yamland compares it with the Ruby validator'sverdict. Hand-written expectations are gone, or kept only as readable
documentation next to the computed ones.
test being edited, and changing the validator the same way fails it as well.
Both are demonstrated, not assumed.
format: dateis enabled, or the resulting mismatch isdocumented as a known exception with its reason.
visible skip, never a silent pass.
References
scripts/validate-metamodel.rb, and commit11176ab(
issue_101: Decide by presence, as the schema does)test/validate_metamodel_test.rb,SCHEMA_OUTCOMESdocs-as-code-toolkit/docs-toolboxfor the pinned toolchain image