@astram/identity 0.12.0 → 0.13.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/features/authz/record-authorization.d.ts +8 -0
- package/dist/features/authz/record-authorization.d.ts.map +1 -1
- package/dist/features/authz/record-authorization.js +21 -1
- package/dist/features/identity-feature.module.d.ts +7 -1
- package/dist/features/identity-feature.module.d.ts.map +1 -1
- package/dist/features/identity-feature.module.js +12 -5
- package/package.json +4 -4
|
@@ -16,6 +16,14 @@ import type { FrameworkSchemas } from '@astram/core';
|
|
|
16
16
|
import { type RecordAuthorizationInputs } from '@astram/guard';
|
|
17
17
|
import type { ObjectTypeInput } from '@astram/engine';
|
|
18
18
|
import type { IdentitySchemaNames } from '../../schema.js';
|
|
19
|
+
/**
|
|
20
|
+
* A pool-size variable: unset or blank gives `undefined`; otherwise plain digits, a positive safe
|
|
21
|
+
* integer, or it throws naming the variable (never the value). The single-layout pool budget in
|
|
22
|
+
* `@astram/guard` (`loadPoolBudget`) applies the same rule, so the budget counts the pools that open.
|
|
23
|
+
*/
|
|
24
|
+
export declare function strictPoolSize(raw: string | undefined, name: string): number | undefined;
|
|
25
|
+
/** The authz pool cap: `APP_AUTHZ_POOL_MAX` (strict), else 4. */
|
|
26
|
+
export declare function authzPoolLimit(env?: NodeJS.ProcessEnv): number;
|
|
19
27
|
/**
|
|
20
28
|
* A lean `mariadb` pool for the authz grant-reads (built from `APP_DB_*` env via guard's
|
|
21
29
|
* `loadDbConfig`). Kept small — these are pre-gate coarse-grant reads, not the main CRUD pool.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-authorization.d.ts","sourceRoot":"","sources":["../../../src/features/authz/record-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAgB,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAIL,KAAK,yBAAyB,EAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAaxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,IAAI,EACV,YAAY,GAAE,SAAS,eAAe,EAAO;AAC7C,0FAA0F;AAC1F,OAAO,CAAC,EAAE,mBAAmB,GAC5B,yBAAyB,CAS3B"}
|
|
1
|
+
{"version":3,"file":"record-authorization.d.ts","sourceRoot":"","sources":["../../../src/features/authz/record-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAgB,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAIL,KAAK,yBAAyB,EAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMxF;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAaxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,IAAI,EACV,YAAY,GAAE,SAAS,eAAe,EAAO;AAC7C,0FAA0F;AAC1F,OAAO,CAAC,EAAE,mBAAmB,GAC5B,yBAAyB,CAS3B"}
|
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.strictPoolSize = strictPoolSize;
|
|
7
|
+
exports.authzPoolLimit = authzPoolLimit;
|
|
6
8
|
exports.createIdentityAuthzPool = createIdentityAuthzPool;
|
|
7
9
|
exports.buildRecordAuthorizationInputs = buildRecordAuthorizationInputs;
|
|
8
10
|
/**
|
|
@@ -23,6 +25,24 @@ const guard_1 = require("@astram/guard");
|
|
|
23
25
|
const objects_js_1 = require("../../objects.js");
|
|
24
26
|
const db_permission_facts_adapter_js_1 = require("./db-permission-facts.adapter.js");
|
|
25
27
|
const session_facts_reader_js_1 = require("./session-facts.reader.js");
|
|
28
|
+
/**
|
|
29
|
+
* A pool-size variable: unset or blank gives `undefined`; otherwise plain digits, a positive safe
|
|
30
|
+
* integer, or it throws naming the variable (never the value). The single-layout pool budget in
|
|
31
|
+
* `@astram/guard` (`loadPoolBudget`) applies the same rule, so the budget counts the pools that open.
|
|
32
|
+
*/
|
|
33
|
+
function strictPoolSize(raw, name) {
|
|
34
|
+
if (raw === undefined || raw.trim() === '')
|
|
35
|
+
return undefined;
|
|
36
|
+
const t = raw.trim();
|
|
37
|
+
const n = /^[0-9]+$/.test(t) ? Number(t) : Number.NaN;
|
|
38
|
+
if (!Number.isSafeInteger(n) || n < 1)
|
|
39
|
+
throw new Error(`${name} must be a positive integer`);
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
42
|
+
/** The authz pool cap: `APP_AUTHZ_POOL_MAX` (strict), else 4. */
|
|
43
|
+
function authzPoolLimit(env = process.env) {
|
|
44
|
+
return strictPoolSize(env.APP_AUTHZ_POOL_MAX, 'APP_AUTHZ_POOL_MAX') ?? 4;
|
|
45
|
+
}
|
|
26
46
|
/**
|
|
27
47
|
* A lean `mariadb` pool for the authz grant-reads (built from `APP_DB_*` env via guard's
|
|
28
48
|
* `loadDbConfig`). Kept small — these are pre-gate coarse-grant reads, not the main CRUD pool.
|
|
@@ -39,7 +59,7 @@ function createIdentityAuthzPool(schemas) {
|
|
|
39
59
|
user: db.user,
|
|
40
60
|
password: db.password,
|
|
41
61
|
database: db.database,
|
|
42
|
-
connectionLimit:
|
|
62
|
+
connectionLimit: authzPoolLimit(process.env),
|
|
43
63
|
// Phase 16: APP_DB_TLS / APP_DB_TLS_CA (production accounts are REQUIRE SSL).
|
|
44
64
|
...(ssl ? { ssl } : {}),
|
|
45
65
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DynamicModule } from '@nestjs/common';
|
|
2
2
|
import { type FrameworkSchemas } from '@astram/core';
|
|
3
|
-
import { type ObjectTypeInput } from '@astram/engine';
|
|
3
|
+
import { type EngineDbConfig, type ObjectTypeInput } from '@astram/engine';
|
|
4
4
|
/**
|
|
5
5
|
* The boot check behind {@link IDENTITY_DECISION_AUTHORITY_CHECK}: with this module wired, the
|
|
6
6
|
* request path must decide with the authority guard built from this module's inputs. A missing
|
|
@@ -30,6 +30,12 @@ export declare function assertFrameworkDatabaseAgrees(identityDatabase: string,
|
|
|
30
30
|
readonly database?: string;
|
|
31
31
|
};
|
|
32
32
|
} | null | undefined): true;
|
|
33
|
+
/**
|
|
34
|
+
* Map guard's DbConfig → the engine's EngineDbConfig (adds the pool cap the engine needs). The
|
|
35
|
+
* database and default user follow `schemas` (the names `forRoot` resolved or was given); an
|
|
36
|
+
* explicit `APP_DB_USER` / `APP_DB_NAME` still wins (QA P2-5).
|
|
37
|
+
*/
|
|
38
|
+
export declare function engineDbFromEnv(schemas: FrameworkSchemas, env?: NodeJS.ProcessEnv): EngineDbConfig;
|
|
33
39
|
/**
|
|
34
40
|
* IdentityFeatureModule — the framework-owned identity FEATURE surface (company/user/role CRUD;
|
|
35
41
|
* more in later phases) as thin controllers over the engine's RecordsService. The CONSUMER imports
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity-feature.module.d.ts","sourceRoot":"","sources":["../../src/features/identity-feature.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,cAAc,CAAC;AACtB,OAAO,
|
|
1
|
+
{"version":3,"file":"identity-feature.module.d.ts","sourceRoot":"","sources":["../../src/features/identity-feature.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAYL,KAAK,cAAc,EAGnB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AA2GxB;;;;;;GAMG;AACH,wBAAgB,0CAA0C,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAUnF;AAKD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GACzC,IAAI,CAwBN;AAKD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,gBAAgB,EAAE,MAAM,EACxB,WAAW,EAAE;IAAE,QAAQ,CAAC,EAAE,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAC/E,IAAI,CAQN;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,gBAAgB,EACzB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,cAAc,CAqBhB;AAED;;;;;;;;;;GAUG;AACH,qBACa,qBAAqB;IAChC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,OAAO,CAAC,EACb,OAAO,EACP,YAAiB,EACjB,OAAO,EAAE,YAAY,GACtB,GAAE;QACD,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC5B,YAAY,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;QAC1C,OAAO,CAAC,EAAE,gBAAgB,CAAC;KACvB,GAAG,aAAa;CA2jBvB"}
|
|
@@ -11,6 +11,7 @@ exports.IdentityFeatureModule = void 0;
|
|
|
11
11
|
exports.assertRequestPathUsesIdentityAuthorization = assertRequestPathUsesIdentityAuthorization;
|
|
12
12
|
exports.assertFrameworkSchemasAgree = assertFrameworkSchemasAgree;
|
|
13
13
|
exports.assertFrameworkDatabaseAgrees = assertFrameworkDatabaseAgrees;
|
|
14
|
+
exports.engineDbFromEnv = engineDbFromEnv;
|
|
14
15
|
const common_1 = require("@nestjs/common");
|
|
15
16
|
const core_1 = require("@nestjs/core");
|
|
16
17
|
const core_2 = require("@astram/core");
|
|
@@ -107,7 +108,7 @@ const IDENTITY_FRAMEWORK_SCHEMAS_CHECK = Symbol('IDENTITY_FRAMEWORK_SCHEMAS_CHEC
|
|
|
107
108
|
* Throws (fail closed) with the namespaces and names only.
|
|
108
109
|
*/
|
|
109
110
|
function assertFrameworkSchemasAgree(identity, guard) {
|
|
110
|
-
const names = (s) => `namespace=${s.namespace} app=${s.app} identity=${s.identity} authz=${s.authz} audit=${s.audit}`;
|
|
111
|
+
const names = (s) => `namespace=${s.namespace} app=${s.app} identity=${s.identity} authz=${s.authz} audit=${s.audit} layout=${s.layout ?? 'four'}`;
|
|
111
112
|
if (guard === undefined || guard === null) {
|
|
112
113
|
if (identity.isDefault)
|
|
113
114
|
return true;
|
|
@@ -117,7 +118,8 @@ function assertFrameworkSchemasAgree(identity, guard) {
|
|
|
117
118
|
const same = identity.app === guard.app &&
|
|
118
119
|
identity.identity === guard.identity &&
|
|
119
120
|
identity.authz === guard.authz &&
|
|
120
|
-
identity.audit === guard.audit
|
|
121
|
+
identity.audit === guard.audit &&
|
|
122
|
+
(identity.layout ?? 'four') === (guard.layout ?? 'four');
|
|
121
123
|
if (!same) {
|
|
122
124
|
throw new Error(`IdentityFeatureModule: framework database names disagree — identity ${names(identity)}; ` +
|
|
123
125
|
`guard ${names(guard)}. Pass the same names (or none) to ShieldModule and ` +
|
|
@@ -147,8 +149,13 @@ function assertFrameworkDatabaseAgrees(identityDatabase, guardConfig) {
|
|
|
147
149
|
* database and default user follow `schemas` (the names `forRoot` resolved or was given); an
|
|
148
150
|
* explicit `APP_DB_USER` / `APP_DB_NAME` still wins (QA P2-5).
|
|
149
151
|
*/
|
|
150
|
-
function engineDbFromEnv(schemas) {
|
|
151
|
-
const db = (0, guard_1.loadDbConfig)(
|
|
152
|
+
function engineDbFromEnv(schemas, env = process.env) {
|
|
153
|
+
const db = (0, guard_1.loadDbConfig)(env, schemas);
|
|
154
|
+
// POOL_MAX_ENGINE, else APP_DB_MAX_CONNECTIONS, else 10; a set but invalid value throws naming
|
|
155
|
+
// the variable. Guard's single-layout pool budget parses these the same way.
|
|
156
|
+
const connectionLimit = (0, record_authorization_js_1.strictPoolSize)(env.POOL_MAX_ENGINE, 'POOL_MAX_ENGINE') ??
|
|
157
|
+
(0, record_authorization_js_1.strictPoolSize)(env.APP_DB_MAX_CONNECTIONS, 'APP_DB_MAX_CONNECTIONS') ??
|
|
158
|
+
10;
|
|
152
159
|
const ssl = (0, guard_1.mariadbSslOption)(db.tls);
|
|
153
160
|
return {
|
|
154
161
|
host: db.host,
|
|
@@ -158,7 +165,7 @@ function engineDbFromEnv(schemas) {
|
|
|
158
165
|
database: db.database,
|
|
159
166
|
// The engine's runtime CRUD pool cap. A conservative default; the app can raise it later via
|
|
160
167
|
// an explicit EngineModule.forRoot if it needs more. (ADR-0018 budget lives app-side.)
|
|
161
|
-
connectionLimit
|
|
168
|
+
connectionLimit,
|
|
162
169
|
// Phase 16: APP_DB_TLS / APP_DB_TLS_CA (production accounts are REQUIRE SSL).
|
|
163
170
|
...(ssl ? { ssl } : {}),
|
|
164
171
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astram/identity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Astram framework — the framework-owned identity + tenancy model. Hosts the identity @ObjectType classes (user, company, membership, posting), framework-authored identity migrations, and the identity resolver. Top of the dependency graph: depends on @astram/engine (for @ObjectType/@Field decorators) + @astram/guard / @astram/core (for the auth ports).",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"mariadb": "^3.5.4",
|
|
39
|
-
"@astram/core": "1.
|
|
40
|
-
"@astram/
|
|
41
|
-
"@astram/
|
|
39
|
+
"@astram/core": "1.8.0",
|
|
40
|
+
"@astram/guard": "0.16.0",
|
|
41
|
+
"@astram/engine": "0.9.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@nestjs/common": "^11",
|