Descripción
El endpoint /biblioteca/crons (y su gemelo server-to-server /api/biblioteca/crons) expone en tiempo real el estado de los 12 cron jobs del workspace CreaRack. Cierra la tarjeta Crons del sistema del Pulse (banda 4), que antes mostraba 9 de 12 crons con —. Con este PR, 11 de 12 crons tienen último-run auténtico.
El único cron sin telemetría es pg_dump · CreaRack-Pro, que corre en PROD (Hetzner) sin acceso D1 desde el workspace — se muestra — honesto con nota explicativa (Regla 13).
Arquitectura
Builder central: functions/_lib/crons.ts
Toda la lógica de agregación reside en buildCronsReport(env: CronsEnv). Es un aggregator sin caché propia: consulta las fuentes en cada request con AbortSignal.timeout(5s) y fallback limpio a null si falla.
CronsEnv
├── DB: D1Database
└── GH_PAT?: string ← PAT con scope actions:read
Fuentes por cron:
| Cron | Fuente | Tabla / API |
|---|---|---|
| Bibliotecario · Ingest | bib_wiki_log (D1) | WHERE operation='ingest' |
| Bibliotecario · Curator | bib_wiki_log (D1) | WHERE operation='curate' |
| Bibliotecario · Lint | bib_wiki_log (D1) | WHERE operation='lint' |
| Reindex · TS/TSX | GitHub Actions API | workflow 265753720 |
| Reindex · AST (Python) | bib_nodes (D1) | MAX(last_indexed_at) WHERE file_path LIKE '%.py' |
| Reindex · claude-method | GitHub Actions API | workflow 279618390 |
| Wiki · Drift-check | GitHub Actions API | workflow 276707608 |
| Wiki · Translate | GitHub Actions API | workflow 276287061 |
| Wiki · Weekly report | GitHub Actions API | workflow 265712084 |
| Sync Cascade · detect | GitHub Actions API | workflow 281534648 |
| DR Backups · workspace | activity_log (D1) | WHERE action='dr_export' |
| pg_dump · CreaRack-Pro | Sin telemetría | null honesto |
Las 6 llamadas a GitHub Actions API se lanzan en paralelo con Promise.all.
Endpoints CF Pages Functions
| URL | Auth | Descripción |
|---|---|---|
/biblioteca/crons | CF Access (browser) | Para el Pulse Panel |
/api/biblioteca/crons | Bearer token (MCP_TOKENS) | Server-to-server / agentes |
Ambos devuelven el mismo CronsReport JSON con Cache-Control: private, max-age=60.
Schema de respuesta
interface CronsReport {
generated_at: string; // ISO UTC
with_data: number; // crons con lastRun !== null
total: number; // siempre 12
crons: CronStatus[];
}
interface CronStatus {
key: string;
label: string;
group: 'Bibliotecario' | 'Reindex' | 'Wiki' | 'Sync' | 'Backups';
schedule: string;
lastRun: string | null; // ISO UTC o null
status: 'success' | 'failure' | 'cancelled' | 'skipped' | 'running' | null;
source: 'github_actions' | 'bib_wiki_log' | 'bib_nodes' | 'activity_log' | 'no-telemetry';
detailUrl: string | null; // enlace al run GHA si aplica
note?: string; // nota honesta si sin telemetría
}
Integración con PulsePanel
CronsHealthCard (en src/components/biblioteca/PulsePanel.tsx) consume /biblioteca/crons con refresh cada 60 segundos (best-effort). La tarjeta:
- Muestra un dot de color por cron:
- 🔴 Rojo (
--danger):status === 'failure' - 🟡 Amarillo (
--warning): último run supera el umbral del grupo - 🟢 Verde (
--success): en plazo - ⚫ Gris (
--fg-dim): sin datos (lastRun === null)
- 🔴 Rojo (
- Los crons con
detailUrl(GHA) enlazan al run en GitHub. - El
titledel dot muestra elstatusdel último run. - Si el endpoint falla: la tarjeta cae a estado “Cargando…” (best-effort, sin romper el Pulse).
Umbrales de staleness por grupo:
| Grupo | Umbral |
|---|---|
| Bibliotecario | 24 h |
| Reindex | 12 h |
| Wiki | 48 h |
| Sync | 24 h |
| Backups | 36 h |
Degradación limpia
- Si
GH_PATno tiene scopeactions:read→ los 6 crons GHA muestran—(sin error). - Si D1 no responde → los crons D1 muestran
—(.catch(() => ({ results: [] }))inline). - Verificación manual:
curl /api/biblioteca/crons(requiere Bearer token).
Archivos clave
| Archivo | Rol |
|---|---|
functions/_lib/crons.ts | Builder buildCronsReport, tipos CronStatus, CronsReport |
functions/biblioteca/crons.ts | Handler CF Pages Function (browser / CF Access) |
functions/api/biblioteca/crons.ts | Handler CF Pages Function (Bearer server-to-server) |
src/components/biblioteca/PulsePanel.tsx | CronsHealthCard + integración estado crons |
Véase también
- [[concept—general—que-es-el-pulse-panel-o-pulsepanel-del-workspace-b]]