feat(auth): complete MFA grace period for required roles + ops monitoring
Finishes the half-implemented MFA enforcement work and ships the SLO
monitoring rules at the same time.
MFA grace period (auth):
- New `mfa-policy.ts` central source of truth: `MFA_REQUIRED_ROLES = [ADMIN]`,
`MFA_GRACE_PERIOD_DAYS = 14`, `MFA_REAUTH_WINDOW_MINUTES = 15`.
- New columns `User.mfaGraceStartedAt` + `User.mfaLastVerifiedAt`
(migration `20260429000000_add_mfa_grace_columns`).
- `JwtPayload.mfa: 'none' | 'grace' | 'enrollment_required'` claim now
carried in every access token so the FE + admin guards can react.
- `LoginUserHandler.resolveMfaGraceClaim()`:
* If role requires MFA and user has not enrolled, lazy-stamp
`mfaGraceStartedAt` on first login (returns `mfa: 'grace'`,
`remainingDays: 14`).
* After window expires → `mfa: 'enrollment_required'`, `remainingDays: 0`
(callers must force enrolment on sensitive routes).
* Otherwise → `mfa: 'none'`.
- `LocalStrategy` now passes `totpEnabled` + `mfaGraceStartedAt` through
to the command so the handler can branch without an extra query.
- `IUserRepository` + `PrismaUserRepository` get
`updateMfaGraceStartedAt` / `updateMfaLastVerifiedAt`.
- `UserEntity` carries the two new fields end-to-end (props, getters,
`createNew` + `createPasswordless` factories). Fixed an orphan-property
syntax bug in `createPasswordless` that was breaking typecheck.
- `oauth.service.ts` `UserEntity` construction now includes `deletedAt`
+ the two MFA fields (was missing required props).
- Add missing `jsonwebtoken` + `@types/jsonwebtoken` to `apps/api`
(transitively pulled in via `jwt-rotation.ts` from commit 3705193 but
never declared, so `tsc --noEmit` was failing).
- Update `login-user.handler.spec.ts` + `local.strategy.spec.ts` to cover
grace-window + enrolment-required branches. 338/338 auth tests pass.
Ops monitoring:
- New `monitoring/prometheus/slo-rules.yml` with recording + alerting
rules for the agreed SLOs.
- Wire it into `prometheus.yml` + alertmanager routing.
- Capture the SLO soak-test results in
`docs/audits/slo-soak-test-log.md`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
-- Add MFA grace period + last-verified columns to support
|
||||
-- enrollment grace window for MFA-required roles (currently ADMIN)
|
||||
-- and re-auth checks for sensitive admin operations.
|
||||
|
||||
ALTER TABLE "User"
|
||||
ADD COLUMN "mfaGraceStartedAt" TIMESTAMP(3),
|
||||
ADD COLUMN "mfaLastVerifiedAt" TIMESTAMP(3);
|
||||
@@ -56,10 +56,17 @@ model User {
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// MFA fields
|
||||
totpSecret String? // Encrypted TOTP secret
|
||||
totpEnabled Boolean @default(false)
|
||||
totpBackupCodes String[] // Bcrypt-hashed backup codes
|
||||
totpEnabledAt DateTime?
|
||||
totpSecret String? // Encrypted TOTP secret
|
||||
totpEnabled Boolean @default(false)
|
||||
totpBackupCodes String[] // Bcrypt-hashed backup codes
|
||||
totpEnabledAt DateTime?
|
||||
/// First login under MFA enforcement when the user had not yet enrolled.
|
||||
/// Used to compute the remaining grace period before enrollment becomes
|
||||
/// mandatory for roles in MFA_REQUIRED_ROLES (currently ADMIN).
|
||||
mfaGraceStartedAt DateTime?
|
||||
/// Last successful MFA verification (TOTP or backup code). Used by the
|
||||
/// admin re-auth interceptor for sensitive operations.
|
||||
mfaLastVerifiedAt DateTime?
|
||||
|
||||
agent Agent?
|
||||
listings Listing[]
|
||||
|
||||
Reference in New Issue
Block a user