[AZ-529] [AZ-530] Cycle-2 documentation refresh

Refreshes _docs/02_document/ to reflect the cycle-2 auth-modernization
+ CMMC hardening landings (AZ-531..AZ-538). Authoritative source for
the ripple set is ripple_log_cycle2.md.

Covered:
- architecture.md (section 1 rewritten, ADRs 6-9 added)
- data_model.md (sessions, audit_events, user columns, migrations)
- system-flows.md (F1 rewritten; F11-F17 added; F2/F7/F9 minor)
- module-layout.md (cycle-2 sub-component table)
- diagrams/flows/flow_login.md (dual-token + MFA)
- components/{01_data_layer,03_auth_and_security,05_admin_api}
- modules/ (12 new, 8 modified — full Argon2id/ES256/MFA/refresh
  /mission/session/audit/jwks rollup)
- tests/{blackbox,security,traceability-matrix}

Step 13 (Update Docs) output for cycle 2.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-14 09:22:53 +03:00
parent c2c659ef62
commit a77b3f8a59
35 changed files with 3624 additions and 468 deletions
@@ -0,0 +1,83 @@
# Module: Azaion.Common.Requests.MfaRequests
## Purpose
Request and response DTOs for the MFA enrollment / login surface introduced in cycle 2 by AZ-534 (Epic AZ-529, TOTP-based 2FA at credential login). All DTOs live in a single `MfaRequests.cs` file.
## Public Interface
### MfaEnrollRequest
| Property | Type | Description |
|----------|------|-------------|
| `Password` | `string` | Re-auth required for enrollment (defends a stolen access token from silently flipping MFA on). |
### MfaEnrollResponse
| Property | Type | Description |
|----------|------|-------------|
| `Secret` | `string` | 32-char base32 TOTP shared secret. Shown once. |
| `OtpAuthUrl` | `string` | Standard `otpauth://` URL the authenticator app consumes. |
| `QrPngBase64` | `string` | PNG encoding of `OtpAuthUrl` (base64). UI inlines as `data:image/png;base64,…`. |
| `RecoveryCodes` | `string[]` | 10 single-use base32 codes (each ≥12 chars). Stored hashed in `users.mfa_recovery_codes`; the plaintext list is unrecoverable after this response. |
### MfaConfirmRequest
| Property | Type | Description |
|----------|------|-------------|
| `Code` | `string` | TOTP code that validates the enrolled secret. On success `users.mfa_enabled` flips to true. |
### MfaDisableRequest
| Property | Type | Description |
|----------|------|-------------|
| `Password` | `string` | Re-auth (same defence as enroll). |
| `Code` | `string` | A valid TOTP code (recovery codes are NOT accepted here — disable should be deliberate). |
### MfaRequiredResponse
Returned by `POST /login` when the user has MFA enabled instead of `LoginResponse`.
| Property | Type | Description |
|----------|------|-------------|
| `MfaRequired` | `bool` | Always `true`. Lets dual-shape clients branch on a single field. |
| `MfaToken` | `string` | Short-lived (5 min) ES256 JWT with audience `azaion-mfa-step2`. Carry to `/login/mfa`. |
| `ExpiresIn` | `int` | Step-1 token TTL in seconds (300). |
### MfaLoginRequest
| Property | Type | Description |
|----------|------|-------------|
| `MfaToken` | `string` | The step-1 token from `MfaRequiredResponse`. |
| `Code` | `string` | A valid TOTP code OR a single-use recovery code. |
## Internal Logic
None — pure data classes.
## Dependencies
None.
## Consumers
- `Program.cs` `/users/me/mfa/enroll``MfaEnrollRequest``MfaEnrollResponse`.
- `Program.cs` `/users/me/mfa/confirm``MfaConfirmRequest`.
- `Program.cs` `/users/me/mfa/disable``MfaDisableRequest`.
- `Program.cs` `/login` — returns `MfaRequiredResponse` when `user.MfaEnabled`.
- `Program.cs` `/login/mfa``MfaLoginRequest``LoginResponse`.
- `MfaService` — consumes every request type and produces the responses.
## Data Models
None directly.
## Configuration
None.
## External Integrations
None — but `MfaToken` validation depends on `IJwtSigningKeyProvider` (ES256 keys) and `JwtConfig.Issuer`.
## Security
- `Password` fields carry plaintext credentials; HTTPS is mandatory in Production (AZ-538 HSTS / HTTPS-redirect).
- `Secret` and `RecoveryCodes` are returned ONCE in `MfaEnrollResponse` — the client must show them immediately and never send them back.
- `MfaToken` is narrowly-scoped (audience `azaion-mfa-step2`) so it cannot be used against any non-MFA endpoint even if leaked.
## Tests
- `e2e/Azaion.E2E/Tests/MfaEnrollmentTests.cs` — AC-1 (enroll shape), AC-2 (confirm), AC-5 (disable), AC-6 (encrypted at rest).
- `e2e/Azaion.E2E/Tests/MfaLoginTests.cs` — AC-3 (two-step + AMR claim), AC-4 (recovery code single-use).