@astram/guard 0.14.0 → 0.16.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/auth.module.d.ts +8 -1
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +76 -31
- package/dist/authentication/mariadb-api-key-store.d.ts +10 -1
- package/dist/authentication/mariadb-api-key-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-api-key-store.js +20 -10
- package/dist/authentication/mariadb-credential-resolver.d.ts +8 -1
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-resolver.js +15 -5
- package/dist/authentication/mariadb-credential-writer.d.ts +6 -1
- package/dist/authentication/mariadb-credential-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-writer.js +9 -3
- package/dist/authentication/mariadb-email-address-changer.d.ts +10 -1
- package/dist/authentication/mariadb-email-address-changer.d.ts.map +1 -1
- package/dist/authentication/mariadb-email-address-changer.js +22 -9
- package/dist/authentication/mariadb-email-change-token-store.d.ts +8 -1
- package/dist/authentication/mariadb-email-change-token-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-email-change-token-store.js +18 -9
- package/dist/authentication/mariadb-mfa-device-store.d.ts +6 -1
- package/dist/authentication/mariadb-mfa-device-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-mfa-device-store.js +22 -13
- package/dist/authentication/mariadb-profile-resolver.d.ts +6 -1
- package/dist/authentication/mariadb-profile-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-resolver.js +12 -6
- package/dist/authentication/mariadb-profile-writer.d.ts +6 -1
- package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-writer.js +11 -4
- package/dist/authentication/mariadb-recovery-code-store.d.ts +6 -1
- package/dist/authentication/mariadb-recovery-code-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-recovery-code-store.js +11 -5
- package/dist/authentication/mariadb-reset-token-store.d.ts +6 -1
- package/dist/authentication/mariadb-reset-token-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-reset-token-store.js +11 -5
- package/dist/authentication/mariadb-session-sweeper.d.ts +6 -1
- package/dist/authentication/mariadb-session-sweeper.d.ts.map +1 -1
- package/dist/authentication/mariadb-session-sweeper.js +11 -5
- package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -1
- package/dist/authz/cross-tenant-grant-writer.js +4 -3
- package/dist/authz/list-scope-sql.d.ts +10 -2
- package/dist/authz/list-scope-sql.d.ts.map +1 -1
- package/dist/authz/list-scope-sql.js +4 -4
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js +4 -3
- package/dist/authz/mariadb-list-scope-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-list-scope-adapter.js +4 -3
- package/dist/authz/mariadb-policy-store.d.ts.map +1 -1
- package/dist/authz/mariadb-policy-store.js +4 -3
- package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-record-rule-adapter.js +4 -3
- package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-record-share-adapter.js +4 -3
- package/dist/authz/record-share-cascade.d.ts.map +1 -1
- package/dist/authz/record-share-cascade.js +4 -3
- package/dist/authz/record-share-writer.d.ts.map +1 -1
- package/dist/authz/record-share-writer.js +4 -3
- package/dist/authz/wire-record-authorization.d.ts +8 -0
- package/dist/authz/wire-record-authorization.d.ts.map +1 -1
- package/dist/authz/wire-record-authorization.js +14 -6
- package/dist/boot/boot-sequence.d.ts +10 -0
- package/dist/boot/boot-sequence.d.ts.map +1 -1
- package/dist/boot/boot-sequence.js +47 -3
- package/dist/boot/migration-ledger-check.d.ts +94 -0
- package/dist/boot/migration-ledger-check.d.ts.map +1 -0
- package/dist/boot/migration-ledger-check.js +280 -0
- package/dist/boot/single-layout-probe.d.ts +66 -0
- package/dist/boot/single-layout-probe.d.ts.map +1 -0
- package/dist/boot/single-layout-probe.js +334 -0
- package/dist/config/app-config.d.ts +46 -3
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js +90 -11
- package/dist/config/config.module.d.ts +7 -0
- package/dist/config/config.module.d.ts.map +1 -1
- package/dist/config/config.module.js +8 -1
- package/dist/config/framework-schema-names.d.ts +29 -0
- package/dist/config/framework-schema-names.d.ts.map +1 -0
- package/dist/config/framework-schema-names.js +41 -0
- package/dist/identity/permission-facts.adapter.d.ts +7 -1
- package/dist/identity/permission-facts.adapter.d.ts.map +1 -1
- package/dist/identity/permission-facts.adapter.js +15 -6
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -2
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +43 -7
- package/dist/session/mariadb-session-record-store.d.ts +8 -1
- package/dist/session/mariadb-session-record-store.d.ts.map +1 -1
- package/dist/session/mariadb-session-record-store.js +23 -13
- package/dist/session/session-restriction-store.d.ts +8 -1
- package/dist/session/session-restriction-store.d.ts.map +1 -1
- package/dist/session/session-restriction-store.js +15 -5
- package/migrations/1710000000006-CreateAuthzSchema.cjs +15 -4
- package/migrations/1710000000007-ExtendPermissionAndRolePermission.cjs +11 -3
- package/migrations/1710000000008-CreateAccessBundleTables.cjs +14 -4
- package/migrations/1710000000009-CreateRecordPermissionRule.cjs +15 -4
- package/migrations/1710000000014-CreateRecordShare.cjs +15 -4
- package/migrations/1710000000015-CreateScopeClosure.cjs +14 -4
- package/migrations/1710000000016-AlterCompanyParentFkRestrict.cjs +20 -9
- package/migrations/1710000000017-CreateServiceAccountKey.cjs +14 -4
- package/package.json +3 -3
|
@@ -63,8 +63,7 @@
|
|
|
63
63
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
64
64
|
exports.CrossTenantGrantWriter = exports.GrantStoreUnavailableError = exports.InvalidGrantError = exports.GrantNotPermittedError = exports.SHIELD_CROSS_TENANT_GRANT_WRITER = void 0;
|
|
65
65
|
const node_crypto_1 = require("node:crypto");
|
|
66
|
-
|
|
67
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
66
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
68
67
|
/** The DI token the writer is bound under. */
|
|
69
68
|
exports.SHIELD_CROSS_TENANT_GRANT_WRITER = Symbol('SHIELD_CROSS_TENANT_GRANT_WRITER');
|
|
70
69
|
/** Thrown when the who-may-grant bound rejects an offer/accept/revoke (fail-closed). */
|
|
@@ -122,7 +121,9 @@ class CrossTenantGrantWriter {
|
|
|
122
121
|
this.db = deps.db;
|
|
123
122
|
this.authorize = deps.authorize;
|
|
124
123
|
this.audit = deps.audit;
|
|
125
|
-
|
|
124
|
+
// The `cross_tenant_grant` database: `deps.schema` (checked), else the resolved authz name
|
|
125
|
+
// (configurable-framework-db), fixed at construction.
|
|
126
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(deps.schema);
|
|
126
127
|
this.now = deps.nowMs ?? (() => Date.now());
|
|
127
128
|
}
|
|
128
129
|
/**
|
|
@@ -107,9 +107,17 @@ export declare class UnknownScopeFieldError extends Error {
|
|
|
107
107
|
* @returns `{ sql, params }` — `sql` carries ONLY `?` + backtick columns; `params` the
|
|
108
108
|
* bound values in `?`-order.
|
|
109
109
|
* @throws {@link UnknownScopeFieldError} if any condition names an unregistered field.
|
|
110
|
+
* @throws FrameworkSchemaConfigError (core) if `opts.schema` is missing or not a safe name.
|
|
110
111
|
*/
|
|
111
|
-
export declare function translateListScope(spec: ListScopeSpec, reg: ObjectType, principal: ListScopePrincipal, opts
|
|
112
|
-
|
|
112
|
+
export declare function translateListScope(spec: ListScopeSpec, reg: ObjectType, principal: ListScopePrincipal, opts: {
|
|
113
|
+
/**
|
|
114
|
+
* REQUIRED: the authz database holding `record_share` / `cross_tenant_grant` (configurable-
|
|
115
|
+
* framework-db). No default: this pure translator runs per request and never reads env, and
|
|
116
|
+
* a silent `shield_authz` default would read another environment's grants under a namespace.
|
|
117
|
+
* The wiring (`buildListScopeFn`) passes the resolved `schemas.authz`. Checked with core
|
|
118
|
+
* `assertSchemaName` on every call (fail closed).
|
|
119
|
+
*/
|
|
120
|
+
schema: string;
|
|
113
121
|
nowMs?: () => number;
|
|
114
122
|
/**
|
|
115
123
|
* The OWNING tenant's deny AND-groups (Task 4.2 — the fail-open leak fix). Applied ONLY to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-scope-sql.d.ts","sourceRoot":"","sources":["../../src/authz/list-scope-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAIf,MAAM,cAAc,CAAC;AACtB,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"list-scope-sql.d.ts","sourceRoot":"","sources":["../../src/authz/list-scope-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAIf,MAAM,cAAc,CAAC;AACtB,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,gBAAgB,CAAC;AAGxB,qFAAqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAED,yFAAyF;AACzF,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAO3C;AAmID;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,kBAAkB,EAC7B,IAAI,EAAE;IACJ;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,cAAc,EAAE,CAAC,EAAE,CAAC;CAC3D,GACA,mBAAmB,CAoJrB"}
|
|
@@ -80,8 +80,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
80
80
|
exports.UnknownScopeFieldError = void 0;
|
|
81
81
|
exports.translateListScope = translateListScope;
|
|
82
82
|
const engine_1 = require("@astram/engine");
|
|
83
|
-
|
|
84
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
83
|
+
const core_1 = require("@astram/core");
|
|
85
84
|
/** Error thrown when a scope condition references a field the type does not register. */
|
|
86
85
|
class UnknownScopeFieldError extends Error {
|
|
87
86
|
constructor(typeKey, field) {
|
|
@@ -211,9 +210,10 @@ function translateGroups(groups, reg, principal, p) {
|
|
|
211
210
|
* @returns `{ sql, params }` — `sql` carries ONLY `?` + backtick columns; `params` the
|
|
212
211
|
* bound values in `?`-order.
|
|
213
212
|
* @throws {@link UnknownScopeFieldError} if any condition names an unregistered field.
|
|
213
|
+
* @throws FrameworkSchemaConfigError (core) if `opts.schema` is missing or not a safe name.
|
|
214
214
|
*/
|
|
215
|
-
function translateListScope(spec, reg, principal, opts
|
|
216
|
-
const schema = opts
|
|
215
|
+
function translateListScope(spec, reg, principal, opts) {
|
|
216
|
+
const schema = (0, core_1.assertSchemaName)(opts?.schema, 'translateListScope opts.schema');
|
|
217
217
|
// The cross-tenant expiry filter binds THIS clock's epoch-ms against the BIGINT
|
|
218
218
|
// `ctg_expires_at_ms` column — timezone-immune (mirrors MariaDbCrossTenantGrantAdapter's
|
|
219
219
|
// injectable clock). Injectable for deterministic tests.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-cross-tenant-grant-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-cross-tenant-grant-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EAEtB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-cross-tenant-grant-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-cross-tenant-grant-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EAEtB,MAAM,cAAc,CAAC;AAItB,wFAAwF;AACxF,eAAO,MAAM,8BAA8B,eAA2C,CAAC;AAEvF,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAsDD;;;;GAIG;AACH,qBAAa,8BAA+B,YAAW,oBAAoB;IACzE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,EAAE,EAAE,cAAc,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;KAAO;IAU9E,eAAe,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAwFrF;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,uBAAuB,CAAC,KAAK,EAAE;QACnC,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAkCtB"}
|
|
@@ -69,10 +69,9 @@
|
|
|
69
69
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
70
70
|
exports.MariaDbCrossTenantGrantAdapter = exports.SHIELD_CROSS_TENANT_GRANT_PORT = void 0;
|
|
71
71
|
const core_1 = require("@astram/core");
|
|
72
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
72
73
|
/** The DI token the adapter is bound under (parity with the share/rule-port tokens). */
|
|
73
74
|
exports.SHIELD_CROSS_TENANT_GRANT_PORT = Symbol('SHIELD_CROSS_TENANT_GRANT_PORT');
|
|
74
|
-
/** Schema the `cross_tenant_grant` table lives in (astram3 ships the migration). */
|
|
75
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
76
75
|
/**
|
|
77
76
|
* Parse `ctg_allowed_actions` to a `string[]`. ⚠️ The `ctg_allowed_actions` column is a JSON
|
|
78
77
|
* column, and the mariadb driver AUTO-PARSES it into a JS ARRAY on read — so `raw` is ALREADY an
|
|
@@ -123,7 +122,9 @@ class MariaDbCrossTenantGrantAdapter {
|
|
|
123
122
|
now;
|
|
124
123
|
constructor(db, opts = {}) {
|
|
125
124
|
this.db = db;
|
|
126
|
-
|
|
125
|
+
// The `cross_tenant_grant` database: `opts.schema` (checked), else the resolved authz name
|
|
126
|
+
// (configurable-framework-db), fixed at construction.
|
|
127
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(opts.schema);
|
|
127
128
|
// The expiry filter binds THIS clock's epoch-ms against the BIGINT `ctg_expires_at_ms`
|
|
128
129
|
// column — timezone-immune (no Date/`NOW()` skew). Injectable for deterministic tests.
|
|
129
130
|
this.now = opts.nowMs ?? (() => Date.now());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-list-scope-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-list-scope-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAGjB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-list-scope-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-list-scope-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAGjB,MAAM,cAAc,CAAC;AAItB,iFAAiF;AACjF,eAAO,MAAM,sBAAsB,eAAmC,CAAC;AAEvE,oFAAoF;AACpF,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAoCD;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,aAAa;IAC3D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAqB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,EAAE,EAAE,kBAAkB,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAO5D,oBAAoB,CACxB,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,oBAAoB,CAAC;CA8EjC"}
|
|
@@ -43,10 +43,9 @@
|
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
44
|
exports.MariaDbListScopeAdapter = exports.SHIELD_LIST_SCOPE_PORT = void 0;
|
|
45
45
|
const core_1 = require("@astram/core");
|
|
46
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
46
47
|
/** The DI token the adapter is bound under (parity with the rule-port token). */
|
|
47
48
|
exports.SHIELD_LIST_SCOPE_PORT = Symbol('SHIELD_LIST_SCOPE_PORT');
|
|
48
|
-
/** Schema the `record_permission_rule` table lives in (framework migration ...009). */
|
|
49
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
50
49
|
/**
|
|
51
50
|
* Whether a rule group's SUBJECT matches the requesting principal — the EXACT mirror of the
|
|
52
51
|
* per-record rule adapter's `subjectMatches` ({@link MariaDbRecordPermissionRuleAdapter}):
|
|
@@ -79,7 +78,9 @@ class MariaDbListScopeAdapter {
|
|
|
79
78
|
schema;
|
|
80
79
|
constructor(db, opts = {}) {
|
|
81
80
|
this.db = db;
|
|
82
|
-
|
|
81
|
+
// The `record_permission_rule` database (framework migration ...009): `opts.schema`
|
|
82
|
+
// (checked), else the resolved authz name (configurable-framework-db), fixed here.
|
|
83
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(opts.schema);
|
|
83
84
|
}
|
|
84
85
|
async listPolicyConditions(typeKey, tenantNodeIds, action, subject) {
|
|
85
86
|
// The caller's reachable subtree (active node + descendants, ADR-0027). A rule scoped to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-policy-store.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-policy-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAmB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-policy-store.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-policy-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAmB,MAAM,cAAc,CAAC;AAGvF,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,eAAgC,CAAC;AAEjE,kFAAkF;AAClF,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAgCD;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,WAAW;IACpD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAgB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,EAAE,EAAE,aAAa,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAO7D;;;;;OAKG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA4CzE;;;;OAIG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;IAiDjF;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnD;;;;;;;;;;OAUG;IACG,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CASjF"}
|
|
@@ -69,10 +69,9 @@
|
|
|
69
69
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
70
70
|
exports.MariaDbPolicyStore = exports.SHIELD_POLICY_STORE = void 0;
|
|
71
71
|
const node_crypto_1 = require("node:crypto");
|
|
72
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
72
73
|
/** The DI token the policy store is bound under (parity with the rule-port token). */
|
|
73
74
|
exports.SHIELD_POLICY_STORE = Symbol('SHIELD_POLICY_STORE');
|
|
74
|
-
/** Schema the `record_permission_rule` table lives in (framework migration ...009). */
|
|
75
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
76
75
|
/**
|
|
77
76
|
* The operators that take NO operand (the read adapter ignores `rpr_value` for
|
|
78
77
|
* these). Their conditions persist `rpr_value = NULL` so a round-trip yields the
|
|
@@ -103,7 +102,9 @@ class MariaDbPolicyStore {
|
|
|
103
102
|
schema;
|
|
104
103
|
constructor(db, opts = {}) {
|
|
105
104
|
this.db = db;
|
|
106
|
-
|
|
105
|
+
// The `record_permission_rule` database (framework migration ...009): `opts.schema`
|
|
106
|
+
// (checked), else the resolved authz name (configurable-framework-db), fixed here.
|
|
107
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(opts.schema);
|
|
107
108
|
}
|
|
108
109
|
/**
|
|
109
110
|
* Persist a guided policy as N `record_permission_rule` rows (ONE row for a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-record-rule-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-record-rule-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-record-rule-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-record-rule-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAI1F,qFAAqF;AACrF,eAAO,MAAM,uBAAuB,eAAoC,CAAC;AAEzE,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAmLD;;;GAGG;AACH,qBAAa,kCAAmC,YAAW,wBAAwB;IACjF,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAgB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,EAAE,EAAE,aAAa,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAOvD,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;CAuE5D"}
|
|
@@ -46,10 +46,9 @@
|
|
|
46
46
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
47
|
exports.MariaDbRecordPermissionRuleAdapter = exports.SHIELD_RECORD_RULE_PORT = void 0;
|
|
48
48
|
const core_1 = require("@astram/core");
|
|
49
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
49
50
|
/** The DI token the adapter is bound under (parity with the session store token). */
|
|
50
51
|
exports.SHIELD_RECORD_RULE_PORT = Symbol('SHIELD_RECORD_RULE_PORT');
|
|
51
|
-
/** Schema the `record_permission_rule` table lives in (astram3 ships the migration). */
|
|
52
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
53
52
|
/** Whether the rule's subject matches this principal (role membership / everyone). */
|
|
54
53
|
function subjectMatches(row, input) {
|
|
55
54
|
const kind = row.rpr_subject_kind;
|
|
@@ -222,7 +221,9 @@ class MariaDbRecordPermissionRuleAdapter {
|
|
|
222
221
|
schema;
|
|
223
222
|
constructor(db, opts = {}) {
|
|
224
223
|
this.db = db;
|
|
225
|
-
|
|
224
|
+
// The `record_permission_rule` database: `opts.schema` (checked), else the resolved authz
|
|
225
|
+
// name (configurable-framework-db), fixed at construction.
|
|
226
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(opts.schema);
|
|
226
227
|
}
|
|
227
228
|
async evaluate(input) {
|
|
228
229
|
// tenant scoping: match rows for the resource's tenant OR the global/system baseline
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mariadb-record-share-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-record-share-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mariadb-record-share-adapter.d.ts","sourceRoot":"","sources":["../../src/authz/mariadb-record-share-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAIpD,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,eAAqC,CAAC;AAE3E,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAOD;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,eAAe;IAC/D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,EAAE,EAAE,cAAc,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAOxD,QAAQ,CACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC;CAqCpB"}
|
|
@@ -57,10 +57,9 @@
|
|
|
57
57
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
58
|
exports.MariaDbRecordShareAdapter = exports.SHIELD_RECORD_SHARE_PORT = void 0;
|
|
59
59
|
const core_1 = require("@astram/core");
|
|
60
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
60
61
|
/** The DI token the adapter is bound under (parity with the rule-port token). */
|
|
61
62
|
exports.SHIELD_RECORD_SHARE_PORT = Symbol('SHIELD_RECORD_SHARE_PORT');
|
|
62
|
-
/** Schema the `record_share` table lives in (astram3 ships the migration). */
|
|
63
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
64
63
|
/**
|
|
65
64
|
* The concrete per-record share adapter. Answers `hasShare` from `record_share`, matching
|
|
66
65
|
* user- and role-granted shares with exact-or-wildcard action.
|
|
@@ -70,7 +69,9 @@ class MariaDbRecordShareAdapter {
|
|
|
70
69
|
schema;
|
|
71
70
|
constructor(db, opts = {}) {
|
|
72
71
|
this.db = db;
|
|
73
|
-
|
|
72
|
+
// The `record_share` database: `opts.schema` (checked), else the resolved authz name
|
|
73
|
+
// (configurable-framework-db), fixed at construction.
|
|
74
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(opts.schema);
|
|
74
75
|
}
|
|
75
76
|
async hasShare(principalId, roleIds, typeKey, recordId, action) {
|
|
76
77
|
// Grantee predicate: the user share OR (only when roles exist) a role share. The role
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-share-cascade.d.ts","sourceRoot":"","sources":["../../src/authz/record-share-cascade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;
|
|
1
|
+
{"version":3,"file":"record-share-cascade.d.ts","sourceRoot":"","sources":["../../src/authz/record-share-cascade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1F;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,iBAAiB,CAgBxF"}
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
34
|
exports.makeShareDeleteCascade = makeShareDeleteCascade;
|
|
35
|
-
|
|
36
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
35
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
37
36
|
/**
|
|
38
37
|
* Build the delete-cascade function (a {@link RecordDeletedHook}) the consumer wires into
|
|
39
38
|
* the engine as `onRecordDeleted`. Removes a deleted record's `record_share` rows,
|
|
@@ -41,7 +40,9 @@ const DEFAULT_SCHEMA = 'shield_authz';
|
|
|
41
40
|
* no pool — the query fn is supplied by the engine on every call.
|
|
42
41
|
*/
|
|
43
42
|
function makeShareDeleteCascade(opts = {}) {
|
|
44
|
-
|
|
43
|
+
// The `record_share` database: explicit, else the resolved authz name, fixed here at build
|
|
44
|
+
// time (configurable-framework-db) — the hook itself never reads env.
|
|
45
|
+
const schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(opts.schema);
|
|
45
46
|
return async (query, typeKey, recordId, tenantId) => {
|
|
46
47
|
await query(`DELETE FROM \`${schema}\`.\`record_share\`` +
|
|
47
48
|
` WHERE rs_tenant_uuid = ? AND rs_type_key = ? AND rs_record_uuid = ?`, [tenantId, typeKey, recordId]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-share-writer.d.ts","sourceRoot":"","sources":["../../src/authz/record-share-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"record-share-writer.d.ts","sourceRoot":"","sources":["../../src/authz/record-share-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,8 +42,7 @@
|
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
43
|
exports.RecordShareWriter = exports.ShareStoreUnavailableError = exports.ShareNotPermittedError = exports.SHIELD_RECORD_SHARE_WRITER = void 0;
|
|
44
44
|
const node_crypto_1 = require("node:crypto");
|
|
45
|
-
|
|
46
|
-
const DEFAULT_SCHEMA = 'shield_authz';
|
|
45
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
47
46
|
/** The DI token the writer is bound under. */
|
|
48
47
|
exports.SHIELD_RECORD_SHARE_WRITER = Symbol('SHIELD_RECORD_SHARE_WRITER');
|
|
49
48
|
/** Thrown when the who-may-share bound rejects a share/unshare (fail-closed). */
|
|
@@ -72,7 +71,9 @@ class RecordShareWriter {
|
|
|
72
71
|
this.db = deps.db;
|
|
73
72
|
this.types = deps.types;
|
|
74
73
|
this.audit = deps.audit;
|
|
75
|
-
|
|
74
|
+
// The `record_share` database: `deps.schema` (checked), else the resolved authz name
|
|
75
|
+
// (configurable-framework-db), fixed at construction.
|
|
76
|
+
this.schema = (0, framework_schema_names_js_1.authzSchemaAtConstruction)(deps.schema);
|
|
76
77
|
this.now = deps.nowMs ?? (() => Date.now());
|
|
77
78
|
}
|
|
78
79
|
/**
|
|
@@ -27,6 +27,7 @@ import type { DecisionAuthority, ModuleRegistry, PermissionFactsPort, Principal,
|
|
|
27
27
|
import type { PermissionVersionReader } from './permission-version-cache.js';
|
|
28
28
|
import type { ObjectType } from '@astram/engine';
|
|
29
29
|
import { type RuleQueryable } from './mariadb-record-rule-adapter.js';
|
|
30
|
+
import { type FrameworkSchemaNames } from '../config/framework-schema-names.js';
|
|
30
31
|
import { type OperationManifestEntry } from './manifest-operation-authority-adapter.js';
|
|
31
32
|
/**
|
|
32
33
|
* The pieces a consumer supplies for the framework to build the real record-tier
|
|
@@ -57,6 +58,13 @@ export interface RecordAuthorizationInputs {
|
|
|
57
58
|
* ENTRIES; the framework owns the ADAPTER.
|
|
58
59
|
*/
|
|
59
60
|
readonly operationManifest?: readonly OperationManifestEntry[];
|
|
61
|
+
/**
|
|
62
|
+
* The resolved framework database names (configurable-framework-db, ADR-0037): every
|
|
63
|
+
* framework-built adapter reads `schemas.authz`. Inject `FRAMEWORK_SCHEMAS`. Absent ⇒ resolved
|
|
64
|
+
* from `SHIELD_DB_NAMESPACE` once, when the authority / list fn is built (never per request);
|
|
65
|
+
* `ShieldModule` fills it from `AppConfig.schemas` when the inputs omit it.
|
|
66
|
+
*/
|
|
67
|
+
readonly schemas?: FrameworkSchemaNames;
|
|
60
68
|
}
|
|
61
69
|
/**
|
|
62
70
|
* Construct the four framework-owned record-tier adapters over the supplied pool +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wire-record-authorization.d.ts","sourceRoot":"","sources":["../../src/authz/wire-record-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EAEd,mBAAmB,EACnB,SAAS,EAET,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAMtB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,kCAAkC,CAAC;AAM1C,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,2CAA2C,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,uFAAuF;IACvF,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAC9C,6FAA6F;IAC7F,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC1C,6GAA6G;IAC7G,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"wire-record-authorization.d.ts","sourceRoot":"","sources":["../../src/authz/wire-record-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EAEd,mBAAmB,EACnB,SAAS,EAET,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAMtB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,kCAAkC,CAAC;AAM1C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,2CAA2C,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,uFAAuF;IACvF,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAC9C,6FAA6F;IAC7F,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC;IAC1C,6GAA6G;IAC7G,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC/D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;CACzC;AAOD;;;;;GAKG;AACH;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,mBAAmB,EACzB,KAAK,EAAE,uBAAuB,GAC7B,mBAAmB,CA2BrB;AAED,6EAA6E;AAC7E,MAAM,WAAW,+BAA+B;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,uBAAuB,CAAC;CACjD;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,yBAAyB,EACjC,OAAO,GAAE,+BAAoC,GAC5C,iBAAiB,CA4BnB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAAC;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,yBAAyB,GAAG,WAAW,CAyE/E"}
|
|
@@ -10,7 +10,12 @@ const mariadb_cross_tenant_grant_adapter_js_1 = require("./mariadb-cross-tenant-
|
|
|
10
10
|
const mariadb_list_scope_adapter_js_1 = require("./mariadb-list-scope-adapter.js");
|
|
11
11
|
const list_scope_sql_js_1 = require("./list-scope-sql.js");
|
|
12
12
|
const session_facts_als_js_1 = require("../request-auth/session-facts-als.js");
|
|
13
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
13
14
|
const manifest_operation_authority_adapter_js_1 = require("./manifest-operation-authority-adapter.js");
|
|
15
|
+
/** The authz database the framework-built adapters read: `inputs.schemas`, else resolved now. */
|
|
16
|
+
function authzSchemaOf(inputs) {
|
|
17
|
+
return (0, framework_schema_names_js_1.schemaNamesAtConstruction)(inputs.schemas).authz;
|
|
18
|
+
}
|
|
14
19
|
/**
|
|
15
20
|
* Construct the four framework-owned record-tier adapters over the supplied pool +
|
|
16
21
|
* manifest, and return the fully-wired core {@link DecisionAuthority}. Behavior-identical
|
|
@@ -65,6 +70,7 @@ function buildRecordAuthorization(inputs, options = {}) {
|
|
|
65
70
|
const facts = options.versionCache !== undefined
|
|
66
71
|
? withRedisPermissionVersion(inputs.permissionFacts, options.versionCache)
|
|
67
72
|
: inputs.permissionFacts;
|
|
73
|
+
const schema = authzSchemaOf(inputs);
|
|
68
74
|
return (0, core_1.createWiredDecisionAuthority)({
|
|
69
75
|
registry: inputs.registry,
|
|
70
76
|
// The app-owned port, wrapped so a gate-5 reload inside an enforcement request notifies the
|
|
@@ -76,13 +82,13 @@ function buildRecordAuthorization(inputs, options = {}) {
|
|
|
76
82
|
// ── The FOUR framework-owned record-tier adapters — constructed HERE, and ONLY here.
|
|
77
83
|
// Record-permit ADMIN rules over `shield_authz.record_permission_rule` (widen the
|
|
78
84
|
// core-owned owner baseline, deny-wins). Empty table ⇒ owner-only (NOT a lockout).
|
|
79
|
-
recordRule: new mariadb_record_rule_adapter_js_1.MariaDbRecordPermissionRuleAdapter(inputs.pool),
|
|
85
|
+
recordRule: new mariadb_record_rule_adapter_js_1.MariaDbRecordPermissionRuleAdapter(inputs.pool, { schema }),
|
|
80
86
|
// Per-record SHARE source over `shield_authz.record_share` (widening permit, union
|
|
81
87
|
// with baseline under deny-wins). No share ⇒ false (baseline still governs).
|
|
82
|
-
recordShare: new mariadb_record_share_adapter_js_1.MariaDbRecordShareAdapter(inputs.pool),
|
|
88
|
+
recordShare: new mariadb_record_share_adapter_js_1.MariaDbRecordShareAdapter(inputs.pool, { schema }),
|
|
83
89
|
// Cross-tenant consented grants over `shield_authz.cross_tenant_grant`. No active
|
|
84
90
|
// grant ⇒ null (deny-by-default for the cross-tenant reach).
|
|
85
|
-
crossTenantGrant: new mariadb_cross_tenant_grant_adapter_js_1.MariaDbCrossTenantGrantAdapter(inputs.pool),
|
|
91
|
+
crossTenantGrant: new mariadb_cross_tenant_grant_adapter_js_1.MariaDbCrossTenantGrantAdapter(inputs.pool, { schema }),
|
|
86
92
|
// Delegation / trusted-operation authority over the DECLARED manifest (no DB).
|
|
87
93
|
// Empty ⇒ pass-through. The app supplies the entries; the framework owns the adapter.
|
|
88
94
|
operationAuthority: new manifest_operation_authority_adapter_js_1.ManifestOperationAuthorityAdapter(inputs.operationManifest ?? []),
|
|
@@ -107,13 +113,15 @@ function buildRecordAuthorization(inputs, options = {}) {
|
|
|
107
113
|
* unknown-field rejection) PROPAGATES so the read fails, NEVER falls open to unbounded.
|
|
108
114
|
*/
|
|
109
115
|
function buildListScopeFn(inputs) {
|
|
116
|
+
// The authz database, resolved ONCE here (build time) and captured by the per-request fn.
|
|
117
|
+
const schema = authzSchemaOf(inputs);
|
|
110
118
|
// Framework-constructed over `inputs.pool` — UN-overridable (not a field of the inputs).
|
|
111
|
-
const listScopePort = new mariadb_list_scope_adapter_js_1.MariaDbListScopeAdapter(inputs.pool);
|
|
119
|
+
const listScopePort = new mariadb_list_scope_adapter_js_1.MariaDbListScopeAdapter(inputs.pool, { schema });
|
|
112
120
|
// The cross-tenant grant adapter — reused HERE to resolve the OWNING tenants a grantee
|
|
113
121
|
// reaches, so the list can apply the OWNING tenant's deny rules to the cross-tenant branch
|
|
114
122
|
// (deny-wins per the resource's tenant — the fail-open leak the Phase-4 review found). Same
|
|
115
123
|
// un-overridable `inputs.pool`.
|
|
116
|
-
const crossTenantAdapter = new mariadb_cross_tenant_grant_adapter_js_1.MariaDbCrossTenantGrantAdapter(inputs.pool);
|
|
124
|
+
const crossTenantAdapter = new mariadb_cross_tenant_grant_adapter_js_1.MariaDbCrossTenantGrantAdapter(inputs.pool, { schema });
|
|
117
125
|
return async (reg, actor, action) => {
|
|
118
126
|
// Bridge the engine `ObjectType` → the core `ComputeListScopeDeps.registry` shape.
|
|
119
127
|
// `computeListScope` reads ONLY `descriptor.access` for the owner-baseline posture
|
|
@@ -156,7 +164,7 @@ function buildListScopeFn(inputs) {
|
|
|
156
164
|
}
|
|
157
165
|
// Translate the abstract spec → SAFE parameterized WHERE fragment. An unknown-field
|
|
158
166
|
// rejection here also PROPAGATES (fail-closed).
|
|
159
|
-
const translated = (0, list_scope_sql_js_1.translateListScope)(spec, reg, { principalId: actor.id, principalTenantId: actor.tenantId }, { owningTenantDeny });
|
|
167
|
+
const translated = (0, list_scope_sql_js_1.translateListScope)(spec, reg, { principalId: actor.id, principalTenantId: actor.tenantId }, { owningTenantDeny, schema });
|
|
160
168
|
return { sql: translated.sql, params: translated.params };
|
|
161
169
|
};
|
|
162
170
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import type { FrameworkSchemas } from '@astram/core';
|
|
2
3
|
import { type AppConfig, type PoolBudgetConfig } from '../config/app-config.js';
|
|
3
4
|
/**
|
|
4
5
|
* Boot sequence extension point (Infrastructure layer — ADR-0018).
|
|
@@ -17,6 +18,7 @@ import { type AppConfig, type PoolBudgetConfig } from '../config/app-config.js';
|
|
|
17
18
|
*/
|
|
18
19
|
export declare class BootSequence implements OnApplicationBootstrap {
|
|
19
20
|
private readonly config;
|
|
21
|
+
private readonly logger;
|
|
20
22
|
constructor(config: AppConfig);
|
|
21
23
|
onApplicationBootstrap(): Promise<void>;
|
|
22
24
|
/**
|
|
@@ -31,6 +33,14 @@ export declare class BootSequence implements OnApplicationBootstrap {
|
|
|
31
33
|
*/
|
|
32
34
|
private assertConnectionPoolReady;
|
|
33
35
|
}
|
|
36
|
+
/** The boot log line naming the resolved framework databases (names only, spec 5.E). */
|
|
37
|
+
export declare function frameworkDatabasesLogLine(s: FrameworkSchemas): string;
|
|
38
|
+
/**
|
|
39
|
+
* Single-database-layout spec §5.C, AC-1 (ADR-0041): the warning for `SHIELD_DB_NAME` set under
|
|
40
|
+
* the four layout (it is read only when `SHIELD_DB_LAYOUT=single`), else `undefined`. Names the
|
|
41
|
+
* variable only, never its value.
|
|
42
|
+
*/
|
|
43
|
+
export declare function shieldDbNameIgnoredWarning(env: NodeJS.ProcessEnv): string | undefined;
|
|
34
44
|
/**
|
|
35
45
|
* Validate a {@link PoolBudgetConfig} against the ADR-0018 budget. Exported so
|
|
36
46
|
* unit tests can assert the throw/no-throw contract directly without booting
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot-sequence.d.ts","sourceRoot":"","sources":["../../src/boot/boot-sequence.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"boot-sequence.d.ts","sourceRoot":"","sources":["../../src/boot/boot-sequence.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;GAcG;AACH,qBACa,YAAa,YAAW,sBAAsB;IAGzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFvD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;gBAEE,MAAM,EAAE,SAAS;IAE5D,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAa7C;;;;;;;;;OASG;YACW,yBAAyB;CAIxC;AAED,wFAAwF;AACxF,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAMrE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,SAAS,CAKrF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAsC5D"}
|
|
@@ -13,6 +13,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.BootSequence = void 0;
|
|
16
|
+
exports.frameworkDatabasesLogLine = frameworkDatabasesLogLine;
|
|
17
|
+
exports.shieldDbNameIgnoredWarning = shieldDbNameIgnoredWarning;
|
|
16
18
|
exports.assertPoolBudget = assertPoolBudget;
|
|
17
19
|
const common_1 = require("@nestjs/common");
|
|
18
20
|
const config_module_js_1 = require("../config/config.module.js");
|
|
@@ -34,12 +36,22 @@ const app_config_js_1 = require("../config/app-config.js");
|
|
|
34
36
|
*/
|
|
35
37
|
let BootSequence = class BootSequence {
|
|
36
38
|
config;
|
|
39
|
+
logger = new common_1.Logger('Shield');
|
|
37
40
|
constructor(config) {
|
|
38
41
|
this.config = config;
|
|
39
42
|
}
|
|
40
43
|
async onApplicationBootstrap() {
|
|
44
|
+
// configurable-framework-db spec 5.E: the resolved database names, once per boot. Names
|
|
45
|
+
// only — never a user, password, host or connection string.
|
|
46
|
+
this.logger.log(frameworkDatabasesLogLine((0, app_config_js_1.frameworkSchemasOf)(this.config)));
|
|
47
|
+
// Spec 5.C/AC-1: SHIELD_DB_NAME is read only in the single layout; say so when it is ignored.
|
|
48
|
+
const ignored = shieldDbNameIgnoredWarning(process.env);
|
|
49
|
+
if (ignored !== undefined)
|
|
50
|
+
this.logger.warn(ignored);
|
|
41
51
|
await this.assertConnectionPoolReady();
|
|
42
|
-
// Future boot-time assertions attach here (each fail-closed).
|
|
52
|
+
// Future boot-time assertions attach here (each fail-closed). The migration ledger check
|
|
53
|
+
// (spec 5.D) needs the runtime pool, so it runs from AuthModule (`auth: true`) and from
|
|
54
|
+
// IdentityFeatureModule: see ./migration-ledger-check.ts.
|
|
43
55
|
}
|
|
44
56
|
/**
|
|
45
57
|
* ADR-0018: assert the configured connection-pool budget fits under the DB
|
|
@@ -62,6 +74,26 @@ exports.BootSequence = BootSequence = __decorate([
|
|
|
62
74
|
__param(0, (0, common_1.Inject)(config_module_js_1.APP_CONFIG)),
|
|
63
75
|
__metadata("design:paramtypes", [Object])
|
|
64
76
|
], BootSequence);
|
|
77
|
+
/** The boot log line naming the resolved framework databases (names only, spec 5.E). */
|
|
78
|
+
function frameworkDatabasesLogLine(s) {
|
|
79
|
+
if (s.layout === 'single')
|
|
80
|
+
return `Shield databases: layout=single database=${s.app}`;
|
|
81
|
+
return (`Shield databases: namespace=${s.namespace} app=${s.app} identity=${s.identity} ` +
|
|
82
|
+
`authz=${s.authz} audit=${s.audit}`);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Single-database-layout spec §5.C, AC-1 (ADR-0041): the warning for `SHIELD_DB_NAME` set under
|
|
86
|
+
* the four layout (it is read only when `SHIELD_DB_LAYOUT=single`), else `undefined`. Names the
|
|
87
|
+
* variable only, never its value.
|
|
88
|
+
*/
|
|
89
|
+
function shieldDbNameIgnoredWarning(env) {
|
|
90
|
+
if (env.SHIELD_DB_LAYOUT === 'single')
|
|
91
|
+
return undefined;
|
|
92
|
+
const v = env.SHIELD_DB_NAME;
|
|
93
|
+
if (v === undefined || v.trim() === '')
|
|
94
|
+
return undefined;
|
|
95
|
+
return 'SHIELD_DB_NAME is read only when SHIELD_DB_LAYOUT=single; ignored.';
|
|
96
|
+
}
|
|
65
97
|
/**
|
|
66
98
|
* Validate a {@link PoolBudgetConfig} against the ADR-0018 budget. Exported so
|
|
67
99
|
* unit tests can assert the throw/no-throw contract directly without booting
|
|
@@ -78,13 +110,25 @@ function assertPoolBudget(cfg) {
|
|
|
78
110
|
'which exceeds the hard cap of 2. DDL is rare + serialized per tenant ' +
|
|
79
111
|
'(ADR-0014 §7) — keep this pool tiny (1–2).');
|
|
80
112
|
}
|
|
113
|
+
if (!e.withinUserBudget) {
|
|
114
|
+
throw new Error('[ADR-0018] connection-pool assertion FAILED (fail-closed): single layout needs ' +
|
|
115
|
+
`${e.requiredConnections} connections (workers(${cfg.workers}) × ` +
|
|
116
|
+
`${e.perWorkerConnections} + headroom(${cfg.headroom})) but the account allows ` +
|
|
117
|
+
`${cfg.maxUserConnections} (APP_DB_MAX_USER_CONNECTIONS). Reduce POOL_MAX_CORE, ` +
|
|
118
|
+
'POOL_MAX_ENGINE, APP_AUTHZ_POOL_MAX, POOL_WORKERS or POOL_HEADROOM, or raise ' +
|
|
119
|
+
'MAX_USER_CONNECTIONS on the account (ADR-0041).');
|
|
120
|
+
}
|
|
81
121
|
if (!e.withinBudget) {
|
|
82
122
|
throw new Error('[ADR-0018] connection-pool assertion FAILED (fail-closed): required ' +
|
|
83
123
|
`connections ${e.requiredConnections} exceed max_connections ` +
|
|
84
124
|
`${cfg.maxConnections}. Budget = workers(${cfg.workers}) × ` +
|
|
85
125
|
`Σ(per-account pool max)(${e.perWorkerConnections}) + headroom(` +
|
|
86
126
|
`${cfg.headroom}) = ${e.requiredConnections} > ${cfg.maxConnections}. ` +
|
|
87
|
-
|
|
88
|
-
|
|
127
|
+
(cfg.layout === 'single'
|
|
128
|
+
? 'Single layout: one account opens POOL_MAX_CORE + POOL_MAX_ENGINE (unset ⇒ ' +
|
|
129
|
+
'APP_DB_MAX_CONNECTIONS, else 10) + APP_AUTHZ_POOL_MAX per worker; set POOL_MAX_ENGINE ' +
|
|
130
|
+
'explicitly, lower a pool cap or the worker count, or raise max_connections.'
|
|
131
|
+
: 'Reduce a per-account pool cap, the worker count, or raise ' +
|
|
132
|
+
'max_connections (and MariaDB my.cnf) to restore the budget.'));
|
|
89
133
|
}
|
|
90
134
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import { type FrameworkSchemas, type MigrationLedgerLocation } from '@astram/core';
|
|
3
|
+
/** Runs one SELECT on the runtime pool (a mariadb `Pool.query` fits). */
|
|
4
|
+
export type LedgerQuery = (sql: string) => Promise<unknown>;
|
|
5
|
+
/** Where the boot check looks for warnings. */
|
|
6
|
+
export interface LedgerCheckLogger {
|
|
7
|
+
warn(message: string): void;
|
|
8
|
+
}
|
|
9
|
+
export type { MigrationLedgerLocation };
|
|
10
|
+
export interface FrameworkMigrationsCheckOptions extends MigrationLedgerLocation {
|
|
11
|
+
/**
|
|
12
|
+
* Further ledger locations, tried in order after `database`/`table` (G-007 QA P1). Empty or
|
|
13
|
+
* absent ⇒ `database`/`table` is read directly. Otherwise each location is probed
|
|
14
|
+
* (information_schema) and the first whose table exists is read; none ⇒ fail closed.
|
|
15
|
+
*/
|
|
16
|
+
readonly alternatives?: readonly MigrationLedgerLocation[];
|
|
17
|
+
readonly query: LedgerQuery;
|
|
18
|
+
/**
|
|
19
|
+
* Directory (or directories) of shipped `.cjs` migrations (`guardMigrationsDir`,
|
|
20
|
+
* `identityMigrationsDir`); ids of several directories are checked as one set.
|
|
21
|
+
*/
|
|
22
|
+
readonly migrationsDir: string | readonly string[];
|
|
23
|
+
/** The raw `NODE_ENV`; only `development` and `test` downgrade a failure to a warning. */
|
|
24
|
+
readonly nodeEnv: string | undefined;
|
|
25
|
+
readonly logger: LedgerCheckLogger;
|
|
26
|
+
}
|
|
27
|
+
export interface FrameworkMigrationsCheckResult {
|
|
28
|
+
/** `true` when every shipped id is in the ledger. */
|
|
29
|
+
readonly ok: boolean;
|
|
30
|
+
/** Shipped ids absent from the ledger (all of them when the ledger is missing or unreadable). */
|
|
31
|
+
readonly missing: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
/** The migration ids shipped in `dir` (`.cjs` files only), ascending. */
|
|
34
|
+
export declare function frameworkMigrationIds(dir: string): string[];
|
|
35
|
+
/**
|
|
36
|
+
* The migrate CLI's ledger location rule (core `resolveMigrationLedgerLocation`: `<ns>_app` when
|
|
37
|
+
* namespaced, else `DDL_DB_NAME ?? <default app>`). The boot check itself uses
|
|
38
|
+
* {@link resolveMigrationLedgerCheck}, which also tries the runtime `APP_DB_NAME`.
|
|
39
|
+
* @throws FrameworkSchemaConfigError on a conflicting `DDL_DB_NAME` or invalid names.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveMigrationLedger(env: NodeJS.ProcessEnv, schemas: FrameworkSchemas): MigrationLedgerLocation;
|
|
42
|
+
/** Where the boot check looks: the first candidate plus the ones tried after it. */
|
|
43
|
+
export interface MigrationLedgerCheckLocation extends MigrationLedgerLocation {
|
|
44
|
+
readonly alternatives: readonly MigrationLedgerLocation[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The boot check's ledger locations for this process's env (G-007 QA P1): core
|
|
48
|
+
* `migrationLedgerCandidates`, split into the first location and its `alternatives`. Namespace
|
|
49
|
+
* set ⇒ `<ns>_app` only; default ⇒ `DDL_DB_NAME`, the runtime `APP_DB_NAME`, `shield_app`.
|
|
50
|
+
* Spread it into {@link FrameworkMigrationsCheckOptions}.
|
|
51
|
+
* @throws FrameworkSchemaConfigError on a conflicting `DDL_DB_NAME` or invalid names.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveMigrationLedgerCheck(env: NodeJS.ProcessEnv, schemas: FrameworkSchemas): MigrationLedgerCheckLocation;
|
|
54
|
+
/**
|
|
55
|
+
* Compare the shipped migration ids in `migrationsDir` with the ledger; throw (production) or
|
|
56
|
+
* warn (development/test) when any is missing or the ledger cannot be read.
|
|
57
|
+
* @throws Error naming the database and up to 10 missing ids, outside development/test; and in
|
|
58
|
+
* every environment for an invalid ledger database or table name (checked before any query).
|
|
59
|
+
*/
|
|
60
|
+
export declare function assertFrameworkMigrationsApplied(options: FrameworkMigrationsCheckOptions): Promise<FrameworkMigrationsCheckResult>;
|
|
61
|
+
/** DI token of the per-app {@link MigrationLedgerRegistry} (provided by `ShieldModule`). */
|
|
62
|
+
export declare const SHIELD_MIGRATION_LEDGER_REGISTRY: unique symbol;
|
|
63
|
+
/** DI token of guard's own check (`AuthModule`); identity provides its check under its own token. */
|
|
64
|
+
export declare const SHIELD_GUARD_MIGRATION_LEDGER_CHECK: unique symbol;
|
|
65
|
+
/**
|
|
66
|
+
* Merges the ledger checks of one application (guard's `AuthModule` and identity) so each ledger
|
|
67
|
+
* location is read once. Hooks {@link register} at construction (all providers exist before any
|
|
68
|
+
* bootstrap hook runs); the first {@link run} for a location checks the union of every registered
|
|
69
|
+
* directory and caches that promise, so later hooks share the result, rejection included.
|
|
70
|
+
*/
|
|
71
|
+
export declare class MigrationLedgerRegistry {
|
|
72
|
+
private readonly entries;
|
|
73
|
+
/** The whole candidate list: hooks with the same list share one probe + read. */
|
|
74
|
+
private static key;
|
|
75
|
+
/** Add `options.migrationsDir` to the check of `options`' ledger location. */
|
|
76
|
+
register(options: FrameworkMigrationsCheckOptions): void;
|
|
77
|
+
/** The (shared) check of `location`'s ledger over every registered directory. */
|
|
78
|
+
run(location: MigrationLedgerLocation & {
|
|
79
|
+
alternatives?: readonly MigrationLedgerLocation[];
|
|
80
|
+
}): Promise<FrameworkMigrationsCheckResult>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The boot hook: runs {@link assertFrameworkMigrationsApplied} once, when Nest bootstraps the
|
|
84
|
+
* application (after module init, before the HTTP server listens). Never on a request. With a
|
|
85
|
+
* {@link MigrationLedgerRegistry}, it shares one read per ledger location with the app's other
|
|
86
|
+
* hooks; without one (`null`/absent), it checks alone.
|
|
87
|
+
*/
|
|
88
|
+
export declare class FrameworkMigrationLedgerCheck implements OnApplicationBootstrap {
|
|
89
|
+
private readonly options;
|
|
90
|
+
private readonly registry;
|
|
91
|
+
constructor(options: FrameworkMigrationsCheckOptions, registry?: MigrationLedgerRegistry | null);
|
|
92
|
+
onApplicationBootstrap(): Promise<void>;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=migration-ledger-check.d.ts.map
|