Summary
The sync path can overwrite a newer local config change with a stale remote-derived result because it reads a snapshot, normalizes off-lock, and then unconditionally writes that result back later.
This is distinct from the basic "sync result not applied" bug. Even after the apply path is corrected, the algorithm still allows stale-snapshot lost updates.
Minimal repro
I checked out the sync-apply fix only (without any generation/retry protection), added a focused repro test, and ran:
go test ./internal/config -run 'TestSyncStaleSnapshotOverwritesConcurrentRoleUpdate'
Repro test intent:
- capture the same role snapshot the pre-retry sync path uses
- derive the normalized remote result from that snapshot
- apply a newer local write
- commit the stale normalized result anyway
- observe the newer local write being overwritten
Representative failing output:
--- FAIL: TestSyncStaleSnapshotOverwritesConcurrentRoleUpdate (0.00s)
sync_concurrency_issue_test.go:56:
expected: "local-newer"
actual : "remote-update"
Messages: stale sync result should not overwrite a newer local update
Analysis
The problem is not just "concurrent work exists"; the current algorithm has a specific stale-snapshot window:
- snapshot current config
- merge/normalize off-lock
- write the result later with no compare-and-swap or retry
If local config changes in that window, the older derived result can win.
Scope
This issue is only about stale-snapshot lost updates in the sync path.
Please keep separate from:
- the base bug where sync results were not applied to live config at all
- broader lock-discipline cleanup across config readers/writers
Summary
The sync path can overwrite a newer local config change with a stale remote-derived result because it reads a snapshot, normalizes off-lock, and then unconditionally writes that result back later.
This is distinct from the basic "sync result not applied" bug. Even after the apply path is corrected, the algorithm still allows stale-snapshot lost updates.
Minimal repro
I checked out the sync-apply fix only (without any generation/retry protection), added a focused repro test, and ran:
Repro test intent:
Representative failing output:
Analysis
The problem is not just "concurrent work exists"; the current algorithm has a specific stale-snapshot window:
If local config changes in that window, the older derived result can win.
Scope
This issue is only about stale-snapshot lost updates in the sync path.
Please keep separate from: