Endpoint /api/tools/deps — API de frescura de dependencias
Fusionada en [[entity—functions—endpoint—tools-deps]] el 28-08-2026 (task #275). Las dos páginas documentaban el mismo endpoint
GET/POST /api/tools/depsy se crearon con un segundo de diferencia el 28-05-2026. El contenido vivo está en la superviviente; esta queda como histórico.
Descripción
Endpoint Cloudflare Pages Function (functions/api/tools/deps/index.ts) que sirve la tabla de frescura de dependencias de CreaRack-Pro y el Workspace. Maneja dos operaciones:
GET /api/tools/deps— lee el snapshot actual, ordenado por desfase (major primero).POST /api/tools/deps— reemplaza el snapshot completo (DELETE + INSERT batch) — invocado por el colector de GitHub Actions.
Métodos
GET /api/tools/deps
Autenticación: CF Access (navegador, vía _middleware.ts)
Response: 200 OK
{
"checked_at": "2026-05-28T19:55:42.123Z",
"count": 147,
"items": [
{
"repo": "crearack-pro",
"ecosystem": "pypi",
"manifest": "requirements.txt",
"package": "requests",
"pinned": "==2.28.0",
"installed": "2.28.0",
"latest": "2.31.0",
"lag_kind": "major",
"is_dev": 0,
"vuln_count": 0,
"vuln_ids": null,
"vuln_severity": null,
"manifests": "requirements.txt,tests/requirements.txt",
"resolved": "2.31.0",
"installed_source": "prod",
"unbounded": 1,
"unbounded_major": 0,
"fix_within_spec": null,
"checked_at": "2026-05-28T19:55:42.123Z"
},
...
]
}
Ordenamiento: con aviso de seguridad primero (vuln_count > 0), dentro de ellos por severidad (critical=0 … unknown=4), luego lag_kind (major=0, minor=1, patch=2, unknown=3, uptodate=4) → repo → lower(package).
POST /api/tools/deps
Autenticación: Bearer token (MCP_TOKEN en _middleware.ts)
Request body:
{
"items": [
{
"repo": "crearack-pro",
"ecosystem": "pypi",
"manifest": "requirements.txt",
"package": "requests",
"pinned": "==2.28.0",
"installed": "2.28.0",
"latest": "2.31.0",
"lag_kind": "major",
"is_dev": false,
"manifests": "requirements.txt,tests/requirements.txt",
"resolved": "2.31.0",
"installed_source": "prod",
"unbounded": true,
"unbounded_major": false,
"fix_within_spec": null
},
...
]
}
Validaciones:
itemsdebe ser un array, y como mucho 5000 filas (por encima →400; el snapshot real ronda unos cientos).- Campos obligatorios por fila:
repo,ecosystem,manifest,package. Una fila a la que le falte alguno se salta en silencio (no rompe el batch). - Campos opcionales:
pinned,installed,latest,is_dev(null/omitido → NULL en DB). lag_kind: valor en['major', 'minor', 'patch', 'uptodate', 'unknown']; si está fuera → se fuerza a'unknown'.vuln_severity: valor en['critical','high','moderate','medium','low','unknown']; fuera de esa lista → NULL.is_dev: boolean → se guarda como 0 o 1.
Campos del motor fiable (task #275, 28-08-2026 — migración 0052). Los payloads viejos no los traen y quedan en NULL/0, así que el endpoint sigue aceptando colectores anteriores:
| Campo | Tipo | Qué guarda |
|---|---|---|
manifests | texto o NULL | Todos los manifiestos donde aparece el paquete, separados por coma (manifest sigue siendo el ganador tras deduplicar: el más restrictivo) |
resolved | texto o NULL | Mayor versión publicada que la horquilla pinned admite — la que se instalaría hoy en un despliegue limpio |
installed_source | prod | runner | lockfile | De dónde salió installed. Cualquier otro valor → NULL |
unbounded | 0/1 | La horquilla no pone techo superior |
unbounded_major | 0/1 | Sin techo y ya corriendo en un major distinto al declarado |
fix_within_spec | 0/1/NULL | Tri-estado: 1 = hay versión con fix dentro de la horquilla (basta redeploy) · 0 = hay que cambiar el pin · NULL = OSV no publica versión con fix. Solo un booleano explícito se guarda como 0/1; ausente o basura → NULL |
Response: 200 OK
{
"inserted": 147,
"checked_at": "2026-05-28T19:55:42.123Z"
}
Response: 400 Bad Request si body.items no es un array.
Operación en DB: Ejecuta en batch:
DELETE FROM deps_freshness(limpia snapshot anterior).INSERT INTO deps_freshness (...)× N filas.- Todas con
checked_at= momento de la llamada.
Tabla D1 subyacente
Tabla: deps_freshness (migración 0042, ampliada por la 0048 y la 0052)
CREATE TABLE deps_freshness (
id INTEGER PRIMARY KEY,
repo TEXT NOT NULL, -- 'crearack-pro' | 'workspace'
ecosystem TEXT NOT NULL, -- 'pypi' | 'npm'
manifest TEXT NOT NULL, -- ruta relativa del manifiesto
package TEXT NOT NULL,
pinned TEXT, -- spec del manifiesto (==6.0.4, ^9.3.0...)
installed TEXT, -- versión resuelta
latest TEXT, -- última en PyPI/npm
lag_kind TEXT NOT NULL CHECK (...), -- 'major' | 'minor' | 'patch' | 'uptodate' | 'unknown'
is_dev INTEGER NOT NULL, -- 1 si es devDependency
checked_at TEXT NOT NULL,
-- 0048: eje de seguridad (OSV.dev)
vuln_count INTEGER, -- nº de avisos publicados para la versión en uso
vuln_ids TEXT, -- 'GHSA-...,PYSEC-...'
vuln_severity TEXT, -- la peor de la fila
-- 0052: motor fiable (task #275)
manifests TEXT, -- todos los manifiestos donde aparece, coma
resolved TEXT, -- mayor versión publicada que 'pinned' admite
installed_source TEXT, -- 'prod' | 'runner' | 'lockfile'
unbounded INTEGER NOT NULL DEFAULT 0, -- la horquilla no pone techo
unbounded_major INTEGER NOT NULL DEFAULT 0, -- ...y ya corre en otro major
fix_within_spec INTEGER -- 1 redeploy basta · 0 cambiar pin · NULL sin fix
);
Índices:
idx_deps_freshness_lag— sobrelag_kind(para filtrar por severidad).idx_deps_freshness_repo— sobre(repo, ecosystem)(para filtrar por origen).
Consumidores
- Frontend:
/tools/deps(Astro page) →DepsPanel.tsx→GET /api/tools/deps. - Hub stats:
ToolsHub.tsx→ agregación de counts de desfase. - Colector:
scripts/deps_freshness.py(CreaRack-Pro) →POST /api/tools/deps+ Bearer.
Flujo temporal
GitHub Actions (semanal o manual)
↓
scripts/deps_freshness.py (+ deps_specs.py, deps_sources.py)
• Lee manifiestos de ambos repos
• Consulta PyPI / npm (última publicada + lista completa de versiones)
• Resuelve cada horquilla a la mayor versión que admite → `resolved`
• Resuelve la "instalada": PROD real → runner del CI → lockfile
· PROD: GET https://crearack.com/api/installed-packages (Bearer
INTERNAL_TOOLS_TOKEN). Falla suave: si no contesta, cae al runner
• Deduplica por (repo, ecosistema, paquete) — gana la horquilla más
restrictiva; el resto de manifiestos queda en `manifests`
• Cruza (instalada || resuelta) con OSV.dev → avisos, severidad y
`fix_within_spec`
• Calcula desfase semver y marca las horquillas sin techo
↓
POST /api/tools/deps + Bearer
↓
DELETE + INSERT batch en D1
↓
GET /api/tools/deps (navegador con CF Access)
↓
DepsPanel + DepsBadges → tabla filtrada, fuente de "en uso" y avisos
Véase también
- [[feature—workspace—tool-dependencias]]
- [[runbook—workspace-tech—tool-dependencias]]
- [[entity—workspace—component—depspanel]]
- [[concept—infra—pages-functions]]