# 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
