@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.
- package/dist/auth/account.controller.d.ts +245 -0
- package/dist/auth/account.controller.d.ts.map +1 -0
- package/dist/auth/account.controller.js +673 -0
- package/dist/auth/account.controller.js.map +1 -0
- package/dist/auth/auth.controller.d.ts +316 -0
- package/dist/auth/auth.controller.d.ts.map +1 -0
- package/dist/auth/auth.controller.js +1091 -0
- package/dist/auth/auth.controller.js.map +1 -0
- package/dist/auth/auth.module.d.ts +202 -0
- package/dist/auth/auth.module.d.ts.map +1 -0
- package/dist/auth/auth.module.js +610 -0
- package/dist/auth/auth.module.js.map +1 -0
- package/dist/auth/connections.d.ts +61 -0
- package/dist/auth/connections.d.ts.map +1 -0
- package/dist/auth/connections.js +116 -0
- package/dist/auth/connections.js.map +1 -0
- package/dist/auth/dto.d.ts +154 -0
- package/dist/auth/dto.d.ts.map +1 -0
- package/dist/auth/dto.js +29 -0
- package/dist/auth/dto.js.map +1 -0
- package/dist/auth/pending-mfa-store.d.ts +72 -0
- package/dist/auth/pending-mfa-store.d.ts.map +1 -0
- package/dist/auth/pending-mfa-store.js +106 -0
- package/dist/auth/pending-mfa-store.js.map +1 -0
- package/dist/auth/persistence.module.d.ts +42 -0
- package/dist/auth/persistence.module.d.ts.map +1 -0
- package/dist/auth/persistence.module.js +94 -0
- package/dist/auth/persistence.module.js.map +1 -0
- package/dist/auth/ports/audit-sink.d.ts +47 -0
- package/dist/auth/ports/audit-sink.d.ts.map +1 -0
- package/dist/auth/ports/audit-sink.js +20 -0
- package/dist/auth/ports/audit-sink.js.map +1 -0
- package/dist/auth/ports/credential-writer.d.ts +23 -0
- package/dist/auth/ports/credential-writer.d.ts.map +1 -0
- package/dist/auth/ports/credential-writer.js +2 -0
- package/dist/auth/ports/credential-writer.js.map +1 -0
- package/dist/auth/ports/email-sender.d.ts +14 -0
- package/dist/auth/ports/email-sender.d.ts.map +1 -0
- package/dist/auth/ports/email-sender.js +2 -0
- package/dist/auth/ports/email-sender.js.map +1 -0
- package/dist/auth/ports/mfa-device-store.d.ts +45 -0
- package/dist/auth/ports/mfa-device-store.d.ts.map +1 -0
- package/dist/auth/ports/mfa-device-store.js +13 -0
- package/dist/auth/ports/mfa-device-store.js.map +1 -0
- package/dist/auth/ports/profile-writer.d.ts +12 -0
- package/dist/auth/ports/profile-writer.d.ts.map +1 -0
- package/dist/auth/ports/profile-writer.js +2 -0
- package/dist/auth/ports/profile-writer.js.map +1 -0
- package/dist/auth/ports/recovery-code-store.d.ts +10 -0
- package/dist/auth/ports/recovery-code-store.d.ts.map +1 -0
- package/dist/auth/ports/recovery-code-store.js +2 -0
- package/dist/auth/ports/recovery-code-store.js.map +1 -0
- package/dist/auth/ports/reset-token-store.d.ts +12 -0
- package/dist/auth/ports/reset-token-store.d.ts.map +1 -0
- package/dist/auth/ports/reset-token-store.js +2 -0
- package/dist/auth/ports/reset-token-store.js.map +1 -0
- package/dist/auth/ports/session-facts-projector.d.ts +44 -0
- package/dist/auth/ports/session-facts-projector.d.ts.map +1 -0
- package/dist/auth/ports/session-facts-projector.js +30 -0
- package/dist/auth/ports/session-facts-projector.js.map +1 -0
- package/dist/auth/ports/session-sweeper.d.ts +12 -0
- package/dist/auth/ports/session-sweeper.d.ts.map +1 -0
- package/dist/auth/ports/session-sweeper.js +2 -0
- package/dist/auth/ports/session-sweeper.js.map +1 -0
- package/dist/auth/profile-resolver.d.ts +73 -0
- package/dist/auth/profile-resolver.d.ts.map +1 -0
- package/dist/auth/profile-resolver.js +28 -0
- package/dist/auth/profile-resolver.js.map +1 -0
- package/dist/auth/rate-limit/attempt-limiter.d.ts +91 -0
- package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -0
- package/dist/auth/rate-limit/attempt-limiter.js +133 -0
- package/dist/auth/rate-limit/attempt-limiter.js.map +1 -0
- package/dist/auth/tokens.d.ts +236 -0
- package/dist/auth/tokens.d.ts.map +1 -0
- package/dist/auth/tokens.js +254 -0
- package/dist/auth/tokens.js.map +1 -0
- package/dist/auth/totp-enrollment.d.ts +42 -0
- package/dist/auth/totp-enrollment.d.ts.map +1 -0
- package/dist/auth/totp-enrollment.js +96 -0
- package/dist/auth/totp-enrollment.js.map +1 -0
- package/dist/authentication/argon2id-password-hasher.js.map +1 -0
- package/dist/authentication/mariadb-credential-resolver.d.ts +110 -0
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -0
- package/dist/authentication/mariadb-credential-resolver.js +170 -0
- package/dist/authentication/mariadb-credential-resolver.js.map +1 -0
- package/dist/authz/cross-tenant-grant-writer.d.ts +259 -0
- package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -0
- package/dist/authz/cross-tenant-grant-writer.js +397 -0
- package/dist/authz/cross-tenant-grant-writer.js.map +1 -0
- package/dist/authz/manifest-operation-authority-adapter.d.ts +65 -0
- package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -0
- package/dist/authz/manifest-operation-authority-adapter.js +108 -0
- package/dist/authz/manifest-operation-authority-adapter.js.map +1 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts +90 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js +211 -0
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +1 -0
- package/dist/authz/mariadb-record-rule-adapter.d.ts +60 -0
- package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -0
- package/dist/authz/mariadb-record-rule-adapter.js +154 -0
- package/dist/authz/mariadb-record-rule-adapter.js.map +1 -0
- package/dist/authz/mariadb-record-share-adapter.d.ts +75 -0
- package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -0
- package/dist/authz/mariadb-record-share-adapter.js +106 -0
- package/dist/authz/mariadb-record-share-adapter.js.map +1 -0
- package/dist/authz/record-share-cascade.d.ts +52 -0
- package/dist/authz/record-share-cascade.d.ts.map +1 -0
- package/dist/authz/record-share-cascade.js +49 -0
- package/dist/authz/record-share-cascade.js.map +1 -0
- package/dist/authz/record-share-writer.d.ts +175 -0
- package/dist/authz/record-share-writer.d.ts.map +1 -0
- package/dist/authz/record-share-writer.js +225 -0
- package/dist/authz/record-share-writer.js.map +1 -0
- package/dist/authz/wire-record-authorization.d.ts +66 -0
- package/dist/authz/wire-record-authorization.d.ts.map +1 -0
- package/dist/authz/wire-record-authorization.js +34 -0
- package/dist/authz/wire-record-authorization.js.map +1 -0
- package/dist/boot/boot-sequence.js.map +1 -0
- package/dist/boot/boot.module.js.map +1 -0
- package/dist/completeness/catalog-reconciler.d.ts +21 -0
- package/dist/completeness/catalog-reconciler.d.ts.map +1 -0
- package/dist/completeness/catalog-reconciler.js +74 -0
- package/dist/completeness/catalog-reconciler.js.map +1 -0
- package/dist/completeness/operation-inventory-scanner.d.ts +17 -0
- package/dist/completeness/operation-inventory-scanner.d.ts.map +1 -0
- package/dist/completeness/operation-inventory-scanner.js +79 -0
- package/dist/completeness/operation-inventory-scanner.js.map +1 -0
- package/dist/completeness/ports/catalog-store.d.ts +33 -0
- package/dist/completeness/ports/catalog-store.d.ts.map +1 -0
- package/dist/completeness/ports/catalog-store.js +2 -0
- package/dist/completeness/ports/catalog-store.js.map +1 -0
- package/dist/config/app-config.d.ts +134 -1
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js +144 -2
- package/dist/config/app-config.js.map +1 -0
- package/dist/config/config.module.js.map +1 -0
- package/dist/enforcement/classification.decorator.d.ts +33 -14
- package/dist/enforcement/classification.decorator.d.ts.map +1 -1
- package/dist/enforcement/classification.decorator.js +34 -14
- package/dist/enforcement/classification.decorator.js.map +1 -0
- package/dist/enforcement/core-seam.js.map +1 -0
- package/dist/enforcement/enforcement.module.js.map +1 -0
- package/dist/enforcement/global-enforcement.guard.d.ts +29 -19
- package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
- package/dist/enforcement/global-enforcement.guard.js +108 -25
- package/dist/enforcement/global-enforcement.guard.js.map +1 -0
- package/dist/enforcement/reenroll-allowlist.d.ts +49 -0
- package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -0
- package/dist/enforcement/reenroll-allowlist.js +77 -0
- package/dist/enforcement/reenroll-allowlist.js.map +1 -0
- package/dist/index.d.ts +43 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +198 -1
- package/dist/index.js.map +1 -0
- package/dist/module/shield-tokens.d.ts +15 -0
- package/dist/module/shield-tokens.d.ts.map +1 -0
- package/dist/module/shield-tokens.js +17 -0
- package/dist/module/shield-tokens.js.map +1 -0
- package/dist/module/shield.module.d.ts +203 -8
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +232 -14
- package/dist/module/shield.module.js.map +1 -0
- package/dist/request-auth/request-principal.d.ts +42 -0
- package/dist/request-auth/request-principal.d.ts.map +1 -0
- package/dist/request-auth/request-principal.js +87 -0
- package/dist/request-auth/request-principal.js.map +1 -0
- package/dist/request-auth/session-facts-als.d.ts +65 -0
- package/dist/request-auth/session-facts-als.d.ts.map +1 -0
- package/dist/request-auth/session-facts-als.js +57 -0
- package/dist/request-auth/session-facts-als.js.map +1 -0
- package/dist/request-auth/session-token-binder.d.ts +130 -0
- package/dist/request-auth/session-token-binder.d.ts.map +1 -0
- package/dist/request-auth/session-token-binder.js +277 -0
- package/dist/request-auth/session-token-binder.js.map +1 -0
- package/dist/request-auth/tokens.d.ts +14 -0
- package/dist/request-auth/tokens.d.ts.map +1 -0
- package/dist/request-auth/tokens.js +16 -0
- package/dist/request-auth/tokens.js.map +1 -0
- package/dist/session/crypto-adapters.js.map +1 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/mariadb-session-record-store.js.map +1 -0
- package/dist/session/redis-hot-session-store.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `AuthModule` — the Phase 0b **composition seam** that assembles the core auth
|
|
4
|
+
* engines from guard's adapters + the live connections, and exposes them under
|
|
5
|
+
* {@link SHIELD_AUTHENTICATOR} / {@link SHIELD_SESSION_AUTHORITY} for Team C's
|
|
6
|
+
* `/auth/*` controllers (spec §4).
|
|
7
|
+
*
|
|
8
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
* Team B (connection + composition) OWNS this file. It wires the frozen tokens to
|
|
10
|
+
* the real engines:
|
|
11
|
+
*
|
|
12
|
+
* SHIELD_PASSWORD_HASHER → new Argon2idPasswordHasher() (the flagged fix —
|
|
13
|
+
* the authenticator factory injects it, so THIS module must provide it).
|
|
14
|
+
* SHIELD_CREDENTIAL_RESOLVER → new MariaDbCredentialResolver(pool) (Team A's
|
|
15
|
+
* class; its `resolve()` body is Team A's — until then it throws not-implemented,
|
|
16
|
+
* which the engine treats as fail-closed `authentication_unavailable`).
|
|
17
|
+
* SHIELD_SESSION_RECORD_STORE → new MariaDbSessionRecordStore(pool).
|
|
18
|
+
* SHIELD_HOT_SESSION_STORE → new RedisHotSessionStore(redis).
|
|
19
|
+
* SHIELD_TOKEN_GENERATOR → new CryptoTokenGenerator().
|
|
20
|
+
* SHIELD_CLOCK → new SystemClock().
|
|
21
|
+
* SHIELD_REFRESH_HASHER → new Sha256RefreshTokenHasher(
|
|
22
|
+
* assertRefreshHmacKey(config.refreshHmacKey)) ⛔ FAIL-CLOSED gate:
|
|
23
|
+
* `assertRefreshHmacKey` THROWS on a blank key, so auth can NEVER compose with
|
|
24
|
+
* an unkeyed refresh-token hasher. This is the boot-time fail-closed point for
|
|
25
|
+
* the required secret (loadAppConfig deliberately does NOT throw, so a
|
|
26
|
+
* non-auth scaffold still boots with no `.env` — see app-config.ts).
|
|
27
|
+
*
|
|
28
|
+
* SHIELD_SESSION_AUTHORITY → createSessionAuthority({ recordStore, hotStore,
|
|
29
|
+
* tokenGenerator, refreshHasher, clock, lifetimes: config.lifetimes }).
|
|
30
|
+
* `createSessionAuthority` validates lifetime bounds eagerly (throws LOUD on a
|
|
31
|
+
* nonsensical config — construction-time, correct).
|
|
32
|
+
*
|
|
33
|
+
* SHIELD_AUTHENTICATOR → createAuthenticator({ hasher, resolver,
|
|
34
|
+
* identityBroker: createIdentityBroker(), // default Internal, empty
|
|
35
|
+
* factorVerifiers: [ createTotpFactorVerifier({ hmacSha1 }) ] }). The TOTP
|
|
36
|
+
* verifier is wired so MFA works; `hmacSha1` is the {@link hmacSha1} node:crypto
|
|
37
|
+
* one-liner (guard owns node:crypto, core does not). `createIdentityBroker()`
|
|
38
|
+
* with no args registers the default Internal adapter with an EMPTY root
|
|
39
|
+
* allowlist (default-deny).
|
|
40
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
*
|
|
42
|
+
* ⛔ OPT-IN (how the integration owner gates this — for the no-`.env` boot):
|
|
43
|
+
* AuthModule opens live connections (via PersistenceModule) and fires the
|
|
44
|
+
* fail-closed `assertRefreshHmacKey` gate the moment it composes. So it MUST be
|
|
45
|
+
* imported ONLY when a deployment wants auth. `ShieldModule.forRoot(options)`
|
|
46
|
+
* should conditionally add `AuthModule.forRoot()` to its `imports` gated behind an
|
|
47
|
+
* option (e.g. `ShieldModule.forRoot({ auth: true })`) or an env flag:
|
|
48
|
+
*
|
|
49
|
+
* imports: [
|
|
50
|
+
* EnforcementModule, BootModule,
|
|
51
|
+
* ...(options?.auth ? [AuthModule.forRoot()] : []), // ← opt-in
|
|
52
|
+
* ],
|
|
53
|
+
* exports: [APP_CONFIG, SHIELD_DECISION_AUTHORITY,
|
|
54
|
+
* ...(options?.auth ? [SHIELD_AUTHENTICATOR, SHIELD_SESSION_AUTHORITY] : [])],
|
|
55
|
+
*
|
|
56
|
+
* An enforcement-only app that does NOT opt in never imports AuthModule → never
|
|
57
|
+
* opens a pool/redis → never calls `assertRefreshHmacKey` → keeps the no-`.env`
|
|
58
|
+
* boot. An auth-enabled app fails LOUD at boot if `SHIELD_REFRESH_HMAC_KEY` is
|
|
59
|
+
* blank — auth can never compose unkeyed. `APP_CONFIG` is already `@Global` from
|
|
60
|
+
* `ShieldModule`, so AuthModule's config-injecting factories resolve. See DONE.md.
|
|
61
|
+
*
|
|
62
|
+
* ADR-0003: the core factories (`createAuthenticator`/`createSessionAuthority`/
|
|
63
|
+
* `createIdentityBroker`/`createTotpFactorVerifier`) are pure; the adapters + the
|
|
64
|
+
* node:crypto HMAC live in guard. Core stays zero-dep + unchanged.
|
|
65
|
+
*/
|
|
66
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
67
|
+
if (k2 === undefined) k2 = k;
|
|
68
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
69
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
70
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
71
|
+
}
|
|
72
|
+
Object.defineProperty(o, k2, desc);
|
|
73
|
+
}) : (function(o, m, k, k2) {
|
|
74
|
+
if (k2 === undefined) k2 = k;
|
|
75
|
+
o[k2] = m[k];
|
|
76
|
+
}));
|
|
77
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
78
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
79
|
+
}) : function(o, v) {
|
|
80
|
+
o["default"] = v;
|
|
81
|
+
});
|
|
82
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
83
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
84
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
85
|
+
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;
|
|
86
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
87
|
+
};
|
|
88
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
89
|
+
var ownKeys = function(o) {
|
|
90
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
91
|
+
var ar = [];
|
|
92
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
93
|
+
return ar;
|
|
94
|
+
};
|
|
95
|
+
return ownKeys(o);
|
|
96
|
+
};
|
|
97
|
+
return function (mod) {
|
|
98
|
+
if (mod && mod.__esModule) return mod;
|
|
99
|
+
var result = {};
|
|
100
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
101
|
+
__setModuleDefault(result, mod);
|
|
102
|
+
return result;
|
|
103
|
+
};
|
|
104
|
+
})();
|
|
105
|
+
var AuthModule_1;
|
|
106
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
107
|
+
exports.AuthModule = exports.hmacSha1 = void 0;
|
|
108
|
+
exports.resolveTotpVerifier = resolveTotpVerifier;
|
|
109
|
+
exports.makeDefaultTotpVerifier = makeDefaultTotpVerifier;
|
|
110
|
+
const common_1 = require("@nestjs/common");
|
|
111
|
+
const node_crypto_1 = require("node:crypto");
|
|
112
|
+
const app_config_js_1 = require("../config/app-config.js");
|
|
113
|
+
const config_module_js_1 = require("../config/config.module.js");
|
|
114
|
+
const argon2id_password_hasher_js_1 = require("../authentication/argon2id-password-hasher.js");
|
|
115
|
+
const mariadb_credential_resolver_js_1 = require("../authentication/mariadb-credential-resolver.js");
|
|
116
|
+
const index_js_1 = require("../session/index.js");
|
|
117
|
+
const persistence_module_js_1 = require("./persistence.module.js");
|
|
118
|
+
const auth_controller_js_1 = require("./auth.controller.js");
|
|
119
|
+
const account_controller_js_1 = require("./account.controller.js");
|
|
120
|
+
const pending_mfa_store_js_1 = require("./pending-mfa-store.js");
|
|
121
|
+
const tokens_js_1 = require("./tokens.js");
|
|
122
|
+
const attempt_limiter_js_1 = require("./rate-limit/attempt-limiter.js");
|
|
123
|
+
const tokens_js_2 = require("../request-auth/tokens.js");
|
|
124
|
+
const session_token_binder_js_1 = require("../request-auth/session-token-binder.js");
|
|
125
|
+
/**
|
|
126
|
+
* The injected HMAC-SHA1 primitive the core TOTP verifier needs (Core is zero-dep
|
|
127
|
+
* + node-type-free, so it cannot import `node:crypto`). Guard owns node:crypto and
|
|
128
|
+
* supplies this one-liner: raw key bytes + message bytes → the 20-byte HMAC-SHA1
|
|
129
|
+
* digest. Never logs the key or message.
|
|
130
|
+
*/
|
|
131
|
+
const hmacSha1 = (key, message) => new Uint8Array((0, node_crypto_1.createHmac)('sha1', Buffer.from(key)).update(Buffer.from(message)).digest());
|
|
132
|
+
exports.hmacSha1 = hmacSha1;
|
|
133
|
+
/**
|
|
134
|
+
* Resolve the login `totp` {@link FactorVerifier}: the consumer's `override` when
|
|
135
|
+
* supplied, else the framework's `defaultVerifier`. A pure, infra-free `??` — the
|
|
136
|
+
* ONE decision point of the Phase-2 verifier seam (override wins; absent → the
|
|
137
|
+
* default RFC-6238 single-secret verify, behavior unchanged).
|
|
138
|
+
*
|
|
139
|
+
* The default is passed IN (rather than built here) because the core factory
|
|
140
|
+
* `createTotpFactorVerifier` is loaded LAZILY via {@link loadCore} (the CJS↔ESM
|
|
141
|
+
* invariant, see the file header) — only reachable inside an async provider factory.
|
|
142
|
+
* So the authenticator's async `useFactory` awaits {@link loadCore}, builds the
|
|
143
|
+
* default, and hands it here alongside the injected override.
|
|
144
|
+
*/
|
|
145
|
+
function resolveTotpVerifier(override, defaultVerifier) {
|
|
146
|
+
return override ?? defaultVerifier;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build the framework's DEFAULT single-secret TOTP {@link FactorVerifier}
|
|
150
|
+
* (`createTotpFactorVerifier({ hmacSha1 })`), loading the core factory lazily (the
|
|
151
|
+
* CJS↔ESM invariant, see the file header). Exported so a CONSUMER can obtain the
|
|
152
|
+
* framework's base per-secret verifier to WRAP (e.g. an OR-matching multi-device
|
|
153
|
+
* verifier delegates to it per device secret) WITHOUT importing `@astram/core`
|
|
154
|
+
* directly — which would become a runtime `require` on the ESM-only core in the
|
|
155
|
+
* consumer's built CJS dist. Async because of {@link loadCore}.
|
|
156
|
+
*/
|
|
157
|
+
async function makeDefaultTotpVerifier() {
|
|
158
|
+
const { createTotpFactorVerifier } = await loadCore();
|
|
159
|
+
return createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 });
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A `Function`-wrapped dynamic `import()` that survives the CommonJS **build**.
|
|
163
|
+
* Under `module: commonjs`, `tsc` rewrites a literal `import()` into
|
|
164
|
+
* `Promise.resolve().then(() => require(...))` — which fails on the ESM-only core.
|
|
165
|
+
* Routing the import through the `Function` constructor hides it from that
|
|
166
|
+
* transform, so the emitted dist keeps a genuine native `import()` and Node's
|
|
167
|
+
* CJS→ESM interop loads core at runtime. (This path is used by the BUILT dist —
|
|
168
|
+
* e.g. example-backend. It does NOT work under vitest, whose sandbox can't resolve
|
|
169
|
+
* a specifier from an eval'd context — hence the two-strategy loadCore() below.)
|
|
170
|
+
*/
|
|
171
|
+
const evalImport = new Function('specifier', 'return import(specifier);');
|
|
172
|
+
let cachedCore;
|
|
173
|
+
/**
|
|
174
|
+
* Lazily load `@astram/core`'s four auth factory functions — invoked ONLY inside
|
|
175
|
+
* the two async provider factories (i.e. only when `forRoot()` actually composes
|
|
176
|
+
* auth), NEVER at module top-level. This keeps a runtime `require('@astram/core')`
|
|
177
|
+
* out of the guard barrel's load path (see the top-of-file note), so importing
|
|
178
|
+
* `@astram/guard`'s built dist for the enforcement-only path does not touch core.
|
|
179
|
+
*
|
|
180
|
+
* TWO strategies, so it works in BOTH runtimes:
|
|
181
|
+
* 1. A plain dynamic `import('@astram/core')` — the vitest/SWC source path keeps
|
|
182
|
+
* this native, and vitest's resolver maps the workspace package. (In the
|
|
183
|
+
* tsc-built CJS dist this literal is downleveled to a `require`, which throws on
|
|
184
|
+
* the ESM core — caught below.)
|
|
185
|
+
* 2. On failure, the {@link evalImport} `Function`-wrapped native `import()` — the
|
|
186
|
+
* BUILT dist path (Node CJS→ESM interop), which vitest can't use.
|
|
187
|
+
* Cached after the first success.
|
|
188
|
+
*/
|
|
189
|
+
async function loadCore() {
|
|
190
|
+
if (cachedCore !== undefined)
|
|
191
|
+
return cachedCore;
|
|
192
|
+
try {
|
|
193
|
+
// Strategy 1 — native in vitest/SWC; a `require` (that may throw) in the CJS dist.
|
|
194
|
+
cachedCore = (await Promise.resolve().then(() => __importStar(require('@astram/core'))));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Strategy 2 — the built-dist path: a genuine `import()` via the Function shim.
|
|
198
|
+
cachedCore = (await evalImport('@astram/core'));
|
|
199
|
+
}
|
|
200
|
+
return cachedCore;
|
|
201
|
+
}
|
|
202
|
+
// --- Adapter-backed providers (Team A resolver + session adapters) ----------
|
|
203
|
+
/** Argon2id password hasher (⛔ the flagged fix — provide it HERE so the authenticator factory's `inject` resolves). */
|
|
204
|
+
const passwordHasherProvider = {
|
|
205
|
+
provide: argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER,
|
|
206
|
+
useFactory: () => new argon2id_password_hasher_js_1.Argon2idPasswordHasher(),
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Credential resolver (the store login checks against).
|
|
210
|
+
*
|
|
211
|
+
* DEFAULT (no consumer override): a `useFactory` that constructs the framework's
|
|
212
|
+
* {@link MariaDbCredentialResolver} injected with the live {@link SHIELD_DB_POOL}
|
|
213
|
+
* — the historical binding, unchanged.
|
|
214
|
+
*
|
|
215
|
+
* OVERRIDE (Phase 1a seam): when the consumer supplies a `credentialResolver`
|
|
216
|
+
* through {@link ShieldModuleOptions.credentialResolver} → {@link AuthModule.forRoot},
|
|
217
|
+
* the token instead binds a plain **value provider** to that instance, so login
|
|
218
|
+
* authenticates against the consumer's OWN store (e.g. a richer users/roles model)
|
|
219
|
+
* WITHOUT editing the framework. The seam swaps the STORE only — the supplied
|
|
220
|
+
* resolver still flows through the SAME composed authenticator (anti-enumeration
|
|
221
|
+
* decoy verify, MFA, no-secret-leak); its `null`/throw contract is unchanged.
|
|
222
|
+
*/
|
|
223
|
+
function makeCredentialResolverProvider(override) {
|
|
224
|
+
return override
|
|
225
|
+
? { provide: tokens_js_1.SHIELD_CREDENTIAL_RESOLVER, useValue: override }
|
|
226
|
+
: {
|
|
227
|
+
provide: tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
|
|
228
|
+
useFactory: (pool) => new mariadb_credential_resolver_js_1.MariaDbCredentialResolver(pool),
|
|
229
|
+
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/** Durable session record store (MariaDB adapter, injected with the live pool). */
|
|
233
|
+
const sessionRecordStoreProvider = {
|
|
234
|
+
provide: index_js_1.SHIELD_SESSION_RECORD_STORE,
|
|
235
|
+
useFactory: (pool) => new index_js_1.MariaDbSessionRecordStore(pool),
|
|
236
|
+
inject: [tokens_js_1.SHIELD_DB_POOL],
|
|
237
|
+
};
|
|
238
|
+
/** Hot session store (Redis adapter, injected with the live client). */
|
|
239
|
+
const hotSessionStoreProvider = {
|
|
240
|
+
provide: index_js_1.SHIELD_HOT_SESSION_STORE,
|
|
241
|
+
useFactory: (redis) => new index_js_1.RedisHotSessionStore(redis),
|
|
242
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* The request-auth token binder (the flagged-gap fill): binds an opaque access token
|
|
246
|
+
* to its principal claims in Redis, so the enforcement guard can turn a later
|
|
247
|
+
* request's bearer token back into a `Principal`. Provided only under `auth: true`
|
|
248
|
+
* (it needs the live Redis client); exported so the enforcement guard injects it.
|
|
249
|
+
*/
|
|
250
|
+
const sessionTokenBinderProvider = {
|
|
251
|
+
provide: tokens_js_2.SHIELD_SESSION_TOKEN_BINDER,
|
|
252
|
+
useFactory: (redis) => new session_token_binder_js_1.SessionTokenBinder(redis),
|
|
253
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* The password-login rate limiter (spec §5 / H1) — a Redis-injected
|
|
257
|
+
* {@link AttemptLimiter}, 10 failures / 15-min window, keyed `login:<hint>`. Same
|
|
258
|
+
* live-Redis provider pattern as {@link sessionTokenBinderProvider} (a `useFactory`
|
|
259
|
+
* injecting {@link SHIELD_REDIS}); provided only under `auth: true`. Fail-open on a
|
|
260
|
+
* Redis outage is the limiter's own behavior (never locks out on a blip).
|
|
261
|
+
*/
|
|
262
|
+
const loginLimiterProvider = {
|
|
263
|
+
provide: tokens_js_1.SHIELD_LOGIN_LIMITER,
|
|
264
|
+
useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 10, windowMs: 15 * 60 * 1000 }),
|
|
265
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* The recovery-code rate limiter (spec §5) — a Redis-injected {@link AttemptLimiter},
|
|
269
|
+
* 5 failures / 15-min window, keyed `recovery:<principalId>` (a lower ceiling than
|
|
270
|
+
* login: recovery codes don't rotate, so they're higher-value). Same live-Redis
|
|
271
|
+
* provider pattern as {@link sessionTokenBinderProvider}; provided only under
|
|
272
|
+
* `auth: true`.
|
|
273
|
+
*/
|
|
274
|
+
const recoveryLimiterProvider = {
|
|
275
|
+
provide: tokens_js_1.SHIELD_RECOVERY_LIMITER,
|
|
276
|
+
useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 5, windowMs: 15 * 60 * 1000 }),
|
|
277
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* The forgot-password rate limiter (feature #141) — a Redis-injected
|
|
281
|
+
* {@link AttemptLimiter}, keyed BY CLIENT IP (`forgot:ip:<ip>`, 5 per 15-min window)
|
|
282
|
+
* AND, separately, per-hint (`forgot:<hint>`, provided as {@link forgotHintLimiterProvider}).
|
|
283
|
+
* NOTE the "attempt" semantics here differ from login: forgot-password is ALWAYS 204
|
|
284
|
+
* (returning 429 would itself be an enumeration signal), so this limiter counts every
|
|
285
|
+
* forgot REQUEST (a request-rate cap), and once the budget is exceeded the handler
|
|
286
|
+
* SILENTLY skips the email-send work while still returning 204. Same live-Redis
|
|
287
|
+
* provider pattern as {@link loginLimiterProvider}; provided only under `auth: true`.
|
|
288
|
+
* Fail-open on a Redis outage is the limiter's own behavior (never silently drops a
|
|
289
|
+
* legitimate reset email on a blip). Threshold chosen to stop IP-spray without locking
|
|
290
|
+
* out a genuine user who requests a couple of resets.
|
|
291
|
+
*/
|
|
292
|
+
const forgotLimiterProvider = {
|
|
293
|
+
provide: tokens_js_1.SHIELD_FORGOT_LIMITER,
|
|
294
|
+
useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 5, windowMs: 15 * 60 * 1000 }),
|
|
295
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
296
|
+
};
|
|
297
|
+
/**
|
|
298
|
+
* The forgot-password PER-HINT rate limiter (feature #141) — a Redis-injected
|
|
299
|
+
* {@link AttemptLimiter}, keyed by the presented hint (`forgot:<hint>`, 3 per 60-min
|
|
300
|
+
* window). This caps how often ANY caller (across IPs) can trigger a reset email for
|
|
301
|
+
* ONE account, so a single victim's inbox can't be email-bombed even from a rotating
|
|
302
|
+
* IP pool. A GENEROUS per-hint ceiling (a real user rarely needs >3 reset emails/hour)
|
|
303
|
+
* with a longer window than the IP cap. Same request-rate-cap semantics as
|
|
304
|
+
* {@link forgotLimiterProvider}: on exceed, SILENTLY skip the send, still 204.
|
|
305
|
+
*/
|
|
306
|
+
const forgotHintLimiterProvider = {
|
|
307
|
+
provide: tokens_js_1.SHIELD_FORGOT_HINT_LIMITER,
|
|
308
|
+
useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 3, windowMs: 60 * 60 * 1000 }),
|
|
309
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* The reset-password rate limiter (feature #141) — a Redis-injected
|
|
313
|
+
* {@link AttemptLimiter}, keyed by CLIENT IP (`reset:ip:<ip>`, 10 per 15-min window).
|
|
314
|
+
* Reset is token-gated (a 256-bit single-use token), so this is DoS/abuse throttling,
|
|
315
|
+
* NOT anti-brute-force — and unlike forgot it MAY return a generic 429 on lockout (a
|
|
316
|
+
* token-gated endpoint is not enumeration-sensitive). `recordFailure` on a bad/invalid
|
|
317
|
+
* token (the abuse signal), `reset` on a successful reset. Same live-Redis provider
|
|
318
|
+
* pattern as {@link loginLimiterProvider}; provided only under `auth: true`. Fail-open
|
|
319
|
+
* on a Redis outage (a legitimate reset is never blocked by a blip).
|
|
320
|
+
*/
|
|
321
|
+
const resetLimiterProvider = {
|
|
322
|
+
provide: tokens_js_1.SHIELD_RESET_LIMITER,
|
|
323
|
+
useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 10, windowMs: 15 * 60 * 1000 }),
|
|
324
|
+
inject: [tokens_js_1.SHIELD_REDIS],
|
|
325
|
+
};
|
|
326
|
+
/** Opaque token generator (node:crypto adapter). */
|
|
327
|
+
const tokenGeneratorProvider = {
|
|
328
|
+
provide: index_js_1.SHIELD_TOKEN_GENERATOR,
|
|
329
|
+
useFactory: () => new index_js_1.CryptoTokenGenerator(),
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Keyed refresh hasher (HMAC adapter). ⛔ FAIL-CLOSED HMAC-key gate:
|
|
333
|
+
* `assertRefreshHmacKey` THROWS on a blank key, so auth can never compose with an
|
|
334
|
+
* unkeyed refresh-token hasher.
|
|
335
|
+
*/
|
|
336
|
+
const refreshHasherProvider = {
|
|
337
|
+
provide: index_js_1.SHIELD_REFRESH_HASHER,
|
|
338
|
+
useFactory: (config) => new index_js_1.Sha256RefreshTokenHasher((0, app_config_js_1.assertRefreshHmacKey)(config.refreshHmacKey)),
|
|
339
|
+
inject: [config_module_js_1.APP_CONFIG],
|
|
340
|
+
};
|
|
341
|
+
/** System clock. */
|
|
342
|
+
const clockProvider = {
|
|
343
|
+
provide: index_js_1.SHIELD_CLOCK,
|
|
344
|
+
useFactory: () => new index_js_1.SystemClock(),
|
|
345
|
+
};
|
|
346
|
+
// --- Composed core engines --------------------------------------------------
|
|
347
|
+
/** The composed SessionAuthority (core) — establish / rotate / revoke. */
|
|
348
|
+
const sessionAuthorityProvider = {
|
|
349
|
+
provide: tokens_js_1.SHIELD_SESSION_AUTHORITY,
|
|
350
|
+
// async: loads the core factory lazily (CJS→ESM, see loadCore()); Nest awaits it.
|
|
351
|
+
useFactory: async (recordStore, hotStore, tokenGenerator, refreshHasher, clock, config) => {
|
|
352
|
+
const { createSessionAuthority } = await loadCore();
|
|
353
|
+
return createSessionAuthority({
|
|
354
|
+
recordStore,
|
|
355
|
+
hotStore,
|
|
356
|
+
tokenGenerator,
|
|
357
|
+
refreshHasher,
|
|
358
|
+
clock,
|
|
359
|
+
lifetimes: config.lifetimes,
|
|
360
|
+
});
|
|
361
|
+
},
|
|
362
|
+
inject: [
|
|
363
|
+
index_js_1.SHIELD_SESSION_RECORD_STORE,
|
|
364
|
+
index_js_1.SHIELD_HOT_SESSION_STORE,
|
|
365
|
+
index_js_1.SHIELD_TOKEN_GENERATOR,
|
|
366
|
+
index_js_1.SHIELD_REFRESH_HASHER,
|
|
367
|
+
index_js_1.SHIELD_CLOCK,
|
|
368
|
+
config_module_js_1.APP_CONFIG,
|
|
369
|
+
],
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* The composed Authenticator (core) — password + TOTP factor, anti-enumeration.
|
|
373
|
+
*
|
|
374
|
+
* The `totp` verifier is the Phase-2 SEAM: {@link resolveTotpVerifier} picks the
|
|
375
|
+
* consumer's `totpOverride` (bound under {@link SHIELD_TOTP_VERIFIER_OVERRIDE}) when
|
|
376
|
+
* supplied, else the framework's default `createTotpFactorVerifier({ hmacSha1 })`.
|
|
377
|
+
* The override reaches this async factory via `inject` (not a captured closure) so
|
|
378
|
+
* the default binding stays exactly as before when no override is plugged.
|
|
379
|
+
*/
|
|
380
|
+
const authenticatorProvider = {
|
|
381
|
+
provide: tokens_js_1.SHIELD_AUTHENTICATOR,
|
|
382
|
+
// async: loads the core factories lazily (CJS→ESM, see loadCore()); Nest awaits it.
|
|
383
|
+
useFactory: async (hasher, resolver, totpOverride, rootIds) => {
|
|
384
|
+
const { createAuthenticator, createIdentityBroker, createTotpFactorVerifier } = await loadCore();
|
|
385
|
+
const totp = resolveTotpVerifier(totpOverride, createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 }));
|
|
386
|
+
return createAuthenticator({
|
|
387
|
+
hasher,
|
|
388
|
+
resolver,
|
|
389
|
+
// ROOT SAFETY: the ONLY way a login mints a root is the
|
|
390
|
+
// server-side allowlist wired here (the Internal adapter keys the trusted
|
|
391
|
+
// signal off it, never off a claim). Absent → `[]` → default-deny (the
|
|
392
|
+
// historical `createIdentityBroker()` behavior, exactly unchanged).
|
|
393
|
+
identityBroker: createIdentityBroker({ internalRootIds: rootIds ?? [] }),
|
|
394
|
+
factorVerifiers: [totp],
|
|
395
|
+
});
|
|
396
|
+
},
|
|
397
|
+
inject: [
|
|
398
|
+
argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER,
|
|
399
|
+
tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
|
|
400
|
+
tokens_js_1.SHIELD_TOTP_VERIFIER_OVERRIDE,
|
|
401
|
+
tokens_js_1.SHIELD_ROOT_IDS,
|
|
402
|
+
],
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* Bind the OPTIONAL login `totp` verifier override (the Phase-2 multi-device seam).
|
|
406
|
+
* Same value-provider pattern as the other seams: the supplied verifier when present,
|
|
407
|
+
* else `null` so the authenticator factory's inject resolves to "no override" → the
|
|
408
|
+
* default RFC-6238 verifier. Always provided so the DI token exists.
|
|
409
|
+
*/
|
|
410
|
+
function makeTotpVerifierOverrideProvider(override) {
|
|
411
|
+
return { provide: tokens_js_1.SHIELD_TOTP_VERIFIER_OVERRIDE, useValue: override ?? null };
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Bind the OPTIONAL root allowlist (the {@link SHIELD_ROOT_IDS}
|
|
415
|
+
* seam). Same value-provider pattern as the other seams: the supplied ids when present,
|
|
416
|
+
* else `null` so the authenticator factory's inject resolves to "no allowlist" → the
|
|
417
|
+
* broker's default-deny empty set (nobody is a root — historical behavior). Always
|
|
418
|
+
* provided so the DI token exists. See {@link SHIELD_ROOT_IDS} for the security
|
|
419
|
+
* rationale (the flag is set SOLELY from this trusted list, never from a claim).
|
|
420
|
+
*/
|
|
421
|
+
function makeRootIdsProvider(rootIds) {
|
|
422
|
+
return { provide: tokens_js_1.SHIELD_ROOT_IDS, useValue: rootIds ?? null };
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* The core TOTP {@link FactorVerifier} — the SAME verifier the login MFA branch uses
|
|
426
|
+
* (`createTotpFactorVerifier({ hmacSha1 })`), provided app-wide so
|
|
427
|
+
* `POST /account/mfa/{enroll/confirm,disable}` can verify a presented code against the
|
|
428
|
+
* pending/stored secret. Built via {@link loadCore} (the CJS→ESM lazy load, see the
|
|
429
|
+
* file header) so guard's built CJS dist never eagerly `require`s the ESM-only core.
|
|
430
|
+
* Injected pre-built into {@link AccountController}, which cannot import the core
|
|
431
|
+
* factory at its own top level.
|
|
432
|
+
*/
|
|
433
|
+
const totpVerifierProvider = {
|
|
434
|
+
provide: tokens_js_1.SHIELD_TOTP_VERIFIER,
|
|
435
|
+
useFactory: async () => {
|
|
436
|
+
const { createTotpFactorVerifier } = await loadCore();
|
|
437
|
+
return createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 });
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* Bind the OPTIONAL current-user profile resolver. When the consumer supplies one it
|
|
442
|
+
* is a value provider under {@link SHIELD_PROFILE_RESOLVER}; when absent we bind
|
|
443
|
+
* `null` so the `@Optional()` injection in the controller resolves cleanly to
|
|
444
|
+
* "no seam" (→ `/auth/me` returns 501). Always provided so the DI token exists.
|
|
445
|
+
*/
|
|
446
|
+
function makeProfileResolverProvider(override) {
|
|
447
|
+
return { provide: tokens_js_1.SHIELD_PROFILE_RESOLVER, useValue: override ?? null };
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Bind each OPTIONAL account/credential-surface seam. Same pattern as
|
|
451
|
+
* {@link makeProfileResolverProvider}: a value provider under the seam's token —
|
|
452
|
+
* the supplied impl when present, else `null` so the route's `@Optional()` injection
|
|
453
|
+
* resolves cleanly to "no seam" (→ 501). Always provided so the DI token exists.
|
|
454
|
+
*/
|
|
455
|
+
function makeCredentialWriterProvider(override) {
|
|
456
|
+
return { provide: tokens_js_1.SHIELD_CREDENTIAL_WRITER, useValue: override ?? null };
|
|
457
|
+
}
|
|
458
|
+
function makeResetTokenStoreProvider(override) {
|
|
459
|
+
return { provide: tokens_js_1.SHIELD_RESET_TOKEN_STORE, useValue: override ?? null };
|
|
460
|
+
}
|
|
461
|
+
function makeEmailSenderProvider(override) {
|
|
462
|
+
return { provide: tokens_js_1.SHIELD_EMAIL_SENDER, useValue: override ?? null };
|
|
463
|
+
}
|
|
464
|
+
function makeRecoveryCodeStoreProvider(override) {
|
|
465
|
+
return { provide: tokens_js_1.SHIELD_RECOVERY_CODE_STORE, useValue: override ?? null };
|
|
466
|
+
}
|
|
467
|
+
function makeProfileWriterProvider(override) {
|
|
468
|
+
return { provide: tokens_js_1.SHIELD_PROFILE_WRITER, useValue: override ?? null };
|
|
469
|
+
}
|
|
470
|
+
function makeSessionSweeperProvider(override) {
|
|
471
|
+
return { provide: tokens_js_1.SHIELD_SESSION_SWEEPER, useValue: override ?? null };
|
|
472
|
+
}
|
|
473
|
+
function makeMfaDeviceStoreProvider(override) {
|
|
474
|
+
return { provide: tokens_js_1.SHIELD_MFA_DEVICE_STORE, useValue: override ?? null };
|
|
475
|
+
}
|
|
476
|
+
function makeAuditSinkProvider(override) {
|
|
477
|
+
return { provide: tokens_js_1.SHIELD_AUDIT_SINK, useValue: override ?? null };
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Bind the OPTIONAL eager session-facts projector (ADR-0011). Same value-provider
|
|
481
|
+
* pattern as the other seams: the supplied impl when present, else `null` so the auth
|
|
482
|
+
* controller's `@Optional()` injection resolves cleanly to "no projector" (→ it omits
|
|
483
|
+
* `cachedFacts` → gate 5 DB-reloads). Always provided so the DI token exists.
|
|
484
|
+
*/
|
|
485
|
+
function makeSessionFactsProjectorProvider(override) {
|
|
486
|
+
return { provide: tokens_js_1.SHIELD_SESSION_FACTS_PROJECTOR, useValue: override ?? null };
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* The reset-link base URL the forgot-password handler builds the emailed link from
|
|
490
|
+
* (`${base}?token=<rawToken>`). A plain string VALUE (not a seam) resolved from the
|
|
491
|
+
* environment (`RESET_LINK_BASE_URL`) with a dev default, so the framework owns the
|
|
492
|
+
* URL composition and {@link SHIELD_EMAIL_SENDER} stays URL-agnostic. Always
|
|
493
|
+
* provided so the `@Optional()` injection resolves.
|
|
494
|
+
*/
|
|
495
|
+
const resetLinkBaseUrlProvider = {
|
|
496
|
+
provide: tokens_js_1.SHIELD_RESET_LINK_BASE_URL,
|
|
497
|
+
useValue: process.env.RESET_LINK_BASE_URL ?? 'http://localhost:5173/reset-password',
|
|
498
|
+
};
|
|
499
|
+
/**
|
|
500
|
+
* The auth composition module. Imports {@link PersistenceModule} (the live
|
|
501
|
+
* connections) and provides the adapters + composed engines. Exports the two
|
|
502
|
+
* engines (Team C consumes them) and the resolver token. Opt-in: imported ONLY by
|
|
503
|
+
* an auth-enabled `ShieldModule.forRoot({ auth: true })` — see the file header +
|
|
504
|
+
* DONE.md for the exact gating the integration owner applies.
|
|
505
|
+
*/
|
|
506
|
+
let AuthModule = AuthModule_1 = class AuthModule {
|
|
507
|
+
/**
|
|
508
|
+
* Compose the auth surface. `options.credentialResolver`, when supplied, REPLACES
|
|
509
|
+
* the default MariaDb store with the consumer's own (a value provider under
|
|
510
|
+
* {@link SHIELD_CREDENTIAL_RESOLVER}); omitted → the historical default binding,
|
|
511
|
+
* EXACTLY unchanged (zero behavior change for existing consumers).
|
|
512
|
+
*/
|
|
513
|
+
static forRoot(options = {}) {
|
|
514
|
+
return {
|
|
515
|
+
module: AuthModule_1,
|
|
516
|
+
imports: [persistence_module_js_1.PersistenceModule.forRoot()],
|
|
517
|
+
// (providers list below adds the profile-resolver seam)
|
|
518
|
+
// Team C's four `@Public()` /auth/* endpoints. Registered here (integration
|
|
519
|
+
// wiring) so the routes exist the moment auth is opted in — the controller
|
|
520
|
+
// injects the two composed engines (below) + PendingMfaStore.
|
|
521
|
+
controllers: [auth_controller_js_1.AuthController, account_controller_js_1.AccountController],
|
|
522
|
+
providers: [
|
|
523
|
+
passwordHasherProvider,
|
|
524
|
+
makeCredentialResolverProvider(options.credentialResolver),
|
|
525
|
+
// The current-user profile seam backing `GET /auth/me` (null when absent).
|
|
526
|
+
makeProfileResolverProvider(options.profileResolver),
|
|
527
|
+
// The account/credential-surface seams (null when absent → route 501).
|
|
528
|
+
makeCredentialWriterProvider(options.credentialWriter),
|
|
529
|
+
makeResetTokenStoreProvider(options.resetTokenStore),
|
|
530
|
+
makeEmailSenderProvider(options.emailSender),
|
|
531
|
+
makeRecoveryCodeStoreProvider(options.recoveryCodeStore),
|
|
532
|
+
makeProfileWriterProvider(options.profileWriter),
|
|
533
|
+
makeSessionSweeperProvider(options.sessionSweeper),
|
|
534
|
+
// The auth-surface audit sink (null when absent → recovery-login audit no-ops).
|
|
535
|
+
makeAuditSinkProvider(options.auditSink),
|
|
536
|
+
// The multi-device MFA store (null when absent → device routes 501).
|
|
537
|
+
makeMfaDeviceStoreProvider(options.mfaDeviceStore),
|
|
538
|
+
// The login totp-verifier override (null when absent → default RFC-6238
|
|
539
|
+
// single-secret verify). Consumed by the authenticator factory.
|
|
540
|
+
makeTotpVerifierOverrideProvider(options.totpVerifier),
|
|
541
|
+
// The root allowlist (null when absent → broker default-deny).
|
|
542
|
+
// Consumed by the authenticator factory (createIdentityBroker). ROOT
|
|
543
|
+
// SAFETY: the ONLY source of the isRoot flag.
|
|
544
|
+
makeRootIdsProvider(options.rootIds),
|
|
545
|
+
// The eager session-facts projector (ADR-0011; null when absent → the auth
|
|
546
|
+
// controller omits cachedFacts → gate 5 DB-reloads). Consumed by AuthController.
|
|
547
|
+
makeSessionFactsProjectorProvider(options.sessionFactsProjector),
|
|
548
|
+
// The reset-link base URL value the forgot-password handler composes into the
|
|
549
|
+
// emailed link (framework-owned URL composition; EmailSender stays dumb).
|
|
550
|
+
resetLinkBaseUrlProvider,
|
|
551
|
+
sessionRecordStoreProvider,
|
|
552
|
+
hotSessionStoreProvider,
|
|
553
|
+
tokenGeneratorProvider,
|
|
554
|
+
refreshHasherProvider,
|
|
555
|
+
clockProvider,
|
|
556
|
+
sessionAuthorityProvider,
|
|
557
|
+
authenticatorProvider,
|
|
558
|
+
// The core TOTP verifier (login MFA + account MFA enroll/disable share it).
|
|
559
|
+
totpVerifierProvider,
|
|
560
|
+
// Team C's server-side, single-use, TTL'd challenge store backing the
|
|
561
|
+
// login→mfa handoff (a plain class provider the controller injects).
|
|
562
|
+
pending_mfa_store_js_1.PendingMfaStore,
|
|
563
|
+
// The request-auth token binder (access-token → principal claims).
|
|
564
|
+
sessionTokenBinderProvider,
|
|
565
|
+
// The anti-brute-force rate limiters (spec §5): login (H1) + recovery, each
|
|
566
|
+
// a Redis-injected AttemptLimiter with its own threshold. Injected into
|
|
567
|
+
// AuthController (@Optional()).
|
|
568
|
+
loginLimiterProvider,
|
|
569
|
+
recoveryLimiterProvider,
|
|
570
|
+
// The forgot/reset-password limiters (feature #141): forgot keyed by client IP
|
|
571
|
+
// + per-hint (request-rate caps → silently skip the send when exceeded, stays
|
|
572
|
+
// 204); reset keyed by client IP (may 429 on lockout — token-gated, not enum-
|
|
573
|
+
// sensitive). Injected into AuthController (@Optional()).
|
|
574
|
+
forgotLimiterProvider,
|
|
575
|
+
forgotHintLimiterProvider,
|
|
576
|
+
resetLimiterProvider,
|
|
577
|
+
],
|
|
578
|
+
exports: [
|
|
579
|
+
tokens_js_1.SHIELD_AUTHENTICATOR,
|
|
580
|
+
tokens_js_1.SHIELD_SESSION_AUTHORITY,
|
|
581
|
+
tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
|
|
582
|
+
argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER,
|
|
583
|
+
// Exported so the (app-wide) enforcement guard can inject it.
|
|
584
|
+
tokens_js_2.SHIELD_SESSION_TOKEN_BINDER,
|
|
585
|
+
// The account/credential-surface seams — exported so the consumer's impls
|
|
586
|
+
// and the account/auth controllers see them app-wide through @Global Shield.
|
|
587
|
+
tokens_js_1.SHIELD_CREDENTIAL_WRITER,
|
|
588
|
+
tokens_js_1.SHIELD_RESET_TOKEN_STORE,
|
|
589
|
+
tokens_js_1.SHIELD_EMAIL_SENDER,
|
|
590
|
+
tokens_js_1.SHIELD_RECOVERY_CODE_STORE,
|
|
591
|
+
tokens_js_1.SHIELD_PROFILE_WRITER,
|
|
592
|
+
tokens_js_1.SHIELD_SESSION_SWEEPER,
|
|
593
|
+
// The auth-surface audit sink (consumed by the /auth/mfa recovery branch).
|
|
594
|
+
tokens_js_1.SHIELD_AUDIT_SINK,
|
|
595
|
+
// The multi-device MFA store (consumed by /account/mfa/devices/*).
|
|
596
|
+
tokens_js_1.SHIELD_MFA_DEVICE_STORE,
|
|
597
|
+
// The reset-link base URL value (consumed by /auth/forgot-password).
|
|
598
|
+
tokens_js_1.SHIELD_RESET_LINK_BASE_URL,
|
|
599
|
+
// The core TOTP verifier (consumed by /account/mfa/{enroll/confirm,disable}).
|
|
600
|
+
tokens_js_1.SHIELD_TOTP_VERIFIER,
|
|
601
|
+
// The eager session-facts projector (consumed by AuthController).
|
|
602
|
+
tokens_js_1.SHIELD_SESSION_FACTS_PROJECTOR,
|
|
603
|
+
],
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
exports.AuthModule = AuthModule;
|
|
608
|
+
exports.AuthModule = AuthModule = AuthModule_1 = __decorate([
|
|
609
|
+
(0, common_1.Module)({})
|
|
610
|
+
], AuthModule);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHH,kDAKC;AAWD,0DAGC;AAjID,2CAA2E;AAC3E,6CAAyC;AA4BzC,2DAA+E;AAC/E,iEAAwD;AACxD,+FAA+G;AAC/G,qGAA6F;AAC7F,kDAW6B;AAC7B,mEAA4D;AAC5D,6DAAsD;AACtD,mEAA4D;AAC5D,iEAAyD;AACzD,2CAyBqB;AAErB,wEAAiE;AAUjE,yDAAwE;AACxE,qFAA6E;AAE7E;;;;;GAKG;AACI,MAAM,QAAQ,GAAa,CAAC,GAAe,EAAE,OAAmB,EAAc,EAAE,CACrF,IAAI,UAAU,CAAC,IAAA,wBAAU,EAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AADhF,QAAA,QAAQ,YACwE;AAE7F;;;;;;;;;;;GAWG;AACH,SAAgB,mBAAmB,CACjC,QAA2C,EAC3C,eAA+B;IAE/B,OAAO,QAAQ,IAAI,eAAe,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,uBAAuB;IAC3C,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;IACtD,OAAO,wBAAwB,CAAC,EAAE,QAAQ,EAAR,gBAAQ,EAAE,CAAC,CAAC;AAChD,CAAC;AAQD;;;;;;;;;GASG;AACH,MAAM,UAAU,GAAG,IAAI,QAAQ,CAAC,WAAW,EAAE,2BAA2B,CAEnD,CAAC;AAEtB,IAAI,UAAmC,CAAC;AAExC;;;;;;;;;;;;;;;GAeG;AACH,KAAK,UAAU,QAAQ;IACrB,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC;IAChD,IAAI,CAAC;QACH,mFAAmF;QACnF,UAAU,GAAG,CAAC,wDAAa,cAAc,GAAC,CAA2B,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,gFAAgF;QAChF,UAAU,GAAG,CAAC,MAAM,UAAU,CAAC,cAAc,CAAC,CAAgB,CAAC;IACjE,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,+EAA+E;AAE/E,uHAAuH;AACvH,MAAM,sBAAsB,GAAa;IACvC,OAAO,EAAE,oDAAsB;IAC/B,UAAU,EAAE,GAAmB,EAAE,CAAC,IAAI,oDAAsB,EAAE;CAC/D,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,SAAS,8BAA8B,CAAC,QAA6B;IACnE,OAAO,QAAQ;QACb,CAAC,CAAC,EAAE,OAAO,EAAE,sCAA0B,EAAE,QAAQ,EAAE,QAAQ,EAAE;QAC7D,CAAC,CAAC;YACE,OAAO,EAAE,sCAA0B;YACnC,UAAU,EAAE,CAAC,IAAU,EAAsB,EAAE,CAAC,IAAI,0DAAyB,CAAC,IAAI,CAAC;YACnF,MAAM,EAAE,CAAC,0BAAc,CAAC;SACzB,CAAC;AACR,CAAC;AAED,mFAAmF;AACnF,MAAM,0BAA0B,GAAa;IAC3C,OAAO,EAAE,sCAA2B;IACpC,UAAU,EAAE,CAAC,IAAU,EAAsB,EAAE,CAAC,IAAI,oCAAyB,CAAC,IAAI,CAAC;IACnF,MAAM,EAAE,CAAC,0BAAc,CAAC;CACzB,CAAC;AAEF,wEAAwE;AACxE,MAAM,uBAAuB,GAAa;IACxC,OAAO,EAAE,mCAAwB;IACjC,UAAU,EAAE,CAAC,KAAY,EAAmB,EAAE,CAAC,IAAI,+BAAoB,CAAC,KAAK,CAAC;IAC9E,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,0BAA0B,GAAa;IAC3C,OAAO,EAAE,uCAA2B;IACpC,UAAU,EAAE,CAAC,KAAY,EAAsB,EAAE,CAAC,IAAI,4CAAkB,CAAC,KAAK,CAAC;IAC/E,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,oBAAoB,GAAa;IACrC,OAAO,EAAE,gCAAoB;IAC7B,UAAU,EAAE,CAAC,KAAY,EAAkB,EAAE,CAC3C,IAAI,mCAAc,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAC1E,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,uBAAuB,GAAa;IACxC,OAAO,EAAE,mCAAuB;IAChC,UAAU,EAAE,CAAC,KAAY,EAAkB,EAAE,CAC3C,IAAI,mCAAc,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IACzE,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,qBAAqB,GAAa;IACtC,OAAO,EAAE,iCAAqB;IAC9B,UAAU,EAAE,CAAC,KAAY,EAAkB,EAAE,CAC3C,IAAI,mCAAc,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IACzE,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,yBAAyB,GAAa;IAC1C,OAAO,EAAE,sCAA0B;IACnC,UAAU,EAAE,CAAC,KAAY,EAAkB,EAAE,CAC3C,IAAI,mCAAc,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IACzE,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,oBAAoB,GAAa;IACrC,OAAO,EAAE,gCAAoB;IAC7B,UAAU,EAAE,CAAC,KAAY,EAAkB,EAAE,CAC3C,IAAI,mCAAc,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAC1E,MAAM,EAAE,CAAC,wBAAY,CAAC;CACvB,CAAC;AAEF,oDAAoD;AACpD,MAAM,sBAAsB,GAAa;IACvC,OAAO,EAAE,iCAAsB;IAC/B,UAAU,EAAE,GAAmB,EAAE,CAAC,IAAI,+BAAoB,EAAE;CAC7D,CAAC;AAEF;;;;GAIG;AACH,MAAM,qBAAqB,GAAa;IACtC,OAAO,EAAE,gCAAqB;IAC9B,UAAU,EAAE,CAAC,MAAiB,EAAsB,EAAE,CACpD,IAAI,mCAAwB,CAAC,IAAA,oCAAoB,EAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAC3E,MAAM,EAAE,CAAC,6BAAU,CAAC;CACrB,CAAC;AAEF,oBAAoB;AACpB,MAAM,aAAa,GAAa;IAC9B,OAAO,EAAE,uBAAY;IACrB,UAAU,EAAE,GAAU,EAAE,CAAC,IAAI,sBAAW,EAAE;CAC3C,CAAC;AAEF,+EAA+E;AAE/E,0EAA0E;AAC1E,MAAM,wBAAwB,GAAa;IACzC,OAAO,EAAE,oCAAwB;IACjC,kFAAkF;IAClF,UAAU,EAAE,KAAK,EACf,WAA+B,EAC/B,QAAyB,EACzB,cAA8B,EAC9B,aAAiC,EACjC,KAAY,EACZ,MAAiB,EACU,EAAE;QAC7B,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QACpD,OAAO,sBAAsB,CAAC;YAC5B,WAAW;YACX,QAAQ;YACR,cAAc;YACd,aAAa;YACb,KAAK;YACL,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,EAAE;QACN,sCAA2B;QAC3B,mCAAwB;QACxB,iCAAsB;QACtB,gCAAqB;QACrB,uBAAY;QACZ,6BAAU;KACX;CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,qBAAqB,GAAa;IACtC,OAAO,EAAE,gCAAoB;IAC7B,oFAAoF;IACpF,UAAU,EAAE,KAAK,EACf,MAAsB,EACtB,QAA4B,EAC5B,YAAmC,EACnC,OAAiC,EACT,EAAE;QAC1B,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,GAC3E,MAAM,QAAQ,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,mBAAmB,CAAC,YAAY,EAAE,wBAAwB,CAAC,EAAE,QAAQ,EAAR,gBAAQ,EAAE,CAAC,CAAC,CAAC;QACvF,OAAO,mBAAmB,CAAC;YACzB,MAAM;YACN,QAAQ;YACR,wDAAwD;YACxD,0EAA0E;YAC1E,uEAAuE;YACvE,oEAAoE;YACpE,cAAc,EAAE,oBAAoB,CAAC,EAAE,eAAe,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;YACxE,eAAe,EAAE,CAAC,IAAI,CAAC;SACxB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,EAAE;QACN,oDAAsB;QACtB,sCAA0B;QAC1B,yCAA6B;QAC7B,2BAAe;KAChB;CACF,CAAC;AAEF;;;;;GAKG;AACH,SAAS,gCAAgC,CAAC,QAAyB;IACjE,OAAO,EAAE,OAAO,EAAE,yCAA6B,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAChF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAAC,OAA2B;IACtD,OAAO,EAAE,OAAO,EAAE,2BAAe,EAAE,QAAQ,EAAE,OAAO,IAAI,IAAI,EAAE,CAAC;AACjE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,oBAAoB,GAAa;IACrC,OAAO,EAAE,gCAAoB;IAC7B,UAAU,EAAE,KAAK,IAA6B,EAAE;QAC9C,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QACtD,OAAO,wBAAwB,CAAC,EAAE,QAAQ,EAAR,gBAAQ,EAAE,CAAC,CAAC;IAChD,CAAC;CACF,CAAC;AAkFF;;;;;GAKG;AACH,SAAS,2BAA2B,CAAC,QAA0B;IAC7D,OAAO,EAAE,OAAO,EAAE,mCAAuB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,SAAS,4BAA4B,CAAC,QAA2B;IAC/D,OAAO,EAAE,OAAO,EAAE,oCAAwB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC3E,CAAC;AACD,SAAS,2BAA2B,CAAC,QAA0B;IAC7D,OAAO,EAAE,OAAO,EAAE,oCAAwB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC3E,CAAC;AACD,SAAS,uBAAuB,CAAC,QAAsB;IACrD,OAAO,EAAE,OAAO,EAAE,+BAAmB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AACtE,CAAC;AACD,SAAS,6BAA6B,CAAC,QAA4B;IACjE,OAAO,EAAE,OAAO,EAAE,sCAA0B,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC7E,CAAC;AACD,SAAS,yBAAyB,CAAC,QAAwB;IACzD,OAAO,EAAE,OAAO,EAAE,iCAAqB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AACxE,CAAC;AACD,SAAS,0BAA0B,CAAC,QAAyB;IAC3D,OAAO,EAAE,OAAO,EAAE,kCAAsB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AACzE,CAAC;AACD,SAAS,0BAA0B,CAAC,QAAyB;IAC3D,OAAO,EAAE,OAAO,EAAE,mCAAuB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC1E,CAAC;AACD,SAAS,qBAAqB,CAAC,QAAoB;IACjD,OAAO,EAAE,OAAO,EAAE,6BAAiB,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AACpE,CAAC;AACD;;;;;GAKG;AACH,SAAS,iCAAiC,CAAC,QAAgC;IACzE,OAAO,EAAE,OAAO,EAAE,0CAA8B,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC;AACjF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,wBAAwB,GAAa;IACzC,OAAO,EAAE,sCAA0B;IACnC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,sCAAsC;CACpF,CAAC;AAEF;;;;;;GAMG;AAEI,IAAM,UAAU,kBAAhB,MAAM,UAAU;IACrB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,UAA6B,EAAE;QAC5C,OAAO;YACL,MAAM,EAAE,YAAU;YAClB,OAAO,EAAE,CAAC,yCAAiB,CAAC,OAAO,EAAE,CAAC;YACtC,wDAAwD;YACxD,4EAA4E;YAC5E,2EAA2E;YAC3E,8DAA8D;YAC9D,WAAW,EAAE,CAAC,mCAAc,EAAE,yCAAiB,CAAC;YAChD,SAAS,EAAE;gBACT,sBAAsB;gBACtB,8BAA8B,CAAC,OAAO,CAAC,kBAAkB,CAAC;gBAC1D,2EAA2E;gBAC3E,2BAA2B,CAAC,OAAO,CAAC,eAAe,CAAC;gBACpD,uEAAuE;gBACvE,4BAA4B,CAAC,OAAO,CAAC,gBAAgB,CAAC;gBACtD,2BAA2B,CAAC,OAAO,CAAC,eAAe,CAAC;gBACpD,uBAAuB,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC5C,6BAA6B,CAAC,OAAO,CAAC,iBAAiB,CAAC;gBACxD,yBAAyB,CAAC,OAAO,CAAC,aAAa,CAAC;gBAChD,0BAA0B,CAAC,OAAO,CAAC,cAAc,CAAC;gBAClD,gFAAgF;gBAChF,qBAAqB,CAAC,OAAO,CAAC,SAAS,CAAC;gBACxC,qEAAqE;gBACrE,0BAA0B,CAAC,OAAO,CAAC,cAAc,CAAC;gBAClD,wEAAwE;gBACxE,gEAAgE;gBAChE,gCAAgC,CAAC,OAAO,CAAC,YAAY,CAAC;gBACtD,+DAA+D;gBAC/D,qEAAqE;gBACrE,8CAA8C;gBAC9C,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC;gBACpC,2EAA2E;gBAC3E,iFAAiF;gBACjF,iCAAiC,CAAC,OAAO,CAAC,qBAAqB,CAAC;gBAChE,8EAA8E;gBAC9E,0EAA0E;gBAC1E,wBAAwB;gBACxB,0BAA0B;gBAC1B,uBAAuB;gBACvB,sBAAsB;gBACtB,qBAAqB;gBACrB,aAAa;gBACb,wBAAwB;gBACxB,qBAAqB;gBACrB,4EAA4E;gBAC5E,oBAAoB;gBACpB,sEAAsE;gBACtE,qEAAqE;gBACrE,sCAAe;gBACf,mEAAmE;gBACnE,0BAA0B;gBAC1B,4EAA4E;gBAC5E,wEAAwE;gBACxE,gCAAgC;gBAChC,oBAAoB;gBACpB,uBAAuB;gBACvB,+EAA+E;gBAC/E,8EAA8E;gBAC9E,8EAA8E;gBAC9E,0DAA0D;gBAC1D,qBAAqB;gBACrB,yBAAyB;gBACzB,oBAAoB;aACrB;YACD,OAAO,EAAE;gBACP,gCAAoB;gBACpB,oCAAwB;gBACxB,sCAA0B;gBAC1B,oDAAsB;gBACtB,8DAA8D;gBAC9D,uCAA2B;gBAC3B,0EAA0E;gBAC1E,6EAA6E;gBAC7E,oCAAwB;gBACxB,oCAAwB;gBACxB,+BAAmB;gBACnB,sCAA0B;gBAC1B,iCAAqB;gBACrB,kCAAsB;gBACtB,2EAA2E;gBAC3E,6BAAiB;gBACjB,mEAAmE;gBACnE,mCAAuB;gBACvB,qEAAqE;gBACrE,sCAA0B;gBAC1B,8EAA8E;gBAC9E,gCAAoB;gBACpB,kEAAkE;gBAClE,0CAA8B;aAC/B;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AApGY,gCAAU;qBAAV,UAAU;IADtB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,UAAU,CAoGtB"}
|