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)
Summary
schemaVersionin nearly every JSON document go-FuSa emits is the full 3-partSpecVersion("1.15.0") instead of theMAJOR.MINORform the spec requires ("1.15").Spec requirement
§3.2 "
schemaVersionsemantics (MUST)": "It is the spec version the document conforms to,MAJOR.MINOR." Every worked example in the spec (§3.1, §9.1, §9.1capabilities) 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:
schemaVersion: "1.15.0"is notMAJOR.MINOR— it carries a stray patch component.Root cause
fusa.goactually already defines the correct helper:But most call sites bypass it and use
fusa.SpecVersion(the raw 3-part constant, currently"1.15.0") directly: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 callfusa.SchemaVersion():This masked the bug until the spec started using 3-part versions (
1.10.10+): whileSpecVersionwas itself two-part (e.g."1.9"),fusa.SpecVersionandfusa.SchemaVersion()produced identical strings, so the divergence at the older, still-buggy call sites was invisible.Fix
Replace
fusa.SpecVersionwithfusa.SchemaVersion()at everySchemaVersion:field assignment inqualify/qualify.go,gapreport/gapreport.go,trace/trace.go,auditpack/auditpack.go,release/release.go(all 3 sites),report/report.go, andcmd/gofusa/cmd_capabilities.go'sSchemaVersionfield (itsSpecVersionfield should stay asfusa.SpecVersion).Environment
main@26c025fdocs/x-fusa-spec.mdin FuSaOps)