@astram/guard 0.7.0 → 0.9.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 (187) hide show
  1. package/dist/auth/account.controller.d.ts +27 -5
  2. package/dist/auth/account.controller.d.ts.map +1 -1
  3. package/dist/auth/account.controller.js +99 -26
  4. package/dist/auth/auth.controller.d.ts +130 -21
  5. package/dist/auth/auth.controller.d.ts.map +1 -1
  6. package/dist/auth/auth.controller.js +537 -143
  7. package/dist/auth/auth.module.d.ts +15 -1
  8. package/dist/auth/auth.module.d.ts.map +1 -1
  9. package/dist/auth/auth.module.js +212 -30
  10. package/dist/auth/connections.d.ts +1 -1
  11. package/dist/auth/connections.d.ts.map +1 -1
  12. package/dist/auth/connections.js +14 -3
  13. package/dist/auth/default-session-facts-projector.d.ts +26 -0
  14. package/dist/auth/default-session-facts-projector.d.ts.map +1 -0
  15. package/dist/auth/default-session-facts-projector.js +21 -0
  16. package/dist/auth/mfa-step-up.d.ts +32 -0
  17. package/dist/auth/mfa-step-up.d.ts.map +1 -0
  18. package/dist/auth/mfa-step-up.js +109 -0
  19. package/dist/auth/pending-mfa-store.d.ts +50 -52
  20. package/dist/auth/pending-mfa-store.d.ts.map +1 -1
  21. package/dist/auth/pending-mfa-store.js +103 -61
  22. package/dist/auth/ports/session-facts-projector.d.ts +5 -0
  23. package/dist/auth/ports/session-facts-projector.d.ts.map +1 -1
  24. package/dist/auth/rate-limit/canonical-hint.d.ts +24 -0
  25. package/dist/auth/rate-limit/canonical-hint.d.ts.map +1 -0
  26. package/dist/auth/rate-limit/canonical-hint.js +63 -0
  27. package/dist/auth/rate-limit/trust-proxy-check.d.ts +46 -0
  28. package/dist/auth/rate-limit/trust-proxy-check.d.ts.map +1 -0
  29. package/dist/auth/rate-limit/trust-proxy-check.js +94 -0
  30. package/dist/auth/tokens.d.ts +70 -11
  31. package/dist/auth/tokens.d.ts.map +1 -1
  32. package/dist/auth/tokens.js +71 -12
  33. package/dist/authentication/log-email-sender.d.ts +9 -4
  34. package/dist/authentication/log-email-sender.d.ts.map +1 -1
  35. package/dist/authentication/mariadb-api-key-store.d.ts +5 -1
  36. package/dist/authentication/mariadb-api-key-store.d.ts.map +1 -1
  37. package/dist/authentication/mariadb-api-key-store.js +43 -7
  38. package/dist/authentication/mariadb-credential-resolver.d.ts +79 -65
  39. package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
  40. package/dist/authentication/mariadb-credential-resolver.js +116 -73
  41. package/dist/authentication/mariadb-credential-writer.d.ts.map +1 -1
  42. package/dist/authentication/mariadb-or-totp-verifier.d.ts +21 -3
  43. package/dist/authentication/mariadb-or-totp-verifier.d.ts.map +1 -1
  44. package/dist/authentication/mariadb-or-totp-verifier.js +37 -6
  45. package/dist/authentication/mariadb-profile-resolver.d.ts.map +1 -1
  46. package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
  47. package/dist/authentication/mariadb-session-sweeper.d.ts +14 -1
  48. package/dist/authentication/mariadb-session-sweeper.d.ts.map +1 -1
  49. package/dist/authentication/mariadb-session-sweeper.js +29 -11
  50. package/dist/authentication/noop-email-sender.d.ts +12 -0
  51. package/dist/authentication/noop-email-sender.d.ts.map +1 -0
  52. package/dist/authentication/noop-email-sender.js +9 -0
  53. package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -1
  54. package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -1
  55. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -1
  56. package/dist/authz/mariadb-cross-tenant-grant-adapter.js +3 -1
  57. package/dist/authz/mariadb-policy-store.js +1 -1
  58. package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -1
  59. package/dist/authz/mariadb-record-rule-adapter.js +1 -4
  60. package/dist/authz/permission-version-cache.d.ts +38 -0
  61. package/dist/authz/permission-version-cache.d.ts.map +1 -0
  62. package/dist/authz/permission-version-cache.js +81 -0
  63. package/dist/authz/wire-record-authorization.d.ts +25 -1
  64. package/dist/authz/wire-record-authorization.d.ts.map +1 -1
  65. package/dist/authz/wire-record-authorization.js +55 -2
  66. package/dist/completeness/catalog-reconciler.d.ts.map +1 -1
  67. package/dist/config/app-config.d.ts +36 -0
  68. package/dist/config/app-config.d.ts.map +1 -1
  69. package/dist/config/app-config.js +44 -4
  70. package/dist/encryption/local-kek-crypto.d.ts.map +1 -1
  71. package/dist/enforcement/enforcement.module.d.ts.map +1 -1
  72. package/dist/enforcement/enforcement.module.js +9 -0
  73. package/dist/enforcement/engine-error.filter.d.ts +57 -0
  74. package/dist/enforcement/engine-error.filter.d.ts.map +1 -0
  75. package/dist/enforcement/engine-error.filter.js +118 -0
  76. package/dist/enforcement/global-enforcement.guard.d.ts +29 -2
  77. package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
  78. package/dist/enforcement/global-enforcement.guard.js +143 -5
  79. package/dist/identity/auth-facts.controller.d.ts.map +1 -1
  80. package/dist/identity/permission-facts.adapter.d.ts.map +1 -1
  81. package/dist/identity/permission-facts.adapter.js +2 -3
  82. package/dist/index.d.ts +13 -7
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +68 -28
  85. package/dist/internal.d.ts +12 -0
  86. package/dist/internal.d.ts.map +1 -0
  87. package/dist/internal.js +16 -0
  88. package/dist/module/shield.module.d.ts +9 -2
  89. package/dist/module/shield.module.d.ts.map +1 -1
  90. package/dist/module/shield.module.js +47 -38
  91. package/dist/request-auth/session-facts-als.d.ts +16 -1
  92. package/dist/request-auth/session-facts-als.d.ts.map +1 -1
  93. package/dist/request-auth/session-facts-als.js +23 -0
  94. package/dist/request-auth/session-token-binder.d.ts +166 -10
  95. package/dist/request-auth/session-token-binder.d.ts.map +1 -1
  96. package/dist/request-auth/session-token-binder.js +408 -28
  97. package/dist/secrets/encrypted-file-secrets.d.ts.map +1 -1
  98. package/dist/secrets/encrypted-file-secrets.js +9 -3
  99. package/dist/session/hot-revoking-session-record-store.d.ts +46 -0
  100. package/dist/session/hot-revoking-session-record-store.d.ts.map +1 -0
  101. package/dist/session/hot-revoking-session-record-store.js +58 -0
  102. package/dist/session/index.d.ts +3 -1
  103. package/dist/session/index.d.ts.map +1 -1
  104. package/dist/session/index.js +8 -1
  105. package/dist/session/mariadb-session-record-store.d.ts +6 -0
  106. package/dist/session/mariadb-session-record-store.d.ts.map +1 -1
  107. package/dist/session/mariadb-session-record-store.js +16 -1
  108. package/dist/session/session-lifetimes.d.ts +30 -0
  109. package/dist/session/session-lifetimes.d.ts.map +1 -0
  110. package/dist/session/session-lifetimes.js +21 -0
  111. package/dist/session/session-restriction-store.d.ts +43 -0
  112. package/dist/session/session-restriction-store.d.ts.map +1 -0
  113. package/dist/session/session-restriction-store.js +35 -0
  114. package/package.json +14 -3
  115. package/dist/auth/account.controller.js.map +0 -1
  116. package/dist/auth/auth.controller.js.map +0 -1
  117. package/dist/auth/auth.module.js.map +0 -1
  118. package/dist/auth/connections.js.map +0 -1
  119. package/dist/auth/dto.js.map +0 -1
  120. package/dist/auth/pending-mfa-store.js.map +0 -1
  121. package/dist/auth/persistence.module.js.map +0 -1
  122. package/dist/auth/ports/audit-sink.js.map +0 -1
  123. package/dist/auth/ports/credential-writer.js.map +0 -1
  124. package/dist/auth/ports/email-sender.js.map +0 -1
  125. package/dist/auth/ports/membership-checker.js.map +0 -1
  126. package/dist/auth/ports/mfa-device-store.js.map +0 -1
  127. package/dist/auth/ports/profile-writer.js.map +0 -1
  128. package/dist/auth/ports/recovery-code-store.js.map +0 -1
  129. package/dist/auth/ports/reset-token-store.js.map +0 -1
  130. package/dist/auth/ports/scope-subtree-resolver.js.map +0 -1
  131. package/dist/auth/ports/session-facts-projector.js.map +0 -1
  132. package/dist/auth/ports/session-sweeper.js.map +0 -1
  133. package/dist/auth/profile-resolver.js.map +0 -1
  134. package/dist/auth/rate-limit/attempt-limiter.js.map +0 -1
  135. package/dist/auth/tokens.js.map +0 -1
  136. package/dist/auth/totp-enrollment.js.map +0 -1
  137. package/dist/authentication/argon2id-password-hasher.js.map +0 -1
  138. package/dist/authentication/log-email-sender.js.map +0 -1
  139. package/dist/authentication/mariadb-credential-resolver.js.map +0 -1
  140. package/dist/authentication/mariadb-credential-writer.js.map +0 -1
  141. package/dist/authentication/mariadb-mfa-device-store.js.map +0 -1
  142. package/dist/authentication/mariadb-or-totp-verifier.js.map +0 -1
  143. package/dist/authentication/mariadb-profile-resolver.js.map +0 -1
  144. package/dist/authentication/mariadb-profile-writer.js.map +0 -1
  145. package/dist/authentication/mariadb-recovery-code-store.js.map +0 -1
  146. package/dist/authentication/mariadb-reset-token-store.js.map +0 -1
  147. package/dist/authentication/mariadb-session-sweeper.js.map +0 -1
  148. package/dist/authz/cross-tenant-grant-writer.js.map +0 -1
  149. package/dist/authz/list-scope-sql.js.map +0 -1
  150. package/dist/authz/manifest-operation-authority-adapter.js.map +0 -1
  151. package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +0 -1
  152. package/dist/authz/mariadb-list-scope-adapter.js.map +0 -1
  153. package/dist/authz/mariadb-policy-store.js.map +0 -1
  154. package/dist/authz/mariadb-record-rule-adapter.js.map +0 -1
  155. package/dist/authz/mariadb-record-share-adapter.js.map +0 -1
  156. package/dist/authz/record-share-cascade.js.map +0 -1
  157. package/dist/authz/record-share-writer.js.map +0 -1
  158. package/dist/authz/wire-record-authorization.js.map +0 -1
  159. package/dist/boot/boot-sequence.js.map +0 -1
  160. package/dist/boot/boot.module.js.map +0 -1
  161. package/dist/completeness/catalog-reconciler.js.map +0 -1
  162. package/dist/completeness/operation-inventory-scanner.js.map +0 -1
  163. package/dist/completeness/ports/catalog-store.js.map +0 -1
  164. package/dist/config/app-config.js.map +0 -1
  165. package/dist/config/config.module.js.map +0 -1
  166. package/dist/enforcement/classification.decorator.js.map +0 -1
  167. package/dist/enforcement/core-seam.js.map +0 -1
  168. package/dist/enforcement/enforcement.module.js.map +0 -1
  169. package/dist/enforcement/global-enforcement.guard.js.map +0 -1
  170. package/dist/enforcement/reenroll-allowlist.js.map +0 -1
  171. package/dist/identity/auth-facts.controller.js.map +0 -1
  172. package/dist/identity/identity-actions.js.map +0 -1
  173. package/dist/identity/module-registry.bridge.js.map +0 -1
  174. package/dist/identity/permission-facts.adapter.js.map +0 -1
  175. package/dist/index.js.map +0 -1
  176. package/dist/migrations-dir.js.map +0 -1
  177. package/dist/module/shield-tokens.js.map +0 -1
  178. package/dist/module/shield.module.js.map +0 -1
  179. package/dist/request-auth/request-principal.js.map +0 -1
  180. package/dist/request-auth/session-facts-als.js.map +0 -1
  181. package/dist/request-auth/session-token-binder.js.map +0 -1
  182. package/dist/request-auth/tokens.js.map +0 -1
  183. package/dist/scope/closure-builder.js.map +0 -1
  184. package/dist/session/crypto-adapters.js.map +0 -1
  185. package/dist/session/index.js.map +0 -1
  186. package/dist/session/mariadb-session-record-store.js.map +0 -1
  187. package/dist/session/redis-hot-session-store.js.map +0 -1
@@ -44,6 +44,8 @@
44
44
  */
45
45
  import type { FactorVerifier, PasswordHasher } from '@astram/core';
46
46
  import type { SessionTokenBinder } from '../request-auth/session-token-binder.js';
47
+ import type { SessionRestrictionStore } from '../session/session-restriction-store.js';
48
+ import type { AttemptLimiter } from './rate-limit/attempt-limiter.js';
47
49
  import type { CredentialWriter } from './ports/credential-writer.js';
48
50
  import type { MfaDevice, MfaDeviceStore } from './ports/mfa-device-store.js';
49
51
  import type { CurrentUserProfile, ProfileResolver } from './profile-resolver.js';
@@ -60,7 +62,11 @@ export declare class AccountController {
60
62
  private readonly profileResolver?;
61
63
  private readonly profileWriter?;
62
64
  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);
65
+ private readonly sessionRestrictions?;
66
+ private readonly loginTotpVerifier?;
67
+ private readonly mfaLimiter?;
68
+ private readonly loginLimiter?;
69
+ 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, sessionRestrictions?: (SessionRestrictionStore | null) | undefined, loginTotpVerifier?: (FactorVerifier | null) | undefined, mfaLimiter?: (AttemptLimiter | null) | undefined, loginLimiter?: (AttemptLimiter | null) | undefined);
64
70
  /**
65
71
  * Resolve a human-readable otpauth account LABEL for the caller (email, else display
66
72
  * name) via the profile resolver. Best-effort: no resolver / null profile / a thrown
@@ -109,8 +115,9 @@ export declare class AccountController {
109
115
  * • no/invalid token → 401 (generic)
110
116
  * • newPassword shorter than the minimum → 422 `{ error: 'weak_password' }`
111
117
  * • writer/hasher seam absent → 501 `{ error: 'not_available' }`
112
- * • wrong current password → 401 (generic, no write)
113
- * • success → 204 (no body)
118
+ * • wrong current password → 401 (generic, no write; counted)
119
+ * • account login budget exhausted → 401 (generic, not verified, no write)
120
+ * • success → 204 (no body; counter reset)
114
121
  */
115
122
  changePassword(authorization: string | undefined, body: {
116
123
  currentPassword?: string;
@@ -154,10 +161,25 @@ export declare class AccountController {
154
161
  private replaceRecoveryCodes;
155
162
  /**
156
163
  * 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.
164
+ * (TOTP) through the replay-guarded login verifier: the secrets are bundled
165
+ * newline-joined (the `OrTotpVerifier` contract) and an accepted code is claimed in
166
+ * Redis, so it cannot be reused on this or any other MFA path inside the window. A
167
+ * Redis error on the claim → 503 (fail closed; never an unguarded accept, never a
168
+ * fall-through to the recovery-code check). Guarded verifier not wired → `false`.
169
+ * NEVER logs the code.
159
170
  */
160
171
  private verifyAgainstAnyDevice;
172
+ /**
173
+ * The shared second-factor proof for the code-gated account routes (Phase 8 #1),
174
+ * mirroring `/auth/mfa`: the `mfa:pid:<principalId>` budget is checked BEFORE any TOTP
175
+ * or recovery-code verification (so a locked caller never triggers the Argon2
176
+ * recovery scan) → a TOTP from any confirmed device, else a recovery code (consumed) →
177
+ * a failed proof records a failure (400), a good one resets the counter. Locked → 429.
178
+ * The limiter fails open on a Redis blip (its documented posture); the TOTP replay
179
+ * claim fails closed (503), and the session itself is Redis-bound, so a Redis outage
180
+ * cannot open this path.
181
+ */
182
+ private requireMfaProof;
161
183
  /**
162
184
  * `GET /account/mfa/devices` — list the caller's CONFIRMED authenticator devices.
163
185
  * `mfaEnabled` reflects whether any confirmed device exists. Pending (unconfirmed)
@@ -1 +1 @@
1
- {"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"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"}
@@ -62,6 +62,7 @@ const classification_decorator_js_1 = require("../enforcement/classification.dec
62
62
  const request_principal_js_1 = require("../request-auth/request-principal.js");
63
63
  const tokens_js_1 = require("../request-auth/tokens.js");
64
64
  const tokens_js_2 = require("./tokens.js");
65
+ const canonical_hint_js_1 = require("./rate-limit/canonical-hint.js");
65
66
  const totp_enrollment_js_1 = require("./totp-enrollment.js");
66
67
  /** Max length of a device name (matches the `md_name VARCHAR(120)` column). */
67
68
  const MAX_DEVICE_NAME_LEN = 120;
@@ -103,6 +104,18 @@ function notAvailable() {
103
104
  function badRequest() {
104
105
  throw new common_1.HttpException({ error: 'invalid_request' }, common_1.HttpStatus.BAD_REQUEST);
105
106
  }
107
+ /**
108
+ * The 429 for a caller whose proof budget is exhausted (Phase 8 #1). These routes are
109
+ * self-scoped and already authenticated, so the throttle signal reveals nothing about
110
+ * another account; a 401 here would read as "session expired" to the client's refresh logic.
111
+ */
112
+ function tooManyRequests() {
113
+ throw new common_1.HttpException({ error: 'too_many_requests' }, common_1.HttpStatus.TOO_MANY_REQUESTS);
114
+ }
115
+ /** The retryable 503 when the replay guard (Redis) cannot answer: fail closed, no mutation. */
116
+ function retryableUnavailable() {
117
+ throw new common_1.HttpException({ error: 'authentication_unavailable' }, common_1.HttpStatus.SERVICE_UNAVAILABLE);
118
+ }
106
119
  /**
107
120
  * The 422 for a semantically invalid profile edit — an empty change (`no_changes`)
108
121
  * or a malformed email (`invalid_email`). Distinct from {@link badRequest}: this is
@@ -122,7 +135,11 @@ let AccountController = class AccountController {
122
135
  profileResolver;
123
136
  profileWriter;
124
137
  mfaDevices;
125
- constructor(binder, hasher, writer, sweeper, recoveryCodes, totpVerifier, profileResolver, profileWriter, mfaDevices) {
138
+ sessionRestrictions;
139
+ loginTotpVerifier;
140
+ mfaLimiter;
141
+ loginLimiter;
142
+ constructor(binder, hasher, writer, sweeper, recoveryCodes, totpVerifier, profileResolver, profileWriter, mfaDevices, sessionRestrictions, loginTotpVerifier, mfaLimiter, loginLimiter) {
126
143
  this.binder = binder;
127
144
  this.hasher = hasher;
128
145
  this.writer = writer;
@@ -132,6 +149,10 @@ let AccountController = class AccountController {
132
149
  this.profileResolver = profileResolver;
133
150
  this.profileWriter = profileWriter;
134
151
  this.mfaDevices = mfaDevices;
152
+ this.sessionRestrictions = sessionRestrictions;
153
+ this.loginTotpVerifier = loginTotpVerifier;
154
+ this.mfaLimiter = mfaLimiter;
155
+ this.loginLimiter = loginLimiter;
135
156
  }
136
157
  /**
137
158
  * Resolve a human-readable otpauth account LABEL for the caller (email, else display
@@ -218,8 +239,9 @@ let AccountController = class AccountController {
218
239
  * • no/invalid token → 401 (generic)
219
240
  * • newPassword shorter than the minimum → 422 `{ error: 'weak_password' }`
220
241
  * • writer/hasher seam absent → 501 `{ error: 'not_available' }`
221
- * • wrong current password → 401 (generic, no write)
222
- * • success → 204 (no body)
242
+ * • wrong current password → 401 (generic, no write; counted)
243
+ * • account login budget exhausted → 401 (generic, not verified, no write)
244
+ * • success → 204 (no body; counter reset)
223
245
  */
224
246
  async changePassword(authorization, body) {
225
247
  const claims = await this.requireClaims(authorization);
@@ -238,14 +260,25 @@ let AccountController = class AccountController {
238
260
  }
239
261
  const writer = this.writer;
240
262
  const hasher = this.hasher;
263
+ // Phase 8 #8: the current-password check spends the SAME per-account budget as
264
+ // password login (`login:pid:<principalId>`, shared counter): checked BEFORE the
265
+ // verify (a locked account never reaches the hasher), a wrong current password records
266
+ // a failure, and a success resets it — exactly as a completed login does. Locked → the
267
+ // same generic 401 as a wrong password (no oracle).
268
+ const loginKey = (0, canonical_hint_js_1.loginHintKey)('', claims.id);
269
+ if (this.loginLimiter != null && !(await this.loginLimiter.check(loginKey))) {
270
+ unauthorized();
271
+ }
241
272
  // Verify the current password: read the stored hash BY PRINCIPAL ID via the writer
242
273
  // seam's `getPasswordHash` (change-password holds the principal id from the token,
243
274
  // whereas CredentialResolver keys by identityHint). A missing hash or a mismatch is
244
275
  // the SAME generic 401 (no oracle), and no write happens.
245
276
  const stored = await writer.getPasswordHash(claims.id);
246
277
  if (stored === null || !(await hasher.verify(stored, currentPassword))) {
278
+ await this.loginLimiter?.recordFailure(loginKey);
247
279
  unauthorized();
248
280
  }
281
+ await this.loginLimiter?.reset(loginKey);
249
282
  const newHash = await hasher.hash(newPassword);
250
283
  await writer.setPassword(claims.id, newHash);
251
284
  // Revoke the caller's OTHER sessions (keep the current one live). Best-effort:
@@ -290,9 +323,7 @@ let AccountController = class AccountController {
290
323
  this.enforceReenroll(claims, false);
291
324
  // Normalize: treat only non-empty string fields as a real change (trim so a
292
325
  // whitespace-only value is not a change).
293
- const name = typeof body?.name === 'string' && body.name.trim().length > 0
294
- ? body.name.trim()
295
- : undefined;
326
+ const name = typeof body?.name === 'string' && body.name.trim().length > 0 ? body.name.trim() : undefined;
296
327
  const email = typeof body?.email === 'string' && body.email.trim().length > 0
297
328
  ? body.email.trim()
298
329
  : undefined;
@@ -339,16 +370,52 @@ let AccountController = class AccountController {
339
370
  }
340
371
  /**
341
372
  * Verify a presented `code` against ANY of the caller's CONFIRMED device secrets
342
- * (TOTP), returning true on the first match. Used by remove/regenerate where the
343
- * proof may come from any live device (not a specific one). NEVER logs the code.
373
+ * (TOTP) through the replay-guarded login verifier: the secrets are bundled
374
+ * newline-joined (the `OrTotpVerifier` contract) and an accepted code is claimed in
375
+ * Redis, so it cannot be reused on this or any other MFA path inside the window. A
376
+ * Redis error on the claim → 503 (fail closed; never an unguarded accept, never a
377
+ * fall-through to the recovery-code check). Guarded verifier not wired → `false`.
378
+ * NEVER logs the code.
344
379
  */
345
380
  async verifyAgainstAnyDevice(store, principalId, code) {
381
+ if (this.loginTotpVerifier === undefined || this.loginTotpVerifier === null)
382
+ return false;
346
383
  const secrets = await store.listConfirmedSecrets(principalId);
347
- for (const secret of secrets) {
348
- if (await this.verifyTotp(secret, code))
349
- return true;
384
+ if (secrets.length === 0)
385
+ return false;
386
+ try {
387
+ const verdict = await this.loginTotpVerifier.verify({ factor: 'totp', payload: { code } }, secrets.join('\n'));
388
+ return verdict.satisfied;
350
389
  }
351
- return false;
390
+ catch {
391
+ retryableUnavailable();
392
+ }
393
+ }
394
+ /**
395
+ * The shared second-factor proof for the code-gated account routes (Phase 8 #1),
396
+ * mirroring `/auth/mfa`: the `mfa:pid:<principalId>` budget is checked BEFORE any TOTP
397
+ * or recovery-code verification (so a locked caller never triggers the Argon2
398
+ * recovery scan) → a TOTP from any confirmed device, else a recovery code (consumed) →
399
+ * a failed proof records a failure (400), a good one resets the counter. Locked → 429.
400
+ * The limiter fails open on a Redis blip (its documented posture); the TOTP replay
401
+ * claim fails closed (503), and the session itself is Redis-bound, so a Redis outage
402
+ * cannot open this path.
403
+ */
404
+ async requireMfaProof(store, principalId, code) {
405
+ const mfaKey = `mfa:pid:${principalId}`;
406
+ if (this.mfaLimiter != null && !(await this.mfaLimiter.check(mfaKey))) {
407
+ tooManyRequests();
408
+ }
409
+ const byTotp = await this.verifyAgainstAnyDevice(store, principalId, code);
410
+ const byRecovery = !byTotp &&
411
+ this.recoveryCodes !== undefined &&
412
+ this.recoveryCodes !== null &&
413
+ (await this.recoveryCodes.consume(principalId, code));
414
+ if (!byTotp && !byRecovery) {
415
+ await this.mfaLimiter?.recordFailure(mfaKey);
416
+ badRequest();
417
+ }
418
+ await this.mfaLimiter?.reset(mfaKey);
352
419
  }
353
420
  /**
354
421
  * `GET /account/mfa/devices` — list the caller's CONFIRMED authenticator devices.
@@ -446,6 +513,11 @@ let AccountController = class AccountController {
446
513
  if (claims.mustReenroll === true && this.binder !== undefined && this.binder !== null) {
447
514
  await this.binder.clearReenroll(claims.sessionId);
448
515
  }
516
+ // Durable side (Phase 3B review P1). Best-effort: a failed clear only means a binding rebuilt
517
+ // after a Redis loss is restricted again (the safe direction); the user re-confirms.
518
+ if (claims.mustReenroll === true && this.sessionRestrictions) {
519
+ await this.sessionRestrictions.clearMustReenroll(claims.sessionId).catch(() => undefined);
520
+ }
449
521
  if (wasFirst) {
450
522
  const recoveryCodes = await this.replaceRecoveryCodes(claims.id, recoveryStore, hasher);
451
523
  return { recoveryCodes };
@@ -499,14 +571,9 @@ let AccountController = class AccountController {
499
571
  const store = this.mfaDevices;
500
572
  const code = typeof body?.code === 'string' ? body.code : '';
501
573
  // Proof BEFORE the delete: a TOTP from any confirmed device (incl. the one being
502
- // removed — legit for the last-device disable) OR a valid recovery code.
503
- const byTotp = await this.verifyAgainstAnyDevice(store, claims.id, code);
504
- const byRecovery = !byTotp &&
505
- this.recoveryCodes !== undefined &&
506
- this.recoveryCodes !== null &&
507
- (await this.recoveryCodes.consume(claims.id, code));
508
- if (!byTotp && !byRecovery)
509
- badRequest();
574
+ // removed — legit for the last-device disable) OR a valid recovery code. Rate-limited
575
+ // and replay-guarded like `/auth/mfa` (Phase 8 #1).
576
+ await this.requireMfaProof(store, claims.id, code);
510
577
  const removed = await store.remove(claims.id, id);
511
578
  if (!removed) {
512
579
  throw new common_1.HttpException({ error: 'not_found' }, common_1.HttpStatus.NOT_FOUND);
@@ -546,11 +613,9 @@ let AccountController = class AccountController {
546
613
  // MFA must be on — else there's nothing to protect / no code source → generic 400.
547
614
  if ((await store.countConfirmed(claims.id)) === 0)
548
615
  badRequest();
549
- // Proof: a TOTP from any confirmed device OR an existing recovery code.
550
- const byTotp = await this.verifyAgainstAnyDevice(store, claims.id, code);
551
- const byRecovery = !byTotp && (await recoveryStore.consume(claims.id, code));
552
- if (!byTotp && !byRecovery)
553
- badRequest();
616
+ // Proof: a TOTP from any confirmed device OR an existing recovery code (rate-limited
617
+ // and replay-guarded like `/auth/mfa`, Phase 8 #1).
618
+ await this.requireMfaProof(store, claims.id, code);
554
619
  const recoveryCodes = await this.replaceRecoveryCodes(claims.id, recoveryStore, hasher);
555
620
  return { recoveryCodes };
556
621
  }
@@ -657,7 +722,15 @@ exports.AccountController = AccountController = __decorate([
657
722
  __param(7, (0, common_1.Inject)(tokens_js_2.SHIELD_PROFILE_WRITER)),
658
723
  __param(8, (0, common_1.Optional)()),
659
724
  __param(8, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_DEVICE_STORE)),
660
- __metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object, Object, Object, Object])
725
+ __param(9, (0, common_1.Optional)()),
726
+ __param(9, (0, common_1.Inject)(tokens_js_2.SHIELD_SESSION_RESTRICTIONS)),
727
+ __param(10, (0, common_1.Optional)()),
728
+ __param(10, (0, common_1.Inject)(tokens_js_2.SHIELD_LOGIN_TOTP_VERIFIER)),
729
+ __param(11, (0, common_1.Optional)()),
730
+ __param(11, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_LIMITER)),
731
+ __param(12, (0, common_1.Optional)()),
732
+ __param(12, (0, common_1.Inject)(tokens_js_2.SHIELD_LOGIN_LIMITER)),
733
+ __metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object])
661
734
  ], AccountController);
662
735
  /**
663
736
  * A deliberately-minimal email shape check (non-empty, a single `@`, a `.` in the
@@ -14,10 +14,13 @@
14
14
  * ── OUTCOME → HTTP STATUS MAP (the security contract) ────────────────────────
15
15
  * login authenticated → 200 SessionSuccess { session(no-secret), tokens }
16
16
  * login mfa_required → 200 MfaChallengeResponse { mfaRequired, challengeToken }
17
+ * (a Redis challenge: principal + hint + credential
18
+ * fingerprint, never the password — M6)
17
19
  * login invalid_credentials → 401 GENERIC ← unknown-user AND wrong-password IDENTICAL
18
20
  * login auth_unavailable → 503 RETRYABLE ← transient blip is NOT a credential deny
19
21
  * mfa success → 200 SessionSuccess
20
22
  * mfa wrong/expired/forged → 401 GENERIC ← indistinguishable from a bad code
23
+ * mfa TOTP step locked (#9) → 401 GENERIC (5 wrong codes / 15 min per account)
21
24
  * mfa auth_unavailable → 503 RETRYABLE
22
25
  * refresh ok → 200 SessionSuccess (new tokens, rotated session)
23
26
  * refresh reuse/invalid → 401 GENERIC session_rejected (lineage-kill is the engine's)
@@ -50,12 +53,17 @@
50
53
  * composed engines via DI tokens; it never news-up an engine or an adapter.
51
54
  */
52
55
  import type { Authenticator, PasswordHasher, SessionAuthority } from '@astram/core';
56
+ import type { SessionRestrictionStore } from '../session/session-restriction-store.js';
57
+ import type { SessionRecordStore } from '@astram/core';
58
+ import type { Clock, SessionLifetimeConfig } from '@astram/core';
59
+ import { type MfaStepUp } from './mfa-step-up.js';
53
60
  import type { SessionFactsProjector } from './ports/session-facts-projector.js';
54
61
  import type { ScopeSubtreeResolver } from './ports/scope-subtree-resolver.js';
55
62
  import type { MembershipChecker } from './ports/membership-checker.js';
56
63
  import type { AttemptLimiter } from './rate-limit/attempt-limiter.js';
64
+ import { TrustProxyBootCheck } from './rate-limit/trust-proxy-check.js';
57
65
  import { PendingMfaStore } from './pending-mfa-store.js';
58
- import type { SessionTokenBinder } from '../request-auth/session-token-binder.js';
66
+ import { type SessionTokenBinder } from '../request-auth/session-token-binder.js';
59
67
  import type { CurrentUserProfile, ProfileResolver } from './profile-resolver.js';
60
68
  import type { CredentialResolver } from '@astram/core';
61
69
  import type { ResetTokenStore } from './ports/reset-token-store.js';
@@ -87,6 +95,8 @@ export declare class AuthController {
87
95
  private readonly resetLinkBaseUrl?;
88
96
  private readonly recoveryCodes?;
89
97
  private readonly loginLimiter?;
98
+ private readonly loginIpLimiter?;
99
+ private readonly trustProxyCheck?;
90
100
  private readonly recoveryLimiter?;
91
101
  private readonly forgotLimiter?;
92
102
  private readonly forgotHintLimiter?;
@@ -96,23 +106,28 @@ export declare class AuthController {
96
106
  private readonly scopeSubtreeResolver?;
97
107
  private readonly membershipChecker?;
98
108
  private readonly permissionFacts?;
99
- constructor(authenticator: Authenticator, sessionAuthority: SessionAuthority, pendingMfa: PendingMfaStore, tokenBinder?: SessionTokenBinder | undefined, profileResolver?: ProfileResolver | undefined, credentialResolver?: (CredentialResolver | null) | undefined, resetTokenStore?: (ResetTokenStore | null) | undefined, emailSender?: (EmailSender | null) | undefined, credentialWriter?: (CredentialWriter | null) | undefined, sessionSweeper?: (SessionSweeper | null) | undefined, passwordHasher?: PasswordHasher | undefined, resetLinkBaseUrl?: string | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, loginLimiter?: (AttemptLimiter | null) | undefined, recoveryLimiter?: (AttemptLimiter | null) | undefined, forgotLimiter?: (AttemptLimiter | null) | undefined, forgotHintLimiter?: (AttemptLimiter | null) | undefined, resetLimiter?: (AttemptLimiter | null) | undefined, auditSink?: (AuditSink | null) | undefined, sessionFactsProjector?: (SessionFactsProjector | null) | undefined, scopeSubtreeResolver?: (ScopeSubtreeResolver | null) | undefined, membershipChecker?: (MembershipChecker | null) | undefined, permissionFacts?: (MariaDbPermissionFactsAdapter | null) | undefined);
109
+ private readonly mfaLimiter?;
110
+ private readonly mfaStepUp?;
111
+ private readonly clock?;
112
+ private readonly lifetimes?;
113
+ private readonly rootIds?;
114
+ private readonly sessionRecords?;
115
+ private readonly sessionRestrictions?;
116
+ constructor(authenticator: Authenticator, sessionAuthority: SessionAuthority, pendingMfa: PendingMfaStore, tokenBinder?: SessionTokenBinder | undefined, profileResolver?: ProfileResolver | undefined, credentialResolver?: (CredentialResolver | null) | undefined, resetTokenStore?: (ResetTokenStore | null) | undefined, emailSender?: (EmailSender | null) | undefined, credentialWriter?: (CredentialWriter | null) | undefined, sessionSweeper?: (SessionSweeper | null) | undefined, passwordHasher?: PasswordHasher | undefined, resetLinkBaseUrl?: string | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, loginLimiter?: (AttemptLimiter | null) | undefined, loginIpLimiter?: (AttemptLimiter | null) | undefined, trustProxyCheck?: (TrustProxyBootCheck | null) | undefined, recoveryLimiter?: (AttemptLimiter | null) | undefined, forgotLimiter?: (AttemptLimiter | null) | undefined, forgotHintLimiter?: (AttemptLimiter | null) | undefined, resetLimiter?: (AttemptLimiter | null) | undefined, auditSink?: (AuditSink | null) | undefined, sessionFactsProjector?: (SessionFactsProjector | null) | undefined, scopeSubtreeResolver?: (ScopeSubtreeResolver | null) | undefined, membershipChecker?: (MembershipChecker | null) | undefined, permissionFacts?: (MariaDbPermissionFactsAdapter | null) | undefined, mfaLimiter?: (AttemptLimiter | null) | undefined, mfaStepUp?: (MfaStepUp | null) | undefined, clock?: (Clock | null) | undefined, lifetimes?: (SessionLifetimeConfig | null) | undefined, rootIds?: (readonly string[] | null) | undefined, sessionRecords?: (Pick<SessionRecordStore, "findSessionById"> | null) | undefined, sessionRestrictions?: (SessionRestrictionStore | null) | undefined);
117
+ /**
118
+ * The access-token binding TTL for an establishment (security hardening #8):
119
+ * `clamp(session.expiresAtMs − now, 1, accessTtlMs)` — on login AND refresh. Never derived
120
+ * from `issuedAtMs` (the original login), which made refresh-minted tokens live for the
121
+ * session's age.
122
+ */
123
+ private accessTtlFor;
100
124
  /**
101
125
  * Bind the established session's access token to the principal's claims (the
102
- * request-auth layer). The access-token TTL is `expiresAtMs - issuedAtMs` from the
103
- * session. Best-effort: a binding failure must not fail the login (the caller still
126
+ * request-auth layer). The access-token TTL is {@link accessTtlFor} (≤ the access TTL).
127
+ * Best-effort: a binding failure must not fail the login (the caller still
104
128
  * gets valid tokens); the guard fails closed if the binding is absent.
105
129
  */
106
130
  private bindSession;
107
- /**
108
- * Project the principal's coarse grants for the session binding (ADR-0011), via the
109
- * OPTIONAL {@link SessionFactsProjector} seam. Returns the {@link CoarseGrants} to
110
- * cache, or `undefined` when there is no projector, the projection yielded nothing,
111
- * OR it threw — every "no facts" path collapses to `undefined` so the caller simply
112
- * omits `cachedFacts` and the request DB-reloads (fail-closed; a projection failure
113
- * NEVER fails the login/refresh and never fabricates a grant).
114
- */
115
- private projectFacts;
116
131
  /**
117
132
  * Project coarse grants for a principal id + tenant (ADR-0011), distinguishing THREE
118
133
  * outcomes for the REFRESH path (which must know whether to carry the existing cache
@@ -148,6 +163,16 @@ export declare class AuthController {
148
163
  * bumped by moveNode/deleteNode) re-derives its CORRECT subtree here, closing the
149
164
  * stale-subtree-after-move window (bounded by the access-token lifetime — ADR-0011).
150
165
  */
166
+ /**
167
+ * The permission version of `tenantId`, read just BEFORE its subtree is resolved, to stamp the
168
+ * binding (`scopeSubtreeVersion`, security hardening Phase 1C): when gate 5 later reloads facts
169
+ * at a newer version, the enforcement guard re-derives the subtree. Read before the resolve so a
170
+ * racing bump leaves the stamp too old (one extra re-derive), never too new. Only when a
171
+ * subtree resolver is wired (no subtree → nothing to stamp, no extra read). Best-effort: no
172
+ * facts adapter, a non-integer, or a throw → `undefined` (unstamped → the guard re-derives once
173
+ * at the next reload). One indexed read at login/refresh/scope-switch, never per request.
174
+ */
175
+ private subtreeVersionFor;
151
176
  private resolveScopeSubtreeFor;
152
177
  /**
153
178
  * Compute the caller's OWN auth-facts projection to INLINE into a login/mfa success
@@ -183,12 +208,33 @@ export declare class AuthController {
183
208
  * never a claim), matching the internal adapter's root-safety.
184
209
  */
185
210
  private principalFromClaims;
211
+ /**
212
+ * The account (principal id) a typed hint resolves to, for keying the per-account
213
+ * limiters (review F1). Goes through the SAME injected {@link CredentialResolver} the
214
+ * composed authenticator uses — the default is the indexed
215
+ * `WHERE ic_identity_hint = ? LIMIT 1` on the `utf8mb4_unicode_ci` column — so the DB
216
+ * collation, not client-side normalisation, decides which spellings are one account.
217
+ * No new access path. The RAW hint is passed (never normalised).
218
+ *
219
+ * Returns `null` for an unknown hint, a blank hint, or when no resolver is wired (→ the
220
+ * canonical-hash fallback key). A store ERROR propagates (the caller fails closed).
221
+ */
222
+ /**
223
+ * The ONE gate for every per-IP limiter (login failures, forgot-password, reset-password):
224
+ * returns the limiter only when bootstrap confirmed an explicit Express `trust proxy`
225
+ * ({@link TrustProxyBootCheck.perIpLimitingEnabled}); otherwise `null` (limiter OFF).
226
+ * Without it every client behind a proxy shares one `req.ip`, so enforcing a per-IP
227
+ * limit would block everyone (an unauthenticated global DoS). Per-account limits are
228
+ * never routed through here.
229
+ */
230
+ private perIp;
231
+ private lookupAccount;
186
232
  /**
187
233
  * `POST /auth/login` — verify a password credential and either establish a
188
234
  * session, issue an MFA challenge, deny generically, or signal a transient
189
235
  * outage. NEVER logs the request body.
190
236
  */
191
- login(body: LoginRequest): Promise<LoginResponse>;
237
+ login(body: LoginRequest, ip: string): Promise<LoginResponse>;
192
238
  /**
193
239
  * `GET /auth/me` — the signed-in user's **display profile** (name, email, active
194
240
  * company name, role names) for the UI header/card. Fills the flagged gap: login
@@ -269,12 +315,27 @@ export declare class AuthController {
269
315
  forgotPassword(body: {
270
316
  identityHint?: string;
271
317
  }, ip: string): Promise<void>;
318
+ /**
319
+ * The detached per-account half of {@link forgotPassword} (review F1):
320
+ * 1. resolve the RAW hint through the same {@link CredentialResolver} the authenticator
321
+ * uses (the DB collation decides which spellings are one account);
322
+ * 2. meter the per-account budget — `forgot:pid:<principalId>`, or the canonical-hash
323
+ * fallback key for an unknown hint — and audit `auth.forgot_password.hint_throttled`
324
+ * ONCE on the edge (distinct from the IP site's `throttled`, so "one account bombed
325
+ * across rotating IPs" is visible). No notify (it would itself be the email-bomb);
326
+ * 3. send only when both budgets allow, the account resolved, and the reset seams exist.
327
+ * A lookup error still meters (fallback key) and skips the send (still 204).
328
+ */
329
+ private meterAndDeliverReset;
272
330
  /**
273
331
  * The detached found-path work for {@link forgotPassword}: mint a raw token, issue
274
332
  * its SHA-256 hash to the store (30-min TTL), resolve the recipient email via the
275
333
  * profile resolver, and send the framework-composed reset link. Runs OUTSIDE the
276
- * request/response timing (fire-and-forget) so it cannot form a timing oracle. Never
277
- * logs the token or the email.
334
+ * request/response timing (fire-and-forget) so it cannot form a timing oracle. This
335
+ * method itself writes no log line — but the raw token and the email ARE handed to the
336
+ * bound {@link EmailSender}, and the dev-only `LogEmailSender` (the default ONLY when
337
+ * NODE_ENV is `development`/`test`) prints the whole message, link included, to stdout.
338
+ * Any other environment must supply a real sender or `emailSender: 'disabled'`.
278
339
  */
279
340
  private deliverResetLink;
280
341
  /**
@@ -298,9 +359,9 @@ export declare class AuthController {
298
359
  * `POST /auth/mfa` — complete a pending MFA login. Consumes the single-use
299
360
  * challenge handle (unknown/expired/forged → same generic 401 as a bad code),
300
361
  * then BRANCHES on the presented factor:
301
- * • `'totp'` → RE-RUNS `authenticate(hint, [password, totp])` with the code
302
- * (the authenticator has no standalone factor-verify seam — the full attempt
303
- * IS the verify). Success → establish + tokens.
362
+ * • `'totp'` → the MFA STEP-UP (M6): verify ONLY the code against the principal the
363
+ * password step recorded (no password is held or re-run). Rate-limited per account
364
+ * (#9). See {@link completeViaTotp}.
304
365
  * • `'recovery_code'` → the lost-device escape hatch: verify a one-time
305
366
  * recovery code (a separate branch, NOT the core factor loop — recovery codes
306
367
  * are N single-use Argon2 hashes, incompatible with the pure one-secret
@@ -308,9 +369,25 @@ export declare class AuthController {
308
369
  * • any other factor → generic 401 (no leak of "unsupported factor").
309
370
  *
310
371
  * Anti-enumeration: unknown/forged/expired challenge, unknown hint, wrong code,
311
- * and wrong recovery code ALL return the identical generic 401.
372
+ * a locked TOTP step, and a wrong recovery code ALL return the identical generic 401.
373
+ * A challenge-store outage is a retryable 503.
312
374
  */
313
375
  mfa(body: MfaRequest): Promise<SessionSuccess>;
376
+ /**
377
+ * The `/auth/mfa` TOTP branch (M6 + #9). The consumed challenge proves the password
378
+ * step passed for `pending.principalId`; this verifies ONLY the code, through the
379
+ * {@link MfaStepUp} (same `OrTotpVerifier` + replay guard as the authenticator, principal
380
+ * minted by the identity broker).
381
+ *
382
+ * - `mfa:pid:<principalId>` is checked BEFORE verifying: locked → generic 401 and the
383
+ * step-up is never consulted.
384
+ * - a rejected code records a failure; the edge where the count first reaches the
385
+ * threshold audits `auth.mfa.locked` ONCE (no notify — pre-auth, see recovery lockout).
386
+ * - a transient outage → 503, never counted.
387
+ * - success → establish + bind, then reset the TOTP counter AND the login counter (the
388
+ * login counter is reset only here, once authentication fully succeeded).
389
+ */
390
+ private completeViaTotp;
314
391
  /**
315
392
  * The `/auth/mfa` RECOVERY-CODE branch (spec §3). The lost-device user completes
316
393
  * login with a pre-issued single-use recovery code instead of a TOTP.
@@ -383,11 +460,43 @@ export declare class AuthController {
383
460
  /**
384
461
  * `POST /auth/refresh` — rotate the refresh token. Reuse/invalid/expired →
385
462
  * generic 401 (`session_rejected`; the engine already killed the lineage,
386
- * ADR-0015). ⚠ See the class header: the engine's rotate collapses a transient
463
+ * ADR-0015, and `HotRevokingSessionRecordStore` unbinds it in Redis so the live access
464
+ * token dies on its next request — M-A). The new access token is bound for ≤ the access
465
+ * TTL; the previous one keeps a 30 s grace (#8, D7). If the session's claims cannot be
466
+ * carried forward (`rebindOnRotate` → false) the refresh is a generic 401 — never an
467
+ * unbound token. ⚠ See the class header: the engine's rotate collapses a transient
387
468
  * store outage into the SAME reject, so refresh cannot emit the ADR-0016 503 from
388
469
  * this seam today (flagged core-API gap).
389
470
  */
390
471
  refresh(body: RefreshRequest): Promise<SessionSuccess>;
472
+ /**
473
+ * The refresh-time projection for one node: coarse grants + live roles (ADR-0035) and the
474
+ * subtree with its version stamp (Phase 1C: the version is read FIRST). Each part is best-effort
475
+ * exactly as at login (`undefined` = carry / omit, `null` facts = strip).
476
+ */
477
+ private projectForNode;
478
+ /**
479
+ * SILENT RECOVERY of a lost session binding (invariant #12, ADR-0013, ADR-0035, GAPS #5).
480
+ * `rotate()` has already proved the durable session is active and inside its idle and absolute
481
+ * windows, and returned its principal + tenant. The rebuilt claims NEVER carry more authority
482
+ * than the session had (Phase 3B review P1); they come from durable sources only:
483
+ * - principal + tenant: the durable session record (the LOGIN node; a scope-switch is not
484
+ * durable, so a rebuilt session returns to the node it was opened on);
485
+ * - the RE-ENROLL restriction: `shield_identity.session.s_must_reenroll`, set at a
486
+ * recovery-code login. A restricted session rebuilds `mustReenroll: true` and NEVER root
487
+ * (exactly how the recovery login bound it);
488
+ * - the account status: a disabled user gets no rebuild;
489
+ * - roles: the live projection (ADR-0035) — `[]` when none is available (non-widening; the
490
+ * first request's gate-5 reload fills them, because no facts are cached then);
491
+ * - `isRoot` (unrestricted sessions only): the server-side root allowlist, never a claim;
492
+ * - subtree: the resolver (absent → the self-node fallback, non-widening);
493
+ * - kind `user` (sessions are human; service accounts authenticate with keys).
494
+ * No restriction store, or any error reading it → no rebuild (fail closed). The claims entry is
495
+ * written with `NX`, then the durable session is READ AGAIN: if a logout or revoke landed
496
+ * meanwhile, the rebuilt binding is dropped and the refresh fails. Returns `true` when the
497
+ * session is bound and still active. Any error → `false` (the caller answers 401).
498
+ */
499
+ private rebuildBinding;
391
500
  /**
392
501
  * `POST /auth/logout` — revoke the session. Idempotent + leak-free: revoking an
393
502
  * unknown or already-revoked session still returns 204 (the engine's `revoke`
@@ -1 +1 @@
1
- {"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}