Skip to content

schemaVersion emits 3-part SpecVersion instead of MAJOR.MINOR across nearly every command (§3.2 MUST) #76

Closed

Description

@SoundMatt

Summary

schemaVersion in nearly every JSON document go-FuSa emits is the full 3-part SpecVersion ("1.15.0") instead of the MAJOR.MINOR form the spec requires ("1.15").

Spec requirement

§3.2 "schemaVersion semantics (MUST)": "It is the spec version the document conforms to, MAJOR.MINOR." Every worked example in the spec (§3.1, §9.1, §9.1 capabilities) shows a two-part value, e.g. "schemaVersion": "1.9".

What I observed

Built go-FuSa @ v0.45.0 (spec v1.15.0) and ran it against its own repo:

$ gofusa check --format json --dir . | jq .schemaVersion
"1.15.0"
$ gofusa trace --format json --dir . | jq .schemaVersion
"1.15.0"
$ gofusa capabilities --format json | jq '.schemaVersion, .specVersion'
"1.15.0"
"1.15.0"
$ gofusa iso26262 --format json --dir . | jq .schemaVersion
"1.15.0"
$ gofusa release --output-dir /tmp/relout --full --dir . && jq .schemaVersion /tmp/relout/sbom.json /tmp/relout/provenance.json /tmp/relout/artifact-manifest.json
"1.15.0"
"1.15.0"
"1.15.0"
$ gofusa audit-pack --dir . --output /tmp/audit-pack.zip && unzip -p /tmp/audit-pack.zip manifest.json | jq .schemaVersion
"1.15.0"
$ gofusa qualify --output /tmp/qualify.json && jq .schemaVersion /tmp/qualify.json
"1.15.0"

schemaVersion: "1.15.0" is not MAJOR.MINOR — it carries a stray patch component.

Root cause

fusa.go actually already defines the correct helper:

// SchemaVersion returns the MAJOR.MINOR prefix of SpecVersion, the value
// every report document's "schemaVersion" header field (§2.8/§3.1) MUST
// carry — ...
func SchemaVersion() string {
	parts := strings.SplitN(SpecVersion, ".", 3)
	if len(parts) < 2 {
		return SpecVersion
	}
	return parts[0] + "." + parts[1]
}

But most call sites bypass it and use fusa.SpecVersion (the raw 3-part constant, currently "1.15.0") directly:

cmd/gofusa/cmd_capabilities.go:46:   SchemaVersion: fusa.SpecVersion,
cmd/gofusa/cmd_capabilities.go:52:   SpecVersion:   fusa.SpecVersion,   (this one is correct — specVersion isn't MAJOR.MINOR-constrained)
cmd/gofusa/cmd_version.go:34:        SpecVersion: fusa.SpecVersion,    (also correct, same reason)
qualify/qualify.go:147:              SchemaVersion: fusa.SpecVersion,
gapreport/gapreport.go:63:           SchemaVersion: fusa.SpecVersion,
trace/trace.go:723:                  SchemaVersion: fusa.SpecVersion,
auditpack/auditpack.go:91:           SchemaVersion: fusa.SpecVersion,
release/release.go:154,205,444:      SchemaVersion: fusa.SpecVersion,
report/report.go:79:                 SchemaVersion: fusa.SpecVersion,

So check, report, trace, qualify, release (sbom/provenance/artifact-manifest), audit-pack, and every <standard> gap-report command are affected — i.e. essentially every §9.1 MUST command FuSaOps consumes.

By contrast, the commands added during the recent content-quality sprint (fmea, tara, hara, sas, sci, safety-case) correctly call fusa.SchemaVersion():

sas/sas.go:129:            SchemaVersion: fusa.SchemaVersion(),
fmea/fmea.go:134:          SchemaVersion: fusa.SchemaVersion(),
hara/hara.go:500:          SchemaVersion:         fusa.SchemaVersion(),
tara/tara.go:133:          SchemaVersion: fusa.SchemaVersion(),
sci/sci.go:124:            SchemaVersion: fusa.SchemaVersion(),
safetycase/safetycase.go:222:  SchemaVersion: fusa.SchemaVersion(),

This masked the bug until the spec started using 3-part versions (1.10.10+): while SpecVersion was itself two-part (e.g. "1.9"), fusa.SpecVersion and fusa.SchemaVersion() produced identical strings, so the divergence at the older, still-buggy call sites was invisible.

Fix

Replace fusa.SpecVersion with fusa.SchemaVersion() at every SchemaVersion: field assignment in qualify/qualify.go, gapreport/gapreport.go, trace/trace.go, auditpack/auditpack.go, release/release.go (all 3 sites), report/report.go, and cmd/gofusa/cmd_capabilities.go's SchemaVersion field (its SpecVersion field should stay as fusa.SpecVersion).

Environment

  • go-FuSa v0.45.0, built from main @ 26c025f
  • x-FuSa spec v1.15.0 (docs/x-fusa-spec.md in FuSaOps)

Activity

  1. SoundMatt commented on Jul 29, 2026

    @SoundMatt
    OwnerAuthor

    Investigated in #84 and found stale — the spec was updated to v1.15.1 explicitly blessing MAJOR.MINOR.PATCH as the correct schemaVersion/specVersion format, reversing the MAJOR.MINOR-only text this issue was filed against. No code change needed; go-FuSa's 3-part schemaVersion is already conformant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions