@astram/guard 0.19.0 → 0.20.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 +3 -1
- package/dist/auth/account.controller.d.ts.map +1 -1
- package/dist/auth/account.controller.js +79 -6
- package/dist/auth/admin-signin-controls.d.ts +80 -0
- package/dist/auth/admin-signin-controls.d.ts.map +1 -0
- package/dist/auth/admin-signin-controls.js +91 -0
- package/dist/auth/auth-audit.d.ts +59 -0
- package/dist/auth/auth-audit.d.ts.map +1 -0
- package/dist/auth/auth-audit.js +93 -0
- package/dist/auth/auth.controller.d.ts +53 -6
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +330 -44
- package/dist/auth/auth.module.d.ts +49 -0
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +149 -4
- package/dist/auth/captcha-gate.d.ts +103 -0
- package/dist/auth/captcha-gate.d.ts.map +1 -0
- package/dist/auth/captcha-gate.js +245 -0
- package/dist/auth/dto.d.ts +22 -1
- package/dist/auth/dto.d.ts.map +1 -1
- package/dist/auth/login-name-count-boot.d.ts +24 -0
- package/dist/auth/login-name-count-boot.d.ts.map +1 -0
- package/dist/auth/login-name-count-boot.js +47 -0
- package/dist/auth/logout-proof.d.ts +55 -0
- package/dist/auth/logout-proof.d.ts.map +1 -0
- package/dist/auth/logout-proof.js +127 -0
- package/dist/auth/pending-mfa-store.d.ts +5 -0
- package/dist/auth/pending-mfa-store.d.ts.map +1 -1
- package/dist/auth/pending-mfa-store.js +2 -0
- package/dist/auth/ports/audit-sink.d.ts +5 -2
- package/dist/auth/ports/audit-sink.d.ts.map +1 -1
- package/dist/auth/ports/mfa-device-store.d.ts +7 -0
- package/dist/auth/ports/mfa-device-store.d.ts.map +1 -1
- package/dist/auth/profile-resolver.d.ts +6 -0
- package/dist/auth/profile-resolver.d.ts.map +1 -1
- package/dist/auth/rate-limit/attempt-limiter.d.ts +6 -0
- package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -1
- package/dist/auth/rate-limit/attempt-limiter.js +14 -0
- package/dist/auth/tokens.d.ts +59 -0
- package/dist/auth/tokens.d.ts.map +1 -1
- package/dist/auth/tokens.js +61 -1
- package/dist/authentication/credential-provisioner.d.ts +7 -0
- package/dist/authentication/credential-provisioner.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-provisioner.d.ts +1 -0
- package/dist/authentication/mariadb-credential-provisioner.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-provisioner.js +7 -0
- package/dist/authentication/mariadb-credential-resolver.d.ts +23 -2
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-resolver.js +45 -1
- package/dist/authentication/mariadb-mfa-device-store.d.ts +7 -0
- package/dist/authentication/mariadb-mfa-device-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-mfa-device-store.js +32 -0
- package/dist/authentication/mariadb-mfa-requirement-source.d.ts +55 -0
- package/dist/authentication/mariadb-mfa-requirement-source.d.ts.map +1 -0
- package/dist/authentication/mariadb-mfa-requirement-source.js +164 -0
- package/dist/authentication/mariadb-mfa-resetter.d.ts +42 -0
- package/dist/authentication/mariadb-mfa-resetter.d.ts.map +1 -0
- package/dist/authentication/mariadb-mfa-resetter.js +59 -0
- package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-writer.js +5 -0
- package/dist/authentication/sign-in-with.d.ts +14 -0
- package/dist/authentication/sign-in-with.d.ts.map +1 -0
- package/dist/authentication/sign-in-with.js +36 -0
- package/dist/authz/core-access.d.ts +11 -0
- package/dist/authz/core-access.d.ts.map +1 -0
- package/dist/authz/core-access.js +14 -0
- package/dist/authz/list-scope-sql.d.ts.map +1 -1
- package/dist/authz/list-scope-sql.js +15 -5
- package/dist/authz/wire-record-authorization.d.ts.map +1 -1
- package/dist/authz/wire-record-authorization.js +21 -3
- package/dist/captcha/captcha.providers.d.ts +18 -0
- package/dist/captcha/captcha.providers.d.ts.map +1 -0
- package/dist/captcha/captcha.providers.js +78 -0
- package/dist/captcha/recaptcha-verifier.d.ts +20 -0
- package/dist/captcha/recaptcha-verifier.d.ts.map +1 -0
- package/dist/captcha/recaptcha-verifier.js +48 -0
- package/dist/captcha/siteverify.d.ts +47 -0
- package/dist/captcha/siteverify.d.ts.map +1 -0
- package/dist/captcha/siteverify.js +98 -0
- package/dist/captcha/turnstile-verifier.d.ts +18 -0
- package/dist/captcha/turnstile-verifier.d.ts.map +1 -0
- package/dist/captcha/turnstile-verifier.js +41 -0
- package/dist/config/captcha-config.d.ts +47 -0
- package/dist/config/captcha-config.d.ts.map +1 -0
- package/dist/config/captcha-config.js +163 -0
- package/dist/config/reserved-principal-ids.d.ts +15 -0
- package/dist/config/reserved-principal-ids.d.ts.map +1 -1
- package/dist/config/reserved-principal-ids.js +20 -3
- package/dist/enforcement/global-enforcement.guard.d.ts +9 -1
- package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
- package/dist/enforcement/global-enforcement.guard.js +52 -10
- package/dist/enforcement/reenroll-allowlist.d.ts +5 -0
- package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -1
- package/dist/enforcement/reenroll-allowlist.js +5 -0
- package/dist/identity/auth-facts.controller.d.ts +31 -4
- package/dist/identity/auth-facts.controller.d.ts.map +1 -1
- package/dist/identity/auth-facts.controller.js +46 -11
- package/dist/identity/identity-actions.d.ts +2 -2
- package/dist/identity/identity-actions.d.ts.map +1 -1
- package/dist/identity/module-registry.bridge.d.ts.map +1 -1
- package/dist/identity/module-registry.bridge.js +3 -6
- package/dist/identity/permission-facts.adapter.d.ts +22 -0
- package/dist/identity/permission-facts.adapter.d.ts.map +1 -1
- package/dist/identity/permission-facts.adapter.js +26 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -10
- package/dist/internal.d.ts +27 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +36 -1
- package/dist/module/shield.module.d.ts +27 -0
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +10 -0
- package/dist/request-auth/request-principal.d.ts +8 -1
- package/dist/request-auth/request-principal.d.ts.map +1 -1
- package/dist/request-auth/request-principal.js +11 -4
- package/dist/request-auth/session-token-binder.d.ts +82 -0
- package/dist/request-auth/session-token-binder.d.ts.map +1 -1
- package/dist/request-auth/session-token-binder.js +203 -1
- package/dist/session/mfa-requirement-service.d.ts +168 -0
- package/dist/session/mfa-requirement-service.d.ts.map +1 -0
- package/dist/session/mfa-requirement-service.js +461 -0
- package/dist/session/session-restriction-store.d.ts +36 -0
- package/dist/session/session-restriction-store.d.ts.map +1 -1
- package/dist/session/session-restriction-store.js +57 -6
- package/dist/session/session-restriction.d.ts +22 -0
- package/dist/session/session-restriction.d.ts.map +1 -0
- package/dist/session/session-restriction.js +23 -0
- package/package.json +5 -5
|
@@ -23,6 +23,8 @@ const request_principal_js_1 = require("../request-auth/request-principal.js");
|
|
|
23
23
|
const tokens_js_2 = require("../auth/tokens.js");
|
|
24
24
|
const session_facts_als_js_1 = require("../request-auth/session-facts-als.js");
|
|
25
25
|
const reenroll_allowlist_js_1 = require("./reenroll-allowlist.js");
|
|
26
|
+
const session_restriction_js_1 = require("../session/session-restriction.js");
|
|
27
|
+
const mfa_requirement_service_js_1 = require("../session/mfa-requirement-service.js");
|
|
26
28
|
/** A subtree re-derive that was due but could not be done (resolver error / empty / junk). */
|
|
27
29
|
const SUBTREE_REDERIVE_FAILED = Symbol('subtree-rederive-failed');
|
|
28
30
|
/**
|
|
@@ -69,12 +71,14 @@ let GlobalEnforcementGuard = class GlobalEnforcementGuard {
|
|
|
69
71
|
tokenBinder;
|
|
70
72
|
serviceAuth;
|
|
71
73
|
scopeSubtreeResolver;
|
|
72
|
-
|
|
74
|
+
mfaRequirement;
|
|
75
|
+
constructor(reflector, decisionAuthority, tokenBinder, serviceAuth, scopeSubtreeResolver, mfaRequirement) {
|
|
73
76
|
this.reflector = reflector;
|
|
74
77
|
this.decisionAuthority = decisionAuthority;
|
|
75
78
|
this.tokenBinder = tokenBinder;
|
|
76
79
|
this.serviceAuth = serviceAuth;
|
|
77
80
|
this.scopeSubtreeResolver = scopeSubtreeResolver;
|
|
81
|
+
this.mfaRequirement = mfaRequirement;
|
|
78
82
|
}
|
|
79
83
|
async canActivate(context) {
|
|
80
84
|
// Only HTTP requests are classified here. Non-HTTP contexts (if ever added)
|
|
@@ -130,13 +134,11 @@ let GlobalEnforcementGuard = class GlobalEnforcementGuard {
|
|
|
130
134
|
// NOT on the allowlist (the allowlist is @Public), so a marked session is always
|
|
131
135
|
// denied — the isReenrollAllowed check below is defense-in-depth for a future
|
|
132
136
|
// classified allowlisted route.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
}
|
|
137
|
+
//
|
|
138
|
+
// D-2 (auth capabilities R2.3): the same gate serves the mandatory-2FA reason
|
|
139
|
+
// (`mfa_enrollment`, also once a grace deadline has passed — compared here, no DB read), with
|
|
140
|
+
// its own 403 code and the same allowlist.
|
|
141
|
+
this.enforceRestriction(claims, req);
|
|
140
142
|
// Attach the resolved principal so downstream handlers can act as this user.
|
|
141
143
|
req.principal = principal;
|
|
142
144
|
// ── ADR-0011 SESSION-FACTS HOT PATH ──────────────────────────────────────────
|
|
@@ -184,7 +186,26 @@ let GlobalEnforcementGuard = class GlobalEnforcementGuard {
|
|
|
184
186
|
// list scope, shares, the engine's record checks all read `req.principal.roleIds`), and the
|
|
185
187
|
// binding is rewritten with the reloaded facts + roles together, so the next requests are
|
|
186
188
|
// served from the cache (GAPS #6) with the same live roles.
|
|
187
|
-
|
|
189
|
+
// MANDATORY 2FA (auth capabilities R2.5, AC-9): re-evaluate when the permission version moved
|
|
190
|
+
// past the session's requirement stamp — gate 5 just told us the version (its reload, or the
|
|
191
|
+
// fresh cached facts it served). Unchanged version ⇒ no DB query. A failed evaluation denies
|
|
192
|
+
// this request (503) and caches nothing, so the next request reloads and retries.
|
|
193
|
+
let enforced = claims;
|
|
194
|
+
let mfaFailed = false;
|
|
195
|
+
const mfa = this.mfaRequirement;
|
|
196
|
+
if (mfa !== undefined && mfa !== null) {
|
|
197
|
+
const token = (0, request_principal_js_1.extractBearerToken)(authHeader);
|
|
198
|
+
try {
|
|
199
|
+
enforced = await mfa.refresh(token ?? '', claims, {
|
|
200
|
+
version: reloaded?.permissionsVersion ?? usableFacts?.permissionsVersion,
|
|
201
|
+
grants: reloaded ?? usableFacts ?? undefined,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
mfaFailed = true;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (reloaded !== undefined && !mfaFailed) {
|
|
188
209
|
const liveRoles = (0, session_token_binder_js_1.liveRoleIds)(reloaded);
|
|
189
210
|
const current = liveRoles !== undefined ? { ...claims, roleIds: liveRoles } : claims;
|
|
190
211
|
const rederived = await this.rederiveSubtreeOnVersionMove(authHeader, current, reloaded.permissionsVersion);
|
|
@@ -202,12 +223,31 @@ let GlobalEnforcementGuard = class GlobalEnforcementGuard {
|
|
|
202
223
|
req.principal = withRoles;
|
|
203
224
|
}
|
|
204
225
|
}
|
|
226
|
+
if (mfaFailed)
|
|
227
|
+
throw new mfa_requirement_service_js_1.MfaRequirementUnavailableError();
|
|
228
|
+
// The requirement may have just changed: enforce it on THIS request (gated routes are never on
|
|
229
|
+
// the allowlist, so a restricted session is denied here).
|
|
230
|
+
if (enforced !== claims)
|
|
231
|
+
this.enforceRestriction(enforced, req);
|
|
205
232
|
if (decision.effect === 'allow') {
|
|
206
233
|
return true;
|
|
207
234
|
}
|
|
208
235
|
// Deny (or any non-allow) → 403. Do NOT leak the reason detail to the caller.
|
|
209
236
|
throw new common_1.ForbiddenException(`Shield enforcement: access denied for ${classification.action} on ${classification.typeKey}.`);
|
|
210
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* The restricted-session gate (spec §4.2, D-2): a restricted session reaches only
|
|
240
|
+
* `REENROLL_ALLOWED`; anything else is 403 with the reason's code (`reenrollment_required` or
|
|
241
|
+
* `mfa_enrollment_required`). Fail closed: an allowlist, so an unknown route is denied too.
|
|
242
|
+
*/
|
|
243
|
+
enforceRestriction(claims, req) {
|
|
244
|
+
const reason = (0, session_restriction_js_1.restrictionOf)(claims, Date.now());
|
|
245
|
+
if (reason === null)
|
|
246
|
+
return;
|
|
247
|
+
if (!(0, reenroll_allowlist_js_1.isReenrollAllowed)(req?.method, req?.originalUrl ?? req?.url)) {
|
|
248
|
+
throw new common_1.ForbiddenException({ error: (0, session_restriction_js_1.restrictionErrorCode)(reason) });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
211
251
|
/**
|
|
212
252
|
* Write gate 5's reloaded grants and the live roles onto the session binding (ADR-0035). Session
|
|
213
253
|
* bindings only: a service-account key has no binding (its roles and scope are read live per
|
|
@@ -297,5 +337,7 @@ exports.GlobalEnforcementGuard = GlobalEnforcementGuard = __decorate([
|
|
|
297
337
|
__param(3, (0, common_1.Inject)(tokens_js_1.SHIELD_SERVICE_AUTHENTICATOR)),
|
|
298
338
|
__param(4, (0, common_1.Optional)()),
|
|
299
339
|
__param(4, (0, common_1.Inject)(tokens_js_2.SHIELD_SCOPE_SUBTREE_RESOLVER)),
|
|
300
|
-
|
|
340
|
+
__param(5, (0, common_1.Optional)()),
|
|
341
|
+
__param(5, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_REQUIREMENT)),
|
|
342
|
+
__metadata("design:paramtypes", [core_1.Reflector, Object, Function, Object, Object, Object])
|
|
301
343
|
], GlobalEnforcementGuard);
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
* the restricted state (`/auth/me`, list devices) or leave it (`/auth/logout`). EVERY
|
|
10
10
|
* other authenticated route returns 403 `{ error: 'reenrollment_required' }`.
|
|
11
11
|
*
|
|
12
|
+
* Auth capabilities D-2: the SAME allowlist serves the mandatory-2FA restriction (`restriction:
|
|
13
|
+
* 'mfa_enrollment'`, or a passed grace deadline), which answers 403 `{ error:
|
|
14
|
+
* 'mfa_enrollment_required' }` instead (`session/session-restriction.ts`); confirming a device
|
|
15
|
+
* lifts either reason.
|
|
16
|
+
*
|
|
12
17
|
* FAIL-CLOSED: this is an allowlist, not a denylist — a route NOT listed here (incl. an
|
|
13
18
|
* unclassified/unknown route) is DENIED for a `mustReenroll` session. Adding a route
|
|
14
19
|
* that a re-enrolling user must reach means adding it HERE, deliberately.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reenroll-allowlist.d.ts","sourceRoot":"","sources":["../../src/enforcement/reenroll-allowlist.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reenroll-allowlist.d.ts","sourceRoot":"","sources":["../../src/enforcement/reenroll-allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,gFAAgF;AAChF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EAO1D,CAAC;AAEH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAO5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAU3E"}
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
* the restricted state (`/auth/me`, list devices) or leave it (`/auth/logout`). EVERY
|
|
11
11
|
* other authenticated route returns 403 `{ error: 'reenrollment_required' }`.
|
|
12
12
|
*
|
|
13
|
+
* Auth capabilities D-2: the SAME allowlist serves the mandatory-2FA restriction (`restriction:
|
|
14
|
+
* 'mfa_enrollment'`, or a passed grace deadline), which answers 403 `{ error:
|
|
15
|
+
* 'mfa_enrollment_required' }` instead (`session/session-restriction.ts`); confirming a device
|
|
16
|
+
* lifts either reason.
|
|
17
|
+
*
|
|
13
18
|
* FAIL-CLOSED: this is an allowlist, not a denylist — a route NOT listed here (incl. an
|
|
14
19
|
* unclassified/unknown route) is DENIED for a `mustReenroll` session. Adding a route
|
|
15
20
|
* that a re-enrolling user must reach means adding it HERE, deliberately.
|
|
@@ -6,19 +6,46 @@
|
|
|
6
6
|
* store outage → 503 (never swallowed into an empty projection / fabricated version — that would
|
|
7
7
|
* fail-OPEN by letting a stale/empty view read as authoritative).
|
|
8
8
|
*
|
|
9
|
+
* Both carry the same freshness token, `authFactsVersion(tenantVersion, isRoot)` (KI #139): a
|
|
10
|
+
* plain integer the SDK compares for equality, so a root grant or removal makes a cached
|
|
11
|
+
* projection stale even though the tenant's permission version did not move.
|
|
12
|
+
*
|
|
9
13
|
* FRAMEWORK-OWNED: mounted by the auth surface when `auth: true`; the consumer implements nothing.
|
|
10
14
|
*/
|
|
11
15
|
import type { SessionTokenBinder } from '../request-auth/session-token-binder.js';
|
|
16
|
+
import type { MfaRequirementService } from '../session/mfa-requirement-service.js';
|
|
17
|
+
import { type SessionRestrictionReason } from '../session/session-restriction.js';
|
|
12
18
|
import { type AuthFactProjection, type MariaDbPermissionFactsAdapter } from './permission-facts.adapter.js';
|
|
19
|
+
/** The `/identity/auth-facts` answer for a restricted session (R15.2): no grants, the flag. */
|
|
20
|
+
export interface RestrictedAuthFactProjection extends AuthFactProjection {
|
|
21
|
+
readonly facts: readonly [];
|
|
22
|
+
/** The restriction reason (D-2): re-enrol, or mandatory 2FA not yet enrolled. */
|
|
23
|
+
readonly restricted: SessionRestrictionReason;
|
|
24
|
+
}
|
|
13
25
|
export declare class AuthFactsController {
|
|
14
26
|
private readonly tokenBinder;
|
|
15
27
|
private readonly facts;
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
private readonly mfaRequirement?;
|
|
29
|
+
constructor(tokenBinder: SessionTokenBinder | undefined, facts: MariaDbPermissionFactsAdapter | undefined, mfaRequirement?: (MfaRequirementService | null) | undefined);
|
|
30
|
+
/**
|
|
31
|
+
* R15.2 (F9): a restricted session (re-enrol after a recovery-code login, or mandatory 2FA not
|
|
32
|
+
* yet enrolled, D-2) gets the same shape with NO grants, `restricted: <reason>` and no
|
|
33
|
+
* `permissionsVersion` (so the SDK treats it as stale and refetches once the restriction is
|
|
34
|
+
* lifted). Unrestricted sessions are unchanged.
|
|
35
|
+
*/
|
|
36
|
+
getAuthFacts(authorization?: string): Promise<AuthFactProjection | RestrictedAuthFactProjection>;
|
|
37
|
+
/**
|
|
38
|
+
* The freshness token. Review round 1, item H: resolved like `/identity/auth-facts` (the
|
|
39
|
+
* mandatory-2FA recompute runs on a version move), and a restricted session gets no version,
|
|
40
|
+
* only `{ restricted: <reason> }` (a transport reads the missing version as stale and refetches
|
|
41
|
+
* the restricted projection). Unrestricted sessions are unchanged.
|
|
42
|
+
*/
|
|
18
43
|
getPermissionsVersion(authorization?: string): Promise<{
|
|
19
44
|
version: number;
|
|
45
|
+
} | {
|
|
46
|
+
restricted: SessionRestrictionReason;
|
|
20
47
|
}>;
|
|
21
|
-
/** Resolve the bearer token → the caller's
|
|
22
|
-
private
|
|
48
|
+
/** Resolve the bearer token → the caller's Principal and bound claims (the restriction), or 401. */
|
|
49
|
+
private authenticateWithClaims;
|
|
23
50
|
}
|
|
24
51
|
//# sourceMappingURL=auth-facts.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-facts.controller.d.ts","sourceRoot":"","sources":["../../src/identity/auth-facts.controller.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth-facts.controller.d.ts","sourceRoot":"","sources":["../../src/identity/auth-facts.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAaH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAGlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAiB,KAAK,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,6BAA6B,EACnC,MAAM,+BAA+B,CAAC;AAEvC,+FAA+F;AAC/F,MAAM,WAAW,4BAA6B,SAAQ,kBAAkB;IACtE,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;CAC/C;AAED,qBACa,mBAAmB;IAI5B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAG5B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAItB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;gBAPf,WAAW,EAAE,kBAAkB,GAAG,SAAS,EAG3C,KAAK,EAAE,6BAA6B,GAAG,SAAS,EAIhD,cAAc,CAAC,GAAE,qBAAqB,GAAG,IAAI,aAAA;IAGhE;;;;;OAKG;IAGG,YAAY,CACU,aAAa,CAAC,EAAE,MAAM,GAC/C,OAAO,CAAC,kBAAkB,GAAG,4BAA4B,CAAC;IA8B7D;;;;;OAKG;IAGG,qBAAqB,CACC,aAAa,CAAC,EAAE,MAAM,GAC/C,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,UAAU,EAAE,wBAAwB,CAAA;KAAE,CAAC;IA0B1E,oGAAoG;YACtF,sBAAsB;CAerC"}
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* store outage → 503 (never swallowed into an empty projection / fabricated version — that would
|
|
8
8
|
* fail-OPEN by letting a stale/empty view read as authoritative).
|
|
9
9
|
*
|
|
10
|
+
* Both carry the same freshness token, `authFactsVersion(tenantVersion, isRoot)` (KI #139): a
|
|
11
|
+
* plain integer the SDK compares for equality, so a root grant or removal makes a cached
|
|
12
|
+
* projection stale even though the tenant's permission version did not move.
|
|
13
|
+
*
|
|
10
14
|
* FRAMEWORK-OWNED: mounted by the auth surface when `auth: true`; the consumer implements nothing.
|
|
11
15
|
*/
|
|
12
16
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
@@ -28,16 +32,34 @@ const classification_decorator_js_1 = require("../enforcement/classification.dec
|
|
|
28
32
|
const tokens_js_1 = require("../request-auth/tokens.js");
|
|
29
33
|
const request_principal_js_1 = require("../request-auth/request-principal.js");
|
|
30
34
|
const tokens_js_2 = require("../auth/tokens.js");
|
|
35
|
+
const session_restriction_js_1 = require("../session/session-restriction.js");
|
|
31
36
|
const permission_facts_adapter_js_1 = require("./permission-facts.adapter.js");
|
|
32
37
|
let AuthFactsController = class AuthFactsController {
|
|
33
38
|
tokenBinder;
|
|
34
39
|
facts;
|
|
35
|
-
|
|
40
|
+
mfaRequirement;
|
|
41
|
+
constructor(tokenBinder, facts, mfaRequirement) {
|
|
36
42
|
this.tokenBinder = tokenBinder;
|
|
37
43
|
this.facts = facts;
|
|
44
|
+
this.mfaRequirement = mfaRequirement;
|
|
38
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* R15.2 (F9): a restricted session (re-enrol after a recovery-code login, or mandatory 2FA not
|
|
48
|
+
* yet enrolled, D-2) gets the same shape with NO grants, `restricted: <reason>` and no
|
|
49
|
+
* `permissionsVersion` (so the SDK treats it as stale and refetches once the restriction is
|
|
50
|
+
* lifted). Unrestricted sessions are unchanged.
|
|
51
|
+
*/
|
|
39
52
|
async getAuthFacts(authorization) {
|
|
40
|
-
const principal = await this.
|
|
53
|
+
const { principal, claims } = await this.authenticateWithClaims(authorization);
|
|
54
|
+
const restricted = (0, session_restriction_js_1.restrictionOf)(claims, Date.now());
|
|
55
|
+
if (restricted !== null) {
|
|
56
|
+
return {
|
|
57
|
+
principalId: principal.id,
|
|
58
|
+
facts: [],
|
|
59
|
+
projectedAt: Date.now(),
|
|
60
|
+
restricted,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
41
63
|
if (this.facts === undefined || this.facts === null) {
|
|
42
64
|
throw new common_1.HttpException({ error: 'authorization_unavailable' }, common_1.HttpStatus.SERVICE_UNAVAILABLE);
|
|
43
65
|
}
|
|
@@ -51,14 +73,25 @@ let AuthFactsController = class AuthFactsController {
|
|
|
51
73
|
throw err;
|
|
52
74
|
}
|
|
53
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* The freshness token. Review round 1, item H: resolved like `/identity/auth-facts` (the
|
|
78
|
+
* mandatory-2FA recompute runs on a version move), and a restricted session gets no version,
|
|
79
|
+
* only `{ restricted: <reason> }` (a transport reads the missing version as stale and refetches
|
|
80
|
+
* the restricted projection). Unrestricted sessions are unchanged.
|
|
81
|
+
*/
|
|
54
82
|
async getPermissionsVersion(authorization) {
|
|
55
|
-
const principal = await this.
|
|
83
|
+
const { principal, claims } = await this.authenticateWithClaims(authorization);
|
|
84
|
+
const restricted = (0, session_restriction_js_1.restrictionOf)(claims, Date.now());
|
|
85
|
+
if (restricted !== null)
|
|
86
|
+
return { restricted };
|
|
56
87
|
if (this.facts === undefined || this.facts === null) {
|
|
57
88
|
throw new common_1.HttpException({ error: 'authorization_unavailable' }, common_1.HttpStatus.SERVICE_UNAVAILABLE);
|
|
58
89
|
}
|
|
59
90
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
91
|
+
// The same freshness token the projection carries: tenant version + root bit (KI #139),
|
|
92
|
+
// so a root grant or removal makes a cached projection stale. See `authFactsVersion`.
|
|
93
|
+
const tenantVersion = await this.facts.currentVersionFor(principal.id, principal.tenantId);
|
|
94
|
+
return { version: (0, permission_facts_adapter_js_1.authFactsVersion)(tenantVersion, principal.isRoot === true) };
|
|
62
95
|
}
|
|
63
96
|
catch (err) {
|
|
64
97
|
if (err instanceof permission_facts_adapter_js_1.AuthorizationUnavailableError) {
|
|
@@ -67,16 +100,16 @@ let AuthFactsController = class AuthFactsController {
|
|
|
67
100
|
throw err;
|
|
68
101
|
}
|
|
69
102
|
}
|
|
70
|
-
/** Resolve the bearer token → the caller's
|
|
71
|
-
async
|
|
103
|
+
/** Resolve the bearer token → the caller's Principal and bound claims (the restriction), or 401. */
|
|
104
|
+
async authenticateWithClaims(authorization) {
|
|
72
105
|
if (this.tokenBinder === undefined || this.tokenBinder === null) {
|
|
73
106
|
throw new common_1.HttpException({ error: 'unauthorized' }, common_1.HttpStatus.UNAUTHORIZED);
|
|
74
107
|
}
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
108
|
+
const resolved = await (0, request_principal_js_1.resolveRequestAuth)(authorization, this.tokenBinder, undefined, this.mfaRequirement);
|
|
109
|
+
if (resolved === null) {
|
|
77
110
|
throw new common_1.HttpException({ error: 'unauthorized' }, common_1.HttpStatus.UNAUTHORIZED);
|
|
78
111
|
}
|
|
79
|
-
return
|
|
112
|
+
return resolved;
|
|
80
113
|
}
|
|
81
114
|
};
|
|
82
115
|
exports.AuthFactsController = AuthFactsController;
|
|
@@ -102,5 +135,7 @@ exports.AuthFactsController = AuthFactsController = __decorate([
|
|
|
102
135
|
__param(0, (0, common_1.Inject)(tokens_js_1.SHIELD_SESSION_TOKEN_BINDER)),
|
|
103
136
|
__param(1, (0, common_1.Optional)()),
|
|
104
137
|
__param(1, (0, common_1.Inject)(tokens_js_2.SHIELD_PERMISSION_FACTS)),
|
|
105
|
-
|
|
138
|
+
__param(2, (0, common_1.Optional)()),
|
|
139
|
+
__param(2, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_REQUIREMENT)),
|
|
140
|
+
__metadata("design:paramtypes", [Object, Object, Object])
|
|
106
141
|
], AuthFactsController);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* ObjectType (`actions` / `crudActions`, ADR-0038) and read through {@link actionsOf}; the
|
|
5
5
|
* constants below stay exported as the single literal each identity object declares.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { ActionDeclaration } from '@astram/engine';
|
|
8
8
|
export declare const MODULE_KEY = "identity";
|
|
9
9
|
export declare const IDENTITY_ACTIONS: readonly ["read", "create", "update", "delete"];
|
|
10
10
|
export type IdentityAction = (typeof IDENTITY_ACTIONS)[number];
|
|
@@ -38,7 +38,7 @@ export type ServiceAccountAction = (typeof SERVICE_ACCOUNT_ACTIONS)[number];
|
|
|
38
38
|
* extras, or exactly the declared list when `crudActions === false`. Delegates to engine
|
|
39
39
|
* `effectiveActions`, so an invalid declaration throws the same `RegistrationError`.
|
|
40
40
|
*/
|
|
41
|
-
export declare function actionsOf(reg:
|
|
41
|
+
export declare function actionsOf(reg: ActionDeclaration): readonly string[];
|
|
42
42
|
/**
|
|
43
43
|
* @deprecated Use {@link actionsOf} with the type's registration. The vocabulary now lives on
|
|
44
44
|
* the object type (ADR-0038), so a typeKey alone cannot name it: this returns the CRUD verbs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity-actions.d.ts","sourceRoot":"","sources":["../../src/identity/identity-actions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"identity-actions.d.ts","sourceRoot":"","sources":["../../src/identity/identity-actions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,eAAO,MAAM,UAAU,aAAa,CAAC;AACrC,eAAO,MAAM,gBAAgB,iDAAkD,CAAC;AAChF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,wCAAyC,CAAC;AACjF,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,4BAA6B,CAAC;AAC/D,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,gEAM1B,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,iBAAiB,GAAG,SAAS,MAAM,EAAE,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAE9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-registry.bridge.d.ts","sourceRoot":"","sources":["../../src/identity/module-registry.bridge.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAc,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"module-registry.bridge.d.ts","sourceRoot":"","sources":["../../src/identity/module-registry.bridge.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAc,eAAe,EAAE,MAAM,gBAAgB,CAAC;AASlE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,cAAc,CAwB9F"}
|
|
@@ -13,18 +13,15 @@ exports.buildIdentityModuleRegistry = buildIdentityModuleRegistry;
|
|
|
13
13
|
const core_1 = require("@astram/core");
|
|
14
14
|
const engine_1 = require("@astram/engine");
|
|
15
15
|
const identity_actions_js_1 = require("./identity-actions.js");
|
|
16
|
+
const core_access_js_1 = require("../authz/core-access.js");
|
|
16
17
|
function toObjectType(input) {
|
|
17
18
|
return typeof input === 'function' ? (0, engine_1.reflectObjectType)(input) : input;
|
|
18
19
|
}
|
|
19
20
|
function buildIdentityModuleRegistry(inputs) {
|
|
20
21
|
const regs = inputs.map(toObjectType);
|
|
21
22
|
const objectTypes = regs.map((r) => {
|
|
22
|
-
|
|
23
|
-
const access =
|
|
24
|
-
...(a.owned !== undefined ? { owned: a.owned } : {}),
|
|
25
|
-
...(a.tenantScoped !== undefined ? { tenantScoped: a.tenantScoped } : {}),
|
|
26
|
-
...(a.system !== undefined ? { system: a.system } : {}),
|
|
27
|
-
};
|
|
23
|
+
// A global type reaches core as `system` (G-022, ADR-0046).
|
|
24
|
+
const access = (0, core_access_js_1.coreAccessOf)(r.access);
|
|
28
25
|
return {
|
|
29
26
|
typeKey: r.typeKey,
|
|
30
27
|
label: r.typeKey,
|
|
@@ -21,6 +21,27 @@ export interface AuthFactProjection {
|
|
|
21
21
|
readonly projectedAt: number;
|
|
22
22
|
readonly permissionsVersion?: number;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* The freshness token `GET /identity/auth-facts` (`permissionsVersion`) and
|
|
26
|
+
* `GET /identity/permissions-version` (`version`) carry: the per-tenant
|
|
27
|
+
* `authz_permission_version` with the caller's root status folded into the low bit,
|
|
28
|
+
* `tenantVersion * 2 + (isRoot ? 1 : 0)` (KI #139).
|
|
29
|
+
*
|
|
30
|
+
* Why: root adds the control-plane keys to the projection, but root membership comes from
|
|
31
|
+
* the server's root allowlist (`SHIELD_ROOT_IDS`), not from the tenant's grants, so nothing
|
|
32
|
+
* bumps the tenant version when it changes. With the bare tenant version, a projection cached
|
|
33
|
+
* before the caller became root (or stopped being root) stayed "fresh" in the SDK. Folding the
|
|
34
|
+
* bit in makes the two projections carry different versions at the same tenant version.
|
|
35
|
+
*
|
|
36
|
+
* Shape stays a plain non-negative integer (backward compatible). It is an opaque token:
|
|
37
|
+
* `@astram/sdk` >= 0.2.1 compares it for equality, so both directions refetch. An older SDK
|
|
38
|
+
* compares `cached >= current`, so it catches a root grant (version goes up) but not a root
|
|
39
|
+
* removal; the template also resets its client at every sign-in, which covers both.
|
|
40
|
+
* No DB read is added: both routes already read the tenant version, and `isRoot` comes from
|
|
41
|
+
* the bound session claims. `currentVersionFor` keeps returning the raw tenant version (the
|
|
42
|
+
* session's subtree stamp compares it with gate 5's reloaded version).
|
|
43
|
+
*/
|
|
44
|
+
export declare function authFactsVersion(tenantVersion: number, isRoot: boolean): number;
|
|
24
45
|
/** A store/dependency outage while computing facts — the controller maps this to 503. */
|
|
25
46
|
export declare class AuthorizationUnavailableError extends Error {
|
|
26
47
|
constructor(message?: string);
|
|
@@ -37,6 +58,7 @@ export declare class MariaDbPermissionFactsAdapter {
|
|
|
37
58
|
/** Framework database names; absent ⇒ resolved from `SHIELD_DB_NAMESPACE` here, once. */
|
|
38
59
|
schemas?: FrameworkSchemaNames);
|
|
39
60
|
projectFor(principalId: string, tenantId: string, isRoot: boolean): Promise<AuthFactProjection>;
|
|
61
|
+
/** The raw per-tenant permission version (not the {@link authFactsVersion} token). */
|
|
40
62
|
currentVersionFor(_principalId: string, tenantId: string): Promise<number>;
|
|
41
63
|
private readRoleIdsForTenant;
|
|
42
64
|
private readGrantKeys;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-facts.adapter.d.ts","sourceRoot":"","sources":["../../src/identity/permission-facts.adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AACD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,yFAAyF;AACzF,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,OAAO,SAA8B;CAIlD;AAYD,qBAAa,6BAA6B;IAMtC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG;IARtB,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAGZ,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,SAAS,MAAM,EAAE,EACpC,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,GAAG,GAAE,MAAM,MAAiB;IAC7C,yFAAyF;IACzF,OAAO,CAAC,EAAE,oBAAoB;IAO1B,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"permission-facts.adapter.d.ts","sourceRoot":"","sources":["../../src/identity/permission-facts.adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AACD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAE/E;AAED,yFAAyF;AACzF,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,OAAO,SAA8B;CAIlD;AAYD,qBAAa,6BAA6B;IAMtC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG;IARtB,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAGZ,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,SAAS,MAAM,EAAE,EACpC,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,GAAG,GAAE,MAAM,MAAiB;IAC7C,yFAAyF;IACzF,OAAO,CAAC,EAAE,oBAAoB;IAO1B,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,kBAAkB,CAAC;IAmB9B,sFAAsF;IAChF,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YASlE,oBAAoB;YAepB,aAAa;YASb,WAAW;IAQzB;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;CAaxB"}
|
|
@@ -10,7 +10,31 @@
|
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.MariaDbPermissionFactsAdapter = exports.AuthorizationUnavailableError = void 0;
|
|
13
|
+
exports.authFactsVersion = authFactsVersion;
|
|
13
14
|
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
15
|
+
/**
|
|
16
|
+
* The freshness token `GET /identity/auth-facts` (`permissionsVersion`) and
|
|
17
|
+
* `GET /identity/permissions-version` (`version`) carry: the per-tenant
|
|
18
|
+
* `authz_permission_version` with the caller's root status folded into the low bit,
|
|
19
|
+
* `tenantVersion * 2 + (isRoot ? 1 : 0)` (KI #139).
|
|
20
|
+
*
|
|
21
|
+
* Why: root adds the control-plane keys to the projection, but root membership comes from
|
|
22
|
+
* the server's root allowlist (`SHIELD_ROOT_IDS`), not from the tenant's grants, so nothing
|
|
23
|
+
* bumps the tenant version when it changes. With the bare tenant version, a projection cached
|
|
24
|
+
* before the caller became root (or stopped being root) stayed "fresh" in the SDK. Folding the
|
|
25
|
+
* bit in makes the two projections carry different versions at the same tenant version.
|
|
26
|
+
*
|
|
27
|
+
* Shape stays a plain non-negative integer (backward compatible). It is an opaque token:
|
|
28
|
+
* `@astram/sdk` >= 0.2.1 compares it for equality, so both directions refetch. An older SDK
|
|
29
|
+
* compares `cached >= current`, so it catches a root grant (version goes up) but not a root
|
|
30
|
+
* removal; the template also resets its client at every sign-in, which covers both.
|
|
31
|
+
* No DB read is added: both routes already read the tenant version, and `isRoot` comes from
|
|
32
|
+
* the bound session claims. `currentVersionFor` keeps returning the raw tenant version (the
|
|
33
|
+
* session's subtree stamp compares it with gate 5's reloaded version).
|
|
34
|
+
*/
|
|
35
|
+
function authFactsVersion(tenantVersion, isRoot) {
|
|
36
|
+
return tenantVersion * 2 + (isRoot ? 1 : 0);
|
|
37
|
+
}
|
|
14
38
|
/** A store/dependency outage while computing facts — the controller maps this to 503. */
|
|
15
39
|
class AuthorizationUnavailableError extends Error {
|
|
16
40
|
constructor(message = 'authorization_unavailable') {
|
|
@@ -44,7 +68,7 @@ class MariaDbPermissionFactsAdapter {
|
|
|
44
68
|
const granted = roleIds.length > 0 ? await this.readGrantKeys(roleIds) : [];
|
|
45
69
|
const expanded = this.expandGrantKeys(granted);
|
|
46
70
|
const keys = isRoot ? [...new Set([...expanded, ...this.controlPlaneKeys])] : expanded;
|
|
47
|
-
const permissionsVersion = await this.readVersion(tenantId);
|
|
71
|
+
const permissionsVersion = authFactsVersion(await this.readVersion(tenantId), isRoot);
|
|
48
72
|
return {
|
|
49
73
|
principalId,
|
|
50
74
|
facts: keys.map((action) => ({ action, allowed: true })),
|
|
@@ -58,6 +82,7 @@ class MariaDbPermissionFactsAdapter {
|
|
|
58
82
|
throw new AuthorizationUnavailableError(err.message);
|
|
59
83
|
}
|
|
60
84
|
}
|
|
85
|
+
/** The raw per-tenant permission version (not the {@link authFactsVersion} token). */
|
|
61
86
|
async currentVersionFor(_principalId, tenantId) {
|
|
62
87
|
try {
|
|
63
88
|
return await this.readVersion(tenantId);
|
package/dist/index.d.ts
CHANGED
|
@@ -72,11 +72,18 @@ export { FRAMEWORK_SCHEMAS } from './config/config.module.js';
|
|
|
72
72
|
export type { FrameworkSchemaNames } from './config/framework-schema-names.js';
|
|
73
73
|
export { frameworkSchemasOf, loadAppConfig, loadPoolBudget, evaluatePoolBudget, DEFAULT_POOL_BUDGET, SCHEMA_SVC_POOL_HARD_CAP, type AppConfig, type PoolBudgetConfig, type PoolBudgetEvaluation, type RuntimeAccountPools, loadDbConfig, loadRedisConfig, loadSessionLifetimes, loadRefreshHmacKey, assertRefreshHmacKey, DEFAULT_DB_CONFIG, DEFAULT_REDIS_URL, type DbConfig, type RedisConfig, type SessionLifetimeOverrides, loadLoginIpLimit, loadRefreshReplayWindowMs, DEFAULT_LOGIN_IP_LIMIT, isDevOrTestNodeEnv, type LoginIpLimitConfig, loadDbTlsConfig, type DbTlsConfig, } from './config/app-config.js';
|
|
74
74
|
export { rootIdsFromEnv } from './config/root-ids-from-env.js';
|
|
75
|
-
export { ORG_BOOTSTRAP_PRINCIPAL_ID, assertNoReservedRootId, } from './config/reserved-principal-ids.js';
|
|
75
|
+
export { ORG_BOOTSTRAP_PRINCIPAL_ID, assertNoReservedRootId, RESERVED_OPERATION_PRINCIPALS, reservedOperationPrincipal, type ReservedOperationPrincipal, } from './config/reserved-principal-ids.js';
|
|
76
76
|
export { mariadbSslOption } from './auth/connections.js';
|
|
77
77
|
export { SHIELD_REDIS, SHIELD_CREDENTIAL_RESOLVER, SHIELD_PROFILE_RESOLVER, SHIELD_AUTHENTICATOR, SHIELD_SESSION_AUTHORITY, SHIELD_CREDENTIAL_WRITER, SHIELD_RESET_TOKEN_STORE, SHIELD_EMAIL_CHANGE_TOKEN_STORE, SHIELD_EMAIL_SENDER, SHIELD_MESSAGE_DISPATCHER, SHIELD_RECOVERY_CODE_STORE, SHIELD_PROFILE_WRITER, SHIELD_SESSION_SWEEPER, SHIELD_AUDIT_SINK, SHIELD_MFA_DEVICE_STORE, SHIELD_TOTP_VERIFIER_OVERRIDE, } from './auth/tokens.js';
|
|
78
78
|
export { MariaDbCredentialResolver } from './authentication/mariadb-credential-resolver.js';
|
|
79
|
-
export
|
|
79
|
+
export { resolveSignInWith, DEFAULT_SIGN_IN_WITH, type SignInMethod, } from './authentication/sign-in-with.js';
|
|
80
|
+
export { SHIELD_SIGN_IN_WITH } from './auth/tokens.js';
|
|
81
|
+
export type { SessionView, SessionTokensView, SessionSuccess, LoginRequest, MfaChallengeResponse, LoginResponse, MfaRequest, MfaResponse, RefreshRequest, RefreshResponse, LogoutRequest, LogoutAck, LoginOptionsView, } from './auth/dto.js';
|
|
82
|
+
export type { ShieldCaptchaOption } from './captcha/captcha.providers.js';
|
|
83
|
+
export { loadCaptchaConfig, CAPTCHA_ENDPOINTS, CAPTCHA_MODES, CAPTCHA_FAIL_MODES, DEFAULT_CAPTCHA_THRESHOLD, DEFAULT_CAPTCHA_MIN_SCORE, DEFAULT_CAPTCHA_TIMEOUT_MS, MAX_CAPTCHA_TIMEOUT_MS, type CaptchaConfig, type CaptchaEndpoint, type CaptchaMode, type CaptchaFailMode, type LoadCaptchaConfigOptions, } from './config/captcha-config.js';
|
|
84
|
+
export { TurnstileVerifier, TURNSTILE_SITEVERIFY_URL, type TurnstileVerifierOptions, } from './captcha/turnstile-verifier.js';
|
|
85
|
+
export { RecaptchaVerifier, RECAPTCHA_SITEVERIFY_URL, type RecaptchaVerifierOptions, } from './captcha/recaptcha-verifier.js';
|
|
86
|
+
export { SHIELD_CAPTCHA_GATE } from './auth/tokens.js';
|
|
80
87
|
export { AuthModule, type AuthModuleOptions } from './auth/auth.module.js';
|
|
81
88
|
export { makeDefaultTotpVerifier, resolveTotpVerifier, hmacSha1 } from './auth/auth.module.js';
|
|
82
89
|
export type { CredentialResolver, ResolvedCredential, RequiredFactor } from '@astram/core';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|