@astram/guard 0.2.0 → 0.3.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.
Files changed (170) hide show
  1. package/dist/auth/account.controller.d.ts +245 -0
  2. package/dist/auth/account.controller.d.ts.map +1 -0
  3. package/dist/auth/account.controller.js +673 -0
  4. package/dist/auth/account.controller.js.map +1 -0
  5. package/dist/auth/auth.controller.d.ts +219 -5
  6. package/dist/auth/auth.controller.d.ts.map +1 -1
  7. package/dist/auth/auth.controller.js +790 -12
  8. package/dist/auth/auth.controller.js.map +1 -0
  9. package/dist/auth/auth.module.d.ts +100 -2
  10. package/dist/auth/auth.module.d.ts.map +1 -1
  11. package/dist/auth/auth.module.js +299 -7
  12. package/dist/auth/auth.module.js.map +1 -0
  13. package/dist/auth/connections.js.map +1 -0
  14. package/dist/auth/dto.d.ts +16 -6
  15. package/dist/auth/dto.d.ts.map +1 -1
  16. package/dist/auth/dto.js.map +1 -0
  17. package/dist/auth/pending-mfa-store.js.map +1 -0
  18. package/dist/auth/persistence.module.js.map +1 -0
  19. package/dist/auth/ports/audit-sink.d.ts +47 -0
  20. package/dist/auth/ports/audit-sink.d.ts.map +1 -0
  21. package/dist/auth/ports/audit-sink.js +20 -0
  22. package/dist/auth/ports/audit-sink.js.map +1 -0
  23. package/dist/auth/ports/credential-writer.d.ts +23 -0
  24. package/dist/auth/ports/credential-writer.d.ts.map +1 -0
  25. package/dist/auth/ports/credential-writer.js +2 -0
  26. package/dist/auth/ports/credential-writer.js.map +1 -0
  27. package/dist/auth/ports/email-sender.d.ts +14 -0
  28. package/dist/auth/ports/email-sender.d.ts.map +1 -0
  29. package/dist/auth/ports/email-sender.js +2 -0
  30. package/dist/auth/ports/email-sender.js.map +1 -0
  31. package/dist/auth/ports/mfa-device-store.d.ts +45 -0
  32. package/dist/auth/ports/mfa-device-store.d.ts.map +1 -0
  33. package/dist/auth/ports/mfa-device-store.js +13 -0
  34. package/dist/auth/ports/mfa-device-store.js.map +1 -0
  35. package/dist/auth/ports/profile-writer.d.ts +12 -0
  36. package/dist/auth/ports/profile-writer.d.ts.map +1 -0
  37. package/dist/auth/ports/profile-writer.js +2 -0
  38. package/dist/auth/ports/profile-writer.js.map +1 -0
  39. package/dist/auth/ports/recovery-code-store.d.ts +10 -0
  40. package/dist/auth/ports/recovery-code-store.d.ts.map +1 -0
  41. package/dist/auth/ports/recovery-code-store.js +2 -0
  42. package/dist/auth/ports/recovery-code-store.js.map +1 -0
  43. package/dist/auth/ports/reset-token-store.d.ts +12 -0
  44. package/dist/auth/ports/reset-token-store.d.ts.map +1 -0
  45. package/dist/auth/ports/reset-token-store.js +2 -0
  46. package/dist/auth/ports/reset-token-store.js.map +1 -0
  47. package/dist/auth/ports/session-facts-projector.d.ts +44 -0
  48. package/dist/auth/ports/session-facts-projector.d.ts.map +1 -0
  49. package/dist/auth/ports/session-facts-projector.js +30 -0
  50. package/dist/auth/ports/session-facts-projector.js.map +1 -0
  51. package/dist/auth/ports/session-sweeper.d.ts +12 -0
  52. package/dist/auth/ports/session-sweeper.d.ts.map +1 -0
  53. package/dist/auth/ports/session-sweeper.js +2 -0
  54. package/dist/auth/ports/session-sweeper.js.map +1 -0
  55. package/dist/auth/profile-resolver.d.ts +73 -0
  56. package/dist/auth/profile-resolver.d.ts.map +1 -0
  57. package/dist/auth/profile-resolver.js +28 -0
  58. package/dist/auth/profile-resolver.js.map +1 -0
  59. package/dist/auth/rate-limit/attempt-limiter.d.ts +91 -0
  60. package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -0
  61. package/dist/auth/rate-limit/attempt-limiter.js +133 -0
  62. package/dist/auth/rate-limit/attempt-limiter.js.map +1 -0
  63. package/dist/auth/tokens.d.ts +174 -0
  64. package/dist/auth/tokens.d.ts.map +1 -1
  65. package/dist/auth/tokens.js +190 -1
  66. package/dist/auth/tokens.js.map +1 -0
  67. package/dist/auth/totp-enrollment.d.ts +42 -0
  68. package/dist/auth/totp-enrollment.d.ts.map +1 -0
  69. package/dist/auth/totp-enrollment.js +96 -0
  70. package/dist/auth/totp-enrollment.js.map +1 -0
  71. package/dist/authentication/argon2id-password-hasher.js.map +1 -0
  72. package/dist/authentication/mariadb-credential-resolver.d.ts +38 -24
  73. package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
  74. package/dist/authentication/mariadb-credential-resolver.js +42 -28
  75. package/dist/authentication/mariadb-credential-resolver.js.map +1 -0
  76. package/dist/authz/cross-tenant-grant-writer.d.ts +259 -0
  77. package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -0
  78. package/dist/authz/cross-tenant-grant-writer.js +397 -0
  79. package/dist/authz/cross-tenant-grant-writer.js.map +1 -0
  80. package/dist/authz/manifest-operation-authority-adapter.d.ts +65 -0
  81. package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -0
  82. package/dist/authz/manifest-operation-authority-adapter.js +108 -0
  83. package/dist/authz/manifest-operation-authority-adapter.js.map +1 -0
  84. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts +90 -0
  85. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -0
  86. package/dist/authz/mariadb-cross-tenant-grant-adapter.js +211 -0
  87. package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +1 -0
  88. package/dist/authz/mariadb-record-rule-adapter.d.ts +60 -0
  89. package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -0
  90. package/dist/authz/mariadb-record-rule-adapter.js +154 -0
  91. package/dist/authz/mariadb-record-rule-adapter.js.map +1 -0
  92. package/dist/authz/mariadb-record-share-adapter.d.ts +75 -0
  93. package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -0
  94. package/dist/authz/mariadb-record-share-adapter.js +106 -0
  95. package/dist/authz/mariadb-record-share-adapter.js.map +1 -0
  96. package/dist/authz/record-share-cascade.d.ts +52 -0
  97. package/dist/authz/record-share-cascade.d.ts.map +1 -0
  98. package/dist/authz/record-share-cascade.js +49 -0
  99. package/dist/authz/record-share-cascade.js.map +1 -0
  100. package/dist/authz/record-share-writer.d.ts +175 -0
  101. package/dist/authz/record-share-writer.d.ts.map +1 -0
  102. package/dist/authz/record-share-writer.js +225 -0
  103. package/dist/authz/record-share-writer.js.map +1 -0
  104. package/dist/authz/wire-record-authorization.d.ts +66 -0
  105. package/dist/authz/wire-record-authorization.d.ts.map +1 -0
  106. package/dist/authz/wire-record-authorization.js +34 -0
  107. package/dist/authz/wire-record-authorization.js.map +1 -0
  108. package/dist/boot/boot-sequence.js.map +1 -0
  109. package/dist/boot/boot.module.js.map +1 -0
  110. package/dist/completeness/catalog-reconciler.d.ts +21 -0
  111. package/dist/completeness/catalog-reconciler.d.ts.map +1 -0
  112. package/dist/completeness/catalog-reconciler.js +74 -0
  113. package/dist/completeness/catalog-reconciler.js.map +1 -0
  114. package/dist/completeness/operation-inventory-scanner.d.ts +17 -0
  115. package/dist/completeness/operation-inventory-scanner.d.ts.map +1 -0
  116. package/dist/completeness/operation-inventory-scanner.js +79 -0
  117. package/dist/completeness/operation-inventory-scanner.js.map +1 -0
  118. package/dist/completeness/ports/catalog-store.d.ts +33 -0
  119. package/dist/completeness/ports/catalog-store.d.ts.map +1 -0
  120. package/dist/completeness/ports/catalog-store.js +2 -0
  121. package/dist/completeness/ports/catalog-store.js.map +1 -0
  122. package/dist/config/app-config.js.map +1 -0
  123. package/dist/config/config.module.js.map +1 -0
  124. package/dist/enforcement/classification.decorator.d.ts +33 -14
  125. package/dist/enforcement/classification.decorator.d.ts.map +1 -1
  126. package/dist/enforcement/classification.decorator.js +34 -14
  127. package/dist/enforcement/classification.decorator.js.map +1 -0
  128. package/dist/enforcement/core-seam.js.map +1 -0
  129. package/dist/enforcement/enforcement.module.js.map +1 -0
  130. package/dist/enforcement/global-enforcement.guard.d.ts +29 -19
  131. package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
  132. package/dist/enforcement/global-enforcement.guard.js +108 -25
  133. package/dist/enforcement/global-enforcement.guard.js.map +1 -0
  134. package/dist/enforcement/reenroll-allowlist.d.ts +49 -0
  135. package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -0
  136. package/dist/enforcement/reenroll-allowlist.js +77 -0
  137. package/dist/enforcement/reenroll-allowlist.js.map +1 -0
  138. package/dist/index.d.ts +35 -3
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/index.js +159 -7
  141. package/dist/index.js.map +1 -0
  142. package/dist/module/shield-tokens.d.ts +15 -0
  143. package/dist/module/shield-tokens.d.ts.map +1 -0
  144. package/dist/module/shield-tokens.js +17 -0
  145. package/dist/module/shield-tokens.js.map +1 -0
  146. package/dist/module/shield.module.d.ts +153 -9
  147. package/dist/module/shield.module.d.ts.map +1 -1
  148. package/dist/module/shield.module.js +181 -24
  149. package/dist/module/shield.module.js.map +1 -0
  150. package/dist/request-auth/request-principal.d.ts +42 -0
  151. package/dist/request-auth/request-principal.d.ts.map +1 -0
  152. package/dist/request-auth/request-principal.js +87 -0
  153. package/dist/request-auth/request-principal.js.map +1 -0
  154. package/dist/request-auth/session-facts-als.d.ts +65 -0
  155. package/dist/request-auth/session-facts-als.d.ts.map +1 -0
  156. package/dist/request-auth/session-facts-als.js +57 -0
  157. package/dist/request-auth/session-facts-als.js.map +1 -0
  158. package/dist/request-auth/session-token-binder.d.ts +130 -0
  159. package/dist/request-auth/session-token-binder.d.ts.map +1 -0
  160. package/dist/request-auth/session-token-binder.js +277 -0
  161. package/dist/request-auth/session-token-binder.js.map +1 -0
  162. package/dist/request-auth/tokens.d.ts +14 -0
  163. package/dist/request-auth/tokens.d.ts.map +1 -0
  164. package/dist/request-auth/tokens.js +16 -0
  165. package/dist/request-auth/tokens.js.map +1 -0
  166. package/dist/session/crypto-adapters.js.map +1 -0
  167. package/dist/session/index.js.map +1 -0
  168. package/dist/session/mariadb-session-record-store.js.map +1 -0
  169. package/dist/session/redis-hot-session-store.js.map +1 -0
  170. 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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"}