@astram/guard 0.5.1 → 0.7.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 (157) hide show
  1. package/dist/auth/account.controller.d.ts.map +1 -1
  2. package/dist/auth/account.controller.js +3 -0
  3. package/dist/auth/account.controller.js.map +1 -0
  4. package/dist/auth/auth.controller.d.ts +90 -1
  5. package/dist/auth/auth.controller.d.ts.map +1 -1
  6. package/dist/auth/auth.controller.js +245 -7
  7. package/dist/auth/auth.controller.js.map +1 -0
  8. package/dist/auth/auth.module.d.ts +21 -0
  9. package/dist/auth/auth.module.d.ts.map +1 -1
  10. package/dist/auth/auth.module.js +57 -0
  11. package/dist/auth/auth.module.js.map +1 -0
  12. package/dist/auth/connections.js.map +1 -0
  13. package/dist/auth/dto.d.ts +32 -0
  14. package/dist/auth/dto.d.ts.map +1 -1
  15. package/dist/auth/dto.js.map +1 -0
  16. package/dist/auth/pending-mfa-store.js.map +1 -0
  17. package/dist/auth/persistence.module.js.map +1 -0
  18. package/dist/auth/ports/audit-sink.js.map +1 -0
  19. package/dist/auth/ports/credential-writer.js.map +1 -0
  20. package/dist/auth/ports/email-sender.js.map +1 -0
  21. package/dist/auth/ports/membership-checker.d.ts +41 -0
  22. package/dist/auth/ports/membership-checker.d.ts.map +1 -0
  23. package/dist/auth/ports/membership-checker.js +32 -0
  24. package/dist/auth/ports/membership-checker.js.map +1 -0
  25. package/dist/auth/ports/mfa-device-store.js.map +1 -0
  26. package/dist/auth/ports/profile-writer.js.map +1 -0
  27. package/dist/auth/ports/recovery-code-store.js.map +1 -0
  28. package/dist/auth/ports/reset-token-store.js.map +1 -0
  29. package/dist/auth/ports/scope-subtree-resolver.d.ts +48 -0
  30. package/dist/auth/ports/scope-subtree-resolver.d.ts.map +1 -0
  31. package/dist/auth/ports/scope-subtree-resolver.js +38 -0
  32. package/dist/auth/ports/scope-subtree-resolver.js.map +1 -0
  33. package/dist/auth/ports/session-facts-projector.js.map +1 -0
  34. package/dist/auth/ports/session-sweeper.js.map +1 -0
  35. package/dist/auth/profile-resolver.js.map +1 -0
  36. package/dist/auth/rate-limit/attempt-limiter.js.map +1 -0
  37. package/dist/auth/tokens.d.ts +25 -0
  38. package/dist/auth/tokens.d.ts.map +1 -1
  39. package/dist/auth/tokens.js +26 -1
  40. package/dist/auth/tokens.js.map +1 -0
  41. package/dist/auth/totp-enrollment.js.map +1 -0
  42. package/dist/authentication/argon2id-password-hasher.js.map +1 -0
  43. package/dist/authentication/log-email-sender.js.map +1 -0
  44. package/dist/authentication/mariadb-api-key-store.d.ts +43 -0
  45. package/dist/authentication/mariadb-api-key-store.d.ts.map +1 -0
  46. package/dist/authentication/mariadb-api-key-store.js +87 -0
  47. package/dist/authentication/mariadb-credential-resolver.js.map +1 -0
  48. package/dist/authentication/mariadb-credential-writer.js.map +1 -0
  49. package/dist/authentication/mariadb-mfa-device-store.js.map +1 -0
  50. package/dist/authentication/mariadb-or-totp-verifier.js.map +1 -0
  51. package/dist/authentication/mariadb-profile-resolver.js.map +1 -0
  52. package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
  53. package/dist/authentication/mariadb-profile-writer.js +10 -1
  54. package/dist/authentication/mariadb-profile-writer.js.map +1 -0
  55. package/dist/authentication/mariadb-recovery-code-store.js.map +1 -0
  56. package/dist/authentication/mariadb-reset-token-store.js.map +1 -0
  57. package/dist/authentication/mariadb-session-sweeper.js.map +1 -0
  58. package/dist/authz/cross-tenant-grant-writer.js.map +1 -0
  59. package/dist/authz/list-scope-sql.d.ts +125 -0
  60. package/dist/authz/list-scope-sql.d.ts.map +1 -0
  61. package/dist/authz/list-scope-sql.js +477 -0
  62. package/dist/authz/list-scope-sql.js.map +1 -0
  63. package/dist/authz/manifest-operation-authority-adapter.js.map +1 -0
  64. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts +28 -0
  65. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -1
  66. package/dist/authz/mariadb-cross-tenant-grant-adapter.js +49 -0
  67. package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +1 -0
  68. package/dist/authz/mariadb-list-scope-adapter.d.ts +61 -0
  69. package/dist/authz/mariadb-list-scope-adapter.d.ts.map +1 -0
  70. package/dist/authz/mariadb-list-scope-adapter.js +157 -0
  71. package/dist/authz/mariadb-list-scope-adapter.js.map +1 -0
  72. package/dist/authz/mariadb-policy-store.d.ts +118 -0
  73. package/dist/authz/mariadb-policy-store.d.ts.map +1 -0
  74. package/dist/authz/mariadb-policy-store.js +225 -0
  75. package/dist/authz/mariadb-policy-store.js.map +1 -0
  76. package/dist/authz/mariadb-record-rule-adapter.d.ts +7 -3
  77. package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -1
  78. package/dist/authz/mariadb-record-rule-adapter.js +156 -13
  79. package/dist/authz/mariadb-record-rule-adapter.js.map +1 -0
  80. package/dist/authz/mariadb-record-share-adapter.js.map +1 -0
  81. package/dist/authz/record-share-cascade.js.map +1 -0
  82. package/dist/authz/record-share-writer.d.ts +22 -0
  83. package/dist/authz/record-share-writer.d.ts.map +1 -1
  84. package/dist/authz/record-share-writer.js +41 -0
  85. package/dist/authz/record-share-writer.js.map +1 -0
  86. package/dist/authz/wire-record-authorization.d.ts +35 -1
  87. package/dist/authz/wire-record-authorization.d.ts.map +1 -1
  88. package/dist/authz/wire-record-authorization.js +75 -0
  89. package/dist/authz/wire-record-authorization.js.map +1 -0
  90. package/dist/boot/boot-sequence.js.map +1 -0
  91. package/dist/boot/boot.module.js.map +1 -0
  92. package/dist/completeness/catalog-reconciler.js.map +1 -0
  93. package/dist/completeness/operation-inventory-scanner.js.map +1 -0
  94. package/dist/completeness/ports/catalog-store.js.map +1 -0
  95. package/dist/config/app-config.d.ts +16 -0
  96. package/dist/config/app-config.d.ts.map +1 -1
  97. package/dist/config/app-config.js +22 -0
  98. package/dist/config/app-config.js.map +1 -0
  99. package/dist/config/config.module.js.map +1 -0
  100. package/dist/encryption/local-kek-crypto.d.ts +15 -0
  101. package/dist/encryption/local-kek-crypto.d.ts.map +1 -0
  102. package/dist/encryption/local-kek-crypto.js +79 -0
  103. package/dist/enforcement/classification.decorator.js.map +1 -0
  104. package/dist/enforcement/core-seam.js.map +1 -0
  105. package/dist/enforcement/enforcement.module.js.map +1 -0
  106. package/dist/enforcement/global-enforcement.guard.d.ts +3 -1
  107. package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
  108. package/dist/enforcement/global-enforcement.guard.js +7 -3
  109. package/dist/enforcement/global-enforcement.guard.js.map +1 -0
  110. package/dist/enforcement/reenroll-allowlist.js.map +1 -0
  111. package/dist/identity/auth-facts.controller.js.map +1 -0
  112. package/dist/identity/identity-actions.d.ts +16 -0
  113. package/dist/identity/identity-actions.d.ts.map +1 -1
  114. package/dist/identity/identity-actions.js +23 -1
  115. package/dist/identity/identity-actions.js.map +1 -0
  116. package/dist/identity/module-registry.bridge.js.map +1 -0
  117. package/dist/identity/permission-facts.adapter.js.map +1 -0
  118. package/dist/index.d.ts +12 -2
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +64 -3
  121. package/dist/index.js.map +1 -0
  122. package/dist/migrations-dir.js.map +1 -0
  123. package/dist/module/shield-tokens.js.map +1 -0
  124. package/dist/module/shield.module.d.ts +33 -0
  125. package/dist/module/shield.module.d.ts.map +1 -1
  126. package/dist/module/shield.module.js +12 -0
  127. package/dist/module/shield.module.js.map +1 -0
  128. package/dist/request-auth/request-principal.d.ts +11 -3
  129. package/dist/request-auth/request-principal.d.ts.map +1 -1
  130. package/dist/request-auth/request-principal.js +70 -2
  131. package/dist/request-auth/request-principal.js.map +1 -0
  132. package/dist/request-auth/session-facts-als.js.map +1 -0
  133. package/dist/request-auth/session-token-binder.d.ts +35 -1
  134. package/dist/request-auth/session-token-binder.d.ts.map +1 -1
  135. package/dist/request-auth/session-token-binder.js +123 -8
  136. package/dist/request-auth/session-token-binder.js.map +1 -0
  137. package/dist/request-auth/tokens.d.ts +10 -0
  138. package/dist/request-auth/tokens.d.ts.map +1 -1
  139. package/dist/request-auth/tokens.js +11 -1
  140. package/dist/request-auth/tokens.js.map +1 -0
  141. package/dist/scope/closure-builder.d.ts +75 -0
  142. package/dist/scope/closure-builder.d.ts.map +1 -0
  143. package/dist/scope/closure-builder.js +134 -0
  144. package/dist/scope/closure-builder.js.map +1 -0
  145. package/dist/secrets/encrypted-file-secrets.d.ts +16 -0
  146. package/dist/secrets/encrypted-file-secrets.d.ts.map +1 -0
  147. package/dist/secrets/encrypted-file-secrets.js +92 -0
  148. package/dist/session/crypto-adapters.js.map +1 -0
  149. package/dist/session/index.js.map +1 -0
  150. package/dist/session/mariadb-session-record-store.js.map +1 -0
  151. package/dist/session/redis-hot-session-store.js.map +1 -0
  152. package/migrations/1710000000009-CreateRecordPermissionRule.cjs +56 -0
  153. package/migrations/1710000000014-CreateRecordShare.cjs +49 -0
  154. package/migrations/1710000000015-CreateScopeClosure.cjs +46 -0
  155. package/migrations/1710000000016-AlterCompanyParentFkRestrict.cjs +71 -0
  156. package/migrations/1710000000017-CreateServiceAccountKey.cjs +41 -0
  157. package/package.json +3 -3
@@ -11,6 +11,8 @@ import type { SessionSweeper } from '../auth/ports/session-sweeper.js';
11
11
  import type { MfaDeviceStore } from '../auth/ports/mfa-device-store.js';
12
12
  import type { AuditSink } from '../auth/ports/audit-sink.js';
13
13
  import type { SessionFactsProjector } from '../auth/ports/session-facts-projector.js';
14
+ import type { ScopeSubtreeResolver } from '../auth/ports/scope-subtree-resolver.js';
15
+ import type { MembershipChecker } from '../auth/ports/membership-checker.js';
14
16
  import type { CoreDecisionAuthority } from '../enforcement/core-seam.js';
15
17
  import { type AppConfig } from '../config/app-config.js';
16
18
  import { SHIELD_DECISION_AUTHORITY } from './shield-tokens.js';
@@ -156,6 +158,25 @@ export interface ShieldModuleOptions {
156
158
  * `cachedFacts`. Only consulted when `auth: true`.
157
159
  */
158
160
  readonly sessionFactsProjector?: SessionFactsProjector;
161
+ /**
162
+ * OPTIONAL active-scope-subtree resolver (Task 2.2, ADR-0027 / ADR-0024) — see
163
+ * {@link AuthModuleOptions.scopeSubtreeResolver}. Threaded straight through to
164
+ * {@link AuthModule.forRoot} (bound under {@link SHIELD_SCOPE_SUBTREE_RESOLVER}, or `null` when
165
+ * absent → the auth controller omits `scopeSubtreeNodeIds` and the per-request path falls back to
166
+ * the self-node `[tenantId]`, today's flat isolation). When supplied, login resolves the
167
+ * principal's closure subtree ONCE and caches it on the session binding so the per-request tenant
168
+ * gate reads the real subtree with zero DB. Only consulted when `auth: true`.
169
+ */
170
+ readonly scopeSubtreeResolver?: ScopeSubtreeResolver;
171
+ /**
172
+ * OPTIONAL scope-switch membership checker (Task 5.2, ADR-0027 / ADR-0024) — see
173
+ * {@link AuthModuleOptions.membershipChecker}. Threaded straight through to
174
+ * {@link AuthModule.forRoot} (bound under {@link SHIELD_MEMBERSHIP_CHECKER}, or `null` when
175
+ * absent → `POST /auth/scope-switch` fails closed, denying every switch — cannot verify the
176
+ * target binding). When supplied, the scope-switch gate confirms the principal holds an active
177
+ * membership at the target node before re-binding the session. Only consulted when `auth: true`.
178
+ */
179
+ readonly membershipChecker?: MembershipChecker;
159
180
  }
160
181
  /** Async variant of {@link ShieldModuleOptions} (DI-computed config). */
161
182
  export interface ShieldModuleAsyncOptions {
@@ -248,6 +269,18 @@ export interface ShieldModuleAsyncOptions {
248
269
  * options. Only consulted when `auth: true`.
249
270
  */
250
271
  readonly sessionFactsProjector?: SessionFactsProjector;
272
+ /**
273
+ * OPTIONAL active-scope-subtree resolver — see {@link ShieldModuleOptions.scopeSubtreeResolver}.
274
+ * STATIC here (like the other seams): a registration-time collaborator threaded into the
275
+ * statically-composed {@link AuthModule} import. Only consulted when `auth: true`.
276
+ */
277
+ readonly scopeSubtreeResolver?: ScopeSubtreeResolver;
278
+ /**
279
+ * OPTIONAL scope-switch membership checker — see {@link ShieldModuleOptions.membershipChecker}.
280
+ * STATIC here (like the other seams): a registration-time collaborator threaded into the
281
+ * statically-composed {@link AuthModule} import. Only consulted when `auth: true`.
282
+ */
283
+ readonly membershipChecker?: MembershipChecker;
251
284
  }
252
285
  /**
253
286
  * `ShieldModule` — the SINGLE registration seam (ADR-0023 §4).
@@ -1 +1 @@
1
- {"version":3,"file":"shield.module.d.ts","sourceRoot":"","sources":["../../src/module/shield.module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shield.module.d.ts","sourceRoot":"","sources":["../../src/module/shield.module.ts"],"names":[],"mappings":"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"}
@@ -197,6 +197,12 @@ let ShieldModule = ShieldModule_1 = class ShieldModule {
197
197
  ...(options.sessionFactsProjector
198
198
  ? { sessionFactsProjector: options.sessionFactsProjector }
199
199
  : {}),
200
+ ...(options.scopeSubtreeResolver
201
+ ? { scopeSubtreeResolver: options.scopeSubtreeResolver }
202
+ : {}),
203
+ ...(options.membershipChecker
204
+ ? { membershipChecker: options.membershipChecker }
205
+ : {}),
200
206
  })
201
207
  : undefined;
202
208
  return {
@@ -308,6 +314,12 @@ let ShieldModule = ShieldModule_1 = class ShieldModule {
308
314
  ...(options.sessionFactsProjector
309
315
  ? { sessionFactsProjector: options.sessionFactsProjector }
310
316
  : {}),
317
+ ...(options.scopeSubtreeResolver
318
+ ? { scopeSubtreeResolver: options.scopeSubtreeResolver }
319
+ : {}),
320
+ ...(options.membershipChecker
321
+ ? { membershipChecker: options.membershipChecker }
322
+ : {}),
311
323
  })
312
324
  : undefined;
313
325
  return {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shield.module.js","sourceRoot":"","sources":["../../src/module/shield.module.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@
12
12
  * captured from the login-time Principal, so a genuinely-root login stays
13
13
  * root; a normal login can never become one on a later request).
14
14
  */
15
- import type { Principal } from '@astram/core';
15
+ import type { Principal, ServiceAuthenticator } from '@astram/core';
16
16
  import type { SessionTokenBinder, BoundPrincipalClaims } from './session-token-binder.js';
17
17
  /** Extract a bearer token from an `Authorization: Bearer <token>` header. */
18
18
  export declare function extractBearerToken(authorizationHeader: unknown): string | null;
@@ -22,11 +22,19 @@ export declare function extractBearerToken(authorizationHeader: unknown): string
22
22
  * a root on the request path.
23
23
  */
24
24
  export declare function principalFromClaims(claims: BoundPrincipalClaims): Principal | null;
25
+ /**
26
+ * Is this bearer token a service-account API key (`ask_…`, ADR-0033) rather than a session
27
+ * access token? A cheap prefix check; the authenticator does the real (constant-time) verify.
28
+ */
29
+ export declare function isApiKey(token: string): boolean;
25
30
  /**
26
31
  * Resolve an HTTP request's bearer token to a `Principal`, or `null` (fail-closed)
27
32
  * when there is no token, no binding, or the binding is malformed.
33
+ *
34
+ * When `serviceAuth` is provided and the bearer token is an API key (`ask_…`, ADR-0033), the token
35
+ * is authenticated as a service account instead of resolved against the session binder.
28
36
  */
29
- export declare function resolveRequestPrincipal(authorizationHeader: unknown, binder: SessionTokenBinder): Promise<Principal | null>;
37
+ export declare function resolveRequestPrincipal(authorizationHeader: unknown, binder: SessionTokenBinder, serviceAuth?: ServiceAuthenticator): Promise<Principal | null>;
30
38
  /**
31
39
  * Resolve an HTTP request's bearer token to BOTH a `Principal` AND the raw
32
40
  * {@link BoundPrincipalClaims}, or `null` (fail-closed) — the same read path as
@@ -35,7 +43,7 @@ export declare function resolveRequestPrincipal(authorizationHeader: unknown, bi
35
43
  * uses this so it can read `claims.mustReenroll` to apply the enforced-re-enroll gate
36
44
  * while still attaching the resolved `Principal` for `decide()`.
37
45
  */
38
- export declare function resolveRequestAuth(authorizationHeader: unknown, binder: SessionTokenBinder): Promise<{
46
+ export declare function resolveRequestAuth(authorizationHeader: unknown, binder: SessionTokenBinder, serviceAuth?: ServiceAuthenticator): Promise<{
39
47
  principal: Principal;
40
48
  claims: BoundPrincipalClaims;
41
49
  } | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"request-principal.d.ts","sourceRoot":"","sources":["../../src/request-auth/request-principal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAK1F,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK9E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI,CAoBlF;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,mBAAmB,EAAE,OAAO,EAC5B,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAM3B;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,mBAAmB,EAAE,OAAO,EAC5B,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAAG,IAAI,CAAC,CAQxE"}
1
+ {"version":3,"file":"request-principal.d.ts","sourceRoot":"","sources":["../../src/request-auth/request-principal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAa1F,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK9E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI,CAiClF;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/C;AA4BD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,mBAAmB,EAAE,OAAO,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,WAAW,CAAC,EAAE,oBAAoB,GACjC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAU3B;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,mBAAmB,EAAE,OAAO,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,WAAW,CAAC,EAAE,oBAAoB,GACjC,OAAO,CAAC;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,GAAG,IAAI,CAAC,CAgBxE"}
@@ -16,10 +16,18 @@
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.extractBearerToken = extractBearerToken;
18
18
  exports.principalFromClaims = principalFromClaims;
19
+ exports.isApiKey = isApiKey;
19
20
  exports.resolveRequestPrincipal = resolveRequestPrincipal;
20
21
  exports.resolveRequestAuth = resolveRequestAuth;
21
22
  /** Valid `Principal.kind` values (mirror of the Core union; validated at rebuild). */
22
23
  const PRINCIPAL_KINDS = new Set(['user', 'role_group', 'service_account']);
24
+ /**
25
+ * The service-account API-key prefix (mirror of Core's `API_KEY_PREFIX = 'ask_'`, ADR-0033) —
26
+ * inlined as a literal so this file keeps its ZERO-runtime-`require('@astram/core')` discipline
27
+ * (importing the value would add a runtime dep; the type-only imports above are erased). Kept in
28
+ * sync with Core by the ADR + a guard test that asserts equality with the Core export.
29
+ */
30
+ const API_KEY_PREFIX = 'ask_';
23
31
  /** Extract a bearer token from an `Authorization: Bearer <token>` header. */
24
32
  function extractBearerToken(authorizationHeader) {
25
33
  if (typeof authorizationHeader !== 'string')
@@ -44,22 +52,73 @@ function principalFromClaims(claims) {
44
52
  const roleIds = Array.isArray(claims.roleIds)
45
53
  ? claims.roleIds.filter((r) => typeof r === 'string')
46
54
  : [];
55
+ // Scope (ADR-0027 / ADR-0024, Task 2.2) — the active scope node IS the bound tenant. The
56
+ // reachable subtree is the CLOSURE-RESOLVED set (self node + descendants) cached on the binding
57
+ // at LOGIN (`claims.scopeSubtreeNodeIds`), read here with ZERO DB — the parity guarantee: the
58
+ // closure query happened once at login, never per request. FAIL-SAFE + NON-WIDENING: when the
59
+ // cached subtree is ABSENT or EMPTY (a legacy binding, an unwired resolver, or a resolver that
60
+ // threw at login), fall back to just the self-node `[tenantId]` — today's flat self-tenant
61
+ // isolation, EXACTLY. A missing subtree can never widen a principal's reach.
62
+ const subtree = Array.isArray(claims.scopeSubtreeNodeIds) && claims.scopeSubtreeNodeIds.length > 0
63
+ ? [...claims.scopeSubtreeNodeIds]
64
+ : [claims.tenantId];
47
65
  return Object.freeze({
48
66
  kind,
49
67
  id: claims.id,
68
+ activeScopeNodeId: claims.tenantId,
69
+ scopeSubtreeNodeIds: Object.freeze(subtree),
50
70
  tenantId: claims.tenantId,
51
71
  roleIds: Object.freeze([...roleIds]),
52
72
  isRoot: claims.isRoot === true,
53
73
  });
54
74
  }
75
+ /**
76
+ * Is this bearer token a service-account API key (`ask_…`, ADR-0033) rather than a session
77
+ * access token? A cheap prefix check; the authenticator does the real (constant-time) verify.
78
+ */
79
+ function isApiKey(token) {
80
+ return token.startsWith(API_KEY_PREFIX);
81
+ }
82
+ /**
83
+ * Synthesize {@link BoundPrincipalClaims} for a machine (service-account) request from its resolved
84
+ * {@link Principal} (ADR-0033). A service account has NO interactive-session state — so the
85
+ * session-only gates are set to their benign defaults:
86
+ * - `mustReenroll: false` — re-enroll is a human recovery-code concern; a machine never re-enrolls.
87
+ * - `sessionId: ''` — there is no durable session row (the key IS the credential); the field is
88
+ * present only to satisfy the claims shape (no logout/liveness correlation applies to a key —
89
+ * revocation is via the key's `revokedAtMs`, enforced at authenticate time).
90
+ * - no `cachedFacts` (absent) — gate 5 DB-reloads the account's grants (fail-closed default; a
91
+ * machine has no login-time projection).
92
+ * The Principal's `scopeSubtreeNodeIds` is carried through so the tenant/scope gate reads the
93
+ * account's own subtree (least privilege).
94
+ */
95
+ function claimsFromServicePrincipal(principal) {
96
+ return {
97
+ id: principal.id,
98
+ tenantId: principal.tenantId,
99
+ roleIds: [...principal.roleIds],
100
+ kind: principal.kind,
101
+ isRoot: false, // a service account is NEVER root (ADR-0033) — defense-in-depth on the claims too.
102
+ sessionId: '',
103
+ mustReenroll: false,
104
+ scopeSubtreeNodeIds: [...principal.scopeSubtreeNodeIds],
105
+ };
106
+ }
55
107
  /**
56
108
  * Resolve an HTTP request's bearer token to a `Principal`, or `null` (fail-closed)
57
109
  * when there is no token, no binding, or the binding is malformed.
110
+ *
111
+ * When `serviceAuth` is provided and the bearer token is an API key (`ask_…`, ADR-0033), the token
112
+ * is authenticated as a service account instead of resolved against the session binder.
58
113
  */
59
- async function resolveRequestPrincipal(authorizationHeader, binder) {
114
+ async function resolveRequestPrincipal(authorizationHeader, binder, serviceAuth) {
60
115
  const token = extractBearerToken(authorizationHeader);
61
116
  if (token === null)
62
117
  return null;
118
+ if (serviceAuth !== undefined && isApiKey(token)) {
119
+ const res = await serviceAuth.authenticateApiKey(token);
120
+ return res.ok ? res.principal : null; // fail-closed uniform on any bad key.
121
+ }
63
122
  const claims = await binder.resolve(token);
64
123
  if (claims === null)
65
124
  return null;
@@ -73,10 +132,19 @@ async function resolveRequestPrincipal(authorizationHeader, binder) {
73
132
  * uses this so it can read `claims.mustReenroll` to apply the enforced-re-enroll gate
74
133
  * while still attaching the resolved `Principal` for `decide()`.
75
134
  */
76
- async function resolveRequestAuth(authorizationHeader, binder) {
135
+ async function resolveRequestAuth(authorizationHeader, binder, serviceAuth) {
77
136
  const token = extractBearerToken(authorizationHeader);
78
137
  if (token === null)
79
138
  return null;
139
+ // Machine path (ADR-0033): an `ask_…` bearer is a service-account API key. Authenticate it and
140
+ // synthesize the claims (benign session defaults) so ALL downstream enforcement — the re-enroll
141
+ // gate, the facts hot-path, decide() — is IDENTICAL to a human's (invariant #3, one authority).
142
+ if (serviceAuth !== undefined && isApiKey(token)) {
143
+ const res = await serviceAuth.authenticateApiKey(token);
144
+ if (!res.ok)
145
+ return null; // uniform fail-closed (malformed/unknown/expired/revoked/outage).
146
+ return { principal: res.principal, claims: claimsFromServicePrincipal(res.principal) };
147
+ }
80
148
  const claims = await binder.resolve(token);
81
149
  if (claims === null)
82
150
  return null;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-principal.js","sourceRoot":"","sources":["../../src/request-auth/request-principal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-facts-als.js","sourceRoot":"","sources":["../../src/request-auth/session-facts-als.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;;;AAEH,uDAAqD;AAmBrD;;;;;;GAMG;AACU,QAAA,wBAAwB,GAAG,IAAI,oCAAiB,EAAqB,CAAC;AAEnF;;;;GAIG;AACU,QAAA,gBAAgB,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC/D,WAAW,EAAE,IAAI;IACjB,kBAAkB,EAAE,CAAC;CACtB,CAAC,CAAC"}
@@ -65,6 +65,20 @@ export interface BoundPrincipalClaims {
65
65
  * `cachedFacts` slot is treated as absent (see `resolve()`), never fabricated.
66
66
  */
67
67
  readonly cachedFacts?: CoarseGrants;
68
+ /**
69
+ * OPTIONAL cached active-scope subtree (ADR-0027 / ADR-0024) — the active scope node + all its
70
+ * descendants, resolved ONCE at session establish from `shield_authz.scope_closure` and stored
71
+ * HERE so the per-request tenant gate reads it from the binding (zero per-request DB — the parity
72
+ * guarantee). The subtree query happens ONLY at login; `resolve()` returns this cached set and
73
+ * `principalFromClaims` reads it with NO DB call.
74
+ *
75
+ * ABSENT (undefined) → `principalFromClaims` falls back to `[tenantId]` (self-node, today's flat
76
+ * isolation) — the fail-safe, NON-WIDENING default for a legacy/old binding, an unwired resolver,
77
+ * or a resolver that threw at login. It is NEVER inferred; only a genuine login-time resolution
78
+ * sets it, and an EMPTY resolution is treated as absent (→ self-node) so a missing closure can
79
+ * never silently widen or empty a principal's reach.
80
+ */
81
+ readonly scopeSubtreeNodeIds?: readonly string[];
68
82
  }
69
83
  export declare class SessionTokenBinder {
70
84
  private readonly redis;
@@ -96,7 +110,27 @@ export declare class SessionTokenBinder {
96
110
  * - `null` → STRIP `cachedFacts` (a projection that yielded nothing → the next
97
111
  * request DB-reloads; fail-closed).
98
112
  */
99
- rebindOnRotate(newAccessToken: string, sessionId: string, ttlMs: number, freshFacts?: CoarseGrants | null): Promise<boolean>;
113
+ rebindOnRotate(newAccessToken: string, sessionId: string, ttlMs: number, freshFacts?: CoarseGrants | null, freshSubtree?: readonly string[]): Promise<boolean>;
114
+ /**
115
+ * SCOPE-SWITCH re-bind (Task 5.2, ADR-0027 / ADR-0024). A principal is switching which
116
+ * active node it acts under; re-bind its CURRENT session (the same access token — no
117
+ * rotate, no new tokens) so the bound `tenantId` becomes `targetNodeId` (the new active
118
+ * scope node → `principalFromClaims` reads `activeScopeNodeId = tenantId`) and
119
+ * `scopeSubtreeNodeIds` becomes the NEW node's closure-resolved subtree. The old node's
120
+ * subtree/tenant is REPLACED — stale authority from the previous scope does NOT carry
121
+ * over (the security point of the switch).
122
+ *
123
+ * Rewrites BOTH the per-access-token binding AND the session-claims cushion (so a later
124
+ * refresh/rotate carries the NEW active scope forward), each preserving its remaining TTL
125
+ * (a scope-switch NEVER extends the session life). The `cachedFacts` slot is STRIPPED —
126
+ * the old node's coarse grants are stale under the new scope; the next request re-projects
127
+ * / DB-reloads (fail-closed, never a stale-grant carry-over). The caller resolves the
128
+ * subtree for the NEW node and passes it in.
129
+ *
130
+ * Returns `true` on a successful re-bind, `false` when the binding is gone (logged out /
131
+ * expired) or Redis is unavailable (the caller then denies the switch — fail-closed).
132
+ */
133
+ rebindActiveScope(accessToken: string, sessionId: string, targetNodeId: string, subtree: readonly string[]): Promise<boolean>;
100
134
  /**
101
135
  * Resolve an access token to its bound claims, or `null` if the binding is
102
136
  * absent/expired. Fail-closed: any Redis error → `null` (the caller denies), never
@@ -1 +1 @@
1
- {"version":3,"file":"session-token-binder.d.ts","sourceRoot":"","sources":["../../src/request-auth/session-token-binder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AAKjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,YAAY,CAAC;CACrC;AA0CD,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,KAAK;IAEzC;;;;;;;OAOG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3F;;;;;;;;;;;;;;;;;OAiBG;IACG,cAAc,CAClB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,YAAY,GAAG,IAAI,GAC/B,OAAO,CAAC,OAAO,CAAC;IAgCnB;;;;;OAKG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA8DxE;;;;;;;;;;;;OAYG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BrD,gDAAgD;IAC1C,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhD;;;;OAIG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOtD"}
1
+ {"version":3,"file":"session-token-binder.d.ts","sourceRoot":"","sources":["../../src/request-auth/session-token-binder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,KAAK,MAAM,SAAS,CAAC;AAKjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,oFAAoF;AACpF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,YAAY,CAAC;IACpC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClD;AAmED,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,KAAK;IAEzC;;;;;;;OAOG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3F;;;;;;;;;;;;;;;;;OAiBG;IACG,cAAc,CAClB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,YAAY,GAAG,IAAI,EAChC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,GAC/B,OAAO,CAAC,OAAO,CAAC;IA2CnB;;;;;;;;;;;;;;;;;;OAkBG;IACG,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAAC,OAAO,CAAC;IAmDnB;;;;;OAKG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAwExE;;;;;;;;;;;;OAYG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BrD,gDAAgD;IAC1C,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhD;;;;OAIG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOtD"}
@@ -45,6 +45,30 @@ function parseCachedFacts(slot) {
45
45
  grantedPermissionKeys: [...c.grantedPermissionKeys],
46
46
  };
47
47
  }
48
+ /**
49
+ * Structurally validate the OPTIONAL `scopeSubtreeNodeIds` slot from the (untrusted) Redis
50
+ * payload. Returns a fresh string[] of the non-empty node ids, or `undefined` when the slot is
51
+ * absent, not an array, empty, or carries any non-string element (fail-safe → the per-request
52
+ * path falls back to the self-node; a junk slot can never widen or empty a principal's reach).
53
+ */
54
+ function parseScopeSubtree(slot) {
55
+ if (!Array.isArray(slot) || slot.length === 0)
56
+ return undefined;
57
+ const out = [];
58
+ for (const n of slot) {
59
+ if (typeof n !== 'string' || n.length === 0)
60
+ return undefined;
61
+ out.push(n);
62
+ }
63
+ return out;
64
+ }
65
+ /** Return the claims with any `scopeSubtreeNodeIds` slot removed (absent → self-node fallback). */
66
+ function stripScopeSubtree(claims) {
67
+ if (!('scopeSubtreeNodeIds' in claims))
68
+ return claims;
69
+ const { scopeSubtreeNodeIds: _drop, ...rest } = claims;
70
+ return rest;
71
+ }
48
72
  /** Return the claims with any `cachedFacts` slot removed (absent → gate 5 DB-reloads). */
49
73
  function stripCachedFacts(claims) {
50
74
  if (!('cachedFacts' in claims))
@@ -100,7 +124,7 @@ class SessionTokenBinder {
100
124
  * - `null` → STRIP `cachedFacts` (a projection that yielded nothing → the next
101
125
  * request DB-reloads; fail-closed).
102
126
  */
103
- async rebindOnRotate(newAccessToken, sessionId, ttlMs, freshFacts) {
127
+ async rebindOnRotate(newAccessToken, sessionId, ttlMs, freshFacts, freshSubtree) {
104
128
  let raw;
105
129
  try {
106
130
  raw = await this.redis.get(sessClaimsKey(sessionId));
@@ -110,16 +134,28 @@ class SessionTokenBinder {
110
134
  }
111
135
  if (raw === null)
112
136
  return false;
113
- // Default: carry the existing payload forward byte-for-byte (facts unchanged).
137
+ // Default: carry the existing payload forward byte-for-byte (facts + subtree unchanged).
114
138
  let payload = raw;
115
- if (freshFacts !== undefined) {
116
- // A refresh-time projection was supplied → rewrite the `cachedFacts` slot on the
117
- // carried-forward claims. A parse failure here is treated as "nothing to update"
118
- // and we carry the original payload forward (fail-safe: never drop the whole
119
- // binding on a transient JSON hiccup — a later request re-projects/DB-reloads).
139
+ if (freshFacts !== undefined || freshSubtree !== undefined) {
140
+ // A refresh-time projection and/or subtree was supplied → rewrite those slots on the
141
+ // carried-forward claims. A parse failure here is treated as "nothing to update" and we
142
+ // carry the original payload forward (fail-safe: never drop the whole binding on a
143
+ // transient JSON hiccup — a later request re-projects/DB-reloads).
120
144
  try {
121
145
  const parsed = JSON.parse(raw);
122
- const next = freshFacts === null ? stripCachedFacts(parsed) : { ...parsed, cachedFacts: freshFacts };
146
+ let next = parsed;
147
+ if (freshFacts !== undefined) {
148
+ next =
149
+ freshFacts === null ? stripCachedFacts(next) : { ...next, cachedFacts: freshFacts };
150
+ }
151
+ // The subtree (the stale-subtree-after-move fix): a non-empty fresh set REPLACES the
152
+ // carried-forward one (a re-parented session gets its correct, possibly-smaller subtree).
153
+ // `undefined` (no resolver / empty / threw at refresh) → carry the existing subtree
154
+ // forward (fail-safe, non-widening — never narrow to self-node on a transient resolver
155
+ // hiccup, never fail the refresh).
156
+ if (freshSubtree !== undefined && freshSubtree.length > 0) {
157
+ next = { ...next, scopeSubtreeNodeIds: [...freshSubtree] };
158
+ }
123
159
  payload = JSON.stringify(next);
124
160
  }
125
161
  catch {
@@ -131,6 +167,77 @@ class SessionTokenBinder {
131
167
  await this.redis.set(sessClaimsKey(sessionId), payload, 'PX', Math.max(ttlMs * 4, ttlMs));
132
168
  return true;
133
169
  }
170
+ /**
171
+ * SCOPE-SWITCH re-bind (Task 5.2, ADR-0027 / ADR-0024). A principal is switching which
172
+ * active node it acts under; re-bind its CURRENT session (the same access token — no
173
+ * rotate, no new tokens) so the bound `tenantId` becomes `targetNodeId` (the new active
174
+ * scope node → `principalFromClaims` reads `activeScopeNodeId = tenantId`) and
175
+ * `scopeSubtreeNodeIds` becomes the NEW node's closure-resolved subtree. The old node's
176
+ * subtree/tenant is REPLACED — stale authority from the previous scope does NOT carry
177
+ * over (the security point of the switch).
178
+ *
179
+ * Rewrites BOTH the per-access-token binding AND the session-claims cushion (so a later
180
+ * refresh/rotate carries the NEW active scope forward), each preserving its remaining TTL
181
+ * (a scope-switch NEVER extends the session life). The `cachedFacts` slot is STRIPPED —
182
+ * the old node's coarse grants are stale under the new scope; the next request re-projects
183
+ * / DB-reloads (fail-closed, never a stale-grant carry-over). The caller resolves the
184
+ * subtree for the NEW node and passes it in.
185
+ *
186
+ * Returns `true` on a successful re-bind, `false` when the binding is gone (logged out /
187
+ * expired) or Redis is unavailable (the caller then denies the switch — fail-closed).
188
+ */
189
+ async rebindActiveScope(accessToken, sessionId, targetNodeId, subtree) {
190
+ // Read the current claims (from the per-access-token entry) + confirm the session is
191
+ // still live (the session-claims entry exists). Any miss / Redis error → fail closed.
192
+ let rawAt;
193
+ let rawSess;
194
+ try {
195
+ rawAt = await this.redis.get(atKey(accessToken));
196
+ rawSess = await this.redis.get(sessClaimsKey(sessionId));
197
+ }
198
+ catch {
199
+ return false; // Redis unavailable → fail closed (no switch).
200
+ }
201
+ if (rawAt === null || rawSess === null)
202
+ return false; // token/session gone → fail closed.
203
+ let current;
204
+ try {
205
+ current = JSON.parse(rawAt);
206
+ }
207
+ catch {
208
+ return false; // malformed → fail closed (a later request re-denies anyway).
209
+ }
210
+ // Build the re-scoped claims: new active node (tenantId) + new subtree, facts stripped.
211
+ // An empty subtree is stored as absent (→ per-request self-node fallback, non-widening) —
212
+ // but the switch caller always passes at least `[targetNodeId]`, so this is defensive.
213
+ const next = stripCachedFacts({
214
+ ...stripScopeSubtree(current),
215
+ tenantId: targetNodeId,
216
+ sessionId,
217
+ ...(subtree.length > 0 ? { scopeSubtreeNodeIds: [...subtree] } : {}),
218
+ });
219
+ const payload = JSON.stringify(next);
220
+ // Preserve each key's remaining TTL — a scope-switch must never extend the session.
221
+ let atTtl;
222
+ let sessTtl;
223
+ try {
224
+ atTtl = await this.redis.pttl(atKey(accessToken));
225
+ sessTtl = await this.redis.pttl(sessClaimsKey(sessionId));
226
+ }
227
+ catch {
228
+ return false;
229
+ }
230
+ if (atTtl <= 0 || sessTtl <= 0)
231
+ return false; // expired between reads → fail closed.
232
+ try {
233
+ await this.redis.set(atKey(accessToken), payload, 'PX', atTtl);
234
+ await this.redis.set(sessClaimsKey(sessionId), payload, 'PX', sessTtl);
235
+ }
236
+ catch {
237
+ return false;
238
+ }
239
+ return true;
240
+ }
134
241
  /**
135
242
  * Resolve an access token to its bound claims, or `null` if the binding is
136
243
  * absent/expired. Fail-closed: any Redis error → `null` (the caller denies), never
@@ -171,6 +278,14 @@ class SessionTokenBinder {
171
278
  parsed = cachedFacts === undefined
172
279
  ? stripCachedFacts(parsed)
173
280
  : { ...parsed, cachedFacts };
281
+ // Normalize the OPTIONAL scope-subtree slot (ADR-0027 / Task 2.2): an absent, empty, or
282
+ // malformed slot is scrubbed to ABSENT (→ `principalFromClaims` falls back to the self-node,
283
+ // non-widening); a well-formed non-empty array is the validated cached subtree. Never
284
+ // fabricated — rebuild the object so a junk slot cannot ride through into a Principal.
285
+ const scopeSubtreeNodeIds = parseScopeSubtree(parsed.scopeSubtreeNodeIds);
286
+ parsed = scopeSubtreeNodeIds === undefined
287
+ ? stripScopeSubtree(parsed)
288
+ : { ...parsed, scopeSubtreeNodeIds };
174
289
  // SESSION-LIVENESS GATE: the per-token binding alone is not enough — a logout
175
290
  // revokes the session but cannot reach every outstanding access-token key. So we
176
291
  // ALSO require the session-claims entry (which `unbindSession` deletes on logout)
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-token-binder.js","sourceRoot":"","sources":["../../src/request-auth/session-token-binder.ts"],"names":[],"mappings":"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"}
@@ -11,4 +11,14 @@
11
11
  * missing (fail-closed).
12
12
  */
13
13
  export declare const SHIELD_SESSION_TOKEN_BINDER: unique symbol;
14
+ /**
15
+ * The {@link import('@astram/core').ServiceAuthenticator} — authenticates a service-account API
16
+ * key (`Authorization: Bearer ask_…`, ADR-0033) into a tenant-bound `service_account` Principal.
17
+ * Provided only when the app wires an {@link import('@astram/core').ApiKeyStore} (i.e. it enables
18
+ * machine/agent access). ABSENT by default — the guard injects it `@Optional()`; when missing, an
19
+ * `ask_…` bearer simply has no authenticator and is treated as an unresolvable token (401,
20
+ * fail-closed), exactly as if the key were unknown. Enabling it opens the machine auth path WITHOUT
21
+ * touching the human session path.
22
+ */
23
+ export declare const SHIELD_SERVICE_AUTHENTICATOR: unique symbol;
14
24
  //# sourceMappingURL=tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/request-auth/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,eAAwC,CAAC"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/request-auth/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,eAAwC,CAAC;AAEjF;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,eAAyC,CAAC"}
@@ -4,7 +4,7 @@
4
4
  * the enforcement guard and the auth wiring can both depend on them without cycles.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.SHIELD_SESSION_TOKEN_BINDER = void 0;
7
+ exports.SHIELD_SERVICE_AUTHENTICATOR = exports.SHIELD_SESSION_TOKEN_BINDER = void 0;
8
8
  /**
9
9
  * The {@link import('./session-token-binder.js').SessionTokenBinder} — binds an
10
10
  * opaque access token to its principal claims (server-side), so the enforcement
@@ -14,3 +14,13 @@ exports.SHIELD_SESSION_TOKEN_BINDER = void 0;
14
14
  * missing (fail-closed).
15
15
  */
16
16
  exports.SHIELD_SESSION_TOKEN_BINDER = Symbol('SHIELD_SESSION_TOKEN_BINDER');
17
+ /**
18
+ * The {@link import('@astram/core').ServiceAuthenticator} — authenticates a service-account API
19
+ * key (`Authorization: Bearer ask_…`, ADR-0033) into a tenant-bound `service_account` Principal.
20
+ * Provided only when the app wires an {@link import('@astram/core').ApiKeyStore} (i.e. it enables
21
+ * machine/agent access). ABSENT by default — the guard injects it `@Optional()`; when missing, an
22
+ * `ask_…` bearer simply has no authenticator and is treated as an unresolvable token (401,
23
+ * fail-closed), exactly as if the key were unknown. Enabling it opens the machine auth path WITHOUT
24
+ * touching the human session path.
25
+ */
26
+ exports.SHIELD_SERVICE_AUTHENTICATOR = Symbol('SHIELD_SERVICE_AUTHENTICATOR');
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/request-auth/tokens.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH;;;;;;;GAOG;AACU,QAAA,2BAA2B,GAAG,MAAM,CAAC,6BAA6B,CAAC,CAAC"}