Backend
Documentación del proyecto api/: contratos, endpoints, autenticación y el
esquema de permisos por rol.
Qué documentar acá
Sección titulada «Qué documentar acá»-
Referencia de API — endpoints, request/response, códigos de error. Un endpoint sin documentar no está terminado.
-
Autenticación — cómo se emite y renueva el token, cómo se cierra sesión.
-
Autorización — cómo se implementa el modelo de permisos.
-
Errores — catálogo de códigos y qué significa cada uno para el cliente.
Estado actual
Sección titulada «Estado actual»Al 21-sep-2026:
- M0 — Auth + RBAC: ✅ (20-ago-2026)
- M1 — Productos: ✅ (22-ago-2026)
- M2 — Stock: ✅ (22-ago-2026)
- M3 — Insumos, M4 — Producción, M5 — Clientes, M6 — Ventas, M7 — Retornables: ✅
- M9 — Proveedores, M11 — Contador, M12 — Alertas: ✅
- M13 — Auditoría: ✅ (transversal desde M0)
- M14 — Clientes ubicables: ✅ (10-sep-2026)
- M15 — Seguimientos: ✅ (21-sep-2026)
- M10 — Precios: ✅ absorbido por M1 y M6
- M8 — Rutas y seller mobile: ⏸ POST-MVP (diferido)
1091 tests en api/, verificados de punta a punta contra web/ y la
base. Bruno corriendo en CI contra un servidor real.
Repositorio: aquazaku-api.
Qué expone hoy
Sección titulada «Qué expone hoy»| Endpoint | Quién puede | Notas |
|---|---|---|
GET /health |
cualquiera | Señal de vida |
POST /api/auth/sign-in/email |
cualquiera | Better-Auth. Límite: 5 intentos / 15 min |
POST /api/auth/request-password-reset |
cualquiera | Límite: 3 / 15 min |
POST /api/auth/reset-password |
con token | Cierra todas las sesiones |
GET /auth/me |
con sesión | Perfil + roles + permisos resueltos |
POST /auth/sign-out |
con sesión | |
POST /auth/change-password |
con sesión | Exige la contraseña actual |
GET /users, GET /users/:id |
usuarios:ver |
Incluye los roles |
POST /users |
usuarios:crear |
|
PATCH /users/:id |
usuarios:editar |
Desactivar cierra sus sesiones |
PUT /users/:id/roles |
usuarios:editar |
Idempotente; hace efecto en el acto |
GET /audit |
auditoria:ver |
Filtros + paginación por cursor |
GET /productos |
productos:ver |
?estado=activos|inactivos|todos, por defecto activos |
GET /productos/:id |
productos:ver |
|
POST /productos |
productos:crear |
El código lo genera el sistema (RN-CAT-11) |
PATCH /productos/:id |
productos:editar |
Solo el nombre — no toca precios |
PATCH /productos/:id/precios |
productos:editar_precios |
Los tres juntos. Audita antes y después |
POST /productos/:id/desactivar |
productos:desactivar |
|
POST /productos/:id/reactivar |
productos:desactivar |
|
GET /stock |
stock:ver |
Por producto: total, vendible y vencido |
GET /stock/:productoId/lotes |
stock:ver |
Con saldo, del más próximo a vencer |
GET /stock/movimientos |
stock:ver |
El libro. Filtros + paginación por cursor |
POST /stock/entradas |
stock:ajustar |
Crea el lote. Motivo obligatorio |
POST /stock/ajustes |
stock:ajustar |
± sobre un lote. Motivo obligatorio |
POST /stock/descartes |
stock:descartar |
Causa obligatoria (RN-STK-06) |
Todos menos los tres primeros pasan por requireAuth y requirePermission.
Módulos
Sección titulada «Módulos»modules/authz/— matriz de permisos ejecutable, alcances,can(),scopedCondition(), middleware y emisión de auditoría. La matriz es una transcripción 1-a-1 de Roles y permisos, y un test la verifica celda por celda contra una lista derivada del documento.modules/auth/— Better-Auth sobre el schema propio, transportes de correo (Resend y Mailpit) y límite de intentos.modules/users/— ABM con la protección del último administrador.modules/audit/— consulta de la bitácora.
Códigos de error
Sección titulada «Códigos de error»| Código | Status | Cuándo |
|---|---|---|
UNAUTHENTICATED |
401 | No vino cookie de sesión |
SESSION_EXPIRED |
401 | Vino una que el servidor ya no acepta |
USER_INACTIVE |
401 | La cuenta fue desactivada (RN-ACC-05) |
FORBIDDEN |
403 | Autenticado, sin permiso. Queda auditado |
AUDIT_UNAVAILABLE |
500 | No se pudo auditar una acción sensible, así que no se ejecutó — ADR-0007 |
RATE_LIMITED |
429 | Trae retry-after y reintentarEn |
VALIDATION_ERROR |
400 | Con detalle por campo |
ULTIMO_ADMIN |
409 | Dejaría el sistema sin administrador (RN-ACC-06) |
EMAIL_EN_USO |
409 | El email ya existe (citext: choca sin importar el case) |
PRODUCTO_NO_ENCONTRADO |
404 | |
PRECIO_MINIMO_INVALIDO |
422 | El piso superaría un precio de lista (RN-CAT-04) |
PRODUCTO_YA_INACTIVO |
409 | Desactivar uno que ya lo estaba |
PRODUCTO_YA_ACTIVO |
409 | Reactivar uno que ya lo estaba |
PRODUCTO_CON_STOCK |
409 | Desactivar uno con unidades en stock (RN-CAT-02) |
STOCK_INSUFICIENTE |
409 | Se pidió más de lo disponible. Trae el saldo real |
LOTE_NO_ENCONTRADO |
404 | |
MOTIVO_REQUERIDO |
422 | Ajuste sin motivo (RN-STK-02) |
CANTIDAD_INVALIDA |
422 | Cero, negativa donde no corresponde, o no entera |
Cómo explorarlo
Sección titulada «Cómo explorarlo»Hay una colección de Bruno versionada en el repo: Explorar la API con Bruno.
Decisiones que salieron de implementar
Sección titulada «Decisiones que salieron de implementar»- ADR-0004 —
audit_loginmutable con dos capas independientes. - ADR-0005 — los alcances fallan cerrados.
- RN-ACC-06 y RN-ACC-07 — dos reglas de negocio que aparecieron construyendo.
Referencias de diseño
Sección titulada «Referencias de diseño»- Spec de M0 — el plan tiene además notas de ejecución task por task, con lo que hubo que corregir.
- ADR-0001 — stack.
- ADR-0003 — matriz y multi-rol.
