Replace the four stub endpoints with real implementations, all requiring
an explicit tenant user (Phase B rule):
- /ingest/check-updates: GraphService now records a SHA-256 content_hash
on every Document node at ingestion time; the endpoint compares those
stored hashes against current Wiki.js page content in one UNWIND Cypher
query per tenant and returns changed/new/deleted page lists (entity-stub
pages excluded, pre-hash-tracking documents flagged stored_hash_missing).
- /ingest/status/{job_id}: backed by the Redis JobManager; jobs are
tenant-scoped (foreign jobs 404). /ingest/page, /ingest/batch and
/ingest/all now create job records and return job_id.
- /ingest/repo-status/{repository}: wiki page count vs indexed Document
nodes under users/{tenant}/{repository} plus tenant job stats.
- /deduplicate/check: tenant-scoped Qdrant similarity scan; chunk pairs
above ~0.9 cosine from different pages grouped per page pair with best
score and page references (read-only).
Supporting changes: get_job_manager dependency (+ shutdown close),
scroll_all_points can return vectors, VectorService.find_duplicate_pairs,
src/core/hashing.compute_content_hash. 13 new offline unit tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbFZyDvYksazX6nYQYZ67L
27 lines
754 B
Python
27 lines
754 B
Python
"""
|
|
Content hashing helpers.
|
|
|
|
A single canonical hash implementation is used everywhere page content is
|
|
fingerprinted (Document nodes at ingestion time, /ingest/check-updates
|
|
comparisons) so hashes computed at different times are comparable.
|
|
"""
|
|
|
|
import hashlib
|
|
|
|
|
|
def compute_content_hash(content: str) -> str:
|
|
"""
|
|
Compute the canonical content hash for wiki page content.
|
|
|
|
Args:
|
|
content: Raw page content (markdown). None-safe: treated as "".
|
|
|
|
Returns:
|
|
Hex-encoded SHA-256 digest of the UTF-8 encoded content.
|
|
|
|
Examples:
|
|
>>> compute_content_hash("hello")
|
|
'2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
|
|
"""
|
|
return hashlib.sha256((content or "").encode("utf-8")).hexdigest()
|