mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-24 16:41:30 +02:00
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.