fix(advice): an empty token must not be used as a guard

None of the 47 existing readings have a token - they all predate it.  A
reading read from the database therefore has an EMPTY token, and the
guard was checking `expected_token is not None`, which is TRUE for an
empty string.  So the write was conditioned on a token that does not
exist, matched nothing, and **the advice would never have been written
for any of the existing readings**.

Verified against the live database, before the fix:

    write with expected_token='' -> 0   (0 = the advice would NEVER be written)

After:

    write for a pre-token live reading: 1   (must be 1)

An empty token is now not a usable guard - there is no token to match -
so the write falls through to the gravity check instead.  A non-empty
token is still the primary guard.

There is a test for it, with a reading inserted the way the existing
ones are - directly, with no token.

178 tests (up from 177).
This commit is contained in:
2026-11-09 18:24:57 +10:00
parent 27a28b5e58
commit 7d9d718b41
2 changed files with 41 additions and 1 deletions
+6 -1
View File
@@ -263,10 +263,15 @@ class BeerRepository:
return 0
query: dict = {"_id": {"$in": doc_id}}
if expected_token is not None:
if expected_token:
# The editing token is the PRIMARY guard: it changes on every
# edit, so it catches a stale generation whatever else
# changed - the gravity, the comment, or nothing.
#
# An EMPTY token is not a usable guard: it means the reading
# predates the token, so there is no token to match.
# Querying on it would match nothing, and the advice would
# never be written for the existing readings.
query["advice_token"] = str(expected_token)
elif expected_sg is not None:
# No token - a direct call with a gravity to check against.