Skip to content

chore: release v0.0.28 (state-commit write-mode pin) - #53

Merged
bdchatham merged 1 commit into
mainfrom
chore/release-v0.0.28
Aug 31, 2026
Merged

chore: release v0.0.28 (state-commit write-mode pin)#53
bdchatham merged 1 commit into
mainfrom
chore/release-v0.0.28

Conversation

@bdchatham

Copy link
Copy Markdown
Collaborator

Bumps version.json to v0.0.28. One line; no source change.

What it carries

Why the key matters

The binary reads sc-write-mode-enable-auto under [state-commit] to decide whether to derive its write mode from committed migration state or honor the configured write_mode. The unified schema had no field for it, so BuildRegistry never produced the key and ApplyOverrides rejected it as unknown — a node could not be pinned to an explicit write mode through the controller at all. Editing app.toml on the volume works only until the next start, when the sidecar renders the file again from the intent.

The field is *bool because all three states are distinct. Nil renders no key and leaves the binary's default in force, which is what every existing node needs. A bare bool cannot express the pin: with omitempty an explicit false is dropped, and without it every node in the fleet starts emitting the key.

Why #52 ships with it

Resolving a pointer field by reusing whatever pointee was already there produced two failures:

Aliasing the caller. ResolveIncrementalIntent shallow-copies the caller's config, so the copy and the original share every pointer. Overriding a non-nil pointer wrote through the shared pointee and silently changed the caller's config — which diff, retry, and rollback logic then read as the pre-override state.

A rejected value becoming a pin. Allocating before parsing left a rejected value behind as a pointer to the zero value. For this key that zero is false, which renders sc-write-mode-enable-auto = false — the pin. ResolveEnv only warns on a bad value and keeps going, so a typo in an env var could have taken a node off a governance-driven migration with nothing surfaced.

The value now parses into a fresh pointee and the pointer is replaced only on success.

Testing

Check Result
make test ok
go vet ./... clean
gofmt -l . clean
staticcheck ./... clean

Ran the tests covering both changes specifically:

  • TestWriteModeEnableAuto_Tristate — unset omits the key, override to false renders false, override to true renders true
  • TestWriteModeEnableAuto_RoundTrip
  • TestApplyOverrides_PointerDoesNotAliasCaller
  • TestApplyOverrides_PointerRejectedValueLeavesFieldUnset

All pass. The tristate behaviour is what the "changes no node's behaviour" claim below rests on.

Behaviour

Releasing changes no node's behaviour. write_mode_enable_auto defaults to nil, which renders no key.

The pointer fix also makes consensus.unsafe_bypass_commit_timeout_override settable through an override for the first time. No existing node can carry it, because setting a pointer field failed before #51.

Consumed next

sei-k8s-controller, whose sidecar resolves overrides during config-apply and is therefore what makes this real on a running node. It pins v0.0.27 today, across all three modules.

🤖 Generated with Claude Code

Carries #51, which adds storage.state_commit.write_mode_enable_auto, and #52,
which fixes two pointer-resolution defects the review of #51 surfaced.

The key matters because the binary reads sc-write-mode-enable-auto under
[state-commit] to decide whether to derive its write mode from committed
migration state or honor the configured write_mode. The unified schema had no
field for it, so BuildRegistry never produced the key and ApplyOverrides
rejected it as unknown: a node could not be pinned to an explicit write mode
through the controller at all. Editing app.toml on the volume works only until
the next start, when the sidecar renders the file again from the intent.

The field is *bool because all three states are distinct. Nil renders no key and
leaves the binary's own default in force, which is what every existing node
needs; a bare bool cannot express the pin, since omitempty drops an explicit
false and its absence makes every node emit the key.

#52 is the reason to take both together. Resolving a pointer field by reusing
whatever pointee was already there produced two failures. ResolveIncrementalIntent
shallow-copies the caller's config, so overriding a non-nil pointer wrote through
the shared pointee and silently changed the caller's config — which diff, retry,
and rollback logic then read as the pre-override state. And allocating before
parsing left a rejected value behind as a pointer to the zero value: for this key
that zero is false, which renders the pin. ResolveEnv only warns on a bad value
and keeps going, so a typo in an env var could have taken a node off a
governance-driven migration with nothing surfaced.

Consumed next by sei-k8s-controller, whose sidecar resolves overrides during
config-apply and is therefore what makes this real on a running node. The
controller pins v0.0.27 today.

Releasing changes no node's behaviour. write_mode_enable_auto defaults to nil,
which renders no key. The pointer fix also makes
consensus.unsafe_bypass_commit_timeout_override settable through an override for
the first time; no existing node can carry it, because setting it failed before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 31, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Single-field version bump with no runtime or source changes in the diff.

Overview
Bumps the package release version in version.json from v0.0.28’s predecessor v0.0.27 to v0.0.28.

There are no code or config schema changes in this diff—only the version string used to tag and consume this module (e.g. by downstream controllers that pin the sidecar).

Reviewed by Cursor Bugbot for commit 7c2803a. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

Copy link
Copy Markdown

Suggested version: v0.0.28

Comparing to: v0.0.27 (diff)

Changes in go.mod file(s):

(empty)

gorelease says:

The following panic happened checking types near:
	/opt/hostedtoolcache/go/1.27.0/x64/src/internal/goarch/goarch.go:20:2
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x645412]

goroutine 116 [running]:
go/types.(*Checker).handleBailout(0x1e5733bbe600, 0x1e57338bfbf8)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/check.go:404 +0x91
panic({0x9bc3f8?, 0xa0fd50?})
	/opt/hostedtoolcache/go/1.27.0/x64/src/runtime/panic.go:859 +0x125
go/types.(*Checker).objDecl.func1()
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/decl.go:55 +0x5c
panic({0x9bc3f8?, 0xa0fd50?})
	/opt/hostedtoolcache/go/1.27.0/x64/src/runtime/panic.go:859 +0x125
go/types.(*StdSizes).Sizeof(0x0, {0x9f34e8, 0xa13dc0})
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/sizes.go:229 +0x312
go/types.(*Config).sizeof(...)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/sizes.go:334
go/types.representableConst.func1(...)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/const.go:89
go/types.representableConst({0x9f52d8, 0x72e940}, 0x1e5733bbe600, 0xa13dc0, 0x1e57338bf490)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/const.go:105 +0x1d9
go/types.(*Checker).representation(0x1e5733bbe600, 0x1e57338de880, 0xa13dc0)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/const.go:269 +0x57
go/types.(*Checker).implicitTypeAndValue(0x1e5733bbe600, 0x1e57338de880, {0x9f3470?, 0x1e57339e4380?})
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/expr.go:405 +0x3dc
go/types.(*Checker).assignment(0x1e5733bbe600, 0x1e57338de880, {0x9f3470, 0x1e57339e4380}, {0x70a855, 0x14})
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/assignments.go:70 +0x445
go/types.(*Checker).initConst(0x1e5733bbe600, 0x1e57338a45a0, 0x1e57338de880)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/assignments.go:143 +0x245
go/types.(*Checker).constDecl(0x1e5733bbe600, 0x1e57338a45a0, {0x9f4528, 0x1e57339144e0}, {0x9f4528, 0x1e5733914500}, 0x0)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/decl.go:430 +0x2f1
go/types.(*Checker).objDecl(0x1e5733bbe600, {0x9f5960, 0x1e57338a45a0})
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/decl.go:153 +0xa05
go/types.(*Checker).packageObjects(0x1e5733bbe600)
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/resolver.go:688 +0x465
go/types.(*Checker).checkFiles(0x1e5733bbe600, {0x1e5733c38120?, 0x200?, 0x9ee4f0?})
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/check.go:451 +0x2b2
go/types.(*Checker).Files(0x10?, {0x1e5733c38120?, 0x3?, 0x6?})
	/opt/hostedtoolcache/go/1.27.0/x64/src/go/types/check.go:422 +0x75
golang.org/x/tools/go/packages.(*loader).loadPackage(0x1e573385e0e0, 0x1e5733826ed0)
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:1037 +0xaa7
golang.org/x/tools/go/packages.(*loader).loadRecursive.func1()
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:847 +0x1c5
sync.(*Once).doSlow(0x0?, 0x0?)
	/opt/hostedtoolcache/go/1.27.0/x64/src/sync/once.go:78 +0xab
sync.(*Once).Do(...)
	/opt/hostedtoolcache/go/1.27.0/x64/src/sync/once.go:69
golang.org/x/tools/go/packages.(*loader).loadRecursive(0x0?, 0x0?)
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:835 +0x3b
golang.org/x/tools/go/packages.(*loader).loadRecursive.func1.1(0x0?)
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:842 +0x26
created by golang.org/x/tools/go/packages.(*loader).loadRecursive.func1 in goroutine 114
	/home/runner/go/pkg/mod/golang.org/x/tools@v0.2.0/go/packages/packages.go:841 +0x99

gocompat says:

Your branch is up to date with 'origin/main'.

Automatically created GitHub Release

A draft GitHub Release has been created.
It is going to be published when this PR is merged.
You can modify its' body to include any release notes you wish to include with the release.

@bdchatham
bdchatham merged commit 82aeb0e into main Aug 31, 2026
5 checks passed
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 participant