feat(F-006): users profile, addresses and RBAC
- users module: profile + address CRUD behind use cases (users_profiles, users_addresses) - roles customer/admin on identity_users; role resolved from DB per request - shared auth contract (Authenticate, requireRole, requireOwnerOrAdmin) injected from composition root; users never imports identity - authorization runs before existence checks; address SQL scoped by user_id - @fastify/cookie registered once at app root (cross-module) - migrations 003_identity_roles + 004_users (reversible) - no new npm dependencies; tests: unit 52, integration 22 Gates: reviewer/security/qa APPROVED; verify.sh green
This commit is contained in:
32
work/artifacts/F-006/architect.md
Normal file
32
work/artifacts/F-006/architect.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Architect — F-006 Users: profile, addresses, RBAC
|
||||
|
||||
done -> work/artifacts/F-006/architect.md
|
||||
|
||||
## Deliverables
|
||||
- specs/F-006-users-rbac/SPEC.md, DESIGN.md, TASKS.md, TESTS.md
|
||||
|
||||
## Key decisions
|
||||
1. **Cross-module auth por inyección, no por imports**: R1 prohíbe que `users` importe
|
||||
`identity`. identity exporta `createSessionAuthenticator` por su index; el
|
||||
composition root lo crea y lo inyecta en `registerUsersRoutes`. El contrato
|
||||
(`CurrentUser`, `Authenticate`, `requireRole`) vive en `src/shared/auth.ts`.
|
||||
2. **Role en identity_users** (migración 003): fuente única de verdad de autorización,
|
||||
viaja con el usuario autenticado, imposible de escalar vía API (register siempre
|
||||
crea 'customer'; solo DB/migración cambia roles).
|
||||
3. **Authz antes que existencia**: no-owner recibe 403 sin importar si el recurso
|
||||
existe (AC1 literal; sin enumeración).
|
||||
4. **Tablas users_profiles / users_addresses** con FK a identity_users solo como
|
||||
integridad de schema; queries runtime tocan únicamente tablas `users_*` (regla de
|
||||
prefijo intacta).
|
||||
5. **Admin endpoint dentro de users**: GET /users lista profiles (tabla propia).
|
||||
Nada obliga a users a leer identity_users en runtime.
|
||||
6. **Cero dependencias nuevas**.
|
||||
|
||||
## Security posture
|
||||
- Session resolution server-side (hash de token, expiración y revocación en SQL).
|
||||
- Owner-or-admin en cada ruta; admin-only con requireRole.
|
||||
- Role jamás proviene del cliente: sale del JOIN sessions+users en DB.
|
||||
|
||||
## Risks
|
||||
- Profiles lazy (no auto-create en register): GET /users lista solo profiles
|
||||
existentes. Aceptado para el slice; documentado.
|
||||
Reference in New Issue
Block a user