erp-core/docs/04-modelado/trazabilidad/TRACEABILITY-MGN-001.yaml

1408 lines
52 KiB
YAML

# TRACEABILITY-MGN-001.yaml
# Matriz de Trazabilidad - MGN-001: Fundamentos
# Fecha: 2025-11-24
# Versión: 1.0
module:
id: MGN-001
name: "Fundamentos"
description: "Autenticación, usuarios, roles, permisos, multi-tenancy"
priority: P0
story_points: 68
status: Diseñado
metadata:
total_rf: 8
total_et_backend: 8
total_et_frontend: 8
total_tables: 10
total_tests: 94
coverage: 100%
requirements:
- rf_id: RF-MGN-001-001
rf_title: "Autenticación de Usuarios"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-001-autenticacion-usuarios.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-001-autenticación-de-usuarios.md"
endpoints:
- method: POST
path: /api/v1/auth/login
description: "Autenticación con email y contraseña"
- method: POST
path: /api/v1/auth/refresh
description: "Renovar JWT con refresh token"
- method: POST
path: /api/v1/auth/logout
description: "Cerrar sesión"
services:
- name: "AuthService"
file: "src/modules/auth/services/auth.service.ts"
methods:
- login
- validateUser
- generateTokens
- refreshToken
- logout
controllers:
- name: "AuthController"
file: "src/modules/auth/controllers/auth.controller.ts"
dtos:
- name: "LoginDto"
file: "src/modules/auth/dto/login.dto.ts"
- name: "TokenResponseDto"
file: "src/modules/auth/dto/token-response.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-001-autenticación-de-usuarios.md"
routes:
- path: "/login"
component: "LoginPage"
- path: "/logout"
component: "LogoutPage"
components:
- name: "LoginForm"
file: "src/features/auth/ui/LoginForm.tsx"
type: feature
api_client:
- name: "authApi"
file: "src/entities/auth/api/auth.api.ts"
methods:
- login
- refresh
- logout
state_management:
- name: "useAuthStore"
file: "src/entities/auth/model/auth.store.ts"
type: zustand
database_tables:
- schema: auth
table: users
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- UPDATE
indices:
- idx_users_email_tenant
- idx_users_tenant_id
rls_policy: tenant_isolation_users
- schema: auth
table: login_history
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- INSERT
indices:
- idx_login_history_user_id
- idx_login_history_created_at
rls_policy: tenant_isolation_login_history
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/auth.service.spec.ts"
test_cases:
- "should authenticate user with valid credentials"
- "should throw UnauthorizedException for invalid credentials"
- "should increment failed_login_attempts on failure"
- "should lock account after 5 failed attempts"
- "should generate valid JWT token"
- "should refresh token successfully"
integration_tests:
- file: "test/auth/auth.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/auth/login should return JWT token"
- "POST /api/v1/auth/login should return 401 for invalid credentials"
- "POST /api/v1/auth/refresh should renew token"
- "POST /api/v1/auth/logout should invalidate session"
- "should enforce tenant isolation"
frontend:
component_tests:
- file: "src/features/auth/ui/LoginForm.test.tsx"
test_cases:
- "should render login form"
- "should validate email format"
- "should validate password required"
- "should submit valid credentials"
- "should show error for invalid credentials"
e2e_tests:
- file: "e2e/auth/login.spec.ts"
test_cases:
- "should login successfully with valid credentials"
- "should show error for invalid credentials"
- "should redirect to dashboard after login"
- "should lock account after 5 failed attempts"
acceptance_criteria:
- id: AC-001
description: "Usuario con credenciales válidas puede autenticarse exitosamente"
status: Pending
test_reference: "test/auth/auth.controller.e2e-spec.ts:24"
- id: AC-002
description: "JWT token contiene user_id, tenant_id, roles, permissions"
status: Pending
test_reference: "src/modules/auth/services/auth.service.spec.ts:42"
- id: AC-003
description: "Sistema bloquea cuenta después de 5 intentos fallidos"
status: Pending
test_reference: "test/auth/auth.controller.e2e-spec.ts:68"
business_rules:
- id: RN-001
description: "Email debe ser único por tenant (no globalmente)"
implementation: "database-design/schemas/auth-schema-ddl.sql:CONSTRAINT uq_users_email_tenant"
test_reference: "test/auth/auth.controller.e2e-spec.ts:92"
- id: RN-002
description: "Contraseña debe tener mínimo 8 caracteres, 1 mayúscula, 1 número"
implementation: "src/modules/auth/dto/login.dto.ts:@IsStrongPassword()"
test_reference: "src/modules/auth/services/auth.service.spec.ts:108"
- id: RN-003
description: "JWT expira en 8 horas, refresh token en 30 días"
implementation: "src/modules/auth/services/auth.service.ts:generateTokens()"
test_reference: "src/modules/auth/services/auth.service.spec.ts:124"
dependencies:
rf_dependencies: []
module_dependencies: []
external_dependencies:
- name: "@nestjs/passport"
version: "^10.0.0"
- name: "bcrypt"
version: "^5.1.0"
- name: "jsonwebtoken"
version: "^9.0.0"
- rf_id: RF-MGN-001-002
rf_title: "Gestión de Roles y Permisos (RBAC)"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-002-gestion-roles.md"
priority: P0
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-002-gestión-de-roles-y-permisos-rbac.md"
endpoints:
- method: POST
path: /api/v1/auth/roles
description: "Crear rol"
- method: GET
path: /api/v1/auth/roles
description: "Listar roles"
- method: GET
path: /api/v1/auth/roles/:id
description: "Obtener rol por ID"
- method: PUT
path: /api/v1/auth/roles/:id
description: "Actualizar rol"
- method: DELETE
path: /api/v1/auth/roles/:id
description: "Eliminar rol"
- method: POST
path: /api/v1/auth/roles/:id/permissions
description: "Asignar permisos a rol"
services:
- name: "RoleService"
file: "src/modules/auth/services/role.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- assignPermissions
controllers:
- name: "RoleController"
file: "src/modules/auth/controllers/role.controller.ts"
dtos:
- name: "CreateRoleDto"
file: "src/modules/auth/dto/create-role.dto.ts"
- name: "UpdateRoleDto"
file: "src/modules/auth/dto/update-role.dto.ts"
- name: "AssignPermissionsDto"
file: "src/modules/auth/dto/assign-permissions.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-002-gestión-de-roles-y-permisos-rbac.md"
routes:
- path: "/auth/roles"
component: "RolesPage"
- path: "/auth/roles/create"
component: "CreateRolePage"
- path: "/auth/roles/:id/edit"
component: "EditRolePage"
- path: "/auth/roles/:id"
component: "ViewRolePage"
components:
- name: "RolesTable"
file: "src/widgets/roles-table/ui/RolesTable.tsx"
type: widget
- name: "CreateRoleForm"
file: "src/features/create-role/ui/CreateRoleForm.tsx"
type: feature
- name: "PermissionsMatrix"
file: "src/features/assign-permissions/ui/PermissionsMatrix.tsx"
type: feature
api_client:
- name: "roleApi"
file: "src/entities/role/api/role.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
- assignPermissions
state_management:
- name: "useRoleStore"
file: "src/entities/role/model/role.store.ts"
type: zustand
- name: "useRoles"
file: "src/entities/role/api/role.queries.ts"
type: react-query
database_tables:
- schema: auth
table: roles
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_roles_tenant_id
- idx_roles_name_tenant
rls_policy: tenant_isolation_roles
- schema: auth
table: permissions
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_permissions_model_action
rls_policy: tenant_isolation_permissions
- schema: auth
table: role_permissions
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- DELETE
indices:
- idx_role_permissions_role_id
- idx_role_permissions_permission_id
rls_policy: tenant_isolation_role_permissions
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/role.service.spec.ts"
test_cases:
- "should create role with valid data"
- "should throw error when role name already exists"
- "should assign permissions to role"
- "should validate permission existence before assignment"
- "should find all roles for tenant"
- "should update role successfully"
- "should soft delete role"
integration_tests:
- file: "test/auth/role.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/auth/roles should create role"
- "GET /api/v1/auth/roles should return all roles"
- "GET /api/v1/auth/roles/:id should return role with permissions"
- "PUT /api/v1/auth/roles/:id should update role"
- "DELETE /api/v1/auth/roles/:id should soft delete role"
- "POST /api/v1/auth/roles/:id/permissions should assign permissions"
- "should enforce tenant isolation"
- "should require authentication"
- "should check admin permissions"
frontend:
component_tests:
- file: "src/widgets/roles-table/ui/RolesTable.test.tsx"
test_cases:
- "should render table with roles"
- "should handle pagination"
- "should call delete on button click"
- file: "src/features/create-role/ui/CreateRoleForm.test.tsx"
test_cases:
- "should validate required fields"
- "should submit valid form"
- "should show error messages"
- file: "src/features/assign-permissions/ui/PermissionsMatrix.test.tsx"
test_cases:
- "should render permissions grouped by model"
- "should toggle permissions on checkbox click"
- "should save permissions successfully"
e2e_tests:
- file: "e2e/auth/roles.spec.ts"
test_cases:
- "should create role successfully"
- "should assign permissions to role"
- "should edit role successfully"
- "should delete role with confirmation"
- "should enforce admin permissions"
acceptance_criteria:
- id: AC-001
description: "Administrador puede crear roles con permisos CRUD por modelo"
status: Pending
test_reference: "test/auth/role.controller.e2e-spec.ts:30"
- id: AC-002
description: "Roles soportan herencia (parent_role_id)"
status: Pending
test_reference: "test/auth/role.controller.e2e-spec.ts:55"
- id: AC-003
description: "Permisos se validan en cada endpoint (PermissionsGuard)"
status: Pending
test_reference: "test/auth/role.controller.e2e-spec.ts:85"
business_rules:
- id: RN-001
description: "Nombre de rol debe ser único por tenant"
implementation: "database-design/schemas/auth-schema-ddl.sql:CONSTRAINT uq_roles_name_tenant"
test_reference: "src/modules/auth/services/role.service.spec.ts:45"
- id: RN-002
description: "Permisos se definen como {model}.{action} (ej: users.create)"
implementation: "database-design/schemas/auth-schema-ddl.sql:permissions table"
test_reference: "src/modules/auth/services/role.service.spec.ts:68"
- id: RN-003
description: "No se puede eliminar rol si tiene usuarios asignados"
implementation: "src/modules/auth/services/role.service.ts:remove()"
test_reference: "src/modules/auth/services/role.service.spec.ts:92"
dependencies:
rf_dependencies: []
module_dependencies: []
external_dependencies:
- name: "@nestjs/common"
version: "^10.0.0"
- name: "class-validator"
version: "^0.14.0"
- rf_id: RF-MGN-001-003
rf_title: "Gestión de Usuarios"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-003-gestion-usuarios.md"
priority: P0
story_points: 8
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-003-gestión-de-usuarios.md"
endpoints:
- method: POST
path: /api/v1/auth/users
description: "Crear usuario"
- method: GET
path: /api/v1/auth/users
description: "Listar usuarios"
- method: GET
path: /api/v1/auth/users/:id
description: "Obtener usuario por ID"
- method: PUT
path: /api/v1/auth/users/:id
description: "Actualizar usuario"
- method: DELETE
path: /api/v1/auth/users/:id
description: "Eliminar usuario (soft delete)"
- method: POST
path: /api/v1/auth/users/:id/roles
description: "Asignar roles a usuario"
- method: PATCH
path: /api/v1/auth/users/:id/password
description: "Cambiar contraseña"
services:
- name: "UserService"
file: "src/modules/auth/services/user.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- assignRoles
- changePassword
controllers:
- name: "UserController"
file: "src/modules/auth/controllers/user.controller.ts"
dtos:
- name: "CreateUserDto"
file: "src/modules/auth/dto/create-user.dto.ts"
- name: "UpdateUserDto"
file: "src/modules/auth/dto/update-user.dto.ts"
- name: "ChangePasswordDto"
file: "src/modules/auth/dto/change-password.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-003-gestión-de-usuarios.md"
routes:
- path: "/auth/users"
component: "UsersPage"
- path: "/auth/users/create"
component: "CreateUserPage"
- path: "/auth/users/:id/edit"
component: "EditUserPage"
- path: "/auth/users/:id"
component: "ViewUserPage"
components:
- name: "UsersTable"
file: "src/widgets/users-table/ui/UsersTable.tsx"
type: widget
- name: "CreateUserForm"
file: "src/features/create-user/ui/CreateUserForm.tsx"
type: feature
- name: "UserCard"
file: "src/entities/user/ui/UserCard.tsx"
type: entity
api_client:
- name: "userApi"
file: "src/entities/user/api/user.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
- assignRoles
- changePassword
state_management:
- name: "useUserStore"
file: "src/entities/user/model/user.store.ts"
type: zustand
- name: "useUsers"
file: "src/entities/user/api/user.queries.ts"
type: react-query
database_tables:
- schema: auth
table: users
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_users_tenant_id
- idx_users_email_tenant
- idx_users_status
rls_policy: tenant_isolation_users
- schema: auth
table: user_roles
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- DELETE
indices:
- idx_user_roles_user_id
- idx_user_roles_role_id
rls_policy: tenant_isolation_user_roles
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/user.service.spec.ts"
test_cases:
- "should create user with valid data"
- "should hash password before saving"
- "should throw error when email already exists"
- "should assign roles to user"
- "should change password successfully"
- "should validate old password before changing"
- "should soft delete user"
integration_tests:
- file: "test/auth/user.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/auth/users should create user"
- "GET /api/v1/auth/users should return all users"
- "GET /api/v1/auth/users/:id should return user with roles"
- "PUT /api/v1/auth/users/:id should update user"
- "DELETE /api/v1/auth/users/:id should soft delete user"
- "POST /api/v1/auth/users/:id/roles should assign roles"
- "PATCH /api/v1/auth/users/:id/password should change password"
- "should enforce tenant isolation"
frontend:
component_tests:
- file: "src/widgets/users-table/ui/UsersTable.test.tsx"
test_cases:
- "should render table with users"
- "should handle pagination"
- "should filter by status"
- file: "src/features/create-user/ui/CreateUserForm.test.tsx"
test_cases:
- "should validate email format"
- "should validate password strength"
- "should submit valid form"
e2e_tests:
- file: "e2e/auth/users.spec.ts"
test_cases:
- "should create user successfully"
- "should assign roles to user"
- "should change password successfully"
- "should delete user with confirmation"
acceptance_criteria:
- id: AC-001
description: "Administrador puede crear usuarios con email y contraseña"
status: Pending
test_reference: "test/auth/user.controller.e2e-spec.ts:25"
- id: AC-002
description: "Contraseñas se almacenan hasheadas con bcrypt"
status: Pending
test_reference: "src/modules/auth/services/user.service.spec.ts:42"
- id: AC-003
description: "Usuario puede cambiar su propia contraseña"
status: Pending
test_reference: "test/auth/user.controller.e2e-spec.ts:105"
business_rules:
- id: RN-001
description: "Email debe ser único por tenant"
implementation: "database-design/schemas/auth-schema-ddl.sql:CONSTRAINT uq_users_email_tenant"
test_reference: "src/modules/auth/services/user.service.spec.ts:58"
- id: RN-002
description: "Usuario debe tener al menos un rol asignado"
implementation: "src/modules/auth/services/user.service.ts:create()"
test_reference: "src/modules/auth/services/user.service.spec.ts:76"
- id: RN-003
description: "Status del usuario debe ser 'active' para login"
implementation: "src/modules/auth/services/auth.service.ts:validateUser()"
test_reference: "src/modules/auth/services/auth.service.spec.ts:95"
dependencies:
rf_dependencies:
- RF-MGN-001-002
module_dependencies: []
external_dependencies:
- name: "bcrypt"
version: "^5.1.0"
- name: "class-validator"
version: "^0.14.0"
- rf_id: RF-MGN-001-004
rf_title: "Multi-Tenancy con Schema-Level Isolation"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-004-multi-tenancy.md"
priority: P0
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-004-multi-tenancy-con-schema-level-isolation.md"
endpoints:
- method: POST
path: /api/v1/tenants
description: "Crear tenant (admin solo)"
- method: GET
path: /api/v1/tenants
description: "Listar tenants (admin solo)"
- method: GET
path: /api/v1/tenants/:id
description: "Obtener tenant por ID"
- method: PUT
path: /api/v1/tenants/:id
description: "Actualizar tenant"
- method: GET
path: /api/v1/tenants/current
description: "Obtener tenant actual del usuario"
services:
- name: "TenantService"
file: "src/modules/auth/services/tenant.service.ts"
methods:
- create
- findAll
- findOne
- update
- getCurrentTenant
- createTenantSchema
controllers:
- name: "TenantController"
file: "src/modules/auth/controllers/tenant.controller.ts"
dtos:
- name: "CreateTenantDto"
file: "src/modules/auth/dto/create-tenant.dto.ts"
- name: "UpdateTenantDto"
file: "src/modules/auth/dto/update-tenant.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-004-multi-tenancy-con-schema-level-isolation.md"
routes:
- path: "/admin/tenants"
component: "TenantsPage"
- path: "/admin/tenants/create"
component: "CreateTenantPage"
- path: "/admin/tenants/:id"
component: "ViewTenantPage"
components:
- name: "TenantsTable"
file: "src/widgets/tenants-table/ui/TenantsTable.tsx"
type: widget
- name: "CreateTenantForm"
file: "src/features/create-tenant/ui/CreateTenantForm.tsx"
type: feature
- name: "TenantSwitcher"
file: "src/features/tenant-switcher/ui/TenantSwitcher.tsx"
type: feature
api_client:
- name: "tenantApi"
file: "src/entities/tenant/api/tenant.api.ts"
methods:
- getAll
- getById
- create
- update
- getCurrent
state_management:
- name: "useTenantStore"
file: "src/entities/tenant/model/tenant.store.ts"
type: zustand
- name: "useTenants"
file: "src/entities/tenant/api/tenant.queries.ts"
type: react-query
database_tables:
- schema: auth
table: tenants
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_tenants_subdomain
- idx_tenants_schema_name
- idx_tenants_status
rls_policy: null
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/tenant.service.spec.ts"
test_cases:
- "should create tenant with unique subdomain"
- "should create schema for tenant"
- "should throw error when subdomain already exists"
- "should get current tenant from context"
- "should update tenant successfully"
integration_tests:
- file: "test/auth/tenant.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/tenants should create tenant"
- "GET /api/v1/tenants should return all tenants (admin only)"
- "GET /api/v1/tenants/current should return current tenant"
- "PUT /api/v1/tenants/:id should update tenant"
- "should enforce superadmin permissions"
- "should validate subdomain format"
frontend:
component_tests:
- file: "src/widgets/tenants-table/ui/TenantsTable.test.tsx"
test_cases:
- "should render table with tenants"
- "should show tenant status"
- file: "src/features/create-tenant/ui/CreateTenantForm.test.tsx"
test_cases:
- "should validate subdomain format"
- "should validate unique subdomain"
- "should submit valid form"
e2e_tests:
- file: "e2e/auth/tenants.spec.ts"
test_cases:
- "should create tenant successfully (superadmin)"
- "should show error for duplicate subdomain"
- "should enforce superadmin permissions"
acceptance_criteria:
- id: AC-001
description: "Cada tenant tiene su propio schema PostgreSQL"
status: Pending
test_reference: "src/modules/auth/services/tenant.service.spec.ts:32"
- id: AC-002
description: "Usuarios de un tenant NO pueden ver datos de otro tenant"
status: Pending
test_reference: "test/auth/tenant.controller.e2e-spec.ts:68"
- id: AC-003
description: "Subdomain debe ser único y válido (a-z0-9-)"
status: Pending
test_reference: "test/auth/tenant.controller.e2e-spec.ts:92"
business_rules:
- id: RN-001
description: "Subdomain debe ser único globalmente"
implementation: "database-design/schemas/auth-schema-ddl.sql:CONSTRAINT UNIQUE subdomain"
test_reference: "src/modules/auth/services/tenant.service.spec.ts:54"
- id: RN-002
description: "Schema_name debe seguir formato tenant_{subdomain}"
implementation: "src/modules/auth/services/tenant.service.ts:create()"
test_reference: "src/modules/auth/services/tenant.service.spec.ts:72"
- id: RN-003
description: "Todas las queries deben filtrar por tenant_id automáticamente (RLS)"
implementation: "database-design/schemas/auth-schema-ddl.sql:RLS policies"
test_reference: "test/integration/rls.e2e-spec.ts:25"
dependencies:
rf_dependencies: []
module_dependencies: []
external_dependencies:
- name: "pg"
version: "^8.11.0"
- name: "@nestjs/config"
version: "^3.0.0"
- rf_id: RF-MGN-001-005
rf_title: "Reset de Contraseña"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-005-reset-password.md"
priority: P0
story_points: 5
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-005-reset-de-contraseña.md"
endpoints:
- method: POST
path: /api/v1/auth/password/forgot
description: "Solicitar reset de contraseña (envía email con token)"
- method: POST
path: /api/v1/auth/password/reset
description: "Resetear contraseña con token"
- method: GET
path: /api/v1/auth/password/verify-token/:token
description: "Verificar validez del token de reset"
services:
- name: "PasswordResetService"
file: "src/modules/auth/services/password-reset.service.ts"
methods:
- requestPasswordReset
- resetPassword
- verifyResetToken
- sendResetEmail
controllers:
- name: "PasswordResetController"
file: "src/modules/auth/controllers/password-reset.controller.ts"
dtos:
- name: "ForgotPasswordDto"
file: "src/modules/auth/dto/forgot-password.dto.ts"
- name: "ResetPasswordDto"
file: "src/modules/auth/dto/reset-password.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-005-reset-de-contraseña.md"
routes:
- path: "/auth/forgot-password"
component: "ForgotPasswordPage"
- path: "/auth/reset-password/:token"
component: "ResetPasswordPage"
components:
- name: "ForgotPasswordForm"
file: "src/features/password-reset/ui/ForgotPasswordForm.tsx"
type: feature
- name: "ResetPasswordForm"
file: "src/features/password-reset/ui/ResetPasswordForm.tsx"
type: feature
api_client:
- name: "passwordResetApi"
file: "src/entities/auth/api/password-reset.api.ts"
methods:
- forgotPassword
- resetPassword
- verifyToken
state_management:
- name: "usePasswordResetStore"
file: "src/entities/auth/model/password-reset.store.ts"
type: zustand
database_tables:
- schema: auth
table: password_reset_tokens
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_password_reset_tokens_token
- idx_password_reset_tokens_user_id
- idx_password_reset_tokens_expires_at
rls_policy: tenant_isolation_password_reset_tokens
- schema: auth
table: users
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- UPDATE
indices:
- idx_users_email_tenant
rls_policy: tenant_isolation_users
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/password-reset.service.spec.ts"
test_cases:
- "should generate reset token and send email"
- "should verify valid reset token"
- "should throw error for expired token"
- "should reset password successfully"
- "should invalidate token after use"
integration_tests:
- file: "test/auth/password-reset.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/auth/password/forgot should send reset email"
- "POST /api/v1/auth/password/reset should reset password with valid token"
- "POST /api/v1/auth/password/reset should fail with expired token"
- "GET /api/v1/auth/password/verify-token/:token should verify token"
- "should enforce tenant isolation"
frontend:
component_tests:
- file: "src/features/password-reset/ui/ForgotPasswordForm.test.tsx"
test_cases:
- "should validate email format"
- "should submit email successfully"
- "should show success message"
- file: "src/features/password-reset/ui/ResetPasswordForm.test.tsx"
test_cases:
- "should validate password strength"
- "should validate password confirmation match"
- "should submit new password successfully"
e2e_tests:
- file: "e2e/auth/password-reset.spec.ts"
test_cases:
- "should request password reset successfully"
- "should reset password with valid token"
- "should show error for expired token"
- "should login with new password"
acceptance_criteria:
- id: AC-001
description: "Usuario puede solicitar reset de contraseña con email"
status: Pending
test_reference: "test/auth/password-reset.controller.e2e-spec.ts:25"
- id: AC-002
description: "Token de reset expira en 24 horas"
status: Pending
test_reference: "src/modules/auth/services/password-reset.service.spec.ts:48"
- id: AC-003
description: "Token se invalida después de usarse"
status: Pending
test_reference: "test/auth/password-reset.controller.e2e-spec.ts:72"
business_rules:
- id: RN-001
description: "Token de reset debe expirar en 24 horas"
implementation: "src/modules/auth/services/password-reset.service.ts:generateToken()"
test_reference: "src/modules/auth/services/password-reset.service.spec.ts:62"
- id: RN-002
description: "Token solo puede usarse una vez"
implementation: "src/modules/auth/services/password-reset.service.ts:resetPassword()"
test_reference: "src/modules/auth/services/password-reset.service.spec.ts:84"
- id: RN-003
description: "Email de reset debe enviarse solo si usuario existe"
implementation: "src/modules/auth/services/password-reset.service.ts:requestPasswordReset()"
test_reference: "src/modules/auth/services/password-reset.service.spec.ts:102"
dependencies:
rf_dependencies:
- RF-MGN-001-003
module_dependencies:
- MGN-014
external_dependencies:
- name: "nodemailer"
version: "^6.9.0"
- name: "crypto"
version: "built-in"
- rf_id: RF-MGN-001-006
rf_title: "Registro de Usuarios (Signup)"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-006-registro-usuarios.md"
priority: P1
story_points: 5
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-006-registro-de-usuarios-signup.md"
endpoints:
- method: POST
path: /api/v1/auth/signup
description: "Registro de nuevo usuario (público)"
- method: POST
path: /api/v1/auth/verify-email
description: "Verificar email con token"
- method: POST
path: /api/v1/auth/resend-verification
description: "Reenviar email de verificación"
services:
- name: "SignupService"
file: "src/modules/auth/services/signup.service.ts"
methods:
- signup
- verifyEmail
- resendVerification
- sendVerificationEmail
controllers:
- name: "SignupController"
file: "src/modules/auth/controllers/signup.controller.ts"
dtos:
- name: "SignupDto"
file: "src/modules/auth/dto/signup.dto.ts"
- name: "VerifyEmailDto"
file: "src/modules/auth/dto/verify-email.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-006-registro-de-usuarios-signup.md"
routes:
- path: "/signup"
component: "SignupPage"
- path: "/verify-email/:token"
component: "VerifyEmailPage"
components:
- name: "SignupForm"
file: "src/features/signup/ui/SignupForm.tsx"
type: feature
- name: "EmailVerificationNotice"
file: "src/features/signup/ui/EmailVerificationNotice.tsx"
type: feature
api_client:
- name: "signupApi"
file: "src/entities/auth/api/signup.api.ts"
methods:
- signup
- verifyEmail
- resendVerification
state_management:
- name: "useSignupStore"
file: "src/entities/auth/model/signup.store.ts"
type: zustand
database_tables:
- schema: auth
table: users
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- INSERT
- SELECT
- UPDATE
indices:
- idx_users_email_tenant
- idx_users_status
rls_policy: tenant_isolation_users
- schema: auth
table: email_verification_tokens
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- INSERT
- SELECT
- DELETE
indices:
- idx_email_verification_tokens_token
- idx_email_verification_tokens_user_id
rls_policy: tenant_isolation_email_verification_tokens
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/signup.service.spec.ts"
test_cases:
- "should create user with pending_verification status"
- "should send verification email"
- "should verify email with valid token"
- "should activate user after email verification"
- "should throw error for expired token"
integration_tests:
- file: "test/auth/signup.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/auth/signup should create user"
- "POST /api/v1/auth/verify-email should verify email"
- "POST /api/v1/auth/resend-verification should resend email"
- "should enforce unique email per tenant"
- "should not allow login before email verification"
frontend:
component_tests:
- file: "src/features/signup/ui/SignupForm.test.tsx"
test_cases:
- "should validate email format"
- "should validate password strength"
- "should validate terms acceptance"
- "should submit valid form"
e2e_tests:
- file: "e2e/auth/signup.spec.ts"
test_cases:
- "should signup successfully"
- "should verify email with token"
- "should login after email verification"
- "should show error for duplicate email"
acceptance_criteria:
- id: AC-001
description: "Usuario puede registrarse con email y contraseña"
status: Pending
test_reference: "test/auth/signup.controller.e2e-spec.ts:28"
- id: AC-002
description: "Email de verificación se envía automáticamente"
status: Pending
test_reference: "src/modules/auth/services/signup.service.spec.ts:45"
- id: AC-003
description: "Usuario no puede login antes de verificar email"
status: Pending
test_reference: "test/auth/signup.controller.e2e-spec.ts:76"
business_rules:
- id: RN-001
description: "Usuario creado con status 'pending_verification'"
implementation: "src/modules/auth/services/signup.service.ts:signup()"
test_reference: "src/modules/auth/services/signup.service.spec.ts:58"
- id: RN-002
description: "Token de verificación expira en 7 días"
implementation: "src/modules/auth/services/signup.service.ts:generateVerificationToken()"
test_reference: "src/modules/auth/services/signup.service.spec.ts:72"
- id: RN-003
description: "Al verificar email, status cambia a 'active'"
implementation: "src/modules/auth/services/signup.service.ts:verifyEmail()"
test_reference: "src/modules/auth/services/signup.service.spec.ts:95"
dependencies:
rf_dependencies:
- RF-MGN-001-003
module_dependencies:
- MGN-014
external_dependencies:
- name: "nodemailer"
version: "^6.9.0"
- rf_id: RF-MGN-001-007
rf_title: "Gestión de Sesiones"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-007-session-management.md"
priority: P0
story_points: 5
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-007-gestión-de-sesiones.md"
endpoints:
- method: GET
path: /api/v1/auth/sessions
description: "Listar sesiones activas del usuario"
- method: DELETE
path: /api/v1/auth/sessions/:id
description: "Cerrar sesión específica"
- method: DELETE
path: /api/v1/auth/sessions/all
description: "Cerrar todas las sesiones (excepto actual)"
- method: GET
path: /api/v1/auth/sessions/current
description: "Obtener sesión actual"
services:
- name: "SessionService"
file: "src/modules/auth/services/session.service.ts"
methods:
- findUserSessions
- revokeSession
- revokeAllSessions
- getCurrentSession
- cleanupExpiredSessions
controllers:
- name: "SessionController"
file: "src/modules/auth/controllers/session.controller.ts"
dtos:
- name: "SessionResponseDto"
file: "src/modules/auth/dto/session-response.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-007-gestión-de-sesiones.md"
routes:
- path: "/profile/sessions"
component: "SessionsPage"
components:
- name: "SessionsTable"
file: "src/widgets/sessions-table/ui/SessionsTable.tsx"
type: widget
- name: "SessionCard"
file: "src/entities/session/ui/SessionCard.tsx"
type: entity
api_client:
- name: "sessionApi"
file: "src/entities/session/api/session.api.ts"
methods:
- getSessions
- revokeSession
- revokeAllSessions
state_management:
- name: "useSessionStore"
file: "src/entities/session/model/session.store.ts"
type: zustand
- name: "useSessions"
file: "src/entities/session/api/session.queries.ts"
type: react-query
database_tables:
- schema: auth
table: sessions
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE
indices:
- idx_sessions_user_id
- idx_sessions_token
- idx_sessions_expires_at
- idx_sessions_status
rls_policy: tenant_isolation_sessions
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/session.service.spec.ts"
test_cases:
- "should create session on login"
- "should list user sessions"
- "should revoke session by id"
- "should revoke all user sessions except current"
- "should cleanup expired sessions"
integration_tests:
- file: "test/auth/session.controller.e2e-spec.ts"
test_cases:
- "GET /api/v1/auth/sessions should return user sessions"
- "DELETE /api/v1/auth/sessions/:id should revoke session"
- "DELETE /api/v1/auth/sessions/all should revoke all sessions"
- "GET /api/v1/auth/sessions/current should return current session"
- "should enforce user can only see own sessions"
frontend:
component_tests:
- file: "src/widgets/sessions-table/ui/SessionsTable.test.tsx"
test_cases:
- "should render table with sessions"
- "should show device and location info"
- "should call revoke on button click"
e2e_tests:
- file: "e2e/auth/sessions.spec.ts"
test_cases:
- "should list active sessions"
- "should revoke specific session"
- "should revoke all sessions except current"
acceptance_criteria:
- id: AC-001
description: "Usuario puede ver todas sus sesiones activas"
status: Pending
test_reference: "test/auth/session.controller.e2e-spec.ts:32"
- id: AC-002
description: "Usuario puede cerrar sesión específica"
status: Pending
test_reference: "test/auth/session.controller.e2e-spec.ts:58"
- id: AC-003
description: "Usuario puede cerrar todas las sesiones excepto la actual"
status: Pending
test_reference: "test/auth/session.controller.e2e-spec.ts:82"
business_rules:
- id: RN-001
description: "Sesión expira después de 8 horas de inactividad"
implementation: "src/modules/auth/services/auth.service.ts:generateTokens()"
test_reference: "src/modules/auth/services/session.service.spec.ts:68"
- id: RN-002
description: "Usuario solo puede ver y revocar sus propias sesiones"
implementation: "src/modules/auth/services/session.service.ts:findUserSessions()"
test_reference: "test/auth/session.controller.e2e-spec.ts:102"
- id: RN-003
description: "Sesiones expiradas se limpian automáticamente cada hora"
implementation: "src/modules/auth/services/session.service.ts:cleanupExpiredSessions()"
test_reference: "src/modules/auth/services/session.service.spec.ts:95"
dependencies:
rf_dependencies:
- RF-MGN-001-001
module_dependencies: []
external_dependencies:
- name: "@nestjs/schedule"
version: "^4.0.0"
- rf_id: RF-MGN-001-008
rf_title: "Record Rules (Row Level Security)"
rf_file: "requerimientos-funcionales/mgn-001/RF-MGN-001-008-record-rules-rls.md"
priority: P1
story_points: 13
et_backend:
file: "especificaciones-tecnicas/backend/mgn-001/ET-BACKEND-MGN-001-008-record-rules-row-level-security.md"
endpoints:
- method: POST
path: /api/v1/auth/record-rules
description: "Crear record rule"
- method: GET
path: /api/v1/auth/record-rules
description: "Listar record rules"
- method: GET
path: /api/v1/auth/record-rules/:id
description: "Obtener record rule por ID"
- method: PUT
path: /api/v1/auth/record-rules/:id
description: "Actualizar record rule"
- method: DELETE
path: /api/v1/auth/record-rules/:id
description: "Eliminar record rule"
services:
- name: "RecordRuleService"
file: "src/modules/auth/services/record-rule.service.ts"
methods:
- create
- findAll
- findOne
- update
- remove
- applyRulesForUser
controllers:
- name: "RecordRuleController"
file: "src/modules/auth/controllers/record-rule.controller.ts"
dtos:
- name: "CreateRecordRuleDto"
file: "src/modules/auth/dto/create-record-rule.dto.ts"
- name: "UpdateRecordRuleDto"
file: "src/modules/auth/dto/update-record-rule.dto.ts"
et_frontend:
file: "especificaciones-tecnicas/frontend/mgn-001/ET-FRONTEND-MGN-001-008-record-rules-row-level-security.md"
routes:
- path: "/auth/record-rules"
component: "RecordRulesPage"
- path: "/auth/record-rules/create"
component: "CreateRecordRulePage"
- path: "/auth/record-rules/:id/edit"
component: "EditRecordRulePage"
components:
- name: "RecordRulesTable"
file: "src/widgets/record-rules-table/ui/RecordRulesTable.tsx"
type: widget
- name: "CreateRecordRuleForm"
file: "src/features/create-record-rule/ui/CreateRecordRuleForm.tsx"
type: feature
- name: "RuleConditionBuilder"
file: "src/features/rule-condition-builder/ui/RuleConditionBuilder.tsx"
type: feature
api_client:
- name: "recordRuleApi"
file: "src/entities/record-rule/api/record-rule.api.ts"
methods:
- getAll
- getById
- create
- update
- delete
state_management:
- name: "useRecordRuleStore"
file: "src/entities/record-rule/model/record-rule.store.ts"
type: zustand
database_tables:
- schema: auth
table: record_rules
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- UPDATE
- DELETE (soft)
indices:
- idx_record_rules_model
- idx_record_rules_tenant_id
rls_policy: tenant_isolation_record_rules
- schema: auth
table: role_record_rules
file: "database-design/schemas/auth-schema-ddl.sql"
operations:
- SELECT
- INSERT
- DELETE
indices:
- idx_role_record_rules_role_id
- idx_role_record_rules_rule_id
rls_policy: tenant_isolation_role_record_rules
tests:
backend:
unit_tests:
- file: "src/modules/auth/services/record-rule.service.spec.ts"
test_cases:
- "should create record rule with SQL filter"
- "should validate SQL syntax"
- "should apply rules for user with role"
- "should combine multiple rules with OR"
- "should update record rule successfully"
integration_tests:
- file: "test/auth/record-rule.controller.e2e-spec.ts"
test_cases:
- "POST /api/v1/auth/record-rules should create rule"
- "GET /api/v1/auth/record-rules should return all rules"
- "PUT /api/v1/auth/record-rules/:id should update rule"
- "DELETE /api/v1/auth/record-rules/:id should delete rule"
- "should enforce admin permissions"
frontend:
component_tests:
- file: "src/widgets/record-rules-table/ui/RecordRulesTable.test.tsx"
test_cases:
- "should render table with rules"
- "should show SQL filter preview"
- file: "src/features/create-record-rule/ui/CreateRecordRuleForm.test.tsx"
test_cases:
- "should validate required fields"
- "should validate SQL syntax"
- "should submit valid form"
e2e_tests:
- file: "e2e/auth/record-rules.spec.ts"
test_cases:
- "should create record rule successfully"
- "should edit record rule successfully"
- "should delete record rule with confirmation"
acceptance_criteria:
- id: AC-001
description: "Administrador puede crear reglas de filtro por rol"
status: Pending
test_reference: "test/auth/record-rule.controller.e2e-spec.ts:32"
- id: AC-002
description: "Reglas se aplican automáticamente en queries SQL"
status: Pending
test_reference: "src/modules/auth/services/record-rule.service.spec.ts:68"
- id: AC-003
description: "Múltiples reglas se combinan con OR"
status: Pending
test_reference: "src/modules/auth/services/record-rule.service.spec.ts:92"
business_rules:
- id: RN-001
description: "Record rule debe tener SQL válido"
implementation: "src/modules/auth/services/record-rule.service.ts:validateSql()"
test_reference: "src/modules/auth/services/record-rule.service.spec.ts:48"
- id: RN-002
description: "Reglas se aplican por modelo (tabla)"
implementation: "database-design/schemas/auth-schema-ddl.sql:record_rules.model"
test_reference: "src/modules/auth/services/record-rule.service.spec.ts:72"
- id: RN-003
description: "Usuario sin reglas no ve ningún registro (restrictivo por defecto)"
implementation: "src/modules/auth/services/record-rule.service.ts:applyRulesForUser()"
test_reference: "src/modules/auth/services/record-rule.service.spec.ts:105"
dependencies:
rf_dependencies:
- RF-MGN-001-002
module_dependencies: []
external_dependencies:
- name: "pg"
version: "^8.11.0"
coverage:
rf_to_et_backend: 100%
rf_to_et_frontend: 100%
rf_to_database: 100%
rf_to_tests: 100%
backend_tests: 100%
frontend_tests: 100%
statistics:
total_endpoints: 38
total_components: 32
total_tables: 10
total_test_cases: 94
estimated_duration_sprints: 4