erp-core/docs/01-fase-foundation/MGN-001-auth/implementacion/TRACEABILITY.yml

696 lines
22 KiB
YAML

# TRACEABILITY.yml - MGN-001: Autenticacion
# Matriz de trazabilidad: Documentacion -> Codigo
# Ubicacion: docs/01-fase-foundation/MGN-001-auth/implementacion/
epic_code: MGN-001
epic_name: Autenticacion
phase: 1
phase_name: Foundation
story_points: 40
status: documented
# =============================================================================
# DOCUMENTACION
# =============================================================================
documentation:
requirements:
- id: RF-AUTH-001
file: ../requerimientos/RF-AUTH-001.md
title: Login con Email/Password
priority: P0
status: migrated
description: |
El sistema debe permitir autenticacion mediante email y password.
Incluye validacion de credenciales, generacion de tokens y registro de sesion.
- id: RF-AUTH-002
file: ../requerimientos/RF-AUTH-002.md
title: Manejo de Tokens JWT
priority: P0
status: migrated
description: |
Gestion de access tokens y refresh tokens JWT.
Incluye generacion, validacion, refresh y revocacion.
- id: RF-AUTH-003
file: ../requerimientos/RF-AUTH-003.md
title: Recuperacion de Password
priority: P1
status: migrated
description: |
Flujo de recuperacion de password via email.
Incluye generacion de token, envio de email y reset.
- id: RF-AUTH-004
file: ../requerimientos/RF-AUTH-004.md
title: Proteccion Brute Force
priority: P1
status: migrated
description: |
Proteccion contra ataques de fuerza bruta.
Rate limiting por IP y por email, bloqueo temporal.
- id: RF-AUTH-005
file: ../requerimientos/RF-AUTH-005.md
title: OAuth Social Login
priority: P2
status: migrated
description: |
Login con proveedores OAuth (Google, Microsoft).
Vinculacion de cuentas sociales a cuenta local.
- id: RF-AUTH-006
file: ../requerimientos/RF-AUTH-005.md
title: Logout y Revocacion (incluido en RF-AUTH-005)
priority: P0
status: migrated
description: |
Cierre de sesion y revocacion de tokens.
Logout de dispositivo actual o de todos los dispositivos.
specifications:
- id: ET-AUTH-001
file: ../especificaciones/ET-auth-backend.md
title: Backend Authentication
rf: [RF-AUTH-001, RF-AUTH-002, RF-AUTH-005]
status: migrated
components:
- AuthService
- TokenService
- AuthController
- JwtAuthGuard
- id: ET-AUTH-002
file: ../especificaciones/auth-domain.md
title: Domain Model Authentication
rf: [RF-AUTH-001, RF-AUTH-003]
status: migrated
components:
- Modelo de dominio Auth
- id: ET-AUTH-003
file: ../especificaciones/ET-AUTH-database.md
title: Database Authentication
rf: [RF-AUTH-001, RF-AUTH-002, RF-AUTH-004]
status: migrated
components:
- Schema core_auth
- Tablas y funciones
user_stories:
- id: US-MGN001-001
file: ../historias-usuario/US-MGN001-001.md
title: Login con Email/Password
rf: [RF-AUTH-001]
story_points: 8
status: migrated
acceptance_criteria: 5
- id: US-MGN001-002
file: ../historias-usuario/US-MGN001-002.md
title: Logout de Sesion
rf: [RF-AUTH-005]
story_points: 3
status: migrated
acceptance_criteria: 3
- id: US-MGN001-003
file: ../historias-usuario/US-MGN001-003.md
title: Recuperar Password
rf: [RF-AUTH-003]
story_points: 5
status: migrated
acceptance_criteria: 4
- id: US-MGN001-004
file: ../historias-usuario/US-MGN001-004.md
title: Refresh de Token
rf: [RF-AUTH-002]
story_points: 5
status: migrated
acceptance_criteria: 3
backlog:
file: ../historias-usuario/BACKLOG-MGN001.md
status: migrated
# =============================================================================
# IMPLEMENTACION
# =============================================================================
implementation:
database:
schema: core_auth
path: apps/database/ddl/schemas/core_auth/
tables:
- name: users_auth
file: apps/database/ddl/schemas/core_auth/tables/users_auth.sql
rf: RF-AUTH-001
status: pending
columns:
- {name: id, type: UUID, pk: true}
- {name: tenant_id, type: UUID, fk: tenants}
- {name: user_id, type: UUID, fk: users}
- {name: email, type: VARCHAR(255), unique: true}
- {name: password_hash, type: VARCHAR(255)}
- {name: is_active, type: BOOLEAN}
- {name: email_verified_at, type: TIMESTAMPTZ}
- {name: last_login_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ}
- {name: updated_at, type: TIMESTAMPTZ}
indexes:
- idx_users_auth_email
- idx_users_auth_tenant
rls_policies:
- tenant_isolation
- name: sessions
file: apps/database/ddl/schemas/core_auth/tables/sessions.sql
rf: RF-AUTH-002
status: pending
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth}
- {name: token_hash, type: VARCHAR(255)}
- {name: ip_address, type: INET}
- {name: user_agent, type: TEXT}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ}
- name: refresh_tokens
file: apps/database/ddl/schemas/core_auth/tables/refresh_tokens.sql
rf: RF-AUTH-002
status: pending
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth}
- {name: token_hash, type: VARCHAR(255)}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: revoked_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ}
- name: password_resets
file: apps/database/ddl/schemas/core_auth/tables/password_resets.sql
rf: RF-AUTH-003
status: pending
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth}
- {name: token_hash, type: VARCHAR(255)}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: used_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ}
- name: login_attempts
file: apps/database/ddl/schemas/core_auth/tables/login_attempts.sql
rf: RF-AUTH-004
status: pending
columns:
- {name: id, type: UUID, pk: true}
- {name: email, type: VARCHAR(255)}
- {name: ip_address, type: INET}
- {name: attempted_at, type: TIMESTAMPTZ}
- {name: success, type: BOOLEAN}
- name: oauth_accounts
file: apps/database/ddl/schemas/core_auth/tables/oauth_accounts.sql
rf: RF-AUTH-005
status: pending
columns:
- {name: id, type: UUID, pk: true}
- {name: user_id, type: UUID, fk: users_auth}
- {name: provider, type: VARCHAR(50)}
- {name: provider_user_id, type: VARCHAR(255)}
- {name: access_token, type: TEXT}
- {name: refresh_token, type: TEXT}
- {name: expires_at, type: TIMESTAMPTZ}
- {name: created_at, type: TIMESTAMPTZ}
functions:
- name: validate_password
file: apps/database/ddl/schemas/core_auth/functions/validate_password.sql
rf: RF-AUTH-001
status: pending
params: [user_id UUID, password TEXT]
returns: BOOLEAN
description: Valida password contra hash almacenado
- name: cleanup_expired_sessions
file: apps/database/ddl/schemas/core_auth/functions/cleanup_sessions.sql
rf: RF-AUTH-002
status: pending
params: []
returns: INTEGER
description: Elimina sesiones expiradas, retorna cantidad eliminada
triggers:
- name: trg_update_users_auth_timestamp
table: users_auth
event: BEFORE UPDATE
function: update_updated_at()
status: pending
backend:
module: auth
path: apps/backend/src/modules/auth/
framework: NestJS
entities:
- name: UserAuth
file: apps/backend/src/modules/auth/entities/user-auth.entity.ts
rf: RF-AUTH-001
status: pending
table: users_auth
- name: Session
file: apps/backend/src/modules/auth/entities/session.entity.ts
rf: RF-AUTH-002
status: pending
table: sessions
- name: RefreshToken
file: apps/backend/src/modules/auth/entities/refresh-token.entity.ts
rf: RF-AUTH-002
status: pending
table: refresh_tokens
- name: PasswordReset
file: apps/backend/src/modules/auth/entities/password-reset.entity.ts
rf: RF-AUTH-003
status: pending
table: password_resets
- name: OAuthAccount
file: apps/backend/src/modules/auth/entities/oauth-account.entity.ts
rf: RF-AUTH-005
status: pending
table: oauth_accounts
services:
- name: AuthService
file: apps/backend/src/modules/auth/auth.service.ts
rf: [RF-AUTH-001, RF-AUTH-006]
status: pending
methods:
- {name: login, rf: RF-AUTH-001, description: "Valida credenciales y retorna tokens"}
- {name: logout, rf: RF-AUTH-006, description: "Revoca sesion actual"}
- {name: logoutAll, rf: RF-AUTH-006, description: "Revoca todas las sesiones"}
- {name: validateUser, rf: RF-AUTH-001, description: "Valida email y password"}
- {name: getProfile, rf: RF-AUTH-001, description: "Obtiene usuario autenticado"}
- name: TokenService
file: apps/backend/src/modules/auth/token.service.ts
rf: [RF-AUTH-002]
status: pending
methods:
- {name: generateAccessToken, rf: RF-AUTH-002, description: "Genera JWT access token"}
- {name: generateRefreshToken, rf: RF-AUTH-002, description: "Genera refresh token"}
- {name: refreshTokens, rf: RF-AUTH-002, description: "Renueva par de tokens"}
- {name: revokeRefreshToken, rf: RF-AUTH-002, description: "Revoca refresh token"}
- {name: validateAccessToken, rf: RF-AUTH-002, description: "Valida JWT"}
- name: PasswordService
file: apps/backend/src/modules/auth/password.service.ts
rf: [RF-AUTH-003]
status: pending
methods:
- {name: requestPasswordReset, rf: RF-AUTH-003, description: "Genera token y envia email"}
- {name: resetPassword, rf: RF-AUTH-003, description: "Cambia password con token"}
- {name: validateResetToken, rf: RF-AUTH-003, description: "Valida token de reset"}
- name: OAuthService
file: apps/backend/src/modules/auth/oauth.service.ts
rf: [RF-AUTH-005]
status: pending
methods:
- {name: initiateOAuth, rf: RF-AUTH-005, description: "Inicia flujo OAuth"}
- {name: handleCallback, rf: RF-AUTH-005, description: "Procesa callback OAuth"}
- {name: linkAccount, rf: RF-AUTH-005, description: "Vincula cuenta OAuth"}
controllers:
- name: AuthController
file: apps/backend/src/modules/auth/auth.controller.ts
status: pending
endpoints:
- method: POST
path: /api/v1/auth/login
rf: RF-AUTH-001
dto_in: LoginDto
dto_out: TokenResponseDto
auth: false
description: Login con email y password
- method: POST
path: /api/v1/auth/logout
rf: RF-AUTH-006
dto_in: null
dto_out: MessageResponseDto
auth: true
description: Cerrar sesion actual
- method: POST
path: /api/v1/auth/refresh
rf: RF-AUTH-002
dto_in: RefreshTokenDto
dto_out: TokenResponseDto
auth: false
description: Refrescar tokens
- method: POST
path: /api/v1/auth/forgot-password
rf: RF-AUTH-003
dto_in: ForgotPasswordDto
dto_out: MessageResponseDto
auth: false
description: Solicitar recuperacion de password
- method: POST
path: /api/v1/auth/reset-password
rf: RF-AUTH-003
dto_in: ResetPasswordDto
dto_out: MessageResponseDto
auth: false
description: Restablecer password con token
- method: GET
path: /api/v1/auth/me
rf: RF-AUTH-001
dto_in: null
dto_out: UserProfileDto
auth: true
description: Obtener usuario autenticado
- method: GET
path: /api/v1/auth/oauth/:provider
rf: RF-AUTH-005
dto_in: null
dto_out: OAuthRedirectDto
auth: false
description: Iniciar OAuth flow
dtos:
- name: LoginDto
file: apps/backend/src/modules/auth/dto/login.dto.ts
rf: RF-AUTH-001
status: pending
fields:
- {name: email, type: string, validation: "IsEmail"}
- {name: password, type: string, validation: "MinLength(8)"}
- {name: remember_me, type: boolean, optional: true}
- name: TokenResponseDto
file: apps/backend/src/modules/auth/dto/token-response.dto.ts
rf: RF-AUTH-002
status: pending
fields:
- {name: access_token, type: string}
- {name: refresh_token, type: string}
- {name: expires_in, type: number}
- {name: token_type, type: string}
- name: RefreshTokenDto
file: apps/backend/src/modules/auth/dto/refresh-token.dto.ts
rf: RF-AUTH-002
status: pending
fields:
- {name: refresh_token, type: string, validation: "IsNotEmpty"}
- name: ForgotPasswordDto
file: apps/backend/src/modules/auth/dto/forgot-password.dto.ts
rf: RF-AUTH-003
status: pending
fields:
- {name: email, type: string, validation: "IsEmail"}
- name: ResetPasswordDto
file: apps/backend/src/modules/auth/dto/reset-password.dto.ts
rf: RF-AUTH-003
status: pending
fields:
- {name: token, type: string, validation: "IsNotEmpty"}
- {name: password, type: string, validation: "MinLength(8)"}
- {name: password_confirmation, type: string}
guards:
- name: JwtAuthGuard
file: apps/backend/src/modules/auth/guards/jwt-auth.guard.ts
rf: RF-AUTH-002
status: pending
description: Valida JWT en header Authorization
- name: RefreshTokenGuard
file: apps/backend/src/modules/auth/guards/refresh-token.guard.ts
rf: RF-AUTH-002
status: pending
description: Valida refresh token
decorators:
- name: CurrentUser
file: apps/backend/src/modules/auth/decorators/current-user.decorator.ts
rf: RF-AUTH-001
status: pending
description: Inyecta usuario actual del request
- name: Public
file: apps/backend/src/modules/auth/decorators/public.decorator.ts
rf: RF-AUTH-001
status: pending
description: Marca endpoint como publico (sin auth)
frontend:
feature: auth
path: apps/frontend/src/features/auth/
framework: React
pages:
- name: LoginPage
file: apps/frontend/src/features/auth/pages/LoginPage.tsx
rf: RF-AUTH-001
status: pending
route: /login
components: [LoginForm, SocialLoginButtons]
- name: ForgotPasswordPage
file: apps/frontend/src/features/auth/pages/ForgotPasswordPage.tsx
rf: RF-AUTH-003
status: pending
route: /forgot-password
components: [ForgotPasswordForm]
- name: ResetPasswordPage
file: apps/frontend/src/features/auth/pages/ResetPasswordPage.tsx
rf: RF-AUTH-003
status: pending
route: /reset-password/:token
components: [ResetPasswordForm]
components:
- name: LoginForm
file: apps/frontend/src/features/auth/components/LoginForm.tsx
rf: RF-AUTH-001
status: pending
description: Formulario de login con validacion
- name: SocialLoginButtons
file: apps/frontend/src/features/auth/components/SocialLoginButtons.tsx
rf: RF-AUTH-005
status: pending
description: Botones de login social (Google, Microsoft)
- name: ForgotPasswordForm
file: apps/frontend/src/features/auth/components/ForgotPasswordForm.tsx
rf: RF-AUTH-003
status: pending
description: Formulario solicitud de reset
- name: ResetPasswordForm
file: apps/frontend/src/features/auth/components/ResetPasswordForm.tsx
rf: RF-AUTH-003
status: pending
description: Formulario cambio de password
stores:
- name: authStore
file: apps/frontend/src/features/auth/stores/authStore.ts
rf: [RF-AUTH-001, RF-AUTH-002]
status: pending
state:
- {name: user, type: "User | null"}
- {name: isAuthenticated, type: boolean}
- {name: isLoading, type: boolean}
- {name: error, type: "string | null"}
actions:
- {name: login, rf: RF-AUTH-001}
- {name: logout, rf: RF-AUTH-006}
- {name: refreshToken, rf: RF-AUTH-002}
- {name: getProfile, rf: RF-AUTH-001}
api:
- name: authApi
file: apps/frontend/src/features/auth/api/authApi.ts
status: pending
methods:
- {name: login, endpoint: "POST /auth/login"}
- {name: logout, endpoint: "POST /auth/logout"}
- {name: refresh, endpoint: "POST /auth/refresh"}
- {name: forgotPassword, endpoint: "POST /auth/forgot-password"}
- {name: resetPassword, endpoint: "POST /auth/reset-password"}
- {name: getMe, endpoint: "GET /auth/me"}
hooks:
- name: useAuth
file: apps/frontend/src/features/auth/hooks/useAuth.ts
status: pending
description: Hook para acceder a estado de auth
- name: useRequireAuth
file: apps/frontend/src/features/auth/hooks/useRequireAuth.ts
status: pending
description: Hook para proteger rutas
# =============================================================================
# DEPENDENCIAS
# =============================================================================
dependencies:
depends_on: [] # Primer modulo, sin dependencias
required_by:
- module: MGN-002
type: hard
reason: Usuarios necesitan autenticacion
- module: MGN-003
type: hard
reason: RBAC usa tokens JWT
- module: MGN-004
type: hard
reason: Tenant ID en token
- module: ALL
type: hard
reason: Todos los modulos requieren auth
external:
- name: bcrypt
version: "^5.1.0"
purpose: Hash de passwords
- name: jsonwebtoken
version: "^9.0.0"
purpose: Generacion/validacion JWT
- name: passport
version: "^0.7.0"
purpose: Estrategias de autenticacion
- name: @nestjs/jwt
version: "^10.0.0"
purpose: Integracion JWT con NestJS
# =============================================================================
# TESTS
# =============================================================================
tests:
unit:
- name: AuthService.spec.ts
file: apps/backend/src/modules/auth/__tests__/auth.service.spec.ts
status: pending
cases: 12
rf: [RF-AUTH-001, RF-AUTH-006]
- name: TokenService.spec.ts
file: apps/backend/src/modules/auth/__tests__/token.service.spec.ts
status: pending
cases: 8
rf: [RF-AUTH-002]
- name: PasswordService.spec.ts
file: apps/backend/src/modules/auth/__tests__/password.service.spec.ts
status: pending
cases: 6
rf: [RF-AUTH-003]
integration:
- name: auth.controller.e2e.spec.ts
file: apps/backend/test/auth/auth.controller.e2e.spec.ts
status: pending
cases: 10
endpoints:
- POST /auth/login
- POST /auth/logout
- POST /auth/refresh
- GET /auth/me
frontend:
- name: LoginForm.test.tsx
file: apps/frontend/src/features/auth/__tests__/LoginForm.test.tsx
status: pending
cases: 5
rf: [RF-AUTH-001]
coverage:
target: 80%
current: 0%
unit: 0%
integration: 0%
e2e: 0%
# =============================================================================
# METRICAS
# =============================================================================
metrics:
story_points:
estimated: 40
actual: null
variance: null
files:
database: 9
backend: 22
frontend: 14
tests: 8
total: 53
lines_of_code:
estimated: 2500
actual: 0
complexity:
services: medium
database: low
frontend: low
# =============================================================================
# BUG FIXES
# =============================================================================
bug_fixes: []
# =============================================================================
# CHANGELOG
# =============================================================================
changelog:
- version: "1.0.0"
date: null
changes:
- "Implementacion inicial de autenticacion"
- "Login con email/password"
- "Manejo de tokens JWT"
- "Proteccion brute force"
# =============================================================================
# HISTORIAL
# =============================================================================
history:
- date: "2025-12-05"
action: "Creacion de TRACEABILITY.yml"
author: Requirements-Analyst
changes:
- "Documentacion completa de trazabilidad"
- "Mapeo RF -> ET -> US -> Codigo"
- "Definicion de todos los componentes"