@astram/engine 0.10.2 → 0.12.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/decorators/object-type.decorator.d.ts +2 -0
- package/dist/decorators/object-type.decorator.d.ts.map +1 -1
- package/dist/decorators/object-type.decorator.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/module/engine.module.d.ts.map +1 -1
- package/dist/module/engine.module.js +9 -0
- package/dist/pipe/context.d.ts +5 -0
- package/dist/pipe/context.d.ts.map +1 -1
- package/dist/pipe/record-engine.d.ts.map +1 -1
- package/dist/pipe/record-engine.js +26 -5
- package/dist/pipe/stages/audit.d.ts.map +1 -1
- package/dist/pipe/stages/audit.js +4 -0
- package/dist/pipe/stages/validate.d.ts.map +1 -1
- package/dist/pipe/stages/validate.js +6 -0
- package/dist/registry.d.ts +25 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +106 -7
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -71,6 +71,8 @@ export interface FieldOptions {
|
|
|
71
71
|
readonly role?: IdentityRole;
|
|
72
72
|
/** Create-only (ADR-0034): ignored on update. See `FieldSpec.immutable`. */
|
|
73
73
|
readonly immutable?: boolean;
|
|
74
|
+
/** G-023: may be written as SQL NULL. See `FieldSpec.nullable`. */
|
|
75
|
+
readonly nullable?: boolean;
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
76
78
|
* `@PrimaryKey` options — the {@link PkStrategy} discriminated union verbatim, so it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-type.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/object-type.decorator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EACV,iBAAiB,EAEjB,SAAS,EACT,YAAY,EACZ,YAAY,EAKZ,UAAU,IAAI,kBAAkB,EAChC,UAAU,EACV,SAAS,EACT,aAAa,EACd,MAAM,aAAa,CAAC;AAarB;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"object-type.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/object-type.decorator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EACV,iBAAiB,EAEjB,SAAS,EACT,YAAY,EACZ,YAAY,EAKZ,UAAU,IAAI,kBAAkB,EAChC,UAAU,EACV,SAAS,EACT,aAAa,EACd,MAAM,aAAa,CAAC;AAarB;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAI3C;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,cAAc,CAIlE;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,UAAW,SAAQ,kBAAkB;CAAG;AAEzD;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,iBAAiB,CAO3D;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,cAAc,CAIlE;AAwBD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,kBAAkB,CAkCnE"}
|
|
@@ -106,6 +106,8 @@ function reflectField(spec) {
|
|
|
106
106
|
// Reflected AS-IS when present (a non-boolean is rejected by the registry at boot).
|
|
107
107
|
if (spec.immutable !== undefined)
|
|
108
108
|
f.immutable = spec.immutable;
|
|
109
|
+
if (spec.nullable !== undefined)
|
|
110
|
+
f.nullable = spec.nullable;
|
|
109
111
|
return f;
|
|
110
112
|
}
|
|
111
113
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export { EngineError, CapabilityNotSupportedError, RegistrationError, Authorizat
|
|
|
26
26
|
export { ObjectType, Field, PrimaryKey, reflectObjectType, type ObjectTypeOptions, type FieldOptions, type PrimaryKeyOptions, } from './decorators/object-type.decorator.js';
|
|
27
27
|
export { AccessBundle, reflectAccessBundle, type AccessBundleOptions, type AccessBundlePermission, type AccessBundleSpec, } from './decorators/access-bundle.decorator.js';
|
|
28
28
|
export { EngineModule, RECORD_ENGINE, ENGINE_ALL_REGISTRATIONS, ENGINE_ALL_ACCESS_BUNDLES, type EngineModuleOptions, type ObjectTypeInput, } from './module/engine.module.js';
|
|
29
|
-
export { TableRegistry, columnOf, uuidPkColumn, isOwned, ownerColumn, tenantColumnOf, columnForRole, requireRole, effectiveActions, } from './registry.js';
|
|
29
|
+
export { TableRegistry, columnOf, uuidPkColumn, isOwned, ownerColumn, tenantColumnOf, columnForRole, requireRole, effectiveActions, isGlobalType, isUnwalledDataType, bootAccessSummary, type ActionDeclaration, type BootAccessSummary, } from './registry.js';
|
|
30
30
|
export { RecordEngineImpl, type RecordEngineDeps } from './pipe/record-engine.js';
|
|
31
31
|
export { RecordsService, BoundRecords, type ServiceAccountResolver, SERVICE_ACCOUNT_RESOLVER, } from './pipe/records-service.js';
|
|
32
32
|
export type { EngineDbConfig } from './adapters/mariadb-unit-of-work.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EACT,cAAc,EACd,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,EACf,SAAS,EACT,SAAS,EACT,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAMpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAKnF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACL,WAAW,EACX,2BAA2B,EAC3B,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAiBrB,OAAO,EACL,UAAU,EACV,KAAK,EACL,UAAU,EACV,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,uCAAuC,CAAC;AAO/C,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,wBAAwB,EACxB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,aAAa,EACb,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EACT,cAAc,EACd,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,EACf,SAAS,EACT,SAAS,EACT,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAMpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAKnF,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACL,WAAW,EACX,2BAA2B,EAC3B,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAiBrB,OAAO,EACL,UAAU,EACV,KAAK,EACL,UAAU,EACV,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,uCAAuC,CAAC;AAO/C,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,yCAAyC,CAAC;AAEjD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,wBAAwB,EACxB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EACL,cAAc,EACd,YAAY,EACZ,KAAK,sBAAsB,EAC3B,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC1F,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC/E,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* `@astram/engine/internal`, which only the composition root may import.
|
|
20
20
|
*/
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.operationOf = exports.MariaDbAuditSink = exports.SERVICE_ACCOUNT_RESOLVER = exports.BoundRecords = exports.RecordsService = exports.RecordEngineImpl = exports.effectiveActions = exports.requireRole = exports.columnForRole = exports.tenantColumnOf = exports.ownerColumn = exports.isOwned = exports.uuidPkColumn = exports.columnOf = exports.TableRegistry = exports.ENGINE_ALL_ACCESS_BUNDLES = exports.ENGINE_ALL_REGISTRATIONS = exports.RECORD_ENGINE = exports.EngineModule = exports.reflectAccessBundle = exports.AccessBundle = exports.reflectObjectType = exports.PrimaryKey = exports.Field = exports.ObjectType = exports.EngineUnavailableError = exports.ValidationError = exports.AuthorizationDeniedError = exports.RegistrationError = exports.CapabilityNotSupportedError = exports.EngineError = exports.canonicalUuid = exports.resolveObjectTypeSchema = exports.FRAMEWORK_SCHEMA = exports.READ_SCOPE_NODES_TOKEN = void 0;
|
|
22
|
+
exports.operationOf = exports.MariaDbAuditSink = exports.SERVICE_ACCOUNT_RESOLVER = exports.BoundRecords = exports.RecordsService = exports.RecordEngineImpl = exports.bootAccessSummary = exports.isUnwalledDataType = exports.isGlobalType = exports.effectiveActions = exports.requireRole = exports.columnForRole = exports.tenantColumnOf = exports.ownerColumn = exports.isOwned = exports.uuidPkColumn = exports.columnOf = exports.TableRegistry = exports.ENGINE_ALL_ACCESS_BUNDLES = exports.ENGINE_ALL_REGISTRATIONS = exports.RECORD_ENGINE = exports.EngineModule = exports.reflectAccessBundle = exports.AccessBundle = exports.reflectObjectType = exports.PrimaryKey = exports.Field = exports.ObjectType = exports.EngineUnavailableError = exports.ValidationError = exports.AuthorizationDeniedError = exports.RegistrationError = exports.CapabilityNotSupportedError = exports.EngineError = exports.canonicalUuid = exports.resolveObjectTypeSchema = exports.FRAMEWORK_SCHEMA = exports.READ_SCOPE_NODES_TOKEN = void 0;
|
|
23
23
|
// The read-scope subtree-id placeholder token (ADR-0027) — a `subtreeSubquery` template
|
|
24
24
|
// uses it; the engine expands it to a `?`-list. Exported so per-type declarations can
|
|
25
25
|
// reference the canonical token (rather than a stringly-typed duplicate).
|
|
@@ -89,6 +89,9 @@ Object.defineProperty(exports, "tenantColumnOf", { enumerable: true, get: functi
|
|
|
89
89
|
Object.defineProperty(exports, "columnForRole", { enumerable: true, get: function () { return registry_js_2.columnForRole; } });
|
|
90
90
|
Object.defineProperty(exports, "requireRole", { enumerable: true, get: function () { return registry_js_2.requireRole; } });
|
|
91
91
|
Object.defineProperty(exports, "effectiveActions", { enumerable: true, get: function () { return registry_js_2.effectiveActions; } });
|
|
92
|
+
Object.defineProperty(exports, "isGlobalType", { enumerable: true, get: function () { return registry_js_2.isGlobalType; } });
|
|
93
|
+
Object.defineProperty(exports, "isUnwalledDataType", { enumerable: true, get: function () { return registry_js_2.isUnwalledDataType; } });
|
|
94
|
+
Object.defineProperty(exports, "bootAccessSummary", { enumerable: true, get: function () { return registry_js_2.bootAccessSummary; } });
|
|
92
95
|
var record_engine_js_1 = require("./pipe/record-engine.js");
|
|
93
96
|
Object.defineProperty(exports, "RecordEngineImpl", { enumerable: true, get: function () { return record_engine_js_1.RecordEngineImpl; } });
|
|
94
97
|
var records_service_js_1 = require("./pipe/records-service.js");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.module.d.ts","sourceRoot":"","sources":["../../src/module/engine.module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,aAAa,EAMnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAuC,OAAO,EAAE,MAAM,aAAa,CAAC;AAIhF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC7F,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,0CAA0C,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAC;AAMpD;;;;2EAI2E;AAC3E,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB;;;;qCAIqC;AACrC,eAAO,MAAM,wBAAwB,eAAqC,CAAC;AAE3E;;;;+CAI+C;AAC/C,eAAO,MAAM,yBAAyB,eAAsC,CAAC;AAmC7E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B;iFAC6E;IAC7E,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IACpC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;;;;;;OAQG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CACnB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;CAC3D;AAYD,qBACa,YAAY;IACvB;;;;;;;;;OASG;IACH,MAAM,CAAC,UAAU,CACf,aAAa,EAAE,SAAS,eAAe,EAAE,EACzC,IAAI,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,SAAS,CAAC,gBAAgB,GAAG,QAAQ,CAAC,EAAE,CAAA;KAAE,GAClE,aAAa;IAMhB;2FACuF;IACvF,MAAM,CAAC,aAAa,IAAI,IAAI;IAK5B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa;
|
|
1
|
+
{"version":3,"file":"engine.module.d.ts","sourceRoot":"","sources":["../../src/module/engine.module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAEL,KAAK,aAAa,EAMnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAuC,OAAO,EAAE,MAAM,aAAa,CAAC;AAIhF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC7F,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,0CAA0C,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAC;AAMpD;;;;2EAI2E;AAC3E,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB;;;;qCAIqC;AACrC,eAAO,MAAM,wBAAwB,eAAqC,CAAC;AAE3E;;;;+CAI+C;AAC/C,eAAO,MAAM,yBAAyB,eAAsC,CAAC;AAmC7E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAC5B;iFAC6E;IAC7E,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IACpC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;;;;;;OAQG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CACnB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;CAC3D;AAYD,qBACa,YAAY;IACvB;;;;;;;;;OASG;IACH,MAAM,CAAC,UAAU,CACf,aAAa,EAAE,SAAS,eAAe,EAAE,EACzC,IAAI,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,SAAS,CAAC,gBAAgB,GAAG,QAAQ,CAAC,EAAE,CAAA;KAAE,GAClE,aAAa;IAMhB;2FACuF;IACvF,MAAM,CAAC,aAAa,IAAI,IAAI;IAK5B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa;CA0H5D"}
|
|
@@ -155,6 +155,15 @@ let EngineModule = EngineModule_1 = class EngineModule {
|
|
|
155
155
|
});
|
|
156
156
|
for (const reg of allRegistrations)
|
|
157
157
|
registry.register(reg);
|
|
158
|
+
// G-022 R7/R8 (ADR-0046): name the global types, and warn about each data-plane type
|
|
159
|
+
// with no tenant wall (its non-root reads and writes are denied).
|
|
160
|
+
const summary = (0, registry_js_1.bootAccessSummary)(registry.all());
|
|
161
|
+
logger.log(`global reference types: ${summary.globalTypes.length > 0 ? summary.globalTypes.join(', ') : 'none'}`);
|
|
162
|
+
for (const typeKey of summary.tenantlessDataTypes) {
|
|
163
|
+
logger.warn(`object type '${typeKey}' is plane 'data' with no tenant wall (no trusted:'tenantId' ` +
|
|
164
|
+
`field, no readScope): non-root reads and writes are denied. Declare it ` +
|
|
165
|
+
`global: true (shared reference data), tenantScoped, or give it a readScope.`);
|
|
166
|
+
}
|
|
158
167
|
return registry;
|
|
159
168
|
},
|
|
160
169
|
};
|
package/dist/pipe/context.d.ts
CHANGED
|
@@ -62,6 +62,11 @@ export interface WriteContext extends PipeBase {
|
|
|
62
62
|
readonly id: string;
|
|
63
63
|
readonly index: number;
|
|
64
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* G-023: keys of the `nullable` fields this write sets to NULL, in declaration order, filled by
|
|
67
|
+
* the validate stage. The audit stage records them as `cleared` (keys only, never values).
|
|
68
|
+
*/
|
|
69
|
+
cleared?: string[];
|
|
65
70
|
}
|
|
66
71
|
/** A stage: a small, ordered, independently-testable unit of the pipe. */
|
|
67
72
|
export interface Stage {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/pipe/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,gDAAgD;AAChD,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAErD,6DAA6D;AAC7D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAClC,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,+CAA+C;IAC/C,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,8CAA8C;IAC9C,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAC7C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/pipe/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,gDAAgD;AAChD,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAErD,6DAA6D;AAC7D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAClC,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,+CAA+C;IAC/C,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,8CAA8C;IAC9C,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;IAC7C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,0EAA0E;AAC1E,MAAM,WAAW,KAAK;IACpB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAO5F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-engine.d.ts","sourceRoot":"","sources":["../../src/pipe/record-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"record-engine.d.ts","sourceRoot":"","sources":["../../src/pipe/record-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -211,11 +211,7 @@ class RecordEngineImpl {
|
|
|
211
211
|
}
|
|
212
212
|
async runWrite(tx, op, typeKey, actor, opts) {
|
|
213
213
|
const registration = this.registry.require(typeKey); // resolve-schema
|
|
214
|
-
|
|
215
|
-
// before any SQL or decision.
|
|
216
|
-
if (registration.crudActions === false) {
|
|
217
|
-
throw new errors_js_1.RegistrationError(`type '${typeKey}' declares crudActions:false; engine ${op} refused`);
|
|
218
|
-
}
|
|
214
|
+
refuseEngineWrite(registration, op, actor);
|
|
219
215
|
const nowMs = this.now();
|
|
220
216
|
return this.inUnit(tx, true, async (query) => {
|
|
221
217
|
const ctx = (0, context_js_1.newWriteContext)({ op, actor, registration, query, nowMs }, {
|
|
@@ -275,6 +271,8 @@ class RecordEngineImpl {
|
|
|
275
271
|
if (inputs.length > CREATE_MANY_CAP) {
|
|
276
272
|
throw new errors_js_2.ValidationError('inputs', `at most ${CREATE_MANY_CAP} rows per call`);
|
|
277
273
|
}
|
|
274
|
+
// Refuse an authority-only, global or unwalled type before the batch opens a transaction.
|
|
275
|
+
refuseEngineWrite(this.registry.require(typeKey), 'create', actor);
|
|
278
276
|
const batchId = (0, node_crypto_1.randomUUID)();
|
|
279
277
|
return this.transactionIn(tx, async () => {
|
|
280
278
|
const state = tx ?? this.activeTx.getStore();
|
|
@@ -647,6 +645,29 @@ class RecordEngineImpl {
|
|
|
647
645
|
}
|
|
648
646
|
}
|
|
649
647
|
exports.RecordEngineImpl = RecordEngineImpl;
|
|
648
|
+
/**
|
|
649
|
+
* Engine write refusals, before any SQL or decision (and, for `createMany`, before the batch
|
|
650
|
+
* opens a transaction). They throw ahead of the unit of work, so nothing was written and a
|
|
651
|
+
* caller's outer transaction is not marked rollback-only.
|
|
652
|
+
* - R2 (ADR-0038): an authority-only (`crudActions:false`) type is never CRUD'd by the engine.
|
|
653
|
+
* - G-022 R4 (D-1): a global type's rows change only by migration — refused for everyone, root too.
|
|
654
|
+
* - R8 (D-2): a data-plane type with no tenant column, no readScope and not global has no
|
|
655
|
+
* tenant wall, so a non-root write is denied, as its reads already are. Root continues to
|
|
656
|
+
* the gate and keeps `root_data_plane_denied`.
|
|
657
|
+
*/
|
|
658
|
+
function refuseEngineWrite(registration, op, actor) {
|
|
659
|
+
const typeKey = registration.typeKey;
|
|
660
|
+
if (registration.crudActions === false) {
|
|
661
|
+
throw new errors_js_1.RegistrationError(`type '${typeKey}' declares crudActions:false; engine ${op} refused`);
|
|
662
|
+
}
|
|
663
|
+
if ((0, registry_js_1.isGlobalType)(registration)) {
|
|
664
|
+
throw new errors_js_1.RegistrationError(`type '${typeKey}' is global reference data (read-only); engine ${op} refused — ` +
|
|
665
|
+
`change its rows with a migration`);
|
|
666
|
+
}
|
|
667
|
+
if (actor.isRoot !== true && (0, registry_js_1.isUnwalledDataType)(registration)) {
|
|
668
|
+
throw new errors_js_2.AuthorizationDeniedError('tenantless_data_write_denied', `'${typeKey}' has no tenant wall; declare it global, tenantScoped or with a readScope`);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
650
671
|
/**
|
|
651
672
|
* Clamp a list/aggregate `limit` to 1..1000. Absent or non-finite (`NaN`, ±Infinity) ⇒ the
|
|
652
673
|
* default 100, so a bad number is never bound as `NULL`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAgC,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,eAAe,CAAC;AAMlE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAgC,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,eAAe,CAAC;AAMlE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CA+ClD"}
|
|
@@ -42,6 +42,10 @@ function auditStage(audit) {
|
|
|
42
42
|
...(ctx.batch !== undefined
|
|
43
43
|
? { batchId: ctx.batch.id, batchIndex: ctx.batch.index }
|
|
44
44
|
: {}),
|
|
45
|
+
// G-023: the nullable fields this write set to NULL (keys only, never values).
|
|
46
|
+
...(ctx.cleared !== undefined && ctx.cleared.length > 0
|
|
47
|
+
? { cleared: [...ctx.cleared] }
|
|
48
|
+
: {}),
|
|
45
49
|
// Bound operation step only (Shield #9): attributable "on behalf of".
|
|
46
50
|
...(binding !== undefined
|
|
47
51
|
? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,gBAAgB,CAAC;AAW3D;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CA6ChE;AAED,wBAAgB,aAAa,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,gBAAgB,CAAC;AAW3D;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CA6ChE;AAED,wBAAgB,aAAa,IAAI,KAAK,CAyCrC"}
|
|
@@ -99,6 +99,12 @@ function validateStage() {
|
|
|
99
99
|
}
|
|
100
100
|
continue; // absent + optional (or update patch) → skip
|
|
101
101
|
}
|
|
102
|
+
// G-023: a declared-nullable field binds SQL NULL as is. Kept out of `coerce()`, which
|
|
103
|
+
// also coerces `where` operands, so filters keep their behaviour.
|
|
104
|
+
if (ctx.columns[col] === null && field.nullable === true) {
|
|
105
|
+
(ctx.cleared ??= []).push(field.key);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
102
108
|
ctx.columns[col] = coerce(field, ctx.columns[col]);
|
|
103
109
|
}
|
|
104
110
|
},
|
package/dist/registry.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* (the no-code phase); the pipe does not distinguish how a registration arrived.
|
|
10
10
|
*/
|
|
11
11
|
import { type FrameworkSchemas } from '@astram/core';
|
|
12
|
-
import type { FieldSpec, PkStrategy, ObjectType, Principal } from './types.js';
|
|
12
|
+
import type { AccessDeclaration, FieldSpec, PkStrategy, ObjectType, Principal } from './types.js';
|
|
13
13
|
/** The four resolved names `resolveObjectTypeSchema` needs (a core `FrameworkSchemas` fits). */
|
|
14
14
|
export type FrameworkSchemaNames = Pick<FrameworkSchemas, 'app' | 'identity' | 'authz' | 'audit'> & Partial<Pick<FrameworkSchemas, 'layout'>>;
|
|
15
15
|
/** Options for {@link TableRegistry} (single-database-layout spec 5.B, ADR-0041). */
|
|
@@ -115,12 +115,34 @@ export declare function writeScopeClause(reg: ObjectType, actor: Principal): {
|
|
|
115
115
|
* walled (fail closed). Root is handled by {@link writeScopeClause} returning `null`.
|
|
116
116
|
*/
|
|
117
117
|
export declare function isCreateWalled(reg: ObjectType): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Whether a type is data-plane, has no tenant column, no `readScope` and is not global
|
|
120
|
+
* (G-022 R8, D-2): nothing walls its rows to a tenant, so its reads already fail closed for
|
|
121
|
+
* non-root (list scope `FALSE`) and the engine refuses its non-root writes the same way.
|
|
122
|
+
*/
|
|
123
|
+
export declare function isUnwalledDataType(reg: ObjectType): boolean;
|
|
124
|
+
/** What the engine logs at boot about tenant-less types (G-022 R7, R8). */
|
|
125
|
+
export interface BootAccessSummary {
|
|
126
|
+
/** Type keys declared `global: true`. */
|
|
127
|
+
readonly globalTypes: readonly string[];
|
|
128
|
+
/** Type keys for which {@link isUnwalledDataType} holds (one boot warning each). */
|
|
129
|
+
readonly tenantlessDataTypes: readonly string[];
|
|
130
|
+
}
|
|
131
|
+
export declare function bootAccessSummary(regs: readonly ObjectType[]): BootAccessSummary;
|
|
118
132
|
/** Boot-enforce that exactly-one field claims `role`; throw if none. */
|
|
119
133
|
export declare function requireRole(reg: ObjectType, role: NonNullable<FieldSpec['role']>): void;
|
|
120
|
-
/**
|
|
121
|
-
|
|
134
|
+
/**
|
|
135
|
+
* What the action vocabulary reads from a registration (typeKey only names it in errors;
|
|
136
|
+
* `access.global` fixes the vocabulary to `read`, G-022).
|
|
137
|
+
*/
|
|
138
|
+
export type ActionDeclaration = Pick<ObjectType, 'actions' | 'crudActions'> & {
|
|
122
139
|
readonly typeKey?: string;
|
|
140
|
+
readonly access?: Pick<AccessDeclaration, 'global'>;
|
|
123
141
|
};
|
|
142
|
+
/** Whether the type is global reference data (`access.global === true`, G-022, ADR-0046). */
|
|
143
|
+
export declare function isGlobalType(reg: {
|
|
144
|
+
readonly access?: Pick<AccessDeclaration, 'global'>;
|
|
145
|
+
}): boolean;
|
|
124
146
|
/**
|
|
125
147
|
* The type's action vocabulary (ADR-0038): `read, create, update, delete` then the declared
|
|
126
148
|
* extras in declared order, or exactly the declared list when `crudActions === false`.
|
|
@@ -129,5 +151,4 @@ type ActionDeclaration = Pick<ObjectType, 'actions' | 'crudActions'> & {
|
|
|
129
151
|
* Framework-facing: the guard registry bridge, identity lookups and `authorize()` read it.
|
|
130
152
|
*/
|
|
131
153
|
export declare function effectiveActions(reg: ActionDeclaration): readonly string[];
|
|
132
|
-
export {};
|
|
133
154
|
//# sourceMappingURL=registry.d.ts.map
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AAOtB,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/registry.js
CHANGED
|
@@ -20,7 +20,10 @@ exports.tenantColumnOf = tenantColumnOf;
|
|
|
20
20
|
exports.columnForRole = columnForRole;
|
|
21
21
|
exports.writeScopeClause = writeScopeClause;
|
|
22
22
|
exports.isCreateWalled = isCreateWalled;
|
|
23
|
+
exports.isUnwalledDataType = isUnwalledDataType;
|
|
24
|
+
exports.bootAccessSummary = bootAccessSummary;
|
|
23
25
|
exports.requireRole = requireRole;
|
|
26
|
+
exports.isGlobalType = isGlobalType;
|
|
24
27
|
exports.effectiveActions = effectiveActions;
|
|
25
28
|
const core_1 = require("@astram/core");
|
|
26
29
|
const errors_js_1 = require("./errors.js");
|
|
@@ -265,6 +268,23 @@ function writeScopeClause(reg, actor) {
|
|
|
265
268
|
function isCreateWalled(reg) {
|
|
266
269
|
return reg.readScope !== undefined && reg.readScope.create !== 'unscoped';
|
|
267
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Whether a type is data-plane, has no tenant column, no `readScope` and is not global
|
|
273
|
+
* (G-022 R8, D-2): nothing walls its rows to a tenant, so its reads already fail closed for
|
|
274
|
+
* non-root (list scope `FALSE`) and the engine refuses its non-root writes the same way.
|
|
275
|
+
*/
|
|
276
|
+
function isUnwalledDataType(reg) {
|
|
277
|
+
return (reg.access.plane === 'data' &&
|
|
278
|
+
tenantColumnOf(reg) === null &&
|
|
279
|
+
reg.readScope === undefined &&
|
|
280
|
+
!isGlobalType(reg));
|
|
281
|
+
}
|
|
282
|
+
function bootAccessSummary(regs) {
|
|
283
|
+
return {
|
|
284
|
+
globalTypes: regs.filter(isGlobalType).map((r) => r.typeKey),
|
|
285
|
+
tenantlessDataTypes: regs.filter(isUnwalledDataType).map((r) => r.typeKey),
|
|
286
|
+
};
|
|
287
|
+
}
|
|
268
288
|
/** Boot-enforce that exactly-one field claims `role`; throw if none. */
|
|
269
289
|
function requireRole(reg, role) {
|
|
270
290
|
if (!reg.fields.some((f) => f.role === role)) {
|
|
@@ -292,6 +312,7 @@ function validate(reg) {
|
|
|
292
312
|
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': field '${f.key}' immutable must be a boolean, got ` +
|
|
293
313
|
`${typeof immutable} (${String(immutable)}).`);
|
|
294
314
|
}
|
|
315
|
+
validateNullable(reg, f);
|
|
295
316
|
}
|
|
296
317
|
// ADR-0034: the create-wall mode is either absent (walled), 'walled' or 'unscoped'. Anything
|
|
297
318
|
// else fails boot — an opt-out is an explicit decision, never a typo.
|
|
@@ -305,6 +326,42 @@ function validate(reg) {
|
|
|
305
326
|
}
|
|
306
327
|
validateAccess(reg);
|
|
307
328
|
validateActions(reg);
|
|
329
|
+
if (isGlobalType(reg))
|
|
330
|
+
validateGlobalActions(reg);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* G-023: `nullable: true` lets a write clear the column to NULL, so it is refused wherever a NULL
|
|
334
|
+
* would erase identity or reach: a server-stamped (`trusted`) field, a primary-key column, a column
|
|
335
|
+
* the `readScope` wall reads, and a `required` field (a value must be supplied). A truthy
|
|
336
|
+
* non-boolean is malformed, never silently read as "not nullable".
|
|
337
|
+
*/
|
|
338
|
+
function validateNullable(reg, f) {
|
|
339
|
+
const nullable = f.nullable;
|
|
340
|
+
if (nullable === undefined)
|
|
341
|
+
return;
|
|
342
|
+
const where = `registration '${reg.typeKey}': field '${f.key}'`;
|
|
343
|
+
if (typeof nullable !== 'boolean') {
|
|
344
|
+
throw new errors_js_1.RegistrationError(`${where} nullable must be a boolean, got ${typeof nullable} (${String(nullable)}).`);
|
|
345
|
+
}
|
|
346
|
+
if (!nullable)
|
|
347
|
+
return;
|
|
348
|
+
const refuse = (why) => {
|
|
349
|
+
throw new errors_js_1.RegistrationError(`${where} cannot be nullable: ${why}.`);
|
|
350
|
+
};
|
|
351
|
+
const col = columnOf(f);
|
|
352
|
+
if (f.trusted !== undefined)
|
|
353
|
+
refuse(`trusted:'${f.trusted}' is stamped server-side`);
|
|
354
|
+
const pk = reg.primaryKey;
|
|
355
|
+
if (f.role === 'primaryKey' ||
|
|
356
|
+
(pk.kind === 'uuid' ? pk.column === col : pk.columns.includes(col))) {
|
|
357
|
+
refuse('it is a primary-key column');
|
|
358
|
+
}
|
|
359
|
+
const rs = reg.readScope;
|
|
360
|
+
if (rs !== undefined && (rs.kind === 'nodeColumn' ? rs.column : rs.pkColumn) === col) {
|
|
361
|
+
refuse('the readScope wall reads it');
|
|
362
|
+
}
|
|
363
|
+
if (f.required === true)
|
|
364
|
+
refuse('required means a value must be supplied');
|
|
308
365
|
}
|
|
309
366
|
/** The CRUD vocabulary, in the `IDENTITY_ACTIONS` order (guard `identity-actions.ts`). */
|
|
310
367
|
const CRUD_ACTIONS = ['read', 'create', 'update', 'delete'];
|
|
@@ -312,6 +369,27 @@ const CRUD_ACTIONS = ['read', 'create', 'update', 'delete'];
|
|
|
312
369
|
const RESERVED_ACTIONS = new Set(['*', 'access']);
|
|
313
370
|
/** The narrowest action column (`perm_action`, `rpr_action`, `rs_action`) is VARCHAR(64). */
|
|
314
371
|
const MAX_ACTION_LENGTH = 64;
|
|
372
|
+
/** The one action a global reference type has (G-022, ADR-0046). */
|
|
373
|
+
const GLOBAL_ACTIONS = ['read'];
|
|
374
|
+
/** Whether the type is global reference data (`access.global === true`, G-022, ADR-0046). */
|
|
375
|
+
function isGlobalType(reg) {
|
|
376
|
+
return reg.access?.global === true;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* A global type's vocabulary is exactly `read`: `actions`/`crudActions` absent, or
|
|
380
|
+
* `crudActions: false` with `actions: ['read']`. Anything else fails boot (R4).
|
|
381
|
+
*/
|
|
382
|
+
function validateGlobalActions(reg) {
|
|
383
|
+
const type = reg.typeKey ?? '(unnamed)';
|
|
384
|
+
const actions = reg.actions ?? [];
|
|
385
|
+
const crud = reg.crudActions;
|
|
386
|
+
const declaredRead = crud === false && actions.length === 1 && actions[0] === 'read';
|
|
387
|
+
const declaredNothing = crud === undefined && reg.actions === undefined;
|
|
388
|
+
if (!declaredRead && !declaredNothing) {
|
|
389
|
+
throw new errors_js_1.RegistrationError(`registration '${type}': access.global types are read-only; their only action is 'read' ` +
|
|
390
|
+
`(omit actions/crudActions, or declare crudActions:false with actions:['read']).`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
315
393
|
/**
|
|
316
394
|
* Boot-time validation of the declared action vocabulary (ADR-0038). Pure, no IO. Every
|
|
317
395
|
* failure is a `RegistrationError` naming the type and the action, so a bad name fails boot
|
|
@@ -366,6 +444,10 @@ function validateActions(reg) {
|
|
|
366
444
|
*/
|
|
367
445
|
function effectiveActions(reg) {
|
|
368
446
|
validateActions(reg);
|
|
447
|
+
if (isGlobalType(reg)) {
|
|
448
|
+
validateGlobalActions(reg);
|
|
449
|
+
return [...GLOBAL_ACTIONS];
|
|
450
|
+
}
|
|
369
451
|
const declared = reg.actions ?? [];
|
|
370
452
|
return reg.crudActions === false ? [...declared] : [...CRUD_ACTIONS, ...declared];
|
|
371
453
|
}
|
|
@@ -389,7 +471,7 @@ function validateAccess(reg) {
|
|
|
389
471
|
const access = reg.access;
|
|
390
472
|
if (!access) {
|
|
391
473
|
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': an access declaration is required ` +
|
|
392
|
-
`(access: { plane, tenantScoped?, owned?, system? }) — no silent default.`);
|
|
474
|
+
`(access: { plane, tenantScoped?, owned?, system?, global? }) — no silent default.`);
|
|
393
475
|
}
|
|
394
476
|
// SECURITY (root-cap axis): `plane` is REQUIRED + explicit. Omitting it would default a
|
|
395
477
|
// new administrative type to `data` and wrongly deny root, with NO error — the exact
|
|
@@ -419,14 +501,31 @@ function validateAccess(reg) {
|
|
|
419
501
|
const tenantScoped = flag('tenantScoped');
|
|
420
502
|
const owned = flag('owned');
|
|
421
503
|
const system = flag('system');
|
|
504
|
+
const global = flag('global');
|
|
422
505
|
// No silent "global by empty object": {} / all-false is "declared nothing" — the same
|
|
423
|
-
// hole as an absent declaration. At least ONE posture must be an explicit choice.
|
|
424
|
-
// global
|
|
425
|
-
// DELIBERATE decision, never the accidental default of an empty/all-false object.
|
|
426
|
-
if (!tenantScoped && !owned && !system) {
|
|
506
|
+
// hole as an absent declaration. At least ONE posture must be an explicit choice. Shared
|
|
507
|
+
// reference data is `global: true`; a grant-governed infrastructure type is `system: true` —
|
|
508
|
+
// each a DELIBERATE decision, never the accidental default of an empty/all-false object.
|
|
509
|
+
if (!tenantScoped && !owned && !system && !global) {
|
|
427
510
|
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': access declares no posture ` +
|
|
428
|
-
`(need at least one of tenantScoped/owned/system=true).
|
|
429
|
-
`
|
|
511
|
+
`(need at least one of tenantScoped/owned/system/global=true). Shared reference data ` +
|
|
512
|
+
`is global:true; 'global' is a decision, not an empty object.`);
|
|
513
|
+
}
|
|
514
|
+
// G-022 (ADR-0046): a global type is readable from every tenant, so nothing on it may suggest
|
|
515
|
+
// a tenant, an owner or a subtree wall.
|
|
516
|
+
if (global) {
|
|
517
|
+
if (tenantScoped || owned || system) {
|
|
518
|
+
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': access.global is mutually exclusive with ` +
|
|
519
|
+
`tenantScoped/owned/system.`);
|
|
520
|
+
}
|
|
521
|
+
if (reg.readScope !== undefined) {
|
|
522
|
+
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': access.global cannot declare a readScope ` +
|
|
523
|
+
`(a global type has no read wall).`);
|
|
524
|
+
}
|
|
525
|
+
if (reg.fields.some((f) => f.trusted === 'tenantId')) {
|
|
526
|
+
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': access.global cannot carry a trusted:'tenantId' field ` +
|
|
527
|
+
`(global rows belong to no tenant).`);
|
|
528
|
+
}
|
|
430
529
|
}
|
|
431
530
|
if (system && (tenantScoped || owned)) {
|
|
432
531
|
throw new errors_js_1.RegistrationError(`registration '${reg.typeKey}': access.system is mutually exclusive with ` +
|
package/dist/types.d.ts
CHANGED
|
@@ -46,6 +46,16 @@ export interface FieldSpec {
|
|
|
46
46
|
* checked operation. Must be a boolean when present (boot-validated).
|
|
47
47
|
*/
|
|
48
48
|
readonly immutable?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* G-023: the field may be written as SQL NULL. With `nullable: true`, create, update and
|
|
51
|
+
* `createMany` accept a JS `null` for it and bind NULL (`json` included: NULL, never the text
|
|
52
|
+
* `"null"`), and the audit attributes name it under `cleared`. Without it, `null` is refused
|
|
53
|
+
* exactly as before. Boot refuses it on `trusted`, primary-key, `readScope` and `required`
|
|
54
|
+
* fields. With `immutable: true` a `null` is accepted at create only (an update ignores the
|
|
55
|
+
* field). The app's migration must make the column NULL-able; the engine does not check DDL.
|
|
56
|
+
* `where` operands are unaffected. Must be a boolean when present (boot-validated).
|
|
57
|
+
*/
|
|
58
|
+
readonly nullable?: boolean;
|
|
49
59
|
}
|
|
50
60
|
/** Server-trusted write-context sources (derive-write-context stage). */
|
|
51
61
|
export type TrustedSource = 'tenantId' | 'actorId';
|
|
@@ -96,6 +106,15 @@ export interface AccessDeclaration {
|
|
|
96
106
|
* `tenantScoped`/`owned`.
|
|
97
107
|
*/
|
|
98
108
|
readonly system?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* true → global reference data (G-022, ADR-0046): the same rows for every tenant (code lists,
|
|
111
|
+
* catalogues, units), readable by any caller holding the type's `read` grant, with no tenant
|
|
112
|
+
* clause and no read wall. Read-only through the engine for everyone, root included: rows are
|
|
113
|
+
* seeded and changed only by app migrations. MUTUALLY EXCLUSIVE with `tenantScoped`/`owned`/
|
|
114
|
+
* `system` and with a `readScope`; may not carry a `trusted:'tenantId'` field; its actions are
|
|
115
|
+
* exactly `['read']`. Never put tenant data in a global type.
|
|
116
|
+
*/
|
|
117
|
+
readonly global?: boolean;
|
|
99
118
|
/**
|
|
100
119
|
* REQUIRED capability plane (the root-cap axis; see the interface note above).
|
|
101
120
|
* `'control'` → identity/access administration; the capped root MAY perform it without
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/D,iFAAiF;AACjF,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAExF,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astram/engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Astram framework — the paved road. ONE unbypassable write pipe (resolve-schema → permission gate → derive-write-context → validate → compute → write → junction-sync → audit → emit-event) over real physical tables, that every feature's CRUD flows through. Feature code receives ONLY the RecordEngine facade — never a raw pool/DataSource/QueryRunner (the physical wall). Security-gate + audit are mandatory stages. Missing capability → a typed CapabilityNotSupportedError (the gap-flag STOP). Builds on @astram/core (metadata contract, decide(), audit) + @astram/guard (decision authority).",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"mariadb": "^3.5.4",
|
|
35
|
-
"@astram/core": "1.
|
|
35
|
+
"@astram/core": "1.11.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@nestjs/common": "^11",
|