Skip to content

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

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)

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