fix(vector-sync): address round-6 review — rename shadowed var, add test
- vector_sync route: rename the response dict from `body` to `resp` so it no longer shadows the request `body` (maintenance trap) - scanner: comment the intentional files-vs-text purge timing asymmetry - tests: add the all-text-types-disabled backstop case (empty allow-set) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d0db530ac9
commit
21ce620a84
@@ -121,16 +121,16 @@ async def purge_doc_types_route(request: Request) -> JSONResponse:
|
||||
# NOT purged (consent not yet enforced for them) — the scanner backstop
|
||||
# still catches these, but the caller shouldn't assume full success.
|
||||
failed = [dt for dt in dict.fromkeys(doc_types) if dt not in purged]
|
||||
body: dict = {"purged": purged}
|
||||
resp: dict = {"purged": purged}
|
||||
if failed:
|
||||
body["failed"] = failed
|
||||
resp["failed"] = failed
|
||||
logger.info(
|
||||
"Vector-sync purge by admin %s: purged=%s failed=%s",
|
||||
user_id,
|
||||
purged,
|
||||
failed,
|
||||
)
|
||||
return JSONResponse(body)
|
||||
return JSONResponse(resp)
|
||||
|
||||
except ProvisioningRequiredError as e:
|
||||
logger.info("Provisioning required for user %s: %s", user_id, e)
|
||||
|
||||
@@ -594,6 +594,9 @@ async def scan_user_documents(
|
||||
# indexed. The deletion-reconcile below then sees every indexed
|
||||
# file as "missing" and purges it after the grace period — the
|
||||
# backstop for the eager purge Astrolabe runs on disable.
|
||||
# Asymmetry (intentional): files purge up to 1.5x scan_interval
|
||||
# later than text types, which get immediate one-shot backstop
|
||||
# deletes via _enqueue_deletes_for_disabled_types.
|
||||
logger.debug(
|
||||
"[SCAN-%s] Files disabled by admin for %s; skipping tagged-file discovery",
|
||||
scan_id,
|
||||
|
||||
@@ -73,6 +73,25 @@ async def test_enqueues_deletes_for_disabled_text_type(monkeypatch):
|
||||
assert all(t.operation == "delete" and t.doc_type == "note" for t in sent)
|
||||
|
||||
|
||||
async def test_all_text_types_disabled_enqueues_all(monkeypatch):
|
||||
# Admin disabled everything at once (empty allow-set): every text type's
|
||||
# indexed points are enqueued for deletion in a single call.
|
||||
_patch_qdrant(
|
||||
monkeypatch, {"note": ["n1"], "news_item": ["ni1"], "deck_card": ["d1"]}
|
||||
)
|
||||
sent: list = []
|
||||
stream = _producer(AsyncMock(side_effect=lambda t: sent.append(t)))
|
||||
|
||||
queued = await _enqueue_deletes_for_disabled_types("alice", stream, frozenset(), 1)
|
||||
|
||||
assert queued == 3
|
||||
assert {(t.doc_type, t.doc_id) for t in sent} == {
|
||||
("note", "n1"),
|
||||
("news_item", "ni1"),
|
||||
("deck_card", "d1"),
|
||||
}
|
||||
|
||||
|
||||
async def test_noop_when_allowed_is_none(monkeypatch):
|
||||
# Fail-open: a transient capability read must never trigger deletion.
|
||||
send = AsyncMock()
|
||||
|
||||
Reference in New Issue
Block a user