@aventara/core 1.0.0-rc.10 → 1.0.0-rc.12

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.
Files changed (112) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/ERRORS.md +82 -82
  3. package/README.md +57 -1
  4. package/dist/compiler/contract-compiler-diagnostic.d.ts +3 -2
  5. package/dist/compiler/contract-compiler-diagnostic.guidance.js +3 -3
  6. package/dist/compiler/contract.compiler.js +64 -12
  7. package/dist/compiler/create-requirements.projector.js +1 -3
  8. package/dist/compiler/field-validator.compiler.js +1 -3
  9. package/dist/compiler/managed-elsewhere.projector.js +5 -5
  10. package/dist/config/cache-stage.factory.d.ts +24 -0
  11. package/dist/config/cache-stage.factory.js +3 -0
  12. package/dist/config/config.resolver.js +1 -7
  13. package/dist/config/config.validator.js +61 -13
  14. package/dist/config/exact-framework-config.d.ts +6 -0
  15. package/dist/config/field-compute.resolver.js +1 -3
  16. package/dist/config/pipeline-config.d.ts +16 -0
  17. package/dist/config/pipeline-tree.resolver.js +2 -3
  18. package/dist/contracts/canonical-json.writer.d.ts +7 -0
  19. package/dist/contracts/canonical-json.writer.js +55 -0
  20. package/dist/contracts/client-contract-structure.validator.d.ts +64 -0
  21. package/dist/contracts/client-contract-structure.validator.js +12 -0
  22. package/dist/contracts/contract-canonicalizer.js +5 -0
  23. package/dist/contracts/contract-limits.d.ts +6 -0
  24. package/dist/contracts/contract-limits.js +2 -0
  25. package/dist/contracts/contract.d.ts +15 -0
  26. package/dist/contracts/json-schema.projector.js +1 -3
  27. package/dist/framework/access-facade.js +1 -3
  28. package/dist/framework/contract-view.d.ts +13 -3
  29. package/dist/framework/framework.factory.js +42 -13
  30. package/dist/framework/operation-facade.d.ts +67 -6
  31. package/dist/framework/operation-facade.js +7 -0
  32. package/dist/framework/operation-set.runner.d.ts +47 -0
  33. package/dist/framework/operation-set.runner.js +168 -0
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.js +2 -0
  36. package/dist/internal.d.ts +2 -0
  37. package/dist/internal.js +2 -0
  38. package/dist/operations/operation-validator-core.js +2 -4
  39. package/dist/operations/structural-limits.walker.js +1 -3
  40. package/dist/policy/access-question.runtime.js +1 -3
  41. package/dist/policy/policy-admission.js +1 -3
  42. package/dist/policy/policy-after-update.runtime.js +1 -3
  43. package/dist/policy/policy-nested-write.runtime.js +3 -12
  44. package/dist/policy/policy-read.runtime.js +1 -3
  45. package/dist/policy/policy-reference-write.runtime.js +2 -11
  46. package/dist/policy/policy-request.d.ts +31 -0
  47. package/dist/policy/policy-request.js +69 -17
  48. package/dist/policy/policy-session.js +1 -3
  49. package/dist/policy/policy-write.runtime.js +1 -3
  50. package/dist/prebuilt/core-version.generated.d.ts +1 -1
  51. package/dist/prebuilt/core-version.generated.js +1 -1
  52. package/dist/prebuilt/prebuilt-changes.js +1 -3
  53. package/dist/prebuilt/prebuilt-contracts.loader.js +1 -3
  54. package/dist/prebuilt/prebuilt-inputs.fingerprint.js +1 -3
  55. package/dist/protocol/absent-route.responder.d.ts +69 -16
  56. package/dist/protocol/absent-route.responder.js +75 -31
  57. package/dist/protocol/contract-document.responder.d.ts +7 -0
  58. package/dist/protocol/contract-document.responder.js +3 -2
  59. package/dist/protocol/http-request.decoder.d.ts +33 -0
  60. package/dist/protocol/http-request.decoder.js +23 -7
  61. package/dist/protocol/http-request.reader.d.ts +4 -0
  62. package/dist/protocol/http-request.reader.js +11 -2
  63. package/dist/protocol/http-response.encoder.d.ts +12 -0
  64. package/dist/protocol/http-response.encoder.js +15 -1
  65. package/dist/protocol/operation-response.guard.js +1 -3
  66. package/dist/protocol/operation-set.decoder.d.ts +48 -0
  67. package/dist/protocol/operation-set.decoder.js +185 -0
  68. package/dist/protocol/operation-set.handler.d.ts +27 -0
  69. package/dist/protocol/operation-set.handler.js +179 -0
  70. package/dist/protocol/protocol-headers.d.ts +9 -0
  71. package/dist/protocol/protocol-headers.js +12 -5
  72. package/dist/protocol/protocol-surface.d.ts +12 -4
  73. package/dist/protocol/protocol-surface.js +34 -1
  74. package/dist/protocol/protocol.binder.d.ts +37 -1
  75. package/dist/protocol/protocol.binder.js +2 -0
  76. package/dist/protocol/protocol.handler.d.ts +35 -2
  77. package/dist/protocol/protocol.handler.js +84 -8
  78. package/dist/protocol/read-cache.responder.d.ts +26 -0
  79. package/dist/protocol/read-cache.responder.js +47 -0
  80. package/dist/protocol/read-query.codec.d.ts +34 -0
  81. package/dist/protocol/read-query.codec.js +125 -0
  82. package/dist/runtime/computed-read-runtime.js +2 -8
  83. package/dist/runtime/create-requirement.js +1 -3
  84. package/dist/runtime/diagnostics-reporter.d.ts +6 -1
  85. package/dist/runtime/diagnostics-reporter.js +3 -8
  86. package/dist/runtime/error.catalog.d.ts +2 -2
  87. package/dist/runtime/error.catalog.js +1 -1
  88. package/dist/runtime/field-stage.runtime.d.ts +0 -2
  89. package/dist/runtime/field-stage.runtime.js +1 -7
  90. package/dist/runtime/field-validator.runtime.js +2 -1
  91. package/dist/runtime/mutation-planner.js +1 -3
  92. package/dist/runtime/nested-write.walker.js +2 -1
  93. package/dist/runtime/output-validator.js +1 -3
  94. package/dist/runtime/owned-execution.registry.d.ts +22 -2
  95. package/dist/runtime/pipeline.d.ts +5 -1
  96. package/dist/runtime/record.guard.d.ts +14 -0
  97. package/dist/runtime/record.guard.js +10 -0
  98. package/dist/runtime/request-envelope.validator.js +13 -10
  99. package/dist/runtime/scalar-runtime.d.ts +0 -10
  100. package/dist/runtime/scalar-runtime.js +1 -10
  101. package/dist/runtime/thenable.guard.d.ts +7 -0
  102. package/dist/runtime/thenable.guard.js +5 -0
  103. package/dist/runtime/unsent-value.normalizer.js +2 -1
  104. package/dist/transactions/operation-arguments-encoder.js +1 -7
  105. package/dist/transactions/sql-statement.validator.js +2 -1
  106. package/dist/transactions/transaction-plan-assembler.js +1 -7
  107. package/dist/transactions/transaction-plan-validator.js +4 -6
  108. package/dist/transactions/transaction-reference-collector.js +8 -10
  109. package/dist/transactions/transaction-reference-resolver.js +1 -3
  110. package/dist/transactions/transaction-runtime.js +31 -2
  111. package/dist/transactions/transaction-stage.runtime.js +1 -3
  112. package/package.json +1 -1
@@ -1,10 +1,13 @@
1
+ import { isRecord } from "./record.guard.js";
1
2
  const ORIGINS = ["application", "client", "agent"];
2
3
  const OPERATION_IDENTITY_MEMBERS = ["resource", "family", "variant"];
3
4
  export function validateOperationEnvelope(request) {
4
5
  if (!isRecord(request)) {
5
6
  return [issue([], "V1001", "Operation request must be an object.")];
6
7
  }
7
- const issues = [...originAndIdentityIssues(request)];
8
+ const issues = [
9
+ ...originAndIdentityIssues(request, request.family === "find"),
10
+ ];
8
11
  for (const member of OPERATION_IDENTITY_MEMBERS) {
9
12
  const failure = requiredStringIssue(request, member);
10
13
  if (failure !== undefined) {
@@ -17,9 +20,9 @@ export function validateTransactionEnvelope(request) {
17
20
  if (!isRecord(request)) {
18
21
  return [issue([], "V1001", "Transaction request must be an object.")];
19
22
  }
20
- return originAndIdentityIssues(request);
23
+ return originAndIdentityIssues(request, false);
21
24
  }
22
- function originAndIdentityIssues(request) {
25
+ function originAndIdentityIssues(request, readable) {
23
26
  const issues = [];
24
27
  const origin = request.origin;
25
28
  if (origin === undefined) {
@@ -46,7 +49,7 @@ function originAndIdentityIssues(request) {
46
49
  if (origin === "client" || origin === "agent") {
47
50
  issues.push(...protocolIssues(request.protocol, origin));
48
51
  if (request.transport !== undefined) {
49
- issues.push(...transportIssues(request.transport));
52
+ issues.push(...transportIssues(request.transport, readable));
50
53
  }
51
54
  }
52
55
  else if (origin === "application") {
@@ -84,15 +87,18 @@ function protocolIssues(protocol, origin) {
84
87
  }
85
88
  return issues;
86
89
  }
87
- function transportIssues(transport) {
90
+ function transportIssues(transport, readable) {
88
91
  if (!isRecord(transport)) {
89
92
  return [
90
93
  issue(["transport"], "V1001", "Transport metadata must be an object."),
91
94
  ];
92
95
  }
93
96
  const issues = [];
94
- if (transport.method !== "POST") {
95
- issues.push(issue(["transport", "method"], "V1001", 'Transport method must be "POST".'));
97
+ if (transport.method !== "POST" &&
98
+ !(readable && transport.method === "GET")) {
99
+ issues.push(issue(["transport", "method"], "V1001", readable
100
+ ? 'Transport method must be "POST" or "GET".'
101
+ : 'Transport method must be "POST".'));
96
102
  }
97
103
  const headers = transport.headers;
98
104
  if (!isRecord(headers)) {
@@ -115,9 +121,6 @@ function requiredStringIssue(request, member) {
115
121
  ? undefined
116
122
  : issue([member], "V1001", `Property "${member}" must be a string.`);
117
123
  }
118
- function isRecord(value) {
119
- return typeof value === "object" && value !== null && !Array.isArray(value);
120
- }
121
124
  function issue(path, code, message) {
122
125
  return { path, code, message };
123
126
  }
@@ -20,16 +20,6 @@ type ScalarValueNormalizationResult = {
20
20
  readonly issues: readonly AvValidationIssue[];
21
21
  };
22
22
  type Path = readonly (string | number)[];
23
- /**
24
- * The one discriminant between an argument OBJECT and a VALUE wherever a position
25
- * admits both — a filter position above all: a **plain** record is an operator object,
26
- * and anything else — a `Date`, a core `AvDecimal`, a `Uint8Array` — is a value, which
27
- * equality shorthand then holds to the field's scalar. The validator (`operation-
28
- * validator-core.ts`) reads a filter position through this same answer, and an
29
- * adapter's filter translation is expected to, so a position cannot be operators to
30
- * one reader and a value to another.
31
- */
32
- export declare function isPlainRecord(value: unknown): value is Readonly<Record<string, unknown>>;
33
23
  /** The `V1001` of an `undefined` the request reads with. */
34
24
  export declare function unsentReadValueIssue(path: Path): AvValidationIssue;
35
25
  /**
@@ -6,6 +6,7 @@ import { decodeBase64, WIRE_SCALAR_PATTERNS, } from "../contracts/wire-scalar-fo
6
6
  import { routeTransactionReferenceCandidate, } from "../transactions/transaction-reference.js";
7
7
  import { AvDecimal, isAvDecimal } from "./decimal.js";
8
8
  import { fieldCheckIssues } from "./field-check.evaluator.js";
9
+ import { isPlainRecord } from "./record.guard.js";
9
10
  const INT_MIN = -(2 ** 31);
10
11
  const INT_MAX = 2 ** 31 - 1;
11
12
  const BIGINT_MIN = -(2n ** 63n);
@@ -15,16 +16,6 @@ const NAMED_FORMATS = new Set(AVZ_FORMATS);
15
16
  function isNamedFormat(format) {
16
17
  return NAMED_FORMATS.has(format);
17
18
  }
18
- function isRecord(value) {
19
- return value !== null && typeof value === "object" && !Array.isArray(value);
20
- }
21
- export function isPlainRecord(value) {
22
- if (!isRecord(value)) {
23
- return false;
24
- }
25
- const prototype = Object.getPrototypeOf(value);
26
- return prototype === Object.prototype || prototype === null;
27
- }
28
19
  function issue(code, path, message) {
29
20
  return { code, path, message };
30
21
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Whether `value` is what `await` waits for rather than answers at once: an
3
+ * object or function whose `then` is a function. Reads `then` once; a `then`
4
+ * getter that throws throws here, so a caller reading an untrusted value guards
5
+ * the call.
6
+ */
7
+ export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
@@ -0,0 +1,5 @@
1
+ export function isThenable(value) {
2
+ return (value !== null &&
3
+ (typeof value === "object" || typeof value === "function") &&
4
+ typeof value.then === "function");
5
+ }
@@ -1,6 +1,7 @@
1
1
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
- import { isPlainRecord, WRITE_KEYS } from "./field-stage.runtime.js";
2
+ import { WRITE_KEYS } from "./field-stage.runtime.js";
3
3
  import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "./mutation-planner.js";
4
+ import { isPlainRecord } from "./record.guard.js";
4
5
  const REMOVE = Symbol("remove");
5
6
  const DEPTH_CEILING = 256;
6
7
  function rebuilt(record, changes) {
@@ -2,14 +2,8 @@ import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
2
  import { encodeBase64 } from "../contracts/wire-scalar-format.js";
3
3
  import { isAvDecimal } from "../runtime/decimal.js";
4
4
  import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "../runtime/mutation-planner.js";
5
+ import { isPlainRecord } from "../runtime/record.guard.js";
5
6
  import { isTransactionReferenceCandidate } from "./transaction-reference.js";
6
- function isPlainRecord(value) {
7
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
8
- return false;
9
- }
10
- const prototype = Object.getPrototypeOf(value);
11
- return prototype === Object.prototype || prototype === null;
12
- }
13
7
  function cloneRecord(value) {
14
8
  return { ...value };
15
9
  }
@@ -5,7 +5,8 @@ import { isAvDecimal } from "../runtime/decimal.js";
5
5
  import { planStepPath } from "../runtime/error-boundary.js";
6
6
  import { operationFailure } from "../runtime/operation-response.js";
7
7
  import { mapValidationOutcome } from "../runtime/outcome-mapper.js";
8
- import { isPlainRecord, normalizeJsonValue, } from "../runtime/scalar-runtime.js";
8
+ import { isPlainRecord } from "../runtime/record.guard.js";
9
+ import { normalizeJsonValue } from "../runtime/scalar-runtime.js";
9
10
  import { inspectReferenceCandidate, invalidSourceIndexIssue, referenceSourceAt, referenceSourceField, } from "./transaction-reference-validator.js";
10
11
  import { transactionOperationFailure } from "./transaction-response.js";
11
12
  function refused(issue, index) {
@@ -3,6 +3,7 @@ import { AvCallerDataError, } from "../runtime/caller-data.copier.js";
3
3
  import { copyAtDoor, refuseCallerData } from "../runtime/caller-data.door.js";
4
4
  import { operationFailure } from "../runtime/operation-response.js";
5
5
  import { mapValidationOutcome } from "../runtime/outcome-mapper.js";
6
+ import { isPlainRecord } from "../runtime/record.guard.js";
6
7
  import { withoutUnsentWriteValues } from "../runtime/unsent-value.normalizer.js";
7
8
  import { encodeOperationArgumentsForWire } from "./operation-arguments-encoder.js";
8
9
  import { computeOperationFingerprint } from "./operation-fingerprint.js";
@@ -10,13 +11,6 @@ import { readSqlTemplate } from "./sql-statement.js";
10
11
  import { routeTransactionReferenceCandidate } from "./transaction-reference.js";
11
12
  import { transactionOperationFailure } from "./transaction-response.js";
12
13
  const SQL_STEP_NODE = Object.freeze({ fingerprint: null });
13
- function isPlainRecord(value) {
14
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
15
- return false;
16
- }
17
- const prototype = Object.getPrototypeOf(value);
18
- return prototype === Object.prototype || prototype === null;
19
- }
20
14
  const KEEP = Symbol("keep");
21
15
  function rebuildArguments(root, leaf) {
22
16
  const pathOf = (parent, key) => () => {
@@ -12,6 +12,7 @@ import { createMisuseReporter } from "../runtime/misuse-reporter.js";
12
12
  import { operationFailure } from "../runtime/operation-response.js";
13
13
  import { activeContract, validateOperationRequest, validateProtocolIdentity, } from "../runtime/operation-runtime.js";
14
14
  import { mapValidationOutcome, VALIDATION_OUTCOME_MESSAGES, } from "../runtime/outcome-mapper.js";
15
+ import { isRecord } from "../runtime/record.guard.js";
15
16
  import { encodeOperationArgumentsForWire } from "./operation-arguments-encoder.js";
16
17
  import { computeOperationFingerprint, isOperationFingerprint, } from "./operation-fingerprint.js";
17
18
  import { validateSqlStatement } from "./sql-statement.validator.js";
@@ -104,9 +105,6 @@ const OPERATION_KEYS = [
104
105
  "args",
105
106
  "fingerprint",
106
107
  ];
107
- function isObject(value) {
108
- return typeof value === "object" && value !== null && !Array.isArray(value);
109
- }
110
108
  function operationKeyFailure(contract, step, operation) {
111
109
  const { resource, family, variant } = step;
112
110
  const issue = typeof family === "string" && typeof variant === "string"
@@ -199,7 +197,7 @@ function* relationTraversals(contract, resourceName, value, path) {
199
197
  }
200
198
  return;
201
199
  }
202
- if (!isObject(value)) {
200
+ if (!isRecord(value)) {
203
201
  return;
204
202
  }
205
203
  for (const [key, entry] of Object.entries(value)) {
@@ -215,7 +213,7 @@ function* relationTraversals(contract, resourceName, value, path) {
215
213
  }
216
214
  }
217
215
  function* operationTraversals(contract, request, index) {
218
- if (!isObject(request.arguments)) {
216
+ if (!isRecord(request.arguments)) {
219
217
  return;
220
218
  }
221
219
  const root = planOperationArgumentsPath(index);
@@ -229,7 +227,7 @@ function* operationTraversals(contract, request, index) {
229
227
  function deletedResources(contract, request, index) {
230
228
  const deleted = request.family === "delete" ? [request.resource] : [];
231
229
  for (const traversal of operationTraversals(contract, request, index)) {
232
- if (isObject(traversal.value) &&
230
+ if (isRecord(traversal.value) &&
233
231
  Object.hasOwn(traversal.value, "$delete")) {
234
232
  deleted.push(traversal.field.target);
235
233
  }
@@ -1,10 +1,8 @@
1
1
  import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
2
2
  import { planOperationArgumentsPath } from "../runtime/error-boundary.js";
3
- import { isPlainRecord, referenceOperandShape, } from "../runtime/scalar-runtime.js";
3
+ import { isPlainRecord, isRecord } from "../runtime/record.guard.js";
4
+ import { referenceOperandShape } from "../runtime/scalar-runtime.js";
4
5
  import { routeTransactionReferenceCandidate, } from "./transaction-reference.js";
5
- function isObject(value) {
6
- return typeof value === "object" && value !== null && !Array.isArray(value);
7
- }
8
6
  function at(position, ...segments) {
9
7
  return { ...position, path: [...position.path, ...segments] };
10
8
  }
@@ -23,7 +21,7 @@ function collectValue(field, shape, value, path, candidates, written = false) {
23
21
  return true;
24
22
  }
25
23
  function collectKey(position, selector, candidates) {
26
- if (!isObject(selector)) {
24
+ if (!isRecord(selector)) {
27
25
  return;
28
26
  }
29
27
  const resource = lookupResource(position.contract, position.resource);
@@ -61,7 +59,7 @@ function collectScalarFilter(field, filter, path, candidates) {
61
59
  }
62
60
  }
63
61
  function collectWhere(position, where, candidates) {
64
- if (!isObject(where)) {
62
+ if (!isRecord(where)) {
65
63
  return;
66
64
  }
67
65
  const resource = lookupResource(position.contract, position.resource);
@@ -87,7 +85,7 @@ function collectWhere(position, where, candidates) {
87
85
  if (field.cardinality === "one") {
88
86
  collectWhere(target, value, candidates);
89
87
  }
90
- else if (isObject(value)) {
88
+ else if (isRecord(value)) {
91
89
  for (const operator of ["some", "every", "none"]) {
92
90
  if (Object.hasOwn(value, operator)) {
93
91
  collectWhere(at(target, operator), value[operator], candidates);
@@ -107,7 +105,7 @@ function eachEntry(position, operand, visit) {
107
105
  visit(position, operand);
108
106
  }
109
107
  function collectRelationDirectives(position, edge, value, candidates) {
110
- if (!isObject(value)) {
108
+ if (!isRecord(value)) {
111
109
  return;
112
110
  }
113
111
  const target = { ...position, resource: edge.target };
@@ -129,7 +127,7 @@ function collectRelationDirectives(position, edge, value, candidates) {
129
127
  case "$delete":
130
128
  case "$upsert":
131
129
  eachEntry(directivePosition, operand, (entryPosition, entry) => {
132
- if (!isObject(entry)) {
130
+ if (!isRecord(entry)) {
133
131
  return;
134
132
  }
135
133
  const where = at(entryPosition, "where");
@@ -150,7 +148,7 @@ function collectRelationDirectives(position, edge, value, candidates) {
150
148
  }
151
149
  }
152
150
  function collectData(position, data, candidates) {
153
- if (!isObject(data)) {
151
+ if (!isRecord(data)) {
154
152
  return;
155
153
  }
156
154
  const resource = lookupResource(position.contract, position.resource);
@@ -1,9 +1,7 @@
1
1
  import { validationIssue } from "../operations/validation-code.js";
2
+ import { isRecord } from "../runtime/record.guard.js";
2
3
  import { copyScalarFieldValue } from "../runtime/scalar-runtime.js";
3
4
  import { replaceTransactionSlotValues } from "./transaction-slot-writer.js";
4
- function isRecord(value) {
5
- return typeof value === "object" && value !== null && !Array.isArray(value);
6
- }
7
5
  function unresolvedIssue(path) {
8
6
  return validationIssue("V1018", [...path, "$ref", "path"], "Transaction reference resolved to no value.");
9
7
  }
@@ -1,5 +1,5 @@
1
1
  import { transactionLevelsOf } from "../config/pipeline-tree.resolver.js";
2
- import { openRequestPolicy, } from "../policy/policy-request.js";
2
+ import { derivePolicyCaller, holdFirstPrincipal, openRequestPolicy, } from "../policy/policy-request.js";
3
3
  import { AdapterBoundary, planOperationArgumentsPath, planStepPath, sanitizeOperationFailure, } from "../runtime/error-boundary.js";
4
4
  import { internalFailure, operationSuccess, } from "../runtime/operation-response.js";
5
5
  import { admitOperation, EVERY_FIELD, executeAdmittedOperation, prepareStep, STEP_PIPES, withRequestState, } from "../runtime/operation-runtime.js";
@@ -82,6 +82,35 @@ function standingReferences(core, operation, args, steps, subject) {
82
82
  }
83
83
  async function executeTransactionPlan(runtime, dependencies, request, plan, state, diagnostics, caller) {
84
84
  const { adapter } = runtime;
85
+ const callers = new Map();
86
+ if (caller !== undefined) {
87
+ for (const step of plan.operations) {
88
+ if (step.kind === "operation") {
89
+ holdFirstPrincipal(runtime.config.policy, {
90
+ origin: step.request.origin,
91
+ state,
92
+ });
93
+ }
94
+ }
95
+ }
96
+ else {
97
+ for (const step of plan.operations) {
98
+ if (step.kind === "sql" || callers.has(step.request.origin)) {
99
+ continue;
100
+ }
101
+ try {
102
+ const derived = derivePolicyCaller(runtime.config.policy, {
103
+ origin: step.request.origin,
104
+ state,
105
+ });
106
+ callers.set(step.request.origin, derived instanceof Promise ? await derived : derived);
107
+ }
108
+ catch (error) {
109
+ diagnostics.operation(step.request, step.index)(error, "A3000");
110
+ return transactionOperationFailure(internalFailure(), step.index);
111
+ }
112
+ }
113
+ }
85
114
  const steps = new Map();
86
115
  const stateful = (operation) => {
87
116
  const known = steps.get(operation);
@@ -95,7 +124,7 @@ async function executeTransactionPlan(runtime, dependencies, request, plan, stat
95
124
  steps.set(operation, step);
96
125
  return step;
97
126
  };
98
- const policy = openRequestPolicy(runtime.config.policy, runtime.contracts.core, { origin: operation.request.origin, state }, caller, adapter);
127
+ const policy = openRequestPolicy(runtime.config.policy, runtime.contracts.core, { origin: operation.request.origin, state }, caller ?? callers.get(operation.request.origin), adapter);
99
128
  return policy instanceof Promise ? policy.then(settle) : settle(policy);
100
129
  };
101
130
  const admitted = [];
@@ -3,6 +3,7 @@ import { runLevelLifecycle, } from "../runtime/level-lifecycle.runtime.js";
3
3
  import { operationFailure } from "../runtime/operation-response.js";
4
4
  import { AvPipeOutputError, PIPE_OUTPUT_FAILURE_MESSAGE, } from "../runtime/pipe-output.validator.js";
5
5
  import { deepFreeze, frozenCopy } from "../runtime/readonly-value.js";
6
+ import { isRecord } from "../runtime/record.guard.js";
6
7
  import { AvTransactionIntegrityError } from "./transaction-integrity-error.js";
7
8
  export const TRANSACTION_ABORT = Object.freeze({ reason: "aventara-transaction-abort" });
8
9
  export const TRANSACTION_PIPES = "Transaction pipes";
@@ -26,9 +27,6 @@ export function touchedTransactionLevels(plan, levelsOf) {
26
27
  }
27
28
  return [...touched].flatMap((resource) => levelsOf(resource));
28
29
  }
29
- function isRecord(value) {
30
- return value !== null && typeof value === "object" && !Array.isArray(value);
31
- }
32
30
  function sameStructure(left, right) {
33
31
  if (Object.is(left, right)) {
34
32
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aventara/core",
3
- "version": "1.0.0-rc.10",
3
+ "version": "1.0.0-rc.12",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "Core runtime, contract compiler, and extension APIs for Aventara.",
6
6
  "type": "module",