@astram/guard 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/account.controller.d.ts +245 -0
- package/dist/auth/account.controller.d.ts.map +1 -0
- package/dist/auth/account.controller.js +673 -0
- package/dist/auth/auth.controller.d.ts +219 -5
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +790 -12
- package/dist/auth/auth.module.d.ts +101 -3
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +300 -8
- package/dist/auth/dto.d.ts +16 -6
- package/dist/auth/dto.d.ts.map +1 -1
- package/dist/auth/ports/audit-sink.d.ts +47 -0
- package/dist/auth/ports/audit-sink.d.ts.map +1 -0
- package/dist/auth/ports/audit-sink.js +20 -0
- package/dist/auth/ports/credential-writer.d.ts +23 -0
- package/dist/auth/ports/credential-writer.d.ts.map +1 -0
- package/dist/auth/ports/credential-writer.js +2 -0
- package/dist/auth/ports/email-sender.d.ts +14 -0
- package/dist/auth/ports/email-sender.d.ts.map +1 -0
- package/dist/auth/ports/email-sender.js +2 -0
- package/dist/auth/ports/mfa-device-store.d.ts +45 -0
- package/dist/auth/ports/mfa-device-store.d.ts.map +1 -0
- package/dist/auth/ports/mfa-device-store.js +13 -0
- package/dist/auth/ports/profile-writer.d.ts +12 -0
- package/dist/auth/ports/profile-writer.d.ts.map +1 -0
- package/dist/auth/ports/profile-writer.js +2 -0
- package/dist/auth/ports/recovery-code-store.d.ts +10 -0
- package/dist/auth/ports/recovery-code-store.d.ts.map +1 -0
- package/dist/auth/ports/recovery-code-store.js +2 -0
- package/dist/auth/ports/reset-token-store.d.ts +12 -0
- package/dist/auth/ports/reset-token-store.d.ts.map +1 -0
- package/dist/auth/ports/reset-token-store.js +2 -0
- package/dist/auth/ports/session-facts-projector.d.ts +44 -0
- package/dist/auth/ports/session-facts-projector.d.ts.map +1 -0
- package/dist/auth/ports/session-facts-projector.js +30 -0
- package/dist/auth/ports/session-sweeper.d.ts +12 -0
- package/dist/auth/ports/session-sweeper.d.ts.map +1 -0
- package/dist/auth/ports/session-sweeper.js +2 -0
- package/dist/auth/profile-resolver.d.ts +73 -0
- package/dist/auth/profile-resolver.d.ts.map +1 -0
- package/dist/auth/profile-resolver.js +28 -0
- package/dist/auth/rate-limit/attempt-limiter.d.ts +91 -0
- package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -0
- package/dist/auth/rate-limit/attempt-limiter.js +133 -0
- package/dist/auth/tokens.d.ts +174 -0
- package/dist/auth/tokens.d.ts.map +1 -1
- package/dist/auth/tokens.js +190 -1
- package/dist/auth/totp-enrollment.d.ts +42 -0
- package/dist/auth/totp-enrollment.d.ts.map +1 -0
- package/dist/auth/totp-enrollment.js +96 -0
- package/dist/authentication/mariadb-credential-resolver.d.ts +38 -24
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-resolver.js +42 -28
- package/dist/authz/cross-tenant-grant-writer.d.ts +259 -0
- package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -0
- package/dist/authz/cross-tenant-grant-writer.js +397 -0
- package/dist/authz/manifest-operation-authority-adapter.d.ts +65 -0
- package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -0
- package/dist/authz/manifest-operation-authority-adapter.js +108 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts +90 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js +211 -0
- package/dist/authz/mariadb-record-rule-adapter.d.ts +60 -0
- package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -0
- package/dist/authz/mariadb-record-rule-adapter.js +154 -0
- package/dist/authz/mariadb-record-share-adapter.d.ts +75 -0
- package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -0
- package/dist/authz/mariadb-record-share-adapter.js +106 -0
- package/dist/authz/record-share-cascade.d.ts +52 -0
- package/dist/authz/record-share-cascade.d.ts.map +1 -0
- package/dist/authz/record-share-cascade.js +49 -0
- package/dist/authz/record-share-writer.d.ts +175 -0
- package/dist/authz/record-share-writer.d.ts.map +1 -0
- package/dist/authz/record-share-writer.js +225 -0
- package/dist/authz/wire-record-authorization.d.ts +66 -0
- package/dist/authz/wire-record-authorization.d.ts.map +1 -0
- package/dist/authz/wire-record-authorization.js +34 -0
- package/dist/completeness/catalog-reconciler.d.ts +21 -0
- package/dist/completeness/catalog-reconciler.d.ts.map +1 -0
- package/dist/completeness/catalog-reconciler.js +74 -0
- package/dist/completeness/operation-inventory-scanner.d.ts +17 -0
- package/dist/completeness/operation-inventory-scanner.d.ts.map +1 -0
- package/dist/completeness/operation-inventory-scanner.js +79 -0
- package/dist/completeness/ports/catalog-store.d.ts +33 -0
- package/dist/completeness/ports/catalog-store.d.ts.map +1 -0
- package/dist/completeness/ports/catalog-store.js +2 -0
- package/dist/config/app-config.d.ts +18 -16
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js +68 -35
- package/dist/enforcement/classification.decorator.d.ts +33 -14
- package/dist/enforcement/classification.decorator.d.ts.map +1 -1
- package/dist/enforcement/classification.decorator.js +34 -14
- package/dist/enforcement/global-enforcement.guard.d.ts +29 -19
- package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
- package/dist/enforcement/global-enforcement.guard.js +108 -25
- package/dist/enforcement/reenroll-allowlist.d.ts +49 -0
- package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -0
- package/dist/enforcement/reenroll-allowlist.js +77 -0
- package/dist/index.d.ts +35 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +159 -7
- package/dist/module/shield-tokens.d.ts +15 -0
- package/dist/module/shield-tokens.d.ts.map +1 -0
- package/dist/module/shield-tokens.js +17 -0
- package/dist/module/shield.module.d.ts +154 -10
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +181 -24
- package/dist/request-auth/request-principal.d.ts +42 -0
- package/dist/request-auth/request-principal.d.ts.map +1 -0
- package/dist/request-auth/request-principal.js +87 -0
- package/dist/request-auth/session-facts-als.d.ts +65 -0
- package/dist/request-auth/session-facts-als.d.ts.map +1 -0
- package/dist/request-auth/session-facts-als.js +57 -0
- package/dist/request-auth/session-token-binder.d.ts +130 -0
- package/dist/request-auth/session-token-binder.d.ts.map +1 -0
- package/dist/request-auth/session-token-binder.js +277 -0
- package/dist/request-auth/tokens.d.ts +14 -0
- package/dist/request-auth/tokens.d.ts.map +1 -0
- package/dist/request-auth/tokens.js +16 -0
- package/package.json +2 -2
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The framework-owned **`/account/*` self-scoped HTTP controller** — the
|
|
3
|
+
* authenticated user acting on THEIR OWN credential/profile (spec §2). Unlike the
|
|
4
|
+
* `/auth/*` routes (which run BEFORE a session exists), these routes authenticate
|
|
5
|
+
* the CALLER first — they resolve the bearer access token to the principal's claims
|
|
6
|
+
* and operate ONLY on `claims.id`. There is NO `decide()`/object-type authorization
|
|
7
|
+
* here: "change my own password" has no `typeKey` to gate on (that is the later
|
|
8
|
+
* permission-management milestone). So the routes are `@Public()` to the
|
|
9
|
+
* classification guard (not object-gated), but NOT unauthenticated.
|
|
10
|
+
*
|
|
11
|
+
* ── AUTH (fail-closed) ── the caller is authenticated by resolving the bearer token
|
|
12
|
+
* DIRECTLY via the {@link SessionTokenBinder} (`binder.resolve(token)`), NOT via
|
|
13
|
+
* `resolveRequestPrincipal` — because change-password needs the caller's
|
|
14
|
+
* `sessionId` (to keep the current session alive while sweeping the others), and
|
|
15
|
+
* `resolveRequestPrincipal` collapses the claims down to a `Principal` (dropping
|
|
16
|
+
* `sessionId`). No token / no binder / resolve → null → generic 401.
|
|
17
|
+
*
|
|
18
|
+
* ── SEAMS (fail-closed → 501) ── the credential read+write goes through the
|
|
19
|
+
* consumer-plugged {@link CredentialWriter} (`getPasswordHash` + `setPassword`, now
|
|
20
|
+
* password-only); the current-password verify uses the {@link PasswordHasher};
|
|
21
|
+
* sessions are swept by the {@link SessionSweeper}. The {@link RecoveryCodeStore},
|
|
22
|
+
* the core {@link FactorVerifier} (single-secret TOTP, for per-device code checks),
|
|
23
|
+
* the {@link ProfileResolver} (otpauth label), and the {@link MfaDeviceStore}
|
|
24
|
+
* (the N-device persistence) are injected here for the multi-device MFA routes. Each
|
|
25
|
+
* is `@Optional()`; when a required seam is absent the route returns an honest 501
|
|
26
|
+
* (`not_available`) rather than a partial mutation.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: TOTP secrets no longer live on the {@link CredentialWriter} — the
|
|
29
|
+
* multi-device MFA model stores every authenticator secret in the `MfaDeviceStore`.
|
|
30
|
+
* The old single-secret `mfa/enroll/{begin,confirm}` + `mfa/disable` routes were
|
|
31
|
+
* removed; the multi-device `/account/mfa/devices/*` routes replace them.
|
|
32
|
+
*
|
|
33
|
+
* ── ROUTES ── `POST /account/change-password` (change own password);
|
|
34
|
+
* `PATCH /account/profile` (edit own display name/email → the refreshed display
|
|
35
|
+
* profile); the multi-device MFA routes — `GET /account/mfa/devices` (list),
|
|
36
|
+
* `POST /account/mfa/devices/begin` (enroll), `POST /account/mfa/devices/confirm`
|
|
37
|
+
* (activate + first-device recovery codes), `PATCH /account/mfa/devices/:id/rename`,
|
|
38
|
+
* `DELETE /account/mfa/devices/:id` (code-gated), `POST
|
|
39
|
+
* /account/mfa/recovery-codes/regenerate` (code-gated).
|
|
40
|
+
*
|
|
41
|
+
* ── NO ORACLE ── a wrong current password is an indistinguishable generic 401
|
|
42
|
+
* (same body as no-token). We never reveal whether the principal exists, nor which
|
|
43
|
+
* check failed. Passwords/hashes are NEVER logged.
|
|
44
|
+
*/
|
|
45
|
+
import type { FactorVerifier, PasswordHasher } from '@astram/core';
|
|
46
|
+
import type { SessionTokenBinder } from '../request-auth/session-token-binder.js';
|
|
47
|
+
import type { CredentialWriter } from './ports/credential-writer.js';
|
|
48
|
+
import type { MfaDevice, MfaDeviceStore } from './ports/mfa-device-store.js';
|
|
49
|
+
import type { CurrentUserProfile, ProfileResolver } from './profile-resolver.js';
|
|
50
|
+
import type { ProfileWriter } from './ports/profile-writer.js';
|
|
51
|
+
import type { RecoveryCodeStore } from './ports/recovery-code-store.js';
|
|
52
|
+
import type { SessionSweeper } from './ports/session-sweeper.js';
|
|
53
|
+
export declare class AccountController {
|
|
54
|
+
private readonly binder?;
|
|
55
|
+
private readonly hasher?;
|
|
56
|
+
private readonly writer?;
|
|
57
|
+
private readonly sweeper?;
|
|
58
|
+
private readonly recoveryCodes?;
|
|
59
|
+
private readonly totpVerifier?;
|
|
60
|
+
private readonly profileResolver?;
|
|
61
|
+
private readonly profileWriter?;
|
|
62
|
+
private readonly mfaDevices?;
|
|
63
|
+
constructor(binder?: SessionTokenBinder | undefined, hasher?: PasswordHasher | undefined, writer?: (CredentialWriter | null) | undefined, sweeper?: (SessionSweeper | null) | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, totpVerifier?: (FactorVerifier | null) | undefined, profileResolver?: (ProfileResolver | null) | undefined, profileWriter?: (ProfileWriter | null) | undefined, mfaDevices?: (MfaDeviceStore | null) | undefined);
|
|
64
|
+
/**
|
|
65
|
+
* Resolve a human-readable otpauth account LABEL for the caller (email, else display
|
|
66
|
+
* name) via the profile resolver. Best-effort: no resolver / null profile / a thrown
|
|
67
|
+
* store error → the generic {@link FALLBACK_OTPAUTH_LABEL}. NEVER returns the raw
|
|
68
|
+
* principal id — the label is shown to the user (in the URI), so a `*_uuid` there
|
|
69
|
+
* would violate the never-show-UUIDs rule.
|
|
70
|
+
*/
|
|
71
|
+
private resolveOtpauthLabel;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the bearer token → the caller's FULL claims (id + sessionId), or throw a
|
|
74
|
+
* generic 401. Uses the binder DIRECTLY (not `resolveRequestPrincipal`) so the
|
|
75
|
+
* `sessionId` survives — change-password needs it to keep the current session.
|
|
76
|
+
*/
|
|
77
|
+
private requireClaims;
|
|
78
|
+
/**
|
|
79
|
+
* ENFORCED-RE-ENROLL GATE for the self-scoped `/account/*` surface (spec §4.2).
|
|
80
|
+
*
|
|
81
|
+
* WHY IT LIVES HERE (not only in the GlobalEnforcementGuard): every `/account/*`
|
|
82
|
+
* route is `@Public()` to the classification guard (it self-authenticates via
|
|
83
|
+
* {@link requireClaims}), so the guard's `mustReenroll` gate — which fires only on
|
|
84
|
+
* `@Classified` routes — NEVER runs on this surface. Without this chokepoint, a
|
|
85
|
+
* recovery-login (`mustReenroll:true`) session could call the account API DIRECTLY —
|
|
86
|
+
* e.g. `DELETE /account/mfa/devices/:id` to strip every device + wipe recovery codes
|
|
87
|
+
* WITHOUT confirming a fresh device — defeating the whole safeguard (spec §4.2:
|
|
88
|
+
* "calling the API directly cannot bypass it").
|
|
89
|
+
*
|
|
90
|
+
* WHY A PER-HANDLER BOOLEAN (not path matching): each handler declares its OWN
|
|
91
|
+
* re-enroll policy via a literal `allowedDuringReenroll`. This is unambiguous and
|
|
92
|
+
* cannot be fooled by URL/path normalization — there is no string matching to trick.
|
|
93
|
+
*
|
|
94
|
+
* POLICY (spec §4.2 + hardening): a `mustReenroll` session may ADD a device
|
|
95
|
+
* (`begin`/`confirm`), REGENERATE codes, and READ its devices — but must NOT
|
|
96
|
+
* REMOVE devices, rename them, change the password, or edit the profile. Removing
|
|
97
|
+
* devices is the exact attack vector (it strips MFA), so `removeDevice` is BLOCKED.
|
|
98
|
+
*
|
|
99
|
+
* A normal (`mustReenroll:false`) session is unaffected — this is a no-op for it.
|
|
100
|
+
*/
|
|
101
|
+
private enforceReenroll;
|
|
102
|
+
/**
|
|
103
|
+
* `POST /account/change-password` — change the AUTHENTICATED caller's own password.
|
|
104
|
+
* Verifies the current password (read by principal id via the writer seam), writes
|
|
105
|
+
* the new hash, then revokes the caller's OTHER sessions (keeping the current one
|
|
106
|
+
* live). Self-scoped: acts only on `claims.id`.
|
|
107
|
+
*
|
|
108
|
+
* Outcomes:
|
|
109
|
+
* • no/invalid token → 401 (generic)
|
|
110
|
+
* • newPassword shorter than the minimum → 422 `{ error: 'weak_password' }`
|
|
111
|
+
* • writer/hasher seam absent → 501 `{ error: 'not_available' }`
|
|
112
|
+
* • wrong current password → 401 (generic, no write)
|
|
113
|
+
* • success → 204 (no body)
|
|
114
|
+
*/
|
|
115
|
+
changePassword(authorization: string | undefined, body: {
|
|
116
|
+
currentPassword?: string;
|
|
117
|
+
newPassword?: string;
|
|
118
|
+
}): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Verify a presented TOTP `code` against a base32 `secret` using the injected core
|
|
121
|
+
* verifier (the SAME RFC-6238 verifier the login MFA branch uses). Returns the
|
|
122
|
+
* verdict's `satisfied` boolean; a malformed code/secret → `false` (the verifier
|
|
123
|
+
* never throws). NEVER logs the code or the secret.
|
|
124
|
+
*/
|
|
125
|
+
private verifyTotp;
|
|
126
|
+
/**
|
|
127
|
+
* `PATCH /account/profile` — edit the AUTHENTICATED caller's OWN display profile
|
|
128
|
+
* (name and/or email). Self-scoped: acts only on `claims.id`. On success returns the
|
|
129
|
+
* refreshed {@link CurrentUserProfile} (display names, never UUIDs — the bare `id`
|
|
130
|
+
* fields are machine-only), so the UI can update the header/user card in place.
|
|
131
|
+
*
|
|
132
|
+
* Only the fields actually supplied are written (partial edit). At least one of
|
|
133
|
+
* `name`/`email` must be present and non-empty; a supplied email must look like an
|
|
134
|
+
* email. These are semantic validations on the caller's OWN profile (no credential
|
|
135
|
+
* oracle), so they return precise 422 reasons rather than a generic 4xx.
|
|
136
|
+
*
|
|
137
|
+
* Outcomes:
|
|
138
|
+
* • no/invalid token → 401 (generic)
|
|
139
|
+
* • profileWriter seam absent → 501 `{ error: 'not_available' }`
|
|
140
|
+
* • neither name nor email supplied → 422 `{ error: 'no_changes' }`
|
|
141
|
+
* • email supplied but malformed → 422 `{ error: 'invalid_email' }`
|
|
142
|
+
* • success → 200 (the refreshed CurrentUserProfile)
|
|
143
|
+
*/
|
|
144
|
+
updateProfile(authorization: string | undefined, body: {
|
|
145
|
+
name?: string;
|
|
146
|
+
email?: string;
|
|
147
|
+
}): Promise<CurrentUserProfile>;
|
|
148
|
+
/**
|
|
149
|
+
* Mint a fresh recovery-code batch, hash each (the SAME Argon2 hasher recovery-code
|
|
150
|
+
* consume verifies against), and REPLACE the caller's prior codes. Returns the RAW
|
|
151
|
+
* codes to show the user exactly once. Caller guarantees the recovery store + hasher
|
|
152
|
+
* are present (checked at the route). NEVER logs the codes or hashes.
|
|
153
|
+
*/
|
|
154
|
+
private replaceRecoveryCodes;
|
|
155
|
+
/**
|
|
156
|
+
* Verify a presented `code` against ANY of the caller's CONFIRMED device secrets
|
|
157
|
+
* (TOTP), returning true on the first match. Used by remove/regenerate where the
|
|
158
|
+
* proof may come from any live device (not a specific one). NEVER logs the code.
|
|
159
|
+
*/
|
|
160
|
+
private verifyAgainstAnyDevice;
|
|
161
|
+
/**
|
|
162
|
+
* `GET /account/mfa/devices` — list the caller's CONFIRMED authenticator devices.
|
|
163
|
+
* `mfaEnabled` reflects whether any confirmed device exists. Pending (unconfirmed)
|
|
164
|
+
* devices are internal and never surfaced. A device `secret` is never included
|
|
165
|
+
* (the {@link MfaDevice} display shape omits it).
|
|
166
|
+
*
|
|
167
|
+
* Outcomes: no/invalid token → 401; store absent → 501; success → 200
|
|
168
|
+
* `{ devices: MfaDevice[], mfaEnabled: boolean }`.
|
|
169
|
+
*/
|
|
170
|
+
listDevices(authorization: string | undefined): Promise<{
|
|
171
|
+
devices: MfaDevice[];
|
|
172
|
+
mfaEnabled: boolean;
|
|
173
|
+
}>;
|
|
174
|
+
/**
|
|
175
|
+
* `POST /account/mfa/devices/begin` — start enrolling a NEW authenticator device.
|
|
176
|
+
* Mints a fresh secret, creates a PENDING device row, and returns the provisioning
|
|
177
|
+
* material (`otpauthUri` for a QR + `secret` for manual entry). NOT active until
|
|
178
|
+
* `confirm`. A blank name defaults to `"Authenticator N"` (N = confirmed count + 1).
|
|
179
|
+
*
|
|
180
|
+
* Outcomes: 401; store absent → 501; success → 200 `{ deviceId, otpauthUri, secret }`.
|
|
181
|
+
*/
|
|
182
|
+
beginDevice(authorization: string | undefined, body: {
|
|
183
|
+
name?: string;
|
|
184
|
+
}): Promise<{
|
|
185
|
+
deviceId: string;
|
|
186
|
+
otpauthUri: string;
|
|
187
|
+
secret: string;
|
|
188
|
+
}>;
|
|
189
|
+
/**
|
|
190
|
+
* `POST /account/mfa/devices/confirm` — activate a pending device by proving a live
|
|
191
|
+
* code from it. Loads THAT device's secret (owned + still pending), verifies the
|
|
192
|
+
* code, and confirms. If this is the caller's FIRST confirmed device, fresh recovery
|
|
193
|
+
* codes are minted (shown once) and returned; subsequent devices return `{}` and do
|
|
194
|
+
* NOT touch recovery codes.
|
|
195
|
+
*
|
|
196
|
+
* Outcomes: 401; store/recovery/hasher absent → 501; device not pending/owned → 404;
|
|
197
|
+
* wrong/expired code → 400 (device stays pending); success → 200 `{ recoveryCodes? }`.
|
|
198
|
+
*/
|
|
199
|
+
confirmDevice(authorization: string | undefined, body: {
|
|
200
|
+
deviceId?: string;
|
|
201
|
+
code?: string;
|
|
202
|
+
}): Promise<{
|
|
203
|
+
recoveryCodes?: string[];
|
|
204
|
+
}>;
|
|
205
|
+
/**
|
|
206
|
+
* `PATCH /account/mfa/devices/:id/rename` — rename one of the caller's devices.
|
|
207
|
+
* Cosmetic (renaming a label doesn't weaken 2FA), so it is session-auth only (no
|
|
208
|
+
* code required), consistent with profile-edit. Trimmed empty name → 422.
|
|
209
|
+
*
|
|
210
|
+
* Outcomes: 401; store absent → 501; blank name → 422; not found/owned → 404;
|
|
211
|
+
* success → 200 `{ device }`.
|
|
212
|
+
*/
|
|
213
|
+
renameDevice(authorization: string | undefined, id: string, body: {
|
|
214
|
+
name?: string;
|
|
215
|
+
}): Promise<{
|
|
216
|
+
device: MfaDevice;
|
|
217
|
+
}>;
|
|
218
|
+
/**
|
|
219
|
+
* `DELETE /account/mfa/devices/:id` — remove one of the caller's devices. Requires
|
|
220
|
+
* proof: a live TOTP code from ANY of the caller's remaining confirmed devices, OR a
|
|
221
|
+
* recovery code — so a hijacked live session can't silently strip MFA. Removing the
|
|
222
|
+
* LAST device is the "disable MFA" path (authorized by that last device's own code)
|
|
223
|
+
* and additionally wipes the account's recovery codes.
|
|
224
|
+
*
|
|
225
|
+
* Outcomes: 401; store absent → 501; wrong code → 400 (no remove); not found/owned →
|
|
226
|
+
* 404; success → 204.
|
|
227
|
+
*/
|
|
228
|
+
removeDevice(authorization: string | undefined, id: string, body: {
|
|
229
|
+
code?: string;
|
|
230
|
+
}): Promise<void>;
|
|
231
|
+
/**
|
|
232
|
+
* `POST /account/mfa/recovery-codes/regenerate` — mint a fresh recovery-code batch
|
|
233
|
+
* (replacing the old set). Requires MFA to be enabled (≥1 confirmed device) and proof
|
|
234
|
+
* — a TOTP from any confirmed device OR an existing recovery code.
|
|
235
|
+
*
|
|
236
|
+
* Outcomes: 401; store/recovery/hasher absent → 501; MFA off → 400; wrong code → 400;
|
|
237
|
+
* success → 200 `{ recoveryCodes }`.
|
|
238
|
+
*/
|
|
239
|
+
regenerateRecoveryCodes(authorization: string | undefined, body: {
|
|
240
|
+
code?: string;
|
|
241
|
+
}): Promise<{
|
|
242
|
+
recoveryCodes: string[];
|
|
243
|
+
}>;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=account.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"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"}
|