fix(advice): make the id helper unusable rather than merely rejected

_as_doc_id returned None for a hostile id.  That was guarded at the one
call site, but the helper could still be misused into "$in needs an
array" - and a caller who forgot the guard would have got an error
rather than a safe no-op.

It now returns an EMPTY LIST for anything that is not a reading id.  An
empty list is a valid $in argument that matches nothing, so the helper
cannot produce a query error, cannot match every document, and cannot be
interpreted as a query operator.

Verified against the live database: a hostile id matches 0 documents and
updates 0 documents.

164 tests.
This commit is contained in:
2026-11-09 16:31:05 +10:00
parent 6dd0b7b046
commit 21fa0d9a12
2 changed files with 14 additions and 2 deletions
+6 -2
View File
@@ -230,7 +230,7 @@ class BeerRepository:
generated or is a note explaining that it could not be.
"""
doc_id = _as_doc_id(reading_id)
if doc_id is None:
if not doc_id:
return 0
# `$in` matches either form. A plain list would be an exact
# ARRAY match in Mongo, which is not what is wanted here.
@@ -422,7 +422,11 @@ def _as_doc_id(value: object):
except Exception:
# Not hex - it can only be the original app's string id.
return [value]
return None
# Anything else - a dict, a list, an int, None - is not a reading
# id. An EMPTY LIST is returned rather than None: it is a valid
# `$in` argument that matches nothing, so the helper cannot be
# misused into a query error or into matching every document.
return []
def _as_date(value: object) -> str: