@astram/guard 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/auth/account.controller.d.ts +245 -0
  2. package/dist/auth/account.controller.d.ts.map +1 -0
  3. package/dist/auth/account.controller.js +673 -0
  4. package/dist/auth/account.controller.js.map +1 -0
  5. package/dist/auth/auth.controller.d.ts +316 -0
  6. package/dist/auth/auth.controller.d.ts.map +1 -0
  7. package/dist/auth/auth.controller.js +1091 -0
  8. package/dist/auth/auth.controller.js.map +1 -0
  9. package/dist/auth/auth.module.d.ts +202 -0
  10. package/dist/auth/auth.module.d.ts.map +1 -0
  11. package/dist/auth/auth.module.js +610 -0
  12. package/dist/auth/auth.module.js.map +1 -0
  13. package/dist/auth/connections.d.ts +61 -0
  14. package/dist/auth/connections.d.ts.map +1 -0
  15. package/dist/auth/connections.js +116 -0
  16. package/dist/auth/connections.js.map +1 -0
  17. package/dist/auth/dto.d.ts +154 -0
  18. package/dist/auth/dto.d.ts.map +1 -0
  19. package/dist/auth/dto.js +29 -0
  20. package/dist/auth/dto.js.map +1 -0
  21. package/dist/auth/pending-mfa-store.d.ts +72 -0
  22. package/dist/auth/pending-mfa-store.d.ts.map +1 -0
  23. package/dist/auth/pending-mfa-store.js +106 -0
  24. package/dist/auth/pending-mfa-store.js.map +1 -0
  25. package/dist/auth/persistence.module.d.ts +42 -0
  26. package/dist/auth/persistence.module.d.ts.map +1 -0
  27. package/dist/auth/persistence.module.js +94 -0
  28. package/dist/auth/persistence.module.js.map +1 -0
  29. package/dist/auth/ports/audit-sink.d.ts +47 -0
  30. package/dist/auth/ports/audit-sink.d.ts.map +1 -0
  31. package/dist/auth/ports/audit-sink.js +20 -0
  32. package/dist/auth/ports/audit-sink.js.map +1 -0
  33. package/dist/auth/ports/credential-writer.d.ts +23 -0
  34. package/dist/auth/ports/credential-writer.d.ts.map +1 -0
  35. package/dist/auth/ports/credential-writer.js +2 -0
  36. package/dist/auth/ports/credential-writer.js.map +1 -0
  37. package/dist/auth/ports/email-sender.d.ts +14 -0
  38. package/dist/auth/ports/email-sender.d.ts.map +1 -0
  39. package/dist/auth/ports/email-sender.js +2 -0
  40. package/dist/auth/ports/email-sender.js.map +1 -0
  41. package/dist/auth/ports/mfa-device-store.d.ts +45 -0
  42. package/dist/auth/ports/mfa-device-store.d.ts.map +1 -0
  43. package/dist/auth/ports/mfa-device-store.js +13 -0
  44. package/dist/auth/ports/mfa-device-store.js.map +1 -0
  45. package/dist/auth/ports/profile-writer.d.ts +12 -0
  46. package/dist/auth/ports/profile-writer.d.ts.map +1 -0
  47. package/dist/auth/ports/profile-writer.js +2 -0
  48. package/dist/auth/ports/profile-writer.js.map +1 -0
  49. package/dist/auth/ports/recovery-code-store.d.ts +10 -0
  50. package/dist/auth/ports/recovery-code-store.d.ts.map +1 -0
  51. package/dist/auth/ports/recovery-code-store.js +2 -0
  52. package/dist/auth/ports/recovery-code-store.js.map +1 -0
  53. package/dist/auth/ports/reset-token-store.d.ts +12 -0
  54. package/dist/auth/ports/reset-token-store.d.ts.map +1 -0
  55. package/dist/auth/ports/reset-token-store.js +2 -0
  56. package/dist/auth/ports/reset-token-store.js.map +1 -0
  57. package/dist/auth/ports/session-facts-projector.d.ts +44 -0
  58. package/dist/auth/ports/session-facts-projector.d.ts.map +1 -0
  59. package/dist/auth/ports/session-facts-projector.js +30 -0
  60. package/dist/auth/ports/session-facts-projector.js.map +1 -0
  61. package/dist/auth/ports/session-sweeper.d.ts +12 -0
  62. package/dist/auth/ports/session-sweeper.d.ts.map +1 -0
  63. package/dist/auth/ports/session-sweeper.js +2 -0
  64. package/dist/auth/ports/session-sweeper.js.map +1 -0
  65. package/dist/auth/profile-resolver.d.ts +73 -0
  66. package/dist/auth/profile-resolver.d.ts.map +1 -0
  67. package/dist/auth/profile-resolver.js +28 -0
  68. package/dist/auth/profile-resolver.js.map +1 -0
  69. package/dist/auth/rate-limit/attempt-limiter.d.ts +91 -0
  70. package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -0
  71. package/dist/auth/rate-limit/attempt-limiter.js +133 -0
  72. package/dist/auth/rate-limit/attempt-limiter.js.map +1 -0
  73. package/dist/auth/tokens.d.ts +236 -0
  74. package/dist/auth/tokens.d.ts.map +1 -0
  75. package/dist/auth/tokens.js +254 -0
  76. package/dist/auth/tokens.js.map +1 -0
  77. package/dist/auth/totp-enrollment.d.ts +42 -0
  78. package/dist/auth/totp-enrollment.d.ts.map +1 -0
  79. package/dist/auth/totp-enrollment.js +96 -0
  80. package/dist/auth/totp-enrollment.js.map +1 -0
  81. package/dist/authentication/argon2id-password-hasher.js.map +1 -0
  82. package/dist/authentication/mariadb-credential-resolver.d.ts +110 -0
  83. package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -0
  84. package/dist/authentication/mariadb-credential-resolver.js +170 -0
  85. package/dist/authentication/mariadb-credential-resolver.js.map +1 -0
  86. package/dist/authz/cross-tenant-grant-writer.d.ts +259 -0
  87. package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -0
  88. package/dist/authz/cross-tenant-grant-writer.js +397 -0
  89. package/dist/authz/cross-tenant-grant-writer.js.map +1 -0
  90. package/dist/authz/manifest-operation-authority-adapter.d.ts +65 -0
  91. package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -0
  92. package/dist/authz/manifest-operation-authority-adapter.js +108 -0
  93. package/dist/authz/manifest-operation-authority-adapter.js.map +1 -0
  94. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts +90 -0
  95. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -0
  96. package/dist/authz/mariadb-cross-tenant-grant-adapter.js +211 -0
  97. package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +1 -0
  98. package/dist/authz/mariadb-record-rule-adapter.d.ts +60 -0
  99. package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -0
  100. package/dist/authz/mariadb-record-rule-adapter.js +154 -0
  101. package/dist/authz/mariadb-record-rule-adapter.js.map +1 -0
  102. package/dist/authz/mariadb-record-share-adapter.d.ts +75 -0
  103. package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -0
  104. package/dist/authz/mariadb-record-share-adapter.js +106 -0
  105. package/dist/authz/mariadb-record-share-adapter.js.map +1 -0
  106. package/dist/authz/record-share-cascade.d.ts +52 -0
  107. package/dist/authz/record-share-cascade.d.ts.map +1 -0
  108. package/dist/authz/record-share-cascade.js +49 -0
  109. package/dist/authz/record-share-cascade.js.map +1 -0
  110. package/dist/authz/record-share-writer.d.ts +175 -0
  111. package/dist/authz/record-share-writer.d.ts.map +1 -0
  112. package/dist/authz/record-share-writer.js +225 -0
  113. package/dist/authz/record-share-writer.js.map +1 -0
  114. package/dist/authz/wire-record-authorization.d.ts +66 -0
  115. package/dist/authz/wire-record-authorization.d.ts.map +1 -0
  116. package/dist/authz/wire-record-authorization.js +34 -0
  117. package/dist/authz/wire-record-authorization.js.map +1 -0
  118. package/dist/boot/boot-sequence.js.map +1 -0
  119. package/dist/boot/boot.module.js.map +1 -0
  120. package/dist/completeness/catalog-reconciler.d.ts +21 -0
  121. package/dist/completeness/catalog-reconciler.d.ts.map +1 -0
  122. package/dist/completeness/catalog-reconciler.js +74 -0
  123. package/dist/completeness/catalog-reconciler.js.map +1 -0
  124. package/dist/completeness/operation-inventory-scanner.d.ts +17 -0
  125. package/dist/completeness/operation-inventory-scanner.d.ts.map +1 -0
  126. package/dist/completeness/operation-inventory-scanner.js +79 -0
  127. package/dist/completeness/operation-inventory-scanner.js.map +1 -0
  128. package/dist/completeness/ports/catalog-store.d.ts +33 -0
  129. package/dist/completeness/ports/catalog-store.d.ts.map +1 -0
  130. package/dist/completeness/ports/catalog-store.js +2 -0
  131. package/dist/completeness/ports/catalog-store.js.map +1 -0
  132. package/dist/config/app-config.d.ts +134 -1
  133. package/dist/config/app-config.d.ts.map +1 -1
  134. package/dist/config/app-config.js +144 -2
  135. package/dist/config/app-config.js.map +1 -0
  136. package/dist/config/config.module.js.map +1 -0
  137. package/dist/enforcement/classification.decorator.d.ts +33 -14
  138. package/dist/enforcement/classification.decorator.d.ts.map +1 -1
  139. package/dist/enforcement/classification.decorator.js +34 -14
  140. package/dist/enforcement/classification.decorator.js.map +1 -0
  141. package/dist/enforcement/core-seam.js.map +1 -0
  142. package/dist/enforcement/enforcement.module.js.map +1 -0
  143. package/dist/enforcement/global-enforcement.guard.d.ts +29 -19
  144. package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
  145. package/dist/enforcement/global-enforcement.guard.js +108 -25
  146. package/dist/enforcement/global-enforcement.guard.js.map +1 -0
  147. package/dist/enforcement/reenroll-allowlist.d.ts +49 -0
  148. package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -0
  149. package/dist/enforcement/reenroll-allowlist.js +77 -0
  150. package/dist/enforcement/reenroll-allowlist.js.map +1 -0
  151. package/dist/index.d.ts +43 -3
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js +198 -1
  154. package/dist/index.js.map +1 -0
  155. package/dist/module/shield-tokens.d.ts +15 -0
  156. package/dist/module/shield-tokens.d.ts.map +1 -0
  157. package/dist/module/shield-tokens.js +17 -0
  158. package/dist/module/shield-tokens.js.map +1 -0
  159. package/dist/module/shield.module.d.ts +203 -8
  160. package/dist/module/shield.module.d.ts.map +1 -1
  161. package/dist/module/shield.module.js +232 -14
  162. package/dist/module/shield.module.js.map +1 -0
  163. package/dist/request-auth/request-principal.d.ts +42 -0
  164. package/dist/request-auth/request-principal.d.ts.map +1 -0
  165. package/dist/request-auth/request-principal.js +87 -0
  166. package/dist/request-auth/request-principal.js.map +1 -0
  167. package/dist/request-auth/session-facts-als.d.ts +65 -0
  168. package/dist/request-auth/session-facts-als.d.ts.map +1 -0
  169. package/dist/request-auth/session-facts-als.js +57 -0
  170. package/dist/request-auth/session-facts-als.js.map +1 -0
  171. package/dist/request-auth/session-token-binder.d.ts +130 -0
  172. package/dist/request-auth/session-token-binder.d.ts.map +1 -0
  173. package/dist/request-auth/session-token-binder.js +277 -0
  174. package/dist/request-auth/session-token-binder.js.map +1 -0
  175. package/dist/request-auth/tokens.d.ts +14 -0
  176. package/dist/request-auth/tokens.d.ts.map +1 -0
  177. package/dist/request-auth/tokens.js +16 -0
  178. package/dist/request-auth/tokens.js.map +1 -0
  179. package/dist/session/crypto-adapters.js.map +1 -0
  180. package/dist/session/index.js.map +1 -0
  181. package/dist/session/mariadb-session-record-store.js.map +1 -0
  182. package/dist/session/redis-hot-session-store.js.map +1 -0
  183. package/package.json +2 -2
@@ -1,14 +1,21 @@
1
1
  import { type DynamicModule } from '@nestjs/common';
2
+ import type { CredentialResolver, FactorVerifier } from '@astram/core';
3
+ import type { RecordAuthorizationInputs } from '../authz/wire-record-authorization.js';
4
+ import type { ProfileResolver } from '../auth/profile-resolver.js';
5
+ import type { CredentialWriter } from '../auth/ports/credential-writer.js';
6
+ import type { ResetTokenStore } from '../auth/ports/reset-token-store.js';
7
+ import type { EmailSender } from '../auth/ports/email-sender.js';
8
+ import type { RecoveryCodeStore } from '../auth/ports/recovery-code-store.js';
9
+ import type { ProfileWriter } from '../auth/ports/profile-writer.js';
10
+ import type { SessionSweeper } from '../auth/ports/session-sweeper.js';
11
+ import type { MfaDeviceStore } from '../auth/ports/mfa-device-store.js';
12
+ import type { AuditSink } from '../auth/ports/audit-sink.js';
13
+ import type { SessionFactsProjector } from '../auth/ports/session-facts-projector.js';
2
14
  import type { CoreDecisionAuthority } from '../enforcement/core-seam.js';
3
15
  import { type AppConfig } from '../config/app-config.js';
4
- /**
5
- * DI token for the Core decision authority (the ADR-0001 single decision
6
- * authority) that the enforcement guard consults. The consumer supplies the real
7
- * `@astram/core` authority through {@link ShieldModule.forRoot}; when omitted the
8
- * framework binds the fail-closed {@link stubDecisionAuthority} (deny-by-default),
9
- * so a mis-wiring cannot silently open a door.
10
- */
11
- export declare const SHIELD_DECISION_AUTHORITY: unique symbol;
16
+ import { SHIELD_DECISION_AUTHORITY } from './shield-tokens.js';
17
+ export { SHIELD_DECISION_AUTHORITY };
18
+ export type { RecordAuthorizationInputs } from '../authz/wire-record-authorization.js';
12
19
  /**
13
20
  * Options for {@link ShieldModule.forRoot}. Intentionally minimal (ADR-0023 §7 —
14
21
  * no speculative abstraction): the consumer declares Shield through this ONE seam.
@@ -21,12 +28,126 @@ export interface ShieldModuleOptions {
21
28
  * the real Core authority — the guard's call site does not change.
22
29
  */
23
30
  readonly decisionAuthority?: CoreDecisionAuthority;
31
+ /**
32
+ * ⛔ FRAMEWORK-OWNED RECORD-TIER WIRING (design §9, Phase 5 — the preferred path).
33
+ *
34
+ * Supply the PIECES the framework needs to build the real Core decision authority
35
+ * ITSELF, instead of a pre-built {@link decisionAuthority}. When present, ShieldModule
36
+ * INTERNALLY constructs the four record-tier adapters
37
+ * (`MariaDbRecordPermissionRuleAdapter` / `MariaDbRecordShareAdapter` /
38
+ * `MariaDbCrossTenantGrantAdapter` / `ManifestOperationAuthorityAdapter`) over the
39
+ * supplied `pool`/`operationManifest` and calls core's `createWiredDecisionAuthority`
40
+ * with them + the app-owned `permissionFacts` / `sessionFacts` / `registry`.
41
+ *
42
+ * The app supplies ONLY: the DB `pool`, the two app-owned ports (`permissionFacts`,
43
+ * `sessionFacts`), the module `registry`, and the operation-manifest DATA. It CANNOT
44
+ * supply — or weaken — the four record-tier read adapters: they are framework-owned and
45
+ * un-overridable BY CONSTRUCTION (a planted fail-open record adapter is impossible —
46
+ * the whole point of the "framework-owns-the-data-layer" initiative).
47
+ *
48
+ * MUTUALLY EXCLUSIVE with {@link decisionAuthority} — supplying BOTH is a misconfig and
49
+ * throws at registration. Supplying NEITHER binds the fail-closed stub (unchanged).
50
+ */
51
+ readonly recordAuthorization?: RecordAuthorizationInputs;
24
52
  /**
25
53
  * Application config (port/environment/ADR-0018 pool budget). Omit to load from
26
54
  * the environment via {@link loadAppConfig}. Supplied here so a consumer can
27
55
  * inject computed config through the one seam rather than editing the framework.
28
56
  */
29
57
  readonly config?: AppConfig;
58
+ /**
59
+ * ⛔ OPT-IN: the framework-owned login → session auth surface (Phase 0b — the
60
+ * `/auth/*` endpoints + the composed `Authenticator` / `SessionAuthority`).
61
+ *
62
+ * DEFAULT `false` (ABSENT): an enforcement-only app does NOT import
63
+ * {@link AuthModule} — so it never opens a MariaDB pool / Redis client, never
64
+ * fires the fail-closed `assertRefreshHmacKey` gate, and keeps the no-`.env`
65
+ * boot promised by `create-astram-app`. `ShieldModule.forRoot()` composes with
66
+ * a blank refresh-HMAC key and no live connection (enforcement-only).
67
+ *
68
+ * `true`: imports {@link AuthModule.forRoot} (which pulls the live connections +
69
+ * composes the authenticator + session authority + registers the four `/auth/*`
70
+ * routes) and re-exports {@link SHIELD_AUTHENTICATOR} / {@link SHIELD_SESSION_AUTHORITY}
71
+ * app-wide. An auth-enabled app fails LOUD at boot if `SHIELD_REFRESH_HMAC_KEY`
72
+ * is blank — auth can never compose unkeyed.
73
+ */
74
+ readonly auth?: boolean;
75
+ /**
76
+ * OPTIONAL custom credential resolver (the store login checks against). Omit →
77
+ * the framework's default `MariaDbCredentialResolver` (reads
78
+ * `shield_identity.identity_credential`). Supply a consumer implementation of the
79
+ * core `CredentialResolver` port to authenticate against your OWN user/identity
80
+ * schema (e.g. a multi-tenant users+roles model) WITHOUT editing the framework.
81
+ *
82
+ * Only consulted when `auth: true` (a no-op without it — no AuthModule composes,
83
+ * so no resolver is wired). The seam swaps the STORE only: a supplied resolver
84
+ * still flows through the SAME composed authenticator (anti-enumeration decoy
85
+ * verify, MFA, no-secret-leak). A resolver returning `null` = unknown principal
86
+ * (generic 401); throwing = fail-closed transient — exactly the default contract.
87
+ */
88
+ readonly credentialResolver?: CredentialResolver;
89
+ /**
90
+ * OPTIONAL current-user profile resolver backing `GET /auth/me`. Omit → `/auth/me`
91
+ * returns an honest 501 (the framework is agnostic to your ORG schema, so it cannot
92
+ * name the user/company/roles without your tables). Supply an implementation of the
93
+ * {@link ProfileResolver} port to return the signed-in user's display profile
94
+ * (names, never UUIDs). Only consulted when `auth: true`.
95
+ */
96
+ readonly profileResolver?: ProfileResolver;
97
+ /**
98
+ * OPTIONAL account/credential-surface seams (forgot/reset, change-password, MFA
99
+ * enrollment, profile edit). Each is threaded straight through to
100
+ * {@link AuthModule.forRoot} (bound under its token, or `null` when absent → the
101
+ * route returns 501). Only consulted when `auth: true`. Supply a consumer
102
+ * implementation of the matching `@astram/guard` port to enable the route.
103
+ */
104
+ readonly credentialWriter?: CredentialWriter;
105
+ readonly resetTokenStore?: ResetTokenStore;
106
+ readonly emailSender?: EmailSender;
107
+ readonly recoveryCodeStore?: RecoveryCodeStore;
108
+ readonly profileWriter?: ProfileWriter;
109
+ readonly sessionSweeper?: SessionSweeper;
110
+ /**
111
+ * OPTIONAL auth-surface audit sink — see {@link AuthModuleOptions.auditSink}.
112
+ * Threaded straight through to {@link AuthModule.forRoot} (bound under its token, or
113
+ * `null` when absent → the recovery-login audit no-ops). Only consulted when
114
+ * `auth: true`.
115
+ */
116
+ readonly auditSink?: AuditSink;
117
+ /**
118
+ * OPTIONAL multi-device MFA store — see {@link AuthModuleOptions.mfaDeviceStore}.
119
+ * Threaded straight through to {@link AuthModule.forRoot} (bound under its token,
120
+ * or `null` when absent → the device routes 501). Only consulted when `auth: true`.
121
+ */
122
+ readonly mfaDeviceStore?: MfaDeviceStore;
123
+ /**
124
+ * OPTIONAL login `totp` verifier override — see {@link AuthModuleOptions.totpVerifier}.
125
+ * Threaded straight through to {@link AuthModule.forRoot} (replaces the default
126
+ * single-secret verifier in the composed authenticator; absent → the default). A
127
+ * consumer plugs an OR-matching multi-device verifier here. Only consulted when
128
+ * `auth: true`.
129
+ */
130
+ readonly totpVerifier?: FactorVerifier;
131
+ /**
132
+ * OPTIONAL root allowlist — the server-side, trusted set of canonical
133
+ * principal ids (user uuids) that ARE roots. Threaded straight through
134
+ * to {@link AuthModule.forRoot} → `createIdentityBroker({ internalRootIds })`.
135
+ * ROOT SAFETY: this is the ONLY way a login mints a root (the
136
+ * Internal identity adapter keys the trusted signal off THIS list, never off a
137
+ * claim). Omit → `[]` → default-deny (nobody is a root). Only consulted when
138
+ * `auth: true`.
139
+ */
140
+ readonly rootIds?: readonly string[];
141
+ /**
142
+ * OPTIONAL eager session-facts projector (ADR-0011) — see
143
+ * {@link AuthModuleOptions.sessionFactsProjector}. Threaded straight through to
144
+ * {@link AuthModule.forRoot} (bound under {@link SHIELD_SESSION_FACTS_PROJECTOR}, or
145
+ * `null` when absent → the auth controller omits `cachedFacts` and gate 5 DB-reloads
146
+ * every request, today's behavior). When supplied, login/refresh cache the principal's
147
+ * coarse grants on the session binding so gate 5 serves them from the request's
148
+ * `cachedFacts`. Only consulted when `auth: true`.
149
+ */
150
+ readonly sessionFactsProjector?: SessionFactsProjector;
30
151
  }
31
152
  /** Async variant of {@link ShieldModuleOptions} (DI-computed config). */
32
153
  export interface ShieldModuleAsyncOptions {
@@ -36,6 +157,80 @@ export interface ShieldModuleAsyncOptions {
36
157
  readonly useFactory: (...args: readonly unknown[]) => Promise<ShieldModuleOptions> | ShieldModuleOptions;
37
158
  /** Modules exporting the injected providers. */
38
159
  readonly imports?: readonly unknown[];
160
+ /**
161
+ * ⛔ OPT-IN auth (see {@link ShieldModuleOptions.auth}). STATIC here (not part of
162
+ * the async factory result): whether an app wires the auth surface is a
163
+ * deployment-topology decision known at REGISTRATION time, and a NestJS
164
+ * `DynamicModule.imports` list is composed statically — it cannot depend on the
165
+ * async-resolved `ShieldModuleOptions`. So the flag lives on the async-options
166
+ * object directly, gating the {@link AuthModule} import + engine re-exports
167
+ * exactly like {@link forRoot}. DEFAULT `false` (no auth → no live connection →
168
+ * no-`.env` boot preserved).
169
+ */
170
+ readonly auth?: boolean;
171
+ /**
172
+ * OPTIONAL custom credential resolver — see {@link ShieldModuleOptions.credentialResolver}.
173
+ * STATIC here (like {@link auth}, NOT part of the async factory result): the
174
+ * resolver instance is a registration-time collaborator threaded into the
175
+ * statically-composed {@link AuthModule} import, so it cannot depend on the
176
+ * async-resolved options. Only consulted when `auth: true`.
177
+ */
178
+ readonly credentialResolver?: CredentialResolver;
179
+ /**
180
+ * OPTIONAL current-user profile resolver — see {@link ShieldModuleOptions.profileResolver}.
181
+ * STATIC here (like {@link credentialResolver}): a registration-time collaborator
182
+ * threaded into the statically-composed {@link AuthModule} import. Only consulted
183
+ * when `auth: true`.
184
+ */
185
+ readonly profileResolver?: ProfileResolver;
186
+ /**
187
+ * OPTIONAL account/credential-surface seams — see
188
+ * {@link ShieldModuleOptions.credentialWriter} et al. STATIC here (like the other
189
+ * seams): registration-time collaborators threaded into the statically-composed
190
+ * {@link AuthModule} import, so they cannot depend on the async-resolved options.
191
+ * Only consulted when `auth: true`.
192
+ */
193
+ readonly credentialWriter?: CredentialWriter;
194
+ readonly resetTokenStore?: ResetTokenStore;
195
+ readonly emailSender?: EmailSender;
196
+ readonly recoveryCodeStore?: RecoveryCodeStore;
197
+ readonly profileWriter?: ProfileWriter;
198
+ readonly sessionSweeper?: SessionSweeper;
199
+ /**
200
+ * OPTIONAL auth-surface audit sink — see {@link ShieldModuleOptions.auditSink}.
201
+ * STATIC here (like the other seams): a registration-time collaborator threaded into
202
+ * the statically-composed {@link AuthModule} import. Only consulted when `auth: true`.
203
+ */
204
+ readonly auditSink?: AuditSink;
205
+ /**
206
+ * OPTIONAL multi-device MFA store — see {@link ShieldModuleOptions.mfaDeviceStore}.
207
+ * STATIC here (like the other seams): a registration-time collaborator threaded into
208
+ * the statically-composed {@link AuthModule} import. Only consulted when `auth: true`.
209
+ */
210
+ readonly mfaDeviceStore?: MfaDeviceStore;
211
+ /**
212
+ * OPTIONAL login `totp` verifier override — see {@link ShieldModuleOptions.totpVerifier}.
213
+ * STATIC here (like the other seams): a registration-time collaborator threaded into
214
+ * the statically-composed {@link AuthModule} import. Only consulted when `auth: true`.
215
+ */
216
+ readonly totpVerifier?: FactorVerifier;
217
+ /**
218
+ * OPTIONAL root allowlist — see {@link ShieldModuleOptions.rootIds}.
219
+ * STATIC here (like the other seams): a registration-time collaborator threaded into
220
+ * the statically-composed {@link AuthModule} import (it is passed to the broker at
221
+ * authenticator-composition time, not part of the async factory result). A consumer
222
+ * that must COMPUTE the list at boot (e.g. read it from a DB) uses `forRootAsync`'s
223
+ * `useFactory` to build the whole options object — the resolved `rootIds` is
224
+ * then threaded exactly like the static case. Only consulted when `auth: true`.
225
+ */
226
+ readonly rootIds?: readonly string[];
227
+ /**
228
+ * OPTIONAL eager session-facts projector — see {@link ShieldModuleOptions.sessionFactsProjector}.
229
+ * STATIC here (like the other seams): a registration-time collaborator threaded into the
230
+ * statically-composed {@link AuthModule} import, so it cannot depend on the async-resolved
231
+ * options. Only consulted when `auth: true`.
232
+ */
233
+ readonly sessionFactsProjector?: SessionFactsProjector;
39
234
  }
40
235
  /**
41
236
  * `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":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AACnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAKzE,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAExE;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,eAAsC,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,qBAAqB,CAAC;IACnD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AAED,yEAAyE;AACzE,MAAM,WAAW,wBAAwB;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACrC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,CACnB,GAAG,IAAI,EAAE,SAAS,OAAO,EAAE,KACxB,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAC;IACxD,gDAAgD;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAEa,YAAY;IACvB,6DAA6D;IAC7D,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa;IAkBhE;;;;;;;;;OASG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa;CA8BtE"}
1
+ {"version":3,"file":"shield.module.d.ts","sourceRoot":"","sources":["../../src/module/shield.module.ts"],"names":[],"mappings":"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"}
@@ -1,27 +1,130 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
2
18
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
19
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
20
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
21
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
22
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
23
  };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
8
41
  var ShieldModule_1;
9
42
  Object.defineProperty(exports, "__esModule", { value: true });
10
43
  exports.ShieldModule = exports.SHIELD_DECISION_AUTHORITY = void 0;
11
44
  const common_1 = require("@nestjs/common");
45
+ const node_url_1 = require("node:url");
12
46
  const core_seam_js_1 = require("../enforcement/core-seam.js");
13
47
  const enforcement_module_js_1 = require("../enforcement/enforcement.module.js");
14
48
  const boot_module_js_1 = require("../boot/boot.module.js");
15
49
  const config_module_js_1 = require("../config/config.module.js");
16
50
  const app_config_js_1 = require("../config/app-config.js");
51
+ // Static import is SAFE: auth.module.ts top-level-imports @astram/core as TYPES
52
+ // only (it loads core's ESM factory VALUES lazily inside its async provider
53
+ // factories — see auth.module.ts loadCore()). So pulling AuthModule here does NOT
54
+ // trigger a runtime `require('@astram/core')`; the opt-in gate below still ensures
55
+ // the enforcement-only path never INSTANTIATES it (no live pool/Redis, no HMAC
56
+ // gate, no core load).
57
+ const auth_module_js_1 = require("../auth/auth.module.js");
58
+ // The `SHIELD_DECISION_AUTHORITY` token now lives in `./shield-tokens.js` so the
59
+ // enforcement guard can import it without a cycle (guard → token → ShieldModule →
60
+ // EnforcementModule → guard). Re-exported here to keep the public import path stable.
61
+ const shield_tokens_js_1 = require("./shield-tokens.js");
62
+ Object.defineProperty(exports, "SHIELD_DECISION_AUTHORITY", { enumerable: true, get: function () { return shield_tokens_js_1.SHIELD_DECISION_AUTHORITY; } });
63
+ /**
64
+ * A `Function`-wrapped dynamic `import()` that survives the CommonJS **build** — the same
65
+ * shim as auth.module.ts's `evalImport`. Under `module: commonjs`, `tsc` would rewrite a
66
+ * literal `import()` into `require(...)`; routing through the `Function` constructor keeps
67
+ * a genuine native `import()` in the emitted dist so this file's OWN compiled output stays
68
+ * free of a top-level `require('../authz/wire-record-authorization.js')` (→ core). We pass
69
+ * the file's absolute URL (resolved off `__dirname` in the CJS dist / `import.meta.url`
70
+ * would not exist here) so the eval'd import has a base to resolve against.
71
+ */
72
+ const evalImport = new Function('specifier', 'return import(specifier);');
73
+ let cachedRecordAuthApi;
17
74
  /**
18
- * DI token for the Core decision authority (the ADR-0001 single decision
19
- * authority) that the enforcement guard consults. The consumer supplies the real
20
- * `@astram/core` authority through {@link ShieldModule.forRoot}; when omitted the
21
- * framework binds the fail-closed {@link stubDecisionAuthority} (deny-by-default),
22
- * so a mis-wiring cannot silently open a door.
75
+ * Lazily load the framework's record-authorization builder. Invoked ONLY inside the
76
+ * `SHIELD_DECISION_AUTHORITY` async factory when a consumer supplies
77
+ * `recordAuthorization` — NEVER at module top-level. The target file value-imports
78
+ * `@astram/core` + the four adapter classes, so deferring its load keeps a runtime
79
+ * `require('@astram/core')` OUT of THIS module's (the enforcement-only) load path.
80
+ *
81
+ * TWO strategies, mirroring auth.module.ts's `loadCore`, so it works in BOTH runtimes:
82
+ * 1. A plain dynamic `import()` — native under vitest/SWC (source path).
83
+ * 2. On failure (the tsc-built CJS dist downlevels #1 to a throwing `require` when the
84
+ * transitive `@astram/core` ESM cannot be `require`d in that context), the
85
+ * {@link evalImport} `Function`-wrapped native `import()` resolved off `__dirname`.
23
86
  */
24
- exports.SHIELD_DECISION_AUTHORITY = Symbol('SHIELD_DECISION_AUTHORITY');
87
+ async function loadBuildRecordAuthorization() {
88
+ if (cachedRecordAuthApi === undefined) {
89
+ try {
90
+ cachedRecordAuthApi = (await Promise.resolve().then(() => __importStar(require('../authz/wire-record-authorization.js'))));
91
+ }
92
+ catch {
93
+ // Built-dist fallback (the CJS dist path — see evalImport). `__dirname` is defined
94
+ // in the emitted CJS module; resolve the compiled sibling relative to it and import
95
+ // it as a file:// URL so Node's CJS→ESM interop loads it (and its ESM-only core dep).
96
+ const base = (0, node_url_1.pathToFileURL)(`${__dirname}/../authz/wire-record-authorization.js`).href;
97
+ cachedRecordAuthApi = (await evalImport(base));
98
+ }
99
+ }
100
+ return cachedRecordAuthApi.buildRecordAuthorization;
101
+ }
102
+ /**
103
+ * Resolve the `SHIELD_DECISION_AUTHORITY` VALUE from the caller's options (the ONE seam,
104
+ * ADR-0023 — only how its value is PRODUCED changes here). Precedence + mutual exclusion:
105
+ *
106
+ * - `recordAuthorization` PRESENT → the framework builds the REAL wired authority itself
107
+ * (the four record-tier adapters constructed inside guard, un-overridable). This is the
108
+ * Phase-5 path: the app can no longer supply or weaken those adapters.
109
+ * - `decisionAuthority` PRESENT (legacy passthrough) → bind the caller's pre-built
110
+ * authority verbatim (kept for other consumers / back-compat).
111
+ * - BOTH present → MISCONFIG: throw a clear error (they are mutually exclusive).
112
+ * - NEITHER → the fail-closed {@link stubDecisionAuthority} (unchanged fallback).
113
+ *
114
+ * Async because the `recordAuthorization` path lazy-loads the (core-touching) builder.
115
+ */
116
+ async function resolveDecisionAuthority(options) {
117
+ if (options.recordAuthorization && options.decisionAuthority) {
118
+ throw new Error('ShieldModule: `recordAuthorization` and `decisionAuthority` are mutually exclusive — ' +
119
+ 'supply the record-authorization inputs (pool + app ports + registry) so the framework ' +
120
+ 'builds the decision authority, OR a pre-built `decisionAuthority`, but not both.');
121
+ }
122
+ if (options.recordAuthorization) {
123
+ const build = await loadBuildRecordAuthorization();
124
+ return build(options.recordAuthorization);
125
+ }
126
+ return options.decisionAuthority ?? core_seam_js_1.stubDecisionAuthority;
127
+ }
25
128
  /**
26
129
  * `ShieldModule` — the SINGLE registration seam (ADR-0023 §4).
27
130
  *
@@ -50,19 +153,80 @@ let ShieldModule = ShieldModule_1 = class ShieldModule {
50
153
  /** Register Shield with static options (the common path). */
51
154
  static forRoot(options = {}) {
52
155
  const config = options.config ?? (0, app_config_js_1.loadAppConfig)();
156
+ // Build the opt-in AuthModule ONCE so the SAME DynamicModule instance is both
157
+ // imported (composes) and re-exported (propagates its exported engine tokens
158
+ // app-wide through the @Global ShieldModule). Re-exporting the two Symbols
159
+ // directly is NOT valid Nest — a module may only re-export a whole imported
160
+ // module (or a token IT provides), so we export the AuthModule dynamic module.
161
+ // When auth is opted in, thread the consumer's optional credentialResolver into
162
+ // AuthModule (it binds the supplied instance under SHIELD_CREDENTIAL_RESOLVER;
163
+ // omitted → the default MariaDb store, unchanged). Without auth the resolver is
164
+ // irrelevant (no AuthModule composes) — a documented no-op.
165
+ const authModule = options.auth
166
+ ? auth_module_js_1.AuthModule.forRoot(
167
+ // Only pass a property when the consumer supplied one — under
168
+ // `exactOptionalPropertyTypes`, an explicit `undefined` is not assignable
169
+ // to an optional field; a spread keeps it truly absent so AuthModule falls
170
+ // back to its defaults (MariaDb credential store; 501 /auth/me).
171
+ {
172
+ ...(options.credentialResolver
173
+ ? { credentialResolver: options.credentialResolver }
174
+ : {}),
175
+ ...(options.profileResolver
176
+ ? { profileResolver: options.profileResolver }
177
+ : {}),
178
+ // The account/credential-surface seams — same spread-when-present rule
179
+ // (an explicit `undefined` is not assignable under
180
+ // exactOptionalPropertyTypes; absent → AuthModule binds `null` → 501).
181
+ ...(options.credentialWriter ? { credentialWriter: options.credentialWriter } : {}),
182
+ ...(options.resetTokenStore ? { resetTokenStore: options.resetTokenStore } : {}),
183
+ ...(options.emailSender ? { emailSender: options.emailSender } : {}),
184
+ ...(options.recoveryCodeStore ? { recoveryCodeStore: options.recoveryCodeStore } : {}),
185
+ ...(options.profileWriter ? { profileWriter: options.profileWriter } : {}),
186
+ ...(options.sessionSweeper ? { sessionSweeper: options.sessionSweeper } : {}),
187
+ ...(options.auditSink ? { auditSink: options.auditSink } : {}),
188
+ ...(options.mfaDeviceStore ? { mfaDeviceStore: options.mfaDeviceStore } : {}),
189
+ ...(options.totpVerifier ? { totpVerifier: options.totpVerifier } : {}),
190
+ ...(options.rootIds ? { rootIds: options.rootIds } : {}),
191
+ ...(options.sessionFactsProjector
192
+ ? { sessionFactsProjector: options.sessionFactsProjector }
193
+ : {}),
194
+ })
195
+ : undefined;
53
196
  return {
54
197
  module: ShieldModule_1,
55
198
  // Compose the framework modules — EnforcementModule holds the ONE APP_GUARD
56
199
  // binding; BootModule holds the boot-sequence hook. No re-declaration here.
57
- imports: [enforcement_module_js_1.EnforcementModule, boot_module_js_1.BootModule],
200
+ // AuthModule is OPT-IN (options.auth === true): only then does the app open a
201
+ // live pool/Redis + fire the fail-closed HMAC gate. Absent/false → the
202
+ // enforcement-only no-`.env` boot survives untouched.
203
+ imports: [enforcement_module_js_1.EnforcementModule, boot_module_js_1.BootModule, ...(authModule ? [authModule] : [])],
58
204
  providers: [
59
205
  { provide: config_module_js_1.APP_CONFIG, useValue: config },
60
206
  {
61
- provide: exports.SHIELD_DECISION_AUTHORITY,
62
- useValue: options.decisionAuthority ?? core_seam_js_1.stubDecisionAuthority,
207
+ // Async factory: the `recordAuthorization` path lazy-loads the (core-touching)
208
+ // builder — see resolveDecisionAuthority. The legacy `decisionAuthority` +
209
+ // stub paths resolve synchronously but flow through the same one seam. Both
210
+ // supplied → throws (mutual exclusion).
211
+ provide: shield_tokens_js_1.SHIELD_DECISION_AUTHORITY,
212
+ useFactory: () => resolveDecisionAuthority({
213
+ ...(options.recordAuthorization
214
+ ? { recordAuthorization: options.recordAuthorization }
215
+ : {}),
216
+ ...(options.decisionAuthority
217
+ ? { decisionAuthority: options.decisionAuthority }
218
+ : {}),
219
+ }),
63
220
  },
64
221
  ],
65
- exports: [config_module_js_1.APP_CONFIG, exports.SHIELD_DECISION_AUTHORITY],
222
+ // Re-export the composed AuthModule app-wide ONLY when auth is opted in — its
223
+ // own `exports` (SHIELD_AUTHENTICATOR / SHIELD_SESSION_AUTHORITY) then become
224
+ // visible to a consumer's controllers/services via the @Global seam.
225
+ exports: [
226
+ config_module_js_1.APP_CONFIG,
227
+ shield_tokens_js_1.SHIELD_DECISION_AUTHORITY,
228
+ ...(authModule ? [authModule] : []),
229
+ ],
66
230
  };
67
231
  }
68
232
  /**
@@ -88,16 +252,70 @@ let ShieldModule = ShieldModule_1 = class ShieldModule {
88
252
  inject: [optionsToken],
89
253
  };
90
254
  const authorityProvider = {
91
- provide: exports.SHIELD_DECISION_AUTHORITY,
92
- useFactory: (opts) => opts.decisionAuthority ?? core_seam_js_1.stubDecisionAuthority,
255
+ provide: shield_tokens_js_1.SHIELD_DECISION_AUTHORITY,
256
+ // Same one-seam resolution as forRoot, over the async-resolved options: the
257
+ // `recordAuthorization` path (the app hands pool + app ports + registry — computed
258
+ // in its useFactory from the injected registrations) has the framework build the
259
+ // real wired authority; `decisionAuthority` is the legacy passthrough; both →
260
+ // throws; neither → stub. Async because the record path lazy-loads the builder.
261
+ useFactory: (opts) => resolveDecisionAuthority({
262
+ ...(opts.recordAuthorization ? { recordAuthorization: opts.recordAuthorization } : {}),
263
+ ...(opts.decisionAuthority ? { decisionAuthority: opts.decisionAuthority } : {}),
264
+ }),
93
265
  inject: [optionsToken],
94
266
  };
267
+ // Same one-instance opt-in AuthModule as forRoot (imported + re-exported).
268
+ // `credentialResolver` is STATIC on the async options (like `auth`) — a
269
+ // registration-time collaborator, threaded straight through here.
270
+ const authModule = options.auth
271
+ ? auth_module_js_1.AuthModule.forRoot(
272
+ // Only pass a property when the consumer supplied one — under
273
+ // `exactOptionalPropertyTypes`, an explicit `undefined` is not assignable
274
+ // to an optional field; a spread keeps it truly absent so AuthModule falls
275
+ // back to its defaults (MariaDb credential store; 501 /auth/me).
276
+ {
277
+ ...(options.credentialResolver
278
+ ? { credentialResolver: options.credentialResolver }
279
+ : {}),
280
+ ...(options.profileResolver
281
+ ? { profileResolver: options.profileResolver }
282
+ : {}),
283
+ // The account/credential-surface seams — same spread-when-present rule
284
+ // (an explicit `undefined` is not assignable under
285
+ // exactOptionalPropertyTypes; absent → AuthModule binds `null` → 501).
286
+ ...(options.credentialWriter ? { credentialWriter: options.credentialWriter } : {}),
287
+ ...(options.resetTokenStore ? { resetTokenStore: options.resetTokenStore } : {}),
288
+ ...(options.emailSender ? { emailSender: options.emailSender } : {}),
289
+ ...(options.recoveryCodeStore ? { recoveryCodeStore: options.recoveryCodeStore } : {}),
290
+ ...(options.profileWriter ? { profileWriter: options.profileWriter } : {}),
291
+ ...(options.sessionSweeper ? { sessionSweeper: options.sessionSweeper } : {}),
292
+ ...(options.auditSink ? { auditSink: options.auditSink } : {}),
293
+ ...(options.mfaDeviceStore ? { mfaDeviceStore: options.mfaDeviceStore } : {}),
294
+ ...(options.totpVerifier ? { totpVerifier: options.totpVerifier } : {}),
295
+ ...(options.rootIds ? { rootIds: options.rootIds } : {}),
296
+ ...(options.sessionFactsProjector
297
+ ? { sessionFactsProjector: options.sessionFactsProjector }
298
+ : {}),
299
+ })
300
+ : undefined;
95
301
  return {
96
302
  module: ShieldModule_1,
97
303
  // Same single-path composition as forRoot (+ the caller's option imports).
98
- imports: [enforcement_module_js_1.EnforcementModule, boot_module_js_1.BootModule, ...(options.imports ?? [])],
304
+ // AuthModule is OPT-IN via the STATIC `options.auth` flag (see the interface
305
+ // doc — the imports list is composed statically, so auth cannot be gated on
306
+ // the async-resolved options).
307
+ imports: [
308
+ enforcement_module_js_1.EnforcementModule,
309
+ boot_module_js_1.BootModule,
310
+ ...(authModule ? [authModule] : []),
311
+ ...(options.imports ?? []),
312
+ ],
99
313
  providers: [asyncOptionsProvider, configProvider, authorityProvider],
100
- exports: [config_module_js_1.APP_CONFIG, exports.SHIELD_DECISION_AUTHORITY],
314
+ exports: [
315
+ config_module_js_1.APP_CONFIG,
316
+ shield_tokens_js_1.SHIELD_DECISION_AUTHORITY,
317
+ ...(authModule ? [authModule] : []),
318
+ ],
101
319
  };
102
320
  }
103
321
  };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shield.module.js","sourceRoot":"","sources":["../../src/module/shield.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAmF;AACnF,uCAAyC;AA0BzC,8DAAoE;AACpE,gFAAyE;AACzE,2DAAoD;AACpD,iEAAwD;AACxD,2DAAwE;AACxE,gFAAgF;AAChF,4EAA4E;AAC5E,kFAAkF;AAClF,mFAAmF;AACnF,+EAA+E;AAC/E,uBAAuB;AACvB,2DAAoD;AAEpD,iFAAiF;AACjF,kFAAkF;AAClF,sFAAsF;AACtF,yDAA+D;AACtD,0GADA,4CAAyB,OACA;AAelC;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,IAAI,QAAQ,CAAC,WAAW,EAAE,2BAA2B,CAEnD,CAAC;AAEtB,IAAI,mBAAuD,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,KAAK,UAAU,4BAA4B;IAGzC,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC;YACH,mBAAmB,GAAG,CAAC,wDACrB,uCAAuC,GACxC,CAAsC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,mFAAmF;YACnF,oFAAoF;YACpF,sFAAsF;YACtF,MAAM,IAAI,GAAG,IAAA,wBAAa,EAAC,GAAG,SAAS,wCAAwC,CAAC,CAAC,IAAI,CAAC;YACtF,mBAAmB,GAAG,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAA2B,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,OAAO,mBAAmB,CAAC,wBAAwB,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,KAAK,UAAU,wBAAwB,CACrC,OAA+E;IAE/E,IAAI,OAAO,CAAC,mBAAmB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,uFAAuF;YACrF,wFAAwF;YACxF,kFAAkF,CACrF,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,4BAA4B,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,OAAO,CAAC,iBAAiB,IAAI,oCAAqB,CAAC;AAC5D,CAAC;AA8ND;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGI,IAAM,YAAY,oBAAlB,MAAM,YAAY;IACvB,6DAA6D;IAC7D,MAAM,CAAC,OAAO,CAAC,UAA+B,EAAE;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAA,6BAAa,GAAE,CAAC;QACjD,8EAA8E;QAC9E,6EAA6E;QAC7E,2EAA2E;QAC3E,4EAA4E;QAC5E,+EAA+E;QAC/E,gFAAgF;QAChF,+EAA+E;QAC/E,gFAAgF;QAChF,4DAA4D;QAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI;YAC7B,CAAC,CAAC,2BAAU,CAAC,OAAO;YAChB,8DAA8D;YAC9D,0EAA0E;YAC1E,2EAA2E;YAC3E,iEAAiE;YACjE;gBACE,GAAG,CAAC,OAAO,CAAC,kBAAkB;oBAC5B,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,EAAE;oBACpD,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,OAAO,CAAC,eAAe;oBACzB,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE;oBAC9C,CAAC,CAAC,EAAE,CAAC;gBACP,uEAAuE;gBACvE,mDAAmD;gBACnD,uEAAuE;gBACvE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnF,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChF,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1E,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,OAAO,CAAC,qBAAqB;oBAC/B,CAAC,CAAC,EAAE,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,EAAE;oBAC1D,CAAC,CAAC,EAAE,CAAC;aACR,CACF;YACH,CAAC,CAAC,SAAS,CAAC;QACd,OAAO;YACL,MAAM,EAAE,cAAY;YACpB,4EAA4E;YAC5E,4EAA4E;YAC5E,8EAA8E;YAC9E,uEAAuE;YACvE,sDAAsD;YACtD,OAAO,EAAE,CAAC,yCAAiB,EAAE,2BAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7E,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,6BAAU,EAAE,QAAQ,EAAE,MAAM,EAAE;gBACzC;oBACE,+EAA+E;oBAC/E,2EAA2E;oBAC3E,4EAA4E;oBAC5E,wCAAwC;oBACxC,OAAO,EAAE,4CAAyB;oBAClC,UAAU,EAAE,GAAmC,EAAE,CAC/C,wBAAwB,CAAC;wBACvB,GAAG,CAAC,OAAO,CAAC,mBAAmB;4BAC7B,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE;4BACtD,CAAC,CAAC,EAAE,CAAC;wBACP,GAAG,CAAC,OAAO,CAAC,iBAAiB;4BAC3B,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE;4BAClD,CAAC,CAAC,EAAE,CAAC;qBACR,CAAC;iBACL;aACF;YACD,8EAA8E;YAC9E,8EAA8E;YAC9E,qEAAqE;YACrE,OAAO,EAAE;gBACP,6BAAU;gBACV,4CAAyB;gBACzB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACpC;SACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,YAAY,CAAC,OAAiC;QACnD,MAAM,YAAY,GAAG,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAErD,MAAM,oBAAoB,GAAa;YACrC,OAAO,EAAE,YAAY;YACrB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAY;SAC1C,CAAC;QAEF,MAAM,cAAc,GAAa;YAC/B,OAAO,EAAE,6BAAU;YACnB,UAAU,EAAE,CAAC,IAAyB,EAAa,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,IAAA,6BAAa,GAAE;YACpF,MAAM,EAAE,CAAC,YAAY,CAAC;SACvB,CAAC;QAEF,MAAM,iBAAiB,GAAa;YAClC,OAAO,EAAE,4CAAyB;YAClC,4EAA4E;YAC5E,mFAAmF;YACnF,iFAAiF;YACjF,8EAA8E;YAC9E,gFAAgF;YAChF,UAAU,EAAE,CAAC,IAAyB,EAAkC,EAAE,CACxE,wBAAwB,CAAC;gBACvB,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjF,CAAC;YACJ,MAAM,EAAE,CAAC,YAAY,CAAC;SACvB,CAAC;QAEF,2EAA2E;QAC3E,wEAAwE;QACxE,kEAAkE;QAClE,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI;YAC7B,CAAC,CAAC,2BAAU,CAAC,OAAO;YAChB,8DAA8D;YAC9D,0EAA0E;YAC1E,2EAA2E;YAC3E,iEAAiE;YACjE;gBACE,GAAG,CAAC,OAAO,CAAC,kBAAkB;oBAC5B,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,EAAE;oBACpD,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,OAAO,CAAC,eAAe;oBACzB,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE;oBAC9C,CAAC,CAAC,EAAE,CAAC;gBACP,uEAAuE;gBACvE,mDAAmD;gBACnD,uEAAuE;gBACvE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnF,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChF,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1E,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9D,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,GAAG,CAAC,OAAO,CAAC,qBAAqB;oBAC/B,CAAC,CAAC,EAAE,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,EAAE;oBAC1D,CAAC,CAAC,EAAE,CAAC;aACR,CACF;YACH,CAAC,CAAC,SAAS,CAAC;QACd,OAAO;YACL,MAAM,EAAE,cAAY;YACpB,2EAA2E;YAC3E,6EAA6E;YAC7E,4EAA4E;YAC5E,+BAA+B;YAC/B,OAAO,EAAE;gBACP,yCAAiB;gBACjB,2BAAU;gBACV,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnC,GAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAa;aACxC;YACD,SAAS,EAAE,CAAC,oBAAoB,EAAE,cAAc,EAAE,iBAAiB,CAAC;YACpE,OAAO,EAAE;gBACP,6BAAU;gBACV,4CAAyB;gBACzB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACpC;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAlLY,oCAAY;uBAAZ,YAAY;IAFxB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,YAAY,CAkLxB"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Request-principal resolution — extract the bearer access token from an HTTP
3
+ * request and resolve it (via the {@link SessionTokenBinder}) to a `Principal`,
4
+ * fail-closed. This is the request-auth read path the enforcement guard uses for
5
+ * `@Classified` routes before calling `decide()`.
6
+ *
7
+ * The `Principal` is rebuilt from the bound claims. We deliberately do NOT re-run
8
+ * the Core identity broker here (which would apply the root allowlist and could
9
+ * mint a root from an id) — instead we reconstruct a plain, non-root
10
+ * Principal from the exact claims captured at login. `isRoot` is set to
11
+ * `false` on the request path unless the binding explicitly recorded it (it is
12
+ * captured from the login-time Principal, so a genuinely-root login stays
13
+ * root; a normal login can never become one on a later request).
14
+ */
15
+ import type { Principal } from '@astram/core';
16
+ import type { SessionTokenBinder, BoundPrincipalClaims } from './session-token-binder.js';
17
+ /** Extract a bearer token from an `Authorization: Bearer <token>` header. */
18
+ export declare function extractBearerToken(authorizationHeader: unknown): string | null;
19
+ /**
20
+ * Rebuild a `Principal` from bound claims (validated). `isRoot` is read
21
+ * from the binding (captured at login), NEVER inferred — a normal user cannot become
22
+ * a root on the request path.
23
+ */
24
+ export declare function principalFromClaims(claims: BoundPrincipalClaims): Principal | null;
25
+ /**
26
+ * Resolve an HTTP request's bearer token to a `Principal`, or `null` (fail-closed)
27
+ * when there is no token, no binding, or the binding is malformed.
28
+ */
29
+ export declare function resolveRequestPrincipal(authorizationHeader: unknown, binder: SessionTokenBinder): Promise<Principal | null>;
30
+ /**
31
+ * Resolve an HTTP request's bearer token to BOTH a `Principal` AND the raw
32
+ * {@link BoundPrincipalClaims}, or `null` (fail-closed) — the same read path as
33
+ * {@link resolveRequestPrincipal}, but it also surfaces the claims the `Principal`
34
+ * projection drops (notably `mustReenroll` and `sessionId`). The enforcement guard
35
+ * uses this so it can read `claims.mustReenroll` to apply the enforced-re-enroll gate
36
+ * while still attaching the resolved `Principal` for `decide()`.
37
+ */
38
+ export declare function resolveRequestAuth(authorizationHeader: unknown, binder: SessionTokenBinder): Promise<{
39
+ principal: Principal;
40
+ claims: BoundPrincipalClaims;
41
+ } | null>;
42
+ //# sourceMappingURL=request-principal.d.ts.map
@@ -0,0 +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"}