Notación UML de paquetes sobre la estructura real de src/. Las flechas indican dependencia (importa/usa) en la dirección del paquete que depende hacia el dependido; la línea punteada marca el único acoplamiento verdaderamente transversal del repo.
Ver versión ilustrada (notación UML de carpetas) ↗flowchart TB
MW["src/middleware.ts<br/>clasificador · rate limit · blocklist · chaos · headers"]
subgraph Presentacion["Presentación"]
direction LR
PAGES["src/pages/*.astro<br/>admin · portal · lab · notes · cv"]
API["src/pages/api/*<br/>admin · portal · auth · cron · payments"]
end
LIB["src/lib/*<br/>auth · payments · notify · monitors · demo<br/>(payments-state.ts es isomorfo, sin dep. de db/)"]
subgraph Transversales["Módulos transversales"]
direction LR
SEC["lib/security/<br/>micro-SIEM: clasificador, ratelimit, blocklist"]
PORTAL["lib/portal/<br/>sesión y auth del portal cliente"]
LAB["lib/lab/<br/>chaos · k6 · SAST (módulo LAB)"]
end
DB[("src/db/<br/>schema.ts · AsyncLocalStorage por request")]
TURSO[("Turso / libSQL<br/>prod y demo, bases físicas distintas")]
MW --> PAGES
MW --> API
MW -.->|consumo directo, pre-routing| SEC
PAGES --> LIB
API --> LIB
LIB --> SEC
LIB --> PORTAL
LIB --> LAB
SEC --> DB
PORTAL --> DB
LAB --> DB
DB --> TURSO
No solo lo consume lib/*: middleware.ts lo invoca directamente en cada request, antes de llegar a páginas o endpoints.
lib/portal/ mantiene sesión y cookie propias, sin compartir lógica ni cookies con Auth.js/GitHub (admin) ni con el pase HMAC (demo pública).
Vive dentro de lib/* pero no depende de db/, por lo que se importa igual desde endpoints del servidor y desde <script> en páginas Astro renderizadas en el navegador.
En modo demo, AsyncLocalStorage enruta las queries haciaTURSO_DEMO_URL, una base física distinta a la de producción.