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