Purpose
The docs build pipeline validates ADRs before Hugo builds the aggregated site.
The validator exists to keep three things true at the same time:
- ADR frontmatter must satisfy the pinned upstream Structured MADR base schema.
- Dataverket-specific metadata and document structure rules must remain consistent across repos.
- The aggregated docs corpus must remain safe to combine into one site without ambiguous ADR filenames.
Where the validator runs
The canonical entrypoint is the Task-based docs pipeline.
task validateruns advisory validation.task validate-strictruns the same validator in strict mode.task buildruns validation before Hugo builds the site.
The CLI command is smadr-validator.
Sources of truth
The validator has three layers of definition:
- Policy configuration:
config/smadr-validator.yaml - Implementation:
internal/smadrvalidator/ - Regression coverage and examples:
internal/smadrvalidator/validator_test.go
Use the configuration file to understand which rules are enabled and whether they are blocking. Use the Go package to understand exact resolution and normalization behavior.
Frontmatter contract
Dataverket ADRs use the Structured MADR frontmatter model.
- Upstream baseline reference: Structured MADR frontmatter specification
- Local Dataverket contract:
internal/smadrvalidator/schemas/dataverket-policy.schema.jsonandconfig/smadr-validator.yaml
For the author-facing field definitions, allowed values, examples, and Dataverket’s guidance on using related for flexible ADR relationships, see ADR frontmatter.
Use the upstream specification to understand the baseline field meanings and structure. Use the local schema and validator config to understand what Dataverket actually accepts.
If this document and the code-backed contract ever disagree, the schema and validator config win.
Enforcement summary
This page focuses on what the validator enforces rather than on frontmatter authoring guidance.
At a high level, the validator enforces three contract layers:
- required and optional fields from the configured JSON Schema
- Dataverket allowlists and filename policy from
config/smadr-validator.yaml - required ADR body sections in markdown
Today that includes Dataverket-specific policy such as local allowlists for project and category, support for status: rejected, support for relative related paths, and required sections Status, Context, Decision, Consequences, Decision Outcome, and Audit.
Validation model
Validation runs in layers.
1. Corpus-level namespace checks
The validator scans all discovered ADRs in the aggregated docs corpus and checks for duplicate basenames.
This is important because ADR references are currently filename-based. If two repos both contain the same ADR basename, filename-only references become ambiguous in the combined site.
Current policy:
duplicate_basenameis a blocking error.
2. Frontmatter parse
Each ADR must have valid YAML frontmatter.
Current policy:
- missing frontmatter is an error
- invalid frontmatter is an error
3. Base Structured MADR schema validation
The validator uses a locally pinned copy of the upstream Structured MADR JSON Schema as its base.
That base schema currently lives at:
internal/smadrvalidator/schemas/structured-madr.schema.json
It is embedded into the validator binary so local runs, CI, and containerized runs all use the same baseline by default.
Dataverket can also replace that default with a local custom schema through schema.path in config/smadr-validator.yaml.
The current local custom schema lives at:
internal/smadrvalidator/schemas/dataverket-policy.schema.json
That schema is a Dataverket-specific copy derived from the upstream baseline. It keeps the standard structure but applies local policy adjustments, such as allowing the rejected status and relative related paths.
Current policy:
schema_validationis a blocking error.
4. Dataverket-specific metadata checks
After base-schema validation, the validator applies Dataverket policy from config/smadr-validator.yaml.
This includes:
- allowed
projectvalues - allowed
categoryvalues - filename format expectations
Current policy:
- unsupported allowed values are errors
- invalid filenames are errors
5. Document structure checks
The validator checks that required ADR sections exist in the markdown body.
Current default sections are:
- Status
- Context
- Decision
- Consequences
- Decision Outcome
- Audit
Current policy:
- missing required sections are warnings
Related ADR resolution
The related field is validated in two ways.
- local relative filesystem references work
- filename-only references are resolved against the aggregated ADR corpus by basename
- external URLs are ignored by this rule
Current policy:
invalid_related_targetis a warning
This makes cross-repo references possible without path traversal in frontmatter, as long as ADR basenames remain globally unique across the aggregated corpus. Duplicate basenames are blocked separately by the duplicate_basename rule because they make filename-only references ambiguous.
Advisory vs strict mode
The validator always reports both errors and warnings.
- advisory mode prints the findings and exits successfully
- strict mode exits non-zero if blocking errors are present
This allows the same validator to support local authoring and later stricter CI behavior.
In practice, the docs-builder entrypoint keeps local builds advisory, while the Forgejo pipeline runs a separate strict validation step before the full site build.
YAML frontmatter notes
The validator uses yaml.v3 through the shared frontmatter parser.
- consistently indented lists work with either 2-space or 4-space indentation
- mixed indentation within the same YAML list can parse in surprising ways and should be treated as invalid authoring
Date-like YAML values are normalized to plain YYYY-MM-DD strings before JSON Schema validation so the upstream date format checks behave consistently.
Maintenance guidance
When changing validator behavior:
- Update
config/smadr-validator.yamlif the policy changes. - Update
internal/smadrvalidator/if the implementation changes. - Update
internal/smadrvalidator/validator_test.gowhen the expected behavior changes. - Update this document if the author-facing contract changes.