fix(vector-sync): address round-3 review — gate purge route, bound set, nits

- app.py: register /api/v1/vector-sync/purge only when vector_sync_enabled, so
  it returns 404 (not a 500 from get_qdrant_client) when sync is off
- scanner: bound _consent_backstop_done so a long-running multi-tenant process
  with user churn can't grow it without limit (clears on overflow)
- purge route: distinct 400 for a missing doc_types key; enforce the admin
  check even for an empty no-op request (destructive route)
- tests: missing-key 400, admin-gated empty no-op, non-admin empty 403

The _consent_narrowed_doc_types precondition is enforced by its non-Optional
frozenset[str] signature (ty rejects a None caller). The httpx.BasicAuth
SonarCloud hotspot matches the existing webhook routes (false positive,
credential from the app-password store) — left consistent for UI triage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-06-16 01:21:01 +02:00
co-authored by Claude Opus 4.8
parent 24b8000a71
commit cef477b877
4 changed files with 64 additions and 11 deletions
+13
View File
@@ -293,6 +293,13 @@ _TEXT_BACKSTOP_DOC_TYPES: tuple[str, ...] = tuple(sorted(INDEXED_DOC_TYPES - {"f
# the type is allowed again, so a later re-disable re-triggers the backstop.
_consent_backstop_done: set[tuple[str, str]] = set()
# Safety bound on the tracking set so a long-running multi-tenant process with
# heavy user churn (deprovisioned users leave stale entries) can't grow it
# without limit. At <= len(INDEXED_DOC_TYPES) entries per user this is generous;
# on overflow we clear the whole set, which at worst re-fires the (idempotent)
# backstop once for currently-disabled types.
_CONSENT_BACKSTOP_MAX = 50_000
async def _enqueue_deletes_for_disabled_types(
user_id: str,
@@ -366,6 +373,12 @@ async def _enqueue_deletes_for_disabled_types(
queued += 1
# Mark this (user, doc_type) backstopped for the current disable episode
# so subsequent scans don't re-enqueue the same idempotent deletes.
if len(_consent_backstop_done) >= _CONSENT_BACKSTOP_MAX:
logger.info(
"consent backstop tracking set hit %d entries; clearing",
_CONSENT_BACKSTOP_MAX,
)
_consent_backstop_done.clear()
_consent_backstop_done.add((user_id, doc_type))
return queued