- CORS: drop allow_credentials (wildcard origin + credentials told
browsers to attach credentials for any site); origins configurable via
CORS_ALLOW_ORIGINS (default * is safe without credentials). Verified
live: preflight no longer advertises access-control-allow-credentials.
- Scheduler tasks: auth moved from a plain Authorization header (which
the Scheduler's rest_api_executor does NOT env-substitute) to its
auth {type: bearer, token: ${LIBRARY_API_KEY}} block, substituted from
the Scheduler's own environment at execution time. The registrar no
longer resolves the real key client-side, so it can never be persisted
into the scheduled_tasks.config JSONB column. Also fixed: JSON bodies
moved from the ignored "body" key to "payload" (the executor only
reads config["payload"], so the tasks would have POSTed empty bodies
and failed required-user validation).
- Reranker: parsed ranking indices are deduplicated preserving first
occurrence (an LLM answer like "3,3,1" duplicated a result).
- HybridRAG wiring consolidated into dependencies.get_hybrid_rag_service
(now including volatile_service); the inline copies in /query/hybrid
and /wiki/pages/smart-create are gone - smart-create previously ran
without the volatile leg, and the singleton was unused.
- Remaining Neo4j writes (GraphService ingestion/deletes/purges/entity
mentions, webhook rename+delete cleanup, document-sync _index_graph,
consolidation mark-processed/add-entity) moved from auto-commit
execute_query to execute_write managed transactions with retry.
Verified end-to-end on the local dev server as llm_tester: /query/hybrid
200 with all five legs ok (volatile now active), background persistence
landed as one transaction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbFZyDvYksazX6nYQYZ67L
173 lines
5.0 KiB
Markdown
173 lines
5.0 KiB
Markdown
# Scheduler Task Definitions (Phase C deploy checklist)
|
|
|
|
Production task payloads for the homelab's database-driven **Scheduler**
|
|
service. These are **definitions only** — nothing in this repo registers
|
|
them automatically. Register them as part of the deploy checklist, either
|
|
via the Scheduler UI/API or with the helper script:
|
|
|
|
```bash
|
|
# Preview exactly what would be sent (default):
|
|
SCHEDULER_URL=http://<scheduler-host>:8090 \
|
|
.venv/bin/python scripts/register_scheduler_tasks.py
|
|
|
|
# Actually register/update the tasks (deploy checklist step):
|
|
SCHEDULER_URL=http://<scheduler-host>:8090 \
|
|
.venv/bin/python scripts/register_scheduler_tasks.py --execute
|
|
```
|
|
|
|
Conventions:
|
|
|
|
- All tasks call the **production** library-desk container
|
|
(`http://library-desk:8089`) with the explicit production tenant
|
|
`user=jpmschweitzer` (there is no default tenant — Phase B).
|
|
- `${LIBRARY_API_KEY}` is a literal placeholder stored in the task's
|
|
`auth.token` field. The Scheduler's `rest_api_executor` substitutes
|
|
`${ENV_VAR}` placeholders from **its own environment at execution
|
|
time** (it substitutes `url`/`payload`/`auth` — NOT plain `headers`),
|
|
so the raw key is never stored in the `scheduled_tasks.config` JSONB
|
|
column. The **Scheduler container** must have `LIBRARY_API_KEY` in its
|
|
environment. Never commit or register the real value.
|
|
- The JSON body goes in `config.payload` (the executor ignores a `body`
|
|
key).
|
|
- Schedule fields use the Scheduler's convention: `-1` = every,
|
|
`day_of_week`: `0` = Monday … `6` = Sunday.
|
|
|
|
---
|
|
|
|
## 1. Nightly integrity check — 04:30 daily
|
|
|
|
Read-only report: pages without vectors, orphaned vectors, unexpected
|
|
Qdrant collections, Document nodes without wiki pages. Caches its result
|
|
in Redis for the weekly quality report.
|
|
|
|
```json
|
|
{
|
|
"task_name": "library_integrity_check",
|
|
"service": "library-desk",
|
|
"executor": "rest_api_executor",
|
|
"priority": 60,
|
|
"description": "Nightly read-only integrity check for the library (vectors/graph/wiki/collections)",
|
|
"enabled": true,
|
|
"max_retries": 2,
|
|
"timeout_seconds": 900,
|
|
"minute": 30,
|
|
"hour": 4,
|
|
"day_of_month": -1,
|
|
"month": -1,
|
|
"day_of_week": -1,
|
|
"config": {
|
|
"method": "POST",
|
|
"url": "http://library-desk:8089/maintenance/integrity-check",
|
|
"headers": {
|
|
"Content-Type": "application/json"
|
|
},
|
|
"payload": {
|
|
"user": "jpmschweitzer"
|
|
},
|
|
"auth": {
|
|
"type": "bearer",
|
|
"token": "${LIBRARY_API_KEY}"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 2. Weekly quality report — Sunday 03:00
|
|
|
|
Runs the duplicate scan, flags stale/metadata-poor pages, folds in the
|
|
latest integrity results, and writes the dated report page to
|
|
`users/jpmschweitzer/system/quality-reports/YYYY-MM-DD`.
|
|
|
|
```json
|
|
{
|
|
"task_name": "library_quality_report",
|
|
"service": "library-desk",
|
|
"executor": "rest_api_executor",
|
|
"priority": 60,
|
|
"description": "Weekly library quality report (dedup, stale pages, missing metadata, integrity) written to the wiki",
|
|
"enabled": true,
|
|
"max_retries": 2,
|
|
"timeout_seconds": 1800,
|
|
"minute": 0,
|
|
"hour": 3,
|
|
"day_of_month": -1,
|
|
"month": -1,
|
|
"day_of_week": 6,
|
|
"config": {
|
|
"method": "POST",
|
|
"url": "http://library-desk:8089/maintenance/quality-report",
|
|
"headers": {
|
|
"Content-Type": "application/json"
|
|
},
|
|
"payload": {
|
|
"user": "jpmschweitzer",
|
|
"stale_days": 30,
|
|
"dedup_threshold": 0.9,
|
|
"write_page": true
|
|
},
|
|
"auth": {
|
|
"type": "bearer",
|
|
"token": "${LIBRARY_API_KEY}"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 3. Daily Paperless orphan cleanup — 05:00
|
|
|
|
Hits the **existing** cleanup endpoint (query parameters, empty payload).
|
|
`dry_run=false` deletes vectors/graph nodes for documents that were
|
|
removed from Paperless-ngx.
|
|
|
|
```json
|
|
{
|
|
"task_name": "library_paperless_orphan_cleanup",
|
|
"service": "library-desk",
|
|
"executor": "rest_api_executor",
|
|
"priority": 60,
|
|
"description": "Daily cleanup of vectors/graph nodes for documents deleted from Paperless-ngx",
|
|
"enabled": true,
|
|
"max_retries": 2,
|
|
"timeout_seconds": 900,
|
|
"minute": 0,
|
|
"hour": 5,
|
|
"day_of_month": -1,
|
|
"month": -1,
|
|
"day_of_week": -1,
|
|
"config": {
|
|
"method": "POST",
|
|
"url": "http://library-desk:8089/maintenance/cleanup/paperless?user=jpmschweitzer&dry_run=false",
|
|
"payload": {},
|
|
"auth": {
|
|
"type": "bearer",
|
|
"token": "${LIBRARY_API_KEY}"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 4. Disable `test_example_task`
|
|
|
|
Not a new task: the leftover example task must be **disabled** (not
|
|
deleted, so its history is preserved).
|
|
|
|
```
|
|
PUT ${SCHEDULER_URL}/tasks/test_example_task
|
|
Content-Type: application/json
|
|
|
|
{"enabled": false}
|
|
```
|
|
|
|
---
|
|
|
|
## Related (already registered / in-process)
|
|
|
|
- `knowledge_consolidation` — every 30 minutes, POST
|
|
`/consolidate/knowledge` (already registered; after the Phase C
|
|
consolidation repair its runs log `searches_processed` and
|
|
`duration_ms`, and searches are no longer consumed while the LLM is
|
|
unavailable).
|
|
- Redis job-set cleanup — runs **in-process** inside library-desk
|
|
(hourly `job_cleanup_loop` started at app startup); no Scheduler task
|
|
needed.
|