Files
netbird/e2e
Brad Ison 29eff3b207 [management] Derive the settings ETag at a precision the store preserves
The validator a bootstrap returns was permanently unusable on PostgreSQL. POST
derives it from the in-memory row, whose CreatedAt carries nanoseconds, while
every later comparison derives it from a row read back out of the store — and
PostgreSQL truncates timestamps to microseconds, MySQL DATETIME to whole
seconds without an fsp. The two never agreed again, so the documented
"conditional PUT without an intervening GET" answered 412 forever.

Hashing CreatedAt at whole-second precision fixes it at the root: seconds is
the floor every supported engine round-trips, so the validator no longer
depends on which store is behind it. The cost is that a delete and
re-bootstrap inside the same second, onto the same endpoint with the same
toggles, derives the same validator — which needs a self-addressed endpoint
reclaimed within one second, since a labeled bootstrap draws a fresh label.

The whole suite ran green against this bug, because every test uses the sqlite
test store and sqlite preserves nanoseconds. The regression guard is therefore
on the type rather than through a store: it asserts the validator is unchanged
by truncation at each engine's precision, so it holds without running the
suite against all three.

Also from review: the concurrency test recorded the winning writer's value in a
slice left zero for the loser, and zero is a retention the API documents as
"keep indefinitely" — so the assertion could be satisfied without matching the
writer that won. It now uses a sentinel and asserts equality. The stale-delete
e2e assertion accepted any error, which a server error or a state-guard refusal
would have satisfied; it now requires a precondition failure. And the 412
message both conditional writes return is a single constant, since on delete
the message is the only thing separating staleness from the state guards.
2026-08-11 12:24:53 +02:00
..