Skip to content

#102 write the downgrade record before the failure sentinel - #133

Merged
matthewdevenny merged 1 commit into
code-cargo:mainfrom
brinkercode:brian/102-downgrade-before-sentinel
Sep 17, 2026
Merged

matthewdevenny merged 1 commit into
code-cargo:mainfrom
brinkercode:brian/102-downgrade-before-sentinel

Conversation

@brinkercode

Copy link
Copy Markdown
Contributor

Summary

Under --api-failure-mode=fail, handlePolicyFetchFailure published the failure sentinel before the downgrade record. The action classifies a sentinel as lockdown from that record, so a reader between the two writes saw a lockdown with no record and treated it as a generic startup crash. With the default fail-on-unsupported: false, that restored resolv.conf under a live lockdown and passed the step. The record is now written first and the sentinel last.

Changes

  • cmd/start.go: writeDowngradeFile runs before writeFailureSentinel in the lockdown branch. The SEMANTICS comment is unchanged; a new ORDER comment records why the sequence matters. writeDowngradeFile stays best-effort, so a failed record write still leaves the sentinel written.
  • cmd/start_test.go: TestLoadCIConfig_LockdownPublishesSentinelLast.

Why this shape

The sentinel is what consumers poll for, so it should be the commit of the state: published only once everything describing that state exists. That fixes the race at the source instead of leaning on the settle delay and sentinel-text fallback from code-cargo/cargowall-action#73, which can stay as a second line of defense.

The test points downgradeFile and FailureFile at the same path. Both writes atomically replace it, so whichever lands last is what remains, and the test asserts that is the sentinel (pid=). That checks the order deterministically, without a goroutine racing two writes that land microseconds apart.

Test plan

main (750c22f) this branch
TestLoadCIConfig_LockdownPublishesSentinelLast fails: file holds the downgrade record passes
go test ./... green
go test -race ./cmd/ green
staticcheck, gofumpt, goimports-reviser clean

Root BPF tests (Multipass VMs, one package per run): pkg/tc, pkg/network, pkg/steps pass on 5.15, 6.8 and 7.0. bpf and pkg/origin pass on 6.8 apart from the known VM-kernel TestTcEgress/Truncated_IP{,v6}_header EINVALs. This change touches only cmd, which none of those packages import.

Related

Closes #102. Raised as item 1 of the post-merge review on code-cargo/cargowall-action#72; mitigated action-side in code-cargo/cargowall-action#73.

Out of scope

Signed-off-by: Brian Joiner <brinkercode@gmail.com>
@brinkercode
brinkercode marked this pull request as ready for review September 17, 2026 03:04
@matthewdevenny
matthewdevenny self-requested a review September 17, 2026 15:10

@matthewdevenny matthewdevenny left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@matthewdevenny
matthewdevenny merged commit 0053242 into code-cargo:main Sep 17, 2026
23 of 29 checks passed
@brinkercode

Copy link
Copy Markdown
Contributor Author

Thanks for the merge! Happy to take on more low-level bugs or enhancements whenever you've got them. I can also open that verifier issue if it's useful.

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.

Write the downgrade record before the failure sentinel

2 participants