Skip to content

fix: carry forward §1.6.2 attestation on regeneration (v0.39.0) - #67

Closed
SoundMatt wants to merge 3 commits into
mainfrom
fix/attestation-carry-forward
Closed

fix: carry forward §1.6.2 attestation on regeneration (v0.39.0)#67
SoundMatt wants to merge 3 commits into
mainfrom
fix/attestation-carry-forward

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

Summary

  • x-FuSa spec §1.6.2 (spec v1.15.0) makes attestation carry-forward a MUST: before an artifact-producing command rebuilds its output, it must load any existing attestation from the prior saved output file and carry it forward, rather than silently discarding a human reviewer's prior "reviewed" status.
  • gofusa fmea/tara/safety-case/sas each unconditionally overwrote their JSON output from a freshly-built report — a hand-added, valid, reviewed attestation was destroyed on every re-run, even with no substantive content change.
  • New carryForwardAttestation helper (cmd/gofusa/helpers.go) loads the attestation key from the prior output file and is now called by all four commands right before they overwrite their output. Staleness still falls out automatically via the existing hash check in stubcheck.AttestationSuppresses/fusa.AttestationValid.

Closes #57. Addresses x-FuSa spec v1.15.0 item 1 from #64 (attestation carry-forward MUST); items 2 and 3 of #64 are addressed in a separate PR.

Test plan

  • go build ./...
  • go vet ./...
  • go test -race -count=1 ./... (88.6% total coverage)
  • golangci-lint run ./... (0 issues)
  • go generate ./... (no diff)
  • Manual binary check: gofusa fmea twice with a hand-added attestation between runs — attestation now survives regeneration
  • New tests: carryForwardAttestation unit tests (absent/malformed/no-attestation-field/present cases) + one end-to-end test per command (fmea/tara/safety-case/sas) round-tripping a "reviewed" attestation through two runs

x-FuSa spec §1.6.2 was updated (spec v1.15.0) to make attestation
carry-forward a MUST: before an artifact-producing command rebuilds its
output, it must load any existing attestation from the prior saved
output file and carry it forward, rather than discarding it. gofusa
fmea/tara/safety-case/sas each unconditionally overwrote their output
with a brand-new report built from scratch — none loaded the existing
file first or copied forward its attestation field, so a hand-added,
valid, reviewed attestation was silently destroyed the moment the
command was re-run, even when the artifact's substantive content hadn't
changed (go-FuSa#57). A project that adopted --require-attestation/
--strict per the spec's suggested CI shape would find their review
wiped on every regeneration, defeating the whole mechanism.

Add carryForwardAttestation (cmd/gofusa/helpers.go), which loads the
"attestation" key from a prior output file — working uniformly across
fmea.json/tara.json/safety-case.json/sas.json without needing each
artifact's full schema — and wire it into each of the four commands
right before they overwrite their JSON output. Staleness continues to
fall out automatically: a carried-forward contentHash that no longer
matches the freshly-computed content hash means AttestationValid (via
stubcheck.AttestationSuppresses) treats the attestation as not currently
suppressing, never that it silently vanished.

Signed-off-by: Matt Jones <matt@jellybaby.com>
Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
Signed-off-by: Matt Jones <matt@jellybaby.com>
Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
if code := runSas([]string{"--dir", dir, "--output", outFile}, &out1, &err1); code != fusa.ExitGateFail && code != fusa.ExitOK {
t.Fatalf("first run: unexpected exit %d, stderr: %s", code, err1.String())
}
if _, err := os.Stat(sasJSONPath); err != nil {
func writeSafetyFuncSource(t *testing.T, dir string) {
t.Helper()
src := "package main\n\n//fusa:req REQ-001\nfunc SafetyFunc() error { return nil }\n"
if err := os.WriteFile(filepath.Join(dir, "main.go"), []byte(src), 0o644); err != nil {
…-forward

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>

# Conflicts:
#	CHANGELOG.md
#	README.md
#	docs/tool-safety-manual.md
#	fusa.go
@SoundMatt
SoundMatt force-pushed the fix/attestation-carry-forward branch from dd32e65 to 445bb0d Compare July 28, 2026 22:19
@SoundMatt

Copy link
Copy Markdown
Owner Author

Closing and replacing for the same reason as #66: the rebase-onto-main merge commit lacked DCO sign-off, and my fix (amend + force-push) violated the no-force-push rule. Replacing with a fresh branch via cherry-pick.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

§1.6.2 attestation is silently wiped on every regeneration of fmea/tara/safety-case/sas

2 participants