# 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"