@astram/engine 0.9.0 → 0.10.1

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/index.d.ts CHANGED
@@ -33,4 +33,5 @@ export type { EngineDbConfig } from './adapters/mariadb-unit-of-work.js';
33
33
  export { MariaDbAuditSink, type AuditSinkConfig } from './adapters/mariadb-audit-sink.js';
34
34
  export type { QueryFn, UnitOfWork, DecisionPort, AuditPort } from './ports.js';
35
35
  export type { Stage, WriteContext, WriteOp, PipeBase } from './pipe/context.js';
36
+ export { operationOf, type OperationBinding } from './pipe/operation-binding.js';
36
37
  //# sourceMappingURL=index.d.ts.map
@@ -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,GACjB,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"}
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,GACjB,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.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.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).
@@ -97,3 +97,5 @@ Object.defineProperty(exports, "BoundRecords", { enumerable: true, get: function
97
97
  Object.defineProperty(exports, "SERVICE_ACCOUNT_RESOLVER", { enumerable: true, get: function () { return records_service_js_1.SERVICE_ACCOUNT_RESOLVER; } });
98
98
  var mariadb_audit_sink_js_1 = require("./adapters/mariadb-audit-sink.js");
99
99
  Object.defineProperty(exports, "MariaDbAuditSink", { enumerable: true, get: function () { return mariadb_audit_sink_js_1.MariaDbAuditSink; } });
100
+ var operation_binding_js_1 = require("./pipe/operation-binding.js");
101
+ Object.defineProperty(exports, "operationOf", { enumerable: true, get: function () { return operation_binding_js_1.operationOf; } });
@@ -7,4 +7,6 @@
7
7
  * the scaffolded app's lint wall rejects this subpath everywhere else.
8
8
  */
9
9
  export { MariaDbUnitOfWork, type EngineDbConfig } from './adapters/mariadb-unit-of-work.js';
10
+ export { bindOperation, type OperationBinding } from './pipe/operation-binding.js';
11
+ export { transactionQueryOf } from './pipe/transaction-query.js';
10
12
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC"}
package/dist/internal.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MariaDbUnitOfWork = void 0;
3
+ exports.transactionQueryOf = exports.bindOperation = exports.MariaDbUnitOfWork = void 0;
4
4
  /**
5
5
  * @astram/engine/internal — composition-root and framework-test surface (Phase 8 #5).
6
6
  *
@@ -11,3 +11,7 @@ exports.MariaDbUnitOfWork = void 0;
11
11
  */
12
12
  var mariadb_unit_of_work_js_1 = require("./adapters/mariadb-unit-of-work.js");
13
13
  Object.defineProperty(exports, "MariaDbUnitOfWork", { enumerable: true, get: function () { return mariadb_unit_of_work_js_1.MariaDbUnitOfWork; } });
14
+ var operation_binding_js_1 = require("./pipe/operation-binding.js");
15
+ Object.defineProperty(exports, "bindOperation", { enumerable: true, get: function () { return operation_binding_js_1.bindOperation; } });
16
+ var transaction_query_js_1 = require("./pipe/transaction-query.js");
17
+ Object.defineProperty(exports, "transactionQueryOf", { enumerable: true, get: function () { return transaction_query_js_1.transactionQueryOf; } });
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Operation binding (G-009): a trusted server operation runs its internal steps as a principal
3
+ * bound to its own declared operation identity (Shield #9). The binding is the ONLY way the
4
+ * engine hands `decide()` the gate-7 delegation marker.
5
+ *
6
+ * ⛔ UNFORGEABLE. A binding lives in a module-private WeakMap keyed by the frozen principal
7
+ * object `bindOperation` returned. A spread, JSON or structural copy is a different object and
8
+ * carries nothing, so a principal read off a request or a record cannot claim an operation.
9
+ * `bindOperation` is exported from `@astram/engine/internal` only (composition/framework code);
10
+ * features get the read-only {@link operationOf}.
11
+ */
12
+ import type { DecisionContext } from '../ports.js';
13
+ import type { Principal } from '../types.js';
14
+ export interface OperationBinding {
15
+ /** Stable key of the trusted operation (its manifest identity). */
16
+ readonly operationKey: string;
17
+ /** Stable key of the internal step being performed. */
18
+ readonly stepKey: string;
19
+ /** Stable id of the human or service the operation acts for (audit "on behalf of"). */
20
+ readonly onBehalfOf: string;
21
+ }
22
+ /** Bind `principal` to a trusted operation step. Returns a NEW frozen principal. */
23
+ export declare function bindOperation(principal: Principal, binding: OperationBinding): Principal;
24
+ /** The operation binding of `principal`, or `undefined` when it is not a bound principal. */
25
+ export declare function operationOf(principal: Principal): OperationBinding | undefined;
26
+ /**
27
+ * The context handed to every engine `decide()`: any `shield.delegation` attribute is dropped
28
+ * first (a field-derived value must never reach decide()), then, for a bound actor only, the
29
+ * real marker is set. The ONE place the engine builds that attribute.
30
+ */
31
+ export declare function withDelegation(actor: Principal, context: DecisionContext): DecisionContext;
32
+ //# sourceMappingURL=operation-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-binding.d.ts","sourceRoot":"","sources":["../../src/pipe/operation-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAWD,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,GAAG,SAAS,CASxF;AAED,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,eAAe,CAa1F"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * Operation binding (G-009): a trusted server operation runs its internal steps as a principal
4
+ * bound to its own declared operation identity (Shield #9). The binding is the ONLY way the
5
+ * engine hands `decide()` the gate-7 delegation marker.
6
+ *
7
+ * ⛔ UNFORGEABLE. A binding lives in a module-private WeakMap keyed by the frozen principal
8
+ * object `bindOperation` returned. A spread, JSON or structural copy is a different object and
9
+ * carries nothing, so a principal read off a request or a record cannot claim an operation.
10
+ * `bindOperation` is exported from `@astram/engine/internal` only (composition/framework code);
11
+ * features get the read-only {@link operationOf}.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.bindOperation = bindOperation;
15
+ exports.operationOf = operationOf;
16
+ exports.withDelegation = withDelegation;
17
+ /** The `DecisionContext.attributes` key core's gate 7 reads (`DELEGATION_MARKER_ATTRIBUTE`). */
18
+ const DELEGATION_ATTRIBUTE = 'shield.delegation';
19
+ const bindings = new WeakMap();
20
+ function requireNonEmpty(name, value) {
21
+ if (typeof value !== 'string' || value.length === 0) {
22
+ throw new TypeError(`bindOperation: ${name} must be a non-empty string`);
23
+ }
24
+ return value;
25
+ }
26
+ /** Bind `principal` to a trusted operation step. Returns a NEW frozen principal. */
27
+ function bindOperation(principal, binding) {
28
+ const bound = Object.freeze({
29
+ operationKey: requireNonEmpty('operationKey', binding.operationKey),
30
+ stepKey: requireNonEmpty('stepKey', binding.stepKey),
31
+ onBehalfOf: requireNonEmpty('onBehalfOf', binding.onBehalfOf),
32
+ });
33
+ const copy = Object.freeze({ ...principal });
34
+ bindings.set(copy, bound);
35
+ return copy;
36
+ }
37
+ /** The operation binding of `principal`, or `undefined` when it is not a bound principal. */
38
+ function operationOf(principal) {
39
+ return typeof principal === 'object' && principal !== null ? bindings.get(principal) : undefined;
40
+ }
41
+ /**
42
+ * The context handed to every engine `decide()`: any `shield.delegation` attribute is dropped
43
+ * first (a field-derived value must never reach decide()), then, for a bound actor only, the
44
+ * real marker is set. The ONE place the engine builds that attribute.
45
+ */
46
+ function withDelegation(actor, context) {
47
+ const binding = operationOf(actor);
48
+ const has = context.attributes !== undefined && DELEGATION_ATTRIBUTE in context.attributes;
49
+ if (!has && binding === undefined)
50
+ return context;
51
+ const attributes = { ...context.attributes };
52
+ delete attributes[DELEGATION_ATTRIBUTE];
53
+ if (binding !== undefined) {
54
+ attributes[DELEGATION_ATTRIBUTE] = {
55
+ operationKey: binding.operationKey,
56
+ stepKey: binding.stepKey,
57
+ };
58
+ }
59
+ return { ...context, attributes };
60
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"record-engine.d.ts","sourceRoot":"","sources":["../../src/pipe/record-engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record-engine.d.ts","sourceRoot":"","sources":["../../src/pipe/record-engine.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,7 @@ const registry_js_1 = require("../registry.js");
25
25
  const types_js_1 = require("../types.js");
26
26
  const context_js_1 = require("./context.js");
27
27
  const fetch_record_js_1 = require("./stages/fetch-record.js");
28
+ const operation_binding_js_1 = require("./operation-binding.js");
28
29
  const where_by_id_js_1 = require("./where-by-id.js");
29
30
  const filter_sql_js_1 = require("./filter-sql.js");
30
31
  const permission_gate_js_1 = require("./stages/permission-gate.js");
@@ -33,6 +34,7 @@ const validate_js_1 = require("./stages/validate.js");
33
34
  const write_js_1 = require("./stages/write.js");
34
35
  const junction_sync_js_1 = require("./stages/junction-sync.js");
35
36
  const audit_js_1 = require("./stages/audit.js");
37
+ const transaction_query_js_1 = require("./transaction-query.js");
36
38
  const errors_js_2 = require("../errors.js");
37
39
  /** `createMany` row cap (list-query-operators SPEC v2 §10). */
38
40
  const CREATE_MANY_CAP = 500;
@@ -128,7 +130,7 @@ class RecordEngineImpl {
128
130
  }
129
131
  /** The transaction-bound engine handle passed to `transaction(fn)`. */
130
132
  handleFor(state) {
131
- return {
133
+ const handle = {
132
134
  create: (typeKey, input, actor) => this.createIn(state, typeKey, input, actor),
133
135
  update: (typeKey, id, input, actor) => this.updateIn(state, typeKey, id, input, actor),
134
136
  delete: (typeKey, id, actor) => this.deleteIn(state, typeKey, id, actor),
@@ -140,6 +142,8 @@ class RecordEngineImpl {
140
142
  aggregate: (typeKey, query, actor) => this.aggregateIn(state, typeKey, query, actor),
141
143
  createMany: (typeKey, inputs, actor) => this.createManyIn(state, typeKey, inputs, actor),
142
144
  };
145
+ (0, transaction_query_js_1.linkTransactionHandle)(handle, { query: state.query, isOpen: () => state.open });
146
+ return handle;
143
147
  }
144
148
  /**
145
149
  * Row lock on one record inside the open transaction (see `RecordEngine.lockForUpdate`). Keyed
@@ -312,7 +316,7 @@ class RecordEngineImpl {
312
316
  };
313
317
  let outcome;
314
318
  try {
315
- outcome = await this.decision.decide(actor, action, resource, context);
319
+ outcome = await this.decision.decide(actor, action, resource, (0, operation_binding_js_1.withDelegation)(actor, context));
316
320
  }
317
321
  catch (err) {
318
322
  throw new errors_js_2.EngineUnavailableError(`decision authority unavailable for read ${registration.typeKey}: ${err.message}`);
@@ -55,6 +55,8 @@ export declare class RecordsService {
55
55
  private actor;
56
56
  private resolveServiceAccount;
57
57
  }
58
+ /** Framework-internal (transaction-query.ts): the engine a BoundRecords wraps. */
59
+ export declare function engineHandleOf(bound: BoundRecords): RecordEngine;
58
60
  /**
59
61
  * The `.as(...)` bound view — same 5 ops, fixed actor. Also the handle `transaction(fn)` passes
60
62
  * (ADR-0034): there `engine` is the transaction-bound engine, so its ops share one unit of work.
@@ -1 +1 @@
1
- {"version":3,"file":"records-service.d.ts","sourceRoot":"","sources":["../../src/pipe/records-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"records-service.d.ts","sourceRoot":"","sources":["../../src/pipe/records-service.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BoundRecords = exports.RecordsService = exports.SERVICE_ACCOUNT_RESOLVER = void 0;
16
+ exports.engineHandleOf = engineHandleOf;
16
17
  const common_1 = require("@nestjs/common");
17
18
  const core_1 = require("@nestjs/core");
18
19
  const tokens_js_1 = require("../module/tokens.js");
@@ -126,6 +127,10 @@ exports.RecordsService = RecordsService = __decorate([
126
127
  __param(2, (0, common_1.Inject)(exports.SERVICE_ACCOUNT_RESOLVER)),
127
128
  __metadata("design:paramtypes", [Object, Object, Object])
128
129
  ], RecordsService);
130
+ /** Framework-internal (transaction-query.ts): the engine a BoundRecords wraps. */
131
+ function engineHandleOf(bound) {
132
+ return bound['engine'];
133
+ }
129
134
  /**
130
135
  * The `.as(...)` bound view — same 5 ops, fixed actor. Also the handle `transaction(fn)` passes
131
136
  * (ADR-0034): there `engine` is the transaction-bound engine, so its ops share one unit of work.
@@ -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;AAC9E,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,eAAe,CAAC;AAMlE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAkClD"}
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,CA2ClD"}
@@ -12,6 +12,7 @@
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.auditStage = auditStage;
15
+ const operation_binding_js_1 = require("../operation-binding.js");
15
16
  function opToActionKey(op) {
16
17
  return op;
17
18
  }
@@ -26,6 +27,7 @@ function auditStage(audit) {
26
27
  tenantId: ctx.actor.tenantId,
27
28
  ...(typeof ctx.resultId === 'string' ? { recordId: ctx.resultId } : {}),
28
29
  };
30
+ const binding = (0, operation_binding_js_1.operationOf)(ctx.actor);
29
31
  const event = {
30
32
  type: 'admin_action',
31
33
  occurredAtMs: ctx.nowMs,
@@ -40,6 +42,14 @@ function auditStage(audit) {
40
42
  ...(ctx.batch !== undefined
41
43
  ? { batchId: ctx.batch.id, batchIndex: ctx.batch.index }
42
44
  : {}),
45
+ // Bound operation step only (Shield #9): attributable "on behalf of".
46
+ ...(binding !== undefined
47
+ ? {
48
+ operation: binding.operationKey,
49
+ step: binding.stepKey,
50
+ onBehalfOf: binding.onBehalfOf,
51
+ }
52
+ : {}),
43
53
  },
44
54
  };
45
55
  // Write the audit row on the pipe's OWN transaction (atomic with the data).
@@ -36,7 +36,8 @@ export declare function decideOrThrow(decision: DecisionPort, actor: Principal,
36
36
  * always `actor.tenantId`, exactly what this stage sends (gates 3 and 5 agree);
37
37
  * - gate 5's coarse key and root-plane rule depend only on (typeKey, action, principal);
38
38
  * - gate 7 (delegation) reads only the `shield.delegation` attribute, which the engine
39
- * never supplies (the record gate's attributes are registered field values).
39
+ * sets from the actor's operation binding on every decide() (`withDelegation`), the
40
+ * same here as at the record gate.
40
41
  * So a deny here is a deny at gate ≤ 5 (or 7) that the record-level call reaches too.
41
42
  *
42
43
  * ── Existence: it runs before any read, so its answer cannot depend on whether the id exists
@@ -1 +1 @@
1
- {"version":3,"file":"permission-gate.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/permission-gate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,eAAe,CAAC;AAQlE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK,CAiCjE;AAOD;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK,CAoB9D"}
1
+ {"version":3,"file":"permission-gate.d.ts","sourceRoot":"","sources":["../../../src/pipe/stages/permission-gate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAyB,MAAM,eAAe,CAAC;AASlE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK,CAiCjE;AAOD;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK,CAoB9D"}
@@ -12,6 +12,7 @@ exports.decideOrThrow = decideOrThrow;
12
12
  exports.typePreGateStage = typePreGateStage;
13
13
  const errors_js_1 = require("../../errors.js");
14
14
  const fetch_record_js_1 = require("./fetch-record.js");
15
+ const operation_binding_js_1 = require("../operation-binding.js");
15
16
  /** Map the pipe op to the stable authorization action key. */
16
17
  function actionKey(op) {
17
18
  return op; // 'create' | 'update' | 'delete' — stable action keys (core §5.2)
@@ -61,7 +62,7 @@ function gateLabel(ctx) {
61
62
  async function decideOrThrow(decision, actor, action, resource, context, label) {
62
63
  let outcome;
63
64
  try {
64
- outcome = await decision.decide(actor, action, resource, context);
65
+ outcome = await decision.decide(actor, action, resource, (0, operation_binding_js_1.withDelegation)(actor, context));
65
66
  }
66
67
  catch (err) {
67
68
  // A thrown decision = transient/unavailable (ADR-0016). Fail-closed: do NOT
@@ -92,7 +93,8 @@ async function decideOrThrow(decision, actor, action, resource, context, label)
92
93
  * always `actor.tenantId`, exactly what this stage sends (gates 3 and 5 agree);
93
94
  * - gate 5's coarse key and root-plane rule depend only on (typeKey, action, principal);
94
95
  * - gate 7 (delegation) reads only the `shield.delegation` attribute, which the engine
95
- * never supplies (the record gate's attributes are registered field values).
96
+ * sets from the actor's operation binding on every decide() (`withDelegation`), the
97
+ * same here as at the record gate.
96
98
  * So a deny here is a deny at gate ≤ 5 (or 7) that the record-level call reaches too.
97
99
  *
98
100
  * ── Existence: it runs before any read, so its answer cannot depend on whether the id exists
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Framework-internal transaction hook (G-009 T7, OD-6). `transactionQueryOf(tx)` returns the raw
3
+ * query of the engine transaction's OWN connection, so one extra framework statement (the locked
4
+ * credential insert) commits or rolls back with the engine's writes. Exported from
5
+ * `@astram/engine/internal` only; features never see it.
6
+ */
7
+ import type { QueryFn } from '../ports.js';
8
+ import type { RecordEngine } from '../types.js';
9
+ import { type BoundRecords } from './records-service.js';
10
+ interface TxLink {
11
+ readonly query: QueryFn;
12
+ readonly isOpen: () => boolean;
13
+ }
14
+ /** Record-engine only: link a transaction handle to its connection while it is open. */
15
+ export declare function linkTransactionHandle(handle: RecordEngine, link: TxLink): void;
16
+ export declare function transactionQueryOf(tx: BoundRecords): QueryFn;
17
+ export {};
18
+ //# sourceMappingURL=transaction-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-query.d.ts","sourceRoot":"","sources":["../../src/pipe/transaction-query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzE,UAAU,MAAM;IACd,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC;CAChC;AAKD,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE9E;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAa5D"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.linkTransactionHandle = linkTransactionHandle;
4
+ exports.transactionQueryOf = transactionQueryOf;
5
+ const records_service_js_1 = require("./records-service.js");
6
+ const errors_js_1 = require("../errors.js");
7
+ /** Transaction engine handles → their connection. Module-private; weak so handles can be collected. */
8
+ const links = new WeakMap();
9
+ /** Record-engine only: link a transaction handle to its connection while it is open. */
10
+ function linkTransactionHandle(handle, link) {
11
+ links.set(handle, link);
12
+ }
13
+ function transactionQueryOf(tx) {
14
+ const link = links.get((0, records_service_js_1.engineHandleOf)(tx));
15
+ if (link === undefined) {
16
+ throw new errors_js_1.EngineUnavailableError('transactionQueryOf needs a handle inside a record transaction.');
17
+ }
18
+ if (!link.isOpen()) {
19
+ throw new errors_js_1.EngineUnavailableError('record transaction has already ended; its query is unusable.');
20
+ }
21
+ return link.query;
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astram/engine",
3
- "version": "0.9.0",
3
+ "version": "0.10.1",
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.8.0"
35
+ "@astram/core": "1.9.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@nestjs/common": "^11",