Skip to content

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

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

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

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

Summary

Replaces #67 (closed — that branch's rebase-onto-main merge commit was missing DCO sign-off, and my fix attempt used a prohibited force-push). Same content, rebuilt via cherry-pick with no merge commits.

  • 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 ./...
  • golangci-lint run ./... (0 issues)
  • 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-v2

Resolves version-bump conflicts (fusa.go, README.md, docs/tool-safety-manual.md,
CHANGELOG.md) against main after #69 (tara enum vocabulary, v0.41.0) merged.
Bumped this branch's own release to v0.42.0 and moved its CHANGELOG entry to
the top of the file.

Signed-off-by: Matt Jones <matt@jellybaby.com>
Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
…-forward-v2

Second round: main advanced to include #73 (hara, v0.42.0) since the
previous merge. This branch's own release was auto-merged to a stale
0.42.0 (textually identical to what main now already ships) with no
conflict — manually bumped it forward to v0.44.0 and reordered/deduped
the CHANGELOG.md entries to reflect the actual chronology.

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

Copy link
Copy Markdown
Owner Author

Closing and replacing: this branch ended up with an unsigned auto-generated merge commit (98a0cae) from a conflict-free git merge origin/main — git auto-commits merges when there's nothing to resolve, silently skipping the -s flag I intended to apply afterward. Replacing with a fresh branch built entirely via cherry-pick + squash onto current main, a single properly-signed commit, no merge commits at all.

@SoundMatt SoundMatt closed this Jul 28, 2026
@SoundMatt
SoundMatt deleted the fix/attestation-carry-forward-v2 branch July 28, 2026 22:50
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