/query/graph scoping was a documented no-op (graph_service returned the
query unscoped) and neo4j_client permitted writes; a live probe showed a
nonexistent user could read the whole graph.
- Add Neo4jClient.execute_read() that opens the session with
default_access_mode=READ_ACCESS so the database refuses writes even if
validation is bypassed.
- GraphService.execute_query() now rejects queries containing
CREATE/MERGE/DELETE/DETACH/SET/REMOVE/DROP/FOREACH/LOAD or any CALL
(conservative word-boundary denylist on the uppercased query) and
executes through the read-only session; the no-op _scope_query_to_user
is removed.
- Remove the false user-scoping claims from /query/graph (main.py) and
/graph/query docs and the CypherQueryRequest model: the endpoints are
documented as admin/debug, unscoped read-only (per-tenant label
injection for arbitrary Cypher would need a real parser; /graph/nodes
remains the tenant-scoped path).
- Offline unit tests: denylist coverage (incl. lowercase/multiline/CALL),
word-boundary false-positive check, and READ_ACCESS session assertion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- /stats passed the bare user name as path prefix (matched nothing, always
reported 0 of 138 pages); it now counts pages under users/{user}
- list_pages applied the API-side limit before client-side path/tag filters,
dropping matching pages that sort late; limit now applies after filtering
- list_all_pages replaced the fake while/break pagination with a real
limit-growth loop: Wiki.js 2.x pages.list supports only a limit argument
(no offset - verified via GraphQL introspection), so the client doubles
the limit until the API returns fewer pages than requested
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- POST /volatile/fetch/environment/{city} fetches both in parallel
- Single geocode lookup shared between API calls
- Uses asyncio.gather() for concurrent external requests
- Fix scheduler executor name (rest_api → rest_api_executor)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add SchedulerClient to communicate with external scheduler service for
registering volatile prefetch tasks discovered during HybridRAG searches.
- Add scheduler_client.py with full REST API for task CRUD operations
- Add scheduler_url config setting (default: http://scheduler:8090)
- Update consolidation service to use scheduler for prefetch registration
- Add scheduler health checks to startup/shutdown lifecycle
When HybridRAG classifies web content as prefetch-worthy, it now creates
scheduled tasks that periodically refresh the volatile cache via the
external scheduler service.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /documents router with webhook, upload, search, health endpoints
- Create DocumentSyncService for indexing documents to vectors/graph
- Add PaperlessClient for REST API integration
- Configure dependency injection for Paperless client
- Add document models for webhook payloads and responses
- Event-driven architecture via Paperless workflow webhooks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Migrate volatile backend from Redis to Qdrant for semantic search
- Add natural language conversion for structured data embedding
- Simplify API: /volatile/search, /volatile/store, /{namespace}/{key}
- Integrate volatile into HybridRAG with priority boost in RRF fusion
- Add POST /maintenance/cleanup/volatile for expiry purging
- Update tests for new Qdrant-based architecture (37/37 pass)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Wiki.js GraphQL API is accessible without authentication.
Make WIKI_GRAPHQL_API env var optional with empty default to fix
container startup failures.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add bulk operations needed for maintenance:
- scroll_all_points(): paginated iteration over all points
- delete_by_ids(): batch delete points by ID list
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace username/password login flow with simpler API token auth:
- Use WIKI_GRAPHQL_API environment variable for JWT token
- Remove login() method and session management
- Add list_pages() method for fetching all pages
- Keep legacy auth fields in config for backwards compatibility
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add temperature control for LLM text generation:
- temperature=0.0 for deterministic outputs (JSON, rankings)
- temperature=0.3-0.5 for controlled creative content
- None uses model default (~0.7 for mistral-nemo)
Based on llm-findings.md recommendations for improving
mistral-nemo output consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /rag/search endpoint for web, news, and image search via SearXNG
- Add /content/extract and /content/extract/batch endpoints
- Add ContentExtractor client using Trafilatura for content extraction
- Enhance HybridRAG web search with full content extraction
- Add Redis caching for search results
- Add new configuration options for search and extraction timeouts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>