> ## Documentation Index
> Fetch the complete documentation index at: https://docs.venezuelateayuda.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Service Bindings y sesiones

> Transporte interno, verificación de sesiones y estado de la migración.

El Worker de frontend usa el binding `BACKEND` para reenviar las rutas de socios
`/api/v1`, las estadísticas públicas y las fotos. Conserva la URL pública, el
método, los encabezados y el cuerpo de la solicitud. Backend aplica la
autenticación de socios, los permisos y los límites de frecuencia; frontend
devuelve su respuesta sin reconstruirla. El Worker exterior conserva sus
encabezados de seguridad y su política de caché pública.

La ausencia o falla del binding devuelve `503` con `Cache-Control: no-store`.
El adaptador conserva cuerpo en streaming, status y encabezados en una Response
con encabezados editables, necesaria para las redirecciones relativas de React
Router; conserva también múltiples Set-Cookie.

Estas rutas no recurren a D1 o R2 de frontend como alternativa. El contrato de las respuestas se conserva. La dirección canónica de socios es
`https://api.venezuelateayuda.com/v1`; `/api/v1` sigue admitido por compatibilidad.
El `fetch` público de backend solo admite esas rutas versionadas.
Frontend y admin enlazan el entrypoint privado `InternalBackend`, que conserva
el dispatcher interno sin exponer sesiones, operaciones administrativas ni D1
a solicitudes públicas. No se añaden Workers ni secretos de transporte.

## Aplicación de administración

Frontend reenvía `/admin`, `/admin/*`, `/admin.data`, `/auth/*` y
`/_admin/*` mediante el binding `ADMIN`. Admin tiene su propio Worker y árbol
de rutas React Router; sus recursos usan `/_admin/` y su manifiesto usa
`/admin/__manifest`. En producción, frontend redirige la navegación administrativa a
`admin.venezuelateayuda.com`, cuya raíz abre `/admin`. El proxy `ADMIN` se
conserva para desarrollo local. Los enlaces entre el registro
y la administración cargan el documento de la aplicación de destino.

Admin solo tiene el binding `BACKEND` y configuración pública del navegador.
D1, R2, WorkOS, correo, tareas programadas y Workflows pertenecen a backend.
Admin renueva la sesión antes de ejecutar los loaders administrativos y conserva
las cookies independientes de cada respuesta. Un fallo de `ADMIN` produce `503`
sin caché. El Worker de frontend conserva los encabezados de seguridad.

## Sesión interna

La sesión se verifica en backend a partir de la cookie sellada `vtb_session`.
Un ID de usuario, rol, permiso u organización enviado en encabezados, parámetros
o JSON no constituye identidad autenticada.

| Operación                            | Resultado                                                                                                       |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| `GET /internal/auth/session`         | `{ "user": null }` o el usuario verificado y sincronizado con su identidad WorkOS.                              |
| `GET /internal/auth/session/refresh` | Estado `unchanged`, `refreshed` o `failed`, con `reason` cuando corresponde y `Set-Cookie` si cambia la cookie. |

Ambas operaciones devuelven `Cache-Control: no-store`. No reciben cuerpo JSON.
La ausencia de sesión es un resultado normal; una falla del servicio devuelve
`503`, no un usuario anónimo. Los métodos distintos de GET/HEAD devuelven `405`.
HEAD conserva el comportamiento del dispatcher: procesa GET y omite el cuerpo.

La renovación conserva la semántica existente: solo `invalid_jwt` intenta
renovar. Una cookie inválida por otra razón se elimina; un intento de renovación
fallido conserva la cookie anterior. Solicitudes concurrentes con la misma
sesión comparten únicamente la renovación en curso, sin almacenar identidades
en caché.

Frontend actualiza la cookie de la solicitud que reciben los loaders y añade
`Set-Cookie` a la respuesta final, incluidos errores y redirecciones. La cookie
mantiene `HttpOnly`, `Path=/`, `SameSite=Lax`, siete días de duración y `Secure`
en HTTPS. El contenido sellado no se devuelve en JSON.

La renovación y la consulta de identidad son operaciones separadas para
conservar el orden actual: renovación antes de React Router; comprobación de
origen antes de autenticar y sincronizar al usuario en acciones protegidas.
Backend vuelve a autorizar cada operación migrada. Esto ya incluye las acciones
de perfil, usuarios, importación y todos los módulos administrativos descritos
abajo. Los comandos de mantenimiento y migración siguen pendientes de traslado.

## Autenticación y ajustes

Las rutas públicas `/auth/login`, `/auth/callback`, `/auth/logout` y
`/webhooks/auth` se reenvían a backend. Se conservan las redirecciones,
`Location`, `Set-Cookie` y el cuerpo original firmado del webhook. La verificación
usa el cuerpo sin volver a serializarlo. El estado del callback conserva el
contrato existente de ruta de retorno; este cambio no añade un nonce de sesión.

Los ajustes `/admin/settings/profile`, `/admin/settings/security`,
`/admin/settings/sessions` y `/admin/settings/users` se cargan en backend. Sus
permisos, organización, sesión y scopes salen de la cookie verificada. Frontend
valida el JSON de los loaders y conserva los errores y redirecciones de las
acciones, incluidos los límites de error de React Router. Los tokens de widgets
siguen siendo respuestas deliberadas para el componente de navegador WorkOS.

Las mutaciones autenticadas verifican primero `Sec-Fetch-Site: same-origin`,
o la igualdad de `Origin` con la URL original si falta ese encabezado; luego
resuelven la sesión y los permisos antes de acceder a D1.
Una solicitud directa rechazada por backend devuelve `403`. React Router puede
rechazar antes una solicitud de navegador con origen cruzado y devolver `400`.

## Importación y persona localizada

La acción `/admin/import` reenvía el multipart original. Backend autoriza
`ingestions:write`, valida UTF-8 y el máximo de 5 MiB, calcula el hash de los
bytes originales y controla la duplicación. Archiva el CSV en DOCUMENTS antes
del lote atómico de D1 y elimina el archivo si ese lote falla. Conserva el límite
de 750 operaciones y las revisiones de coincidencias posteriores al commit.
La interfaz de validación y la receta CSV conservan sus contratos.

## Registro público y recursos

Backend procesa GET `/`, las seis acciones del registro y GET `/resources`.
Conserva la proyección pública original, las reglas de menores, la búsqueda y
paginación de 24 resultados y la selección de una persona fuera de la página.
La caché del loader conserva 15 segundos de frescura y cinco minutos de respaldo
por clave; los fallbacks mantienen `Cache-Control: no-store` y
`X-VTB-Fallback: d1-transient` al cruzar React Router. Recursos no añade fallback.

Todas las mutaciones verifican honeypot y Turnstile una sola vez en backend.
Si el widget de Turnstile no carga o falla, frontend muestra un aviso con una
acción para reintentar la verificación sin borrar los datos del formulario.
El reintento no omite la validación en backend.
Registro conserva detección de duplicados, fotos, suscripción y auditoría en su
orden existente; edición pública sigue denegada. Tips y reportes conservan su
comprobación de persona activa, incluso privada, mientras suscripción requiere
una persona pública desaparecida. Esta transferencia no cambia esa diferencia.
`markFound` sigue encolando correo, iniciándolo con `waitUntil` y auditando la
actualización. Los errores de formulario y transporte conservan su respuesta
inline. GET `/api/health` también se reenvía sin leer D1 en frontend.

## Formularios y administración

Los formularios de coordinación `/forms/C36PV1U4` y `/forms/DU2INZQ4`
están retirados. Sus lecturas y mutaciones devuelven 404 sin acceder a D1.

El layout administrativo consulta `/internal/admin/bootstrap` con la ruta
administrativa original validada para conservar login y onboarding. La página
`/admin` carga por separado el dashboard y procesa el inbox, derivando permisos
y scope de la cookie verificada. Marcar todas como leídas actualiza todos los
pendientes del destinatario en lotes de hasta 98 IDs dentro de un único batch
atómico, incluidos los que no aparecen en la página actual. La auditoría ocurre
después y no revierte esa actualización si falla.

## Moderación y operaciones administrativas

Backend controla los loaders y acciones de `/admin/persons` y su detalle,
`/admin/tips`, `/admin/reports`, `/admin/resources`, `/admin/duplicates` y su
detalle. Conserva filtros, paginación, permisos y scopes.
Las acciones de detalle de persona leen el intent antes de elegir el permiso, y autorizan antes
de consultar o modificar datos. Cada solicitud deriva actor y acceso de la
sesión verificada; no confía en IDs o scopes enviados por frontend.

Frontend valida el JSON de los loaders y reenvía multipart, cookies, errores y
redirecciones. Los formularios conservan `{ success, errors, data }`, la primera
ocurrencia del intent y la última de cada campo escalar cuando así lo hacía el
formulario original. Las menciones explícitas conservan todos sus valores.
Los contactos opcionales nulos de revisiones históricas siguen siendo válidos.

Persona conserva la auditoría de lectura, privacidad, tratamiento
de fotos y la secuencia de escrituras/auditorías. Las menciones se auditan desde
las filas persistidas elegibles, sin incluir contenido del comentario. Una
falla posterior de auditoría no deshace las escrituras previas.

## CRM y ajustes

Las rutas de familias, contactos y organizaciones también
cargan y modifican datos exclusivamente en backend. Conservan sus permisos,
scopes y secuencias originales. Familias mantienen los límites de búsqueda de
personas y la redacción sensible. Contactos y organizaciones conservan acceso
por permisos globales, sin añadir un filtro de centro durante este traslado.
Las escrituras de contacto, vínculo y auditoría siguen siendo etapas separadas.

Los centros y las colocaciones no tienen rutas ni controles activos. Las familias
nuevas no se asignan a centros; sus miembros no generan ni modifican colocaciones.
El alcance histórico se conserva en las autorizaciones de personas y familias.
Crear una familia sin centro requiere alcance no restringido y `families:write`.
Los DTO de contactos no incluyen centros ni nombres de centros, y los de personas
y familias no incluyen colocaciones ni selectores de centros.

La lógica de claves API pertenece a `apps/backend/src/api-keys`. Sus permisos
compartidos pertenecen a `packages/auth/constants`; no hay paquete `api-keys`.

`/admin/settings/api-keys` verifica `api_keys:read` o `api_keys:write`, deriva
la organización de la sesión y devuelve solo claves activas en el listado.
La creación devuelve el plaintext una vez; no se incluye en la auditoría.
Se conserva el primer valor de campos repetidos. Una falla de auditoría después
de crear o revocar mantiene la escritura y devuelve el error inline existente.
Las respuestas usan `Cache-Control: no-store`.

Actividad exige `admin:manage` y `events:read`. Lista y detalle conservan
visibilidad de la organización más eventos globales, páginas de 25 filas y el
orden por fecha/ID. Los tipos históricos de eventos y sus snapshots se conservan;
frontend analiza únicamente los datos de presentación, sin consultar D1.

## Enlaces públicos de entrega

`/delivery/:token` está retirado: GET y las mutaciones devuelven 404.
No se emiten ni confirman entregas. Los tokens y registros históricos permanecen
en la base de datos; no se requiere `PUBLIC_DELIVERY_LINK_SECRET` en ejecución.

## Trabajos y almacenamiento

Backend es el único propietario configurado del cron de quince minutos,
`IngestTriggerWorkflow`, `IngestWorkflow` y `DuplicateScanWorkflow`. Conserva
nombres de workflows y pasos, reclamaciones atómicas, leases, reintentos,
contadores crudos y cursores combinados de pacientes/admisiones. Las fotos
conservan claves, metadatos, límite de 10 MiB y aborto de fetch a los 15 segundos.

La recuperación de correo conserva lotes de 25, reclamaciones de diez minutos
y tres intentos. Los estados y las auditorías conservan su orden existente;
no se promete entrega exactamente una vez. Un fallo después del envío puede
provocar una nueva entrega al recuperar una reclamación expirada.

Frontend ya no tiene D1, R2, EMAIL, cron ni bindings/clases de Workflow.
Backend ejecuta todas las operaciones de datos y fotos, además de los comandos
de mantenimiento y migración. Los 105 archivos de migración permanecen en `packages/db`.

## Configuración y despliegue

Backend necesita `WORKOS_API_KEY`, `WORKOS_CLIENT_ID`, `WORKOS_COOKIE_PASSWORD`,
`WORKOS_REDIRECT_URI` y `WORKOS_WEBHOOK_SECRET`; el redirect apunta al frontend
público. Frontend ya no consume esos secretos. Doppler sigue siendo la fuente
de configuración; los archivos de ejemplo no contienen credenciales.

`DEV_AUTH_USER_ID=dev-user-local` solo se admite en configuración local de
backend para solicitudes HTTP con host `localhost`, `127.0.0.1` o `[::1]`.
Nunca configure ese override en producción;
una opción equivalente en frontend o en una solicitud no lo activa.

Backend necesita `TURNSTILE_SECRET_KEY`, `PUBLIC_DELIVERY_LINK_SECRET` y el
binding `PUBLIC_WRITE_RATE_LIMIT`; frontend ya no los consume. El site key de
Turnstile permanece público. Backend comparte el token del proyecto de analítica
administrativa mientras frontend mantiene sus consumidores actuales; conserva
solo eventos y propiedades aprobados, sin consultas ni IDs en las URLs.
Las credenciales de proveedores se trasladan
sin generar valores nuevos. EMAIL y sus remitentes, DOCUMENTS y los tres bindings
de Workflow están declarados en backend.

Vite inicia backend como Worker auxiliar y comparte D1/R2 en
`apps/frontend/.wrangler/state/v3`. Los comandos de mantenimiento e ingesta en
`apps/backend/scripts` resuelven la configuración de backend y esa ruta desde
el módulo, sin depender del directorio actual ni mover los datos existentes.
Wrangler CLI recibe el directorio padre `state`, pues agrega `v3`; los proxies
locales reciben `state/v3`. Las rutas de entrada/salida indicadas por el operador
siguen siendo relativas a su directorio actual. Cada aplicación conserva su
build independiente.

Antes de un despliegue autorizado, comprobar instancias activas y el traspaso
de propietario de los tres Workflows existentes. Conservar nombres e IDs de
instancia/paso; evitar crons activos simultáneamente en ambos Workers.
Configurar backend antes de publicar los adaptadores frontend. La configuración
actual es el destino del cambio, no prueba de que producción se haya transferido.
No se ha desplegado este cambio ni ejecutado una migración de producción.

## Retiro de coordinación

Las rutas `/admin/schedules`, `/admin/requests`, `/admin/inventory`,
`/admin/orders`, `/admin/fulfillments` y `/admin/sites`, incluidos sus detalles y
mutaciones, devuelven 404. Personas, familias, contactos y organizaciones conservan
sus rutas. El Inbox y las menciones admiten únicamente los destinos de CRM activos;
las notificaciones antiguas de coordinación permanecen almacenadas.

Se eliminaron los paquetes de solicitudes, inventario, pedidos, entregas, centros
y colocaciones. Este retiro conserva tablas, esquema, migraciones y datos como
respaldo temporal; no ejecuta migraciones ni modifica el contrato público `/api/v1`.

## Compatibilidad de colecciones relacionadas

Las lecturas de reportes de una persona y de tips para varias personas usan páginas
internas de 50 registros por defecto, con un máximo de 100. La continuación valida
el conjunto de personas, el estado cuando corresponde, la visibilidad y el orden,
con el identificador como desempate único.

Backend consume explícitamente estas páginas para conservar las listas completas
que ya devuelve la API y los tips incluidos en personas. Los formatos públicos y
sus reglas de minimización no cambian. Las lecturas públicas excluyen personas
privadas o eliminadas; únicamente los consumidores que ya autorizaron esas
personas habilitan la lectura de sus colecciones administrativas.

La colección paginada de tips de una sola persona conserva el límite público de
50 registros por defecto y 100 como máximo. Acepta cursores públicos anteriores
sin el filtro interno de visibilidad o sin identificador de persona; la consulta
siempre permanece limitada a la persona de la ruta. Los cursores actuales validan
la persona, el orden y la visibilidad durante la continuación.

Las fuentes de una persona se agrupan después de reunir sus páginas,
conservando notas, identificadores y la selección de fechas entre páginas.

Los alcances de autorización reúnen todas sus páginas internas de 100 sedes.
No limitan los permisos a las primeras 100 asignaciones y conservan las reglas
existentes de relaciones e inclusión por estado.

Comment mention recipients need explicit stored read permissions for comments and their target. Empty or malformed permissions grant no recipient access. Contact deletion removes the contact and its comments in one transaction; a failure preserves both.

El endpoint de salud conserva el estado de D1 y almacenamiento, sin un campo
`version`. La versión desplegada se consulta en Cloudflare; no hay variable
`VERSION` en los Workers.
