fix(vector-sync): address PR review — dict guard, symmetric backstop, metrics
- purge route: 400 (not 500) on a valid-JSON non-object body
- scanner: backstop-purge admin-disabled note/news_item/deck_card points
(their deletion-tracking lives inside the skipped scan_* fns), mirroring the
files path; gated on a concrete allow-set so fail-open never deletes
- processor: record_ingest_dropped("admin_disabled") so consent-skipped index
tasks are observable/alertable
- app.py: list /api/v1/vector-sync/purge in the endpoints log line
- capabilities: drop empty-string doc types; return frozenset throughout
- purge: document the count-before-delete approximation
- tests: non-object body -> 400, ProvisioningRequiredError -> 428, cache TTL
expiry refetch, and the scanner consent backstop
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
ef5b3f3873
commit
477fb02b0a
@@ -38,13 +38,13 @@ class _CapabilitiesClientProtocol(Protocol):
|
||||
async def capabilities(self) -> Any: ...
|
||||
|
||||
|
||||
def _parse_enabled_doc_types(payload: Any) -> set[str] | None:
|
||||
def _parse_enabled_doc_types(payload: Any) -> frozenset[str] | None:
|
||||
"""Extract ``enabled_doc_types`` from an OCS capabilities payload.
|
||||
|
||||
Returns ``None`` when the ``astrolabe.semantic_search`` block is absent or
|
||||
malformed (treated as "no restriction"). Returns a set (possibly empty) when
|
||||
the block is present and well-formed; an empty set means the admin disabled
|
||||
every source.
|
||||
malformed (treated as "no restriction"). Returns a frozenset (possibly
|
||||
empty) when the block is present and well-formed; an empty set means the
|
||||
admin disabled every source.
|
||||
"""
|
||||
if not isinstance(payload, dict):
|
||||
return None
|
||||
@@ -63,7 +63,7 @@ def _parse_enabled_doc_types(payload: Any) -> set[str] | None:
|
||||
raw = semantic.get("enabled_doc_types")
|
||||
if not isinstance(raw, list):
|
||||
return None
|
||||
return {dt for dt in raw if isinstance(dt, str)}
|
||||
return frozenset(dt for dt in raw if isinstance(dt, str) and dt)
|
||||
|
||||
|
||||
async def allowed_doc_types(
|
||||
@@ -92,8 +92,7 @@ async def allowed_doc_types(
|
||||
)
|
||||
return None # don't cache failures — retry next call
|
||||
|
||||
parsed = _parse_enabled_doc_types(payload)
|
||||
result = frozenset(parsed) if parsed is not None else None
|
||||
result = _parse_enabled_doc_types(payload)
|
||||
_cache[user_id] = (now, result)
|
||||
_cache.move_to_end(user_id)
|
||||
while len(_cache) > _CACHE_MAXSIZE:
|
||||
|
||||
Reference in New Issue
Block a user