fix(vector): address PR review round 12 — bool guard + strict doc_id validation

- _group_int_doc_ids: use type(value) is not int instead of isinstance,
  since bool is an int subclass and would otherwise stringify to
  "True"/"False" and corrupt legacy payloads on backfill.
- Replace doc_id.isdigit() guards in 5 boundary sites
  (api/visualization, auth/viz_routes, search/context note/news_item/
  deck_card branches) with a shared is_valid_nextcloud_doc_id helper
  that rejects "0", leading zeros, and Unicode digit classes
  (superscripts, Arabic-Indic, Devanagari) which pass isdigit() but
  cannot be valid MySQL AUTO_INCREMENT IDs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-05-09 20:28:47 +02:00
co-authored by Claude Opus 4.7
parent f3ce46da0f
commit f9ad7dc52e
8 changed files with 133 additions and 24 deletions
+8 -6
View File
@@ -204,12 +204,14 @@ def _group_int_doc_ids(points: list[Any]) -> tuple[dict[str, list[Any]], int]:
value = payload.get("doc_id")
if value is None or isinstance(value, str):
continue
if not isinstance(value, int):
# Producers only ever write int or str; anything else is a
# producer bug. Stringifying e.g. a float would write "3.0",
# which producers (str(int)) and the keyword index would
# never match, and which int() on the verification side
# would later reject. Skip and log loudly instead.
# Strict type check: bool is a subclass of int in Python, so an
# `isinstance(value, int)` guard would let `True`/`False` slip
# through and be stringified to `"True"`/`"False"` — which the
# keyword index would never match and the verification side
# would later reject. Producers only ever write int or str;
# anything else (bool, float, etc.) is a producer bug. Skip
# and log loudly instead.
if type(value) is not int:
logger.warning(
"Unexpected doc_id type %s on point %s; skipping rewrite",
type(value).__name__,