@aventara/core 0.1.0-pilot.4 → 1.0.0-rc.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.
Files changed (255) hide show
  1. package/CHANGELOG.md +1478 -0
  2. package/README.md +275 -11
  3. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  4. package/dist/adapters/adapter-field.d.ts +11 -11
  5. package/dist/adapters/adapter-identifier.d.ts +6 -6
  6. package/dist/adapters/adapter-model.d.ts +17 -9
  7. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  8. package/dist/adapters/adapter-operation.d.ts +3 -3
  9. package/dist/adapters/adapter-resource.d.ts +18 -9
  10. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  11. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  12. package/dist/adapters/adapter.interface.d.ts +49 -25
  13. package/dist/avz/avz-check.factory.d.ts +83 -0
  14. package/dist/avz/avz-check.factory.js +116 -0
  15. package/dist/avz/avz-check.registry.d.ts +35 -0
  16. package/dist/avz/avz-check.registry.js +9 -0
  17. package/dist/avz/avz.d.ts +203 -0
  18. package/dist/avz/avz.js +354 -0
  19. package/dist/avz/index.d.ts +7 -0
  20. package/dist/avz/index.js +1 -0
  21. package/dist/avz/json-shape.registry.d.ts +22 -0
  22. package/dist/avz/json-shape.registry.js +16 -0
  23. package/dist/avz/zod-issue.translator.d.ts +57 -0
  24. package/dist/avz/zod-issue.translator.js +149 -0
  25. package/dist/compiler/contract-compiler-diagnostic.d.ts +37 -5
  26. package/dist/compiler/contract.compiler.d.ts +18 -18
  27. package/dist/compiler/contract.compiler.js +595 -421
  28. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  29. package/dist/compiler/create-requirements.projector.js +423 -0
  30. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  31. package/dist/compiler/field-validator.compiler.js +238 -0
  32. package/dist/config/any-framework-config.d.ts +19 -12
  33. package/dist/config/config-diagnostic.d.ts +11 -4
  34. package/dist/config/config-layer.d.ts +15 -6
  35. package/dist/config/config.resolver.d.ts +75 -29
  36. package/dist/config/config.resolver.js +109 -44
  37. package/dist/config/config.validator.d.ts +7 -7
  38. package/dist/config/config.validator.js +586 -71
  39. package/dist/config/define-resource.d.ts +57 -0
  40. package/dist/config/define-resource.js +14 -0
  41. package/dist/config/effective-fields.d.ts +19 -23
  42. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  43. package/dist/config/exact-framework-config.d.ts +280 -0
  44. package/dist/config/field-compute.resolver.d.ts +19 -0
  45. package/dist/config/field-compute.resolver.js +115 -0
  46. package/dist/config/field-pipeline-config.d.ts +47 -0
  47. package/dist/config/forced-operation.validator.d.ts +10 -0
  48. package/dist/config/forced-operation.validator.js +66 -0
  49. package/dist/config/framework-config.d.ts +111 -37
  50. package/dist/config/framework-exemptions-config.d.ts +91 -0
  51. package/dist/config/framework-exemptions-config.js +1 -0
  52. package/dist/config/framework-field-definition.d.ts +78 -0
  53. package/dist/config/framework-field-definition.js +28 -0
  54. package/dist/config/framework-resources-config.d.ts +116 -0
  55. package/dist/config/framework-resources-config.js +1 -0
  56. package/dist/config/pipeline-config.d.ts +56 -20
  57. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  58. package/dist/config/pipeline-tree.resolver.js +220 -0
  59. package/dist/config/stage-type.eraser.d.ts +65 -0
  60. package/dist/config/stage-type.eraser.js +1 -0
  61. package/dist/contracts/capability.d.ts +11 -11
  62. package/dist/contracts/client-contract-structure.validator.d.ts +344 -29
  63. package/dist/contracts/client-contract-structure.validator.js +248 -7
  64. package/dist/contracts/contract-canonicalizer.d.ts +19 -3
  65. package/dist/contracts/contract-canonicalizer.js +172 -27
  66. package/dist/contracts/contract-hash.d.ts +12 -7
  67. package/dist/contracts/contract-hash.js +3 -2
  68. package/dist/contracts/contract-limits.d.ts +4 -1
  69. package/dist/contracts/contract-limits.js +1 -0
  70. package/dist/contracts/contract-lookup.d.ts +5 -5
  71. package/dist/contracts/contract-protocol.d.ts +4 -4
  72. package/dist/contracts/contract.d.ts +31 -16
  73. package/dist/contracts/create-requirements.d.ts +35 -0
  74. package/dist/contracts/create-requirements.js +1 -0
  75. package/dist/contracts/enum-definition.d.ts +1 -1
  76. package/dist/contracts/field-check.d.ts +101 -0
  77. package/dist/contracts/field-check.js +1 -0
  78. package/dist/contracts/field.d.ts +61 -41
  79. package/dist/contracts/identifier.d.ts +4 -4
  80. package/dist/contracts/json-shape.d.ts +76 -0
  81. package/dist/contracts/json-shape.js +1 -0
  82. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  83. package/dist/contracts/reference-write-limit.d.ts +7 -0
  84. package/dist/contracts/reference-write-limit.js +1 -0
  85. package/dist/contracts/resource-operations.d.ts +28 -28
  86. package/dist/contracts/resource.d.ts +15 -9
  87. package/dist/contracts/scalar-value-type.d.ts +25 -14
  88. package/dist/contracts/scalar.d.ts +3 -3
  89. package/dist/contracts/transaction-capability.d.ts +1 -1
  90. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  91. package/dist/framework/contract-view.d.ts +234 -63
  92. package/dist/framework/framework-construction.error.d.ts +10 -10
  93. package/dist/framework/framework-construction.error.js +2 -2
  94. package/dist/framework/framework.d.ts +50 -24
  95. package/dist/framework/framework.factory.d.ts +8 -6
  96. package/dist/framework/framework.factory.js +95 -32
  97. package/dist/framework/operation-facade.d.ts +123 -52
  98. package/dist/framework/operation-facade.js +9 -1
  99. package/dist/index.d.ts +55 -82
  100. package/dist/index.js +6 -26
  101. package/dist/internal.d.ts +40 -0
  102. package/dist/internal.js +18 -0
  103. package/dist/operations/operation-arguments.d.ts +316 -201
  104. package/dist/operations/operation-call.d.ts +27 -28
  105. package/dist/operations/operation-identity.d.ts +12 -10
  106. package/dist/operations/operation-identity.js +3 -0
  107. package/dist/operations/operation-result.d.ts +21 -21
  108. package/dist/operations/operation-validator-core.d.ts +6 -6
  109. package/dist/operations/operation-validator-core.js +41 -12
  110. package/dist/operations/operation-validator.d.ts +24 -9
  111. package/dist/operations/operation-validator.js +26 -10
  112. package/dist/operations/projection-scope.resolver.d.ts +7 -7
  113. package/dist/operations/structural-limits.walker.d.ts +19 -0
  114. package/dist/operations/structural-limits.walker.js +489 -0
  115. package/dist/operations/validation-code.d.ts +11 -6
  116. package/dist/operations/validation-code.js +4 -0
  117. package/dist/operations/write-scope.resolver.d.ts +6 -6
  118. package/dist/protocol/absent-route.responder.d.ts +13 -11
  119. package/dist/protocol/absent-route.responder.js +42 -16
  120. package/dist/protocol/contract-document.responder.d.ts +3 -3
  121. package/dist/protocol/contract-document.responder.js +2 -2
  122. package/dist/protocol/http-request.decoder.d.ts +23 -13
  123. package/dist/protocol/http-request.decoder.js +19 -11
  124. package/dist/protocol/http-request.reader.d.ts +3 -3
  125. package/dist/protocol/http-response.encoder.d.ts +4 -4
  126. package/dist/protocol/http-response.encoder.js +94 -55
  127. package/dist/protocol/http-status.table.d.ts +2 -2
  128. package/dist/protocol/operation-response.guard.d.ts +2 -2
  129. package/dist/protocol/protocol-surface.d.ts +4 -4
  130. package/dist/protocol/protocol.binder.d.ts +52 -27
  131. package/dist/protocol/protocol.binder.js +14 -9
  132. package/dist/protocol/protocol.handler.d.ts +28 -15
  133. package/dist/protocol/protocol.handler.js +55 -10
  134. package/dist/protocol/unmounted-route.error.d.ts +19 -0
  135. package/dist/protocol/unmounted-route.error.js +10 -0
  136. package/dist/runtime/caller-data.copier.d.ts +59 -0
  137. package/dist/runtime/caller-data.copier.js +470 -0
  138. package/dist/runtime/caller-data.door.d.ts +56 -0
  139. package/dist/runtime/caller-data.door.js +67 -0
  140. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  141. package/dist/runtime/computed-read-runtime.js +61 -55
  142. package/dist/runtime/computed-value.error.d.ts +13 -0
  143. package/dist/runtime/computed-value.error.js +9 -0
  144. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  145. package/dist/runtime/context-executor.runtime.js +275 -0
  146. package/dist/runtime/create-requirement.d.ts +22 -57
  147. package/dist/runtime/create-requirement.js +140 -37
  148. package/dist/runtime/decimal.d.ts +2 -2
  149. package/dist/runtime/decimal.js +1 -1
  150. package/dist/runtime/diagnostics-reporter.d.ts +64 -22
  151. package/dist/runtime/diagnostics-reporter.js +35 -4
  152. package/dist/runtime/error-boundary.d.ts +73 -8
  153. package/dist/runtime/error-boundary.js +104 -48
  154. package/dist/runtime/execution-options.d.ts +10 -2
  155. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  156. package/dist/runtime/field-check.evaluator.js +521 -0
  157. package/dist/runtime/field-compute.d.ts +64 -0
  158. package/dist/runtime/field-compute.js +1 -0
  159. package/dist/runtime/field-stage.plan.d.ts +15 -0
  160. package/dist/runtime/field-stage.plan.js +27 -0
  161. package/dist/runtime/field-stage.runtime.d.ts +35 -0
  162. package/dist/runtime/field-stage.runtime.js +143 -0
  163. package/dist/runtime/field-validator.runtime.d.ts +11 -0
  164. package/dist/runtime/field-validator.runtime.js +87 -0
  165. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  166. package/dist/runtime/framework-error-class.table.js +25 -0
  167. package/dist/runtime/framework-error.d.ts +79 -7
  168. package/dist/runtime/framework-error.factory.d.ts +4 -0
  169. package/dist/runtime/framework-error.factory.js +15 -0
  170. package/dist/runtime/framework-error.js +23 -2
  171. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  172. package/dist/runtime/interceptor-next.error.js +6 -0
  173. package/dist/runtime/json-value.d.ts +3 -3
  174. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  175. package/dist/runtime/level-lifecycle.runtime.js +42 -0
  176. package/dist/runtime/misuse-reporter.d.ts +32 -0
  177. package/dist/runtime/misuse-reporter.js +19 -0
  178. package/dist/runtime/mutation-planner.d.ts +19 -10
  179. package/dist/runtime/mutation-planner.js +62 -36
  180. package/dist/runtime/nested-write.walker.d.ts +32 -0
  181. package/dist/runtime/nested-write.walker.js +73 -0
  182. package/dist/runtime/operation-request.d.ts +35 -15
  183. package/dist/runtime/operation-response.d.ts +17 -17
  184. package/dist/runtime/operation-runtime.d.ts +125 -30
  185. package/dist/runtime/operation-runtime.js +423 -83
  186. package/dist/runtime/outcome-mapper.d.ts +16 -5
  187. package/dist/runtime/outcome-mapper.js +35 -8
  188. package/dist/runtime/output-validator.d.ts +16 -6
  189. package/dist/runtime/output-validator.js +12 -1
  190. package/dist/runtime/owned-execution.registry.d.ts +13 -0
  191. package/dist/runtime/owned-execution.registry.js +7 -0
  192. package/dist/runtime/pipe-output.validator.d.ts +33 -18
  193. package/dist/runtime/pipe-output.validator.js +12 -12
  194. package/dist/runtime/pipeline.d.ts +202 -28
  195. package/dist/runtime/readonly-value.d.ts +32 -0
  196. package/dist/runtime/readonly-value.js +141 -0
  197. package/dist/runtime/referential-action.d.ts +7 -0
  198. package/dist/runtime/request-envelope.validator.d.ts +5 -0
  199. package/dist/runtime/request-envelope.validator.js +123 -0
  200. package/dist/runtime/request-id.d.ts +1 -1
  201. package/dist/runtime/request-state.d.ts +14 -0
  202. package/dist/runtime/request-state.js +1 -0
  203. package/dist/runtime/request-state.resolver.d.ts +12 -0
  204. package/dist/runtime/request-state.resolver.js +20 -0
  205. package/dist/runtime/scalar-runtime.d.ts +56 -13
  206. package/dist/runtime/scalar-runtime.js +167 -86
  207. package/dist/transactions/deferred-operation.d.ts +35 -20
  208. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  209. package/dist/transactions/operation-arguments-encoder.js +2 -2
  210. package/dist/transactions/sql-statement.d.ts +77 -0
  211. package/dist/transactions/sql-statement.js +47 -0
  212. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  213. package/dist/transactions/sql-statement.validator.js +134 -0
  214. package/dist/transactions/transaction-envelope.d.ts +4 -4
  215. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  216. package/dist/transactions/transaction-integrity-error.js +5 -2
  217. package/dist/transactions/transaction-plan-assembler.d.ts +23 -9
  218. package/dist/transactions/transaction-plan-assembler.js +195 -82
  219. package/dist/transactions/transaction-plan-validator.d.ts +53 -21
  220. package/dist/transactions/transaction-plan-validator.js +246 -163
  221. package/dist/transactions/transaction-reference-collector.d.ts +30 -0
  222. package/dist/transactions/transaction-reference-collector.js +204 -0
  223. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  224. package/dist/transactions/transaction-reference-resolver.js +27 -10
  225. package/dist/transactions/transaction-reference-validator.d.ts +34 -4
  226. package/dist/transactions/transaction-reference-validator.js +82 -43
  227. package/dist/transactions/transaction-reference.d.ts +30 -58
  228. package/dist/transactions/transaction-request.d.ts +20 -7
  229. package/dist/transactions/transaction-response.d.ts +12 -7
  230. package/dist/transactions/transaction-response.js +24 -1
  231. package/dist/transactions/transaction-runtime.d.ts +11 -8
  232. package/dist/transactions/transaction-runtime.js +167 -50
  233. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  234. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  235. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  236. package/dist/transactions/transaction-slot-path-error.js +2 -2
  237. package/dist/transactions/transaction-slot-writer.js +2 -2
  238. package/dist/transactions/transaction-stage.runtime.d.ts +81 -0
  239. package/dist/transactions/transaction-stage.runtime.js +123 -0
  240. package/package.json +18 -3
  241. package/src/runtime/field-check.evaluator.ts +720 -0
  242. package/dist/config/define-fields.d.ts +0 -35
  243. package/dist/config/define-fields.js +0 -3
  244. package/dist/config/framework-behaviors-config.d.ts +0 -30
  245. package/dist/config/framework-fields-config.d.ts +0 -36
  246. package/dist/config/framework-restrictions-config.d.ts +0 -142
  247. package/dist/operations/operation-boolean-nodes.d.ts +0 -11
  248. package/dist/operations/operation-boolean-nodes.js +0 -283
  249. package/dist/operations/operation-nesting.d.ts +0 -8
  250. package/dist/operations/operation-nesting.js +0 -307
  251. package/dist/runtime/field-behavior.d.ts +0 -48
  252. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  253. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  254. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  255. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -1,17 +1,75 @@
1
- import { CanonicalJsonError } from "../contracts/contract-canonicalizer.js";
2
- import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
1
+ import { AvCanonicalJsonError } from "../contracts/contract-canonicalizer.js";
2
+ import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
3
3
  import { parseOperationIdentity } from "../operations/operation-identity.js";
4
+ import { findOperationAvailabilityIssue, operationUnavailableIssue, unavailableOperationKey, } from "../operations/operation-validator.js";
5
+ import { resourceUnavailableIssue } from "../operations/operation-validator-core.js";
4
6
  import { VALIDATION_CODE_MESSAGES, validationIssue, } from "../operations/validation-code.js";
7
+ import { AvCallerDataError, locateCallerDataError, } from "../runtime/caller-data.copier.js";
8
+ import { copyAtDoor, misuseIdentityOf, refuseCallerData, } from "../runtime/caller-data.door.js";
5
9
  import { planReadOperation, } from "../runtime/computed-read-runtime.js";
6
- import { OPERATION_ARGUMENTS_PATH, planOperationArgumentsPath, } from "../runtime/error-boundary.js";
10
+ import { planOperationArgumentsPath, planStepPath, } from "../runtime/error-boundary.js";
11
+ import { createMisuseReporter } from "../runtime/misuse-reporter.js";
7
12
  import { operationFailure } from "../runtime/operation-response.js";
8
13
  import { activeContract, validateOperationRequest, validateProtocolIdentity, } from "../runtime/operation-runtime.js";
14
+ import { mapValidationOutcome, VALIDATION_OUTCOME_MESSAGES, } from "../runtime/outcome-mapper.js";
9
15
  import { encodeOperationArgumentsForWire } from "./operation-arguments-encoder.js";
10
16
  import { computeOperationFingerprint, isOperationFingerprint, } from "./operation-fingerprint.js";
17
+ import { validateSqlStatement } from "./sql-statement.validator.js";
11
18
  import { inspectTransactionEnvelope, inspectTransactionOperationEntry, inspectTransactionOperations, } from "./transaction-envelope.js";
12
- import { routeTransactionReferenceCandidate } from "./transaction-reference.js";
19
+ import { routeTransactionReferenceCandidate, } from "./transaction-reference.js";
20
+ import { collectTransactionReferenceCandidates, } from "./transaction-reference-collector.js";
13
21
  import { validateTransactionReferences } from "./transaction-reference-validator.js";
14
22
  import { transactionOperationFailure } from "./transaction-response.js";
23
+ const CALLER_PLAN = { source: "caller" };
24
+ const STEP_ARGUMENTS_POLICY = {
25
+ mirror: (value) => Object.hasOwn(value, "$ref"),
26
+ };
27
+ function captureSteps(operations, operationCount, planArguments) {
28
+ const steps = [];
29
+ const statements = planArguments.source === "owned" ? planArguments.statements : undefined;
30
+ for (let index = 0; index < operationCount; index += 1) {
31
+ const statement = statements?.get(index);
32
+ if (statement !== undefined) {
33
+ steps.push({ ok: true, kind: "sql", statement });
34
+ continue;
35
+ }
36
+ const operationEntry = inspectTransactionOperationEntry(operations, index);
37
+ if (!operationEntry.ok) {
38
+ steps.push({
39
+ ok: false,
40
+ response: structuralFailure(operationEntry.issue),
41
+ });
42
+ break;
43
+ }
44
+ const nodeEnvelope = inspectTransactionEnvelope(operationEntry.value, {
45
+ required: OPERATION_KEYS,
46
+ invalidContainerPath: [],
47
+ invalidContainerMessage: "Operation node must be an object.",
48
+ });
49
+ if (!nodeEnvelope.ok) {
50
+ steps.push({
51
+ ok: false,
52
+ response: structuralFailure(nodeEnvelope.issue, index),
53
+ });
54
+ break;
55
+ }
56
+ const node = nodeEnvelope.values;
57
+ const args = node.get("args");
58
+ const refused = planArguments.source === "owned"
59
+ ? planArguments.refused?.get(index)
60
+ : undefined;
61
+ const copy = refused !== undefined
62
+ ? { ok: false, error: refused }
63
+ : planArguments.source === "owned"
64
+ ? { ok: true, value: args }
65
+ : copyAtDoor(args, STEP_ARGUMENTS_POLICY);
66
+ steps.push({ ok: true, kind: "operation", node, args: copy });
67
+ if (!copy.ok) {
68
+ break;
69
+ }
70
+ }
71
+ return steps;
72
+ }
15
73
  const PLAN_KEYS = ["operations"];
16
74
  const OPERATION_KEYS = [
17
75
  "resource",
@@ -23,25 +81,44 @@ const OPERATION_KEYS = [
23
81
  function isObject(value) {
24
82
  return typeof value === "object" && value !== null && !Array.isArray(value);
25
83
  }
84
+ function operationKeyFailure(contract, step, operation) {
85
+ const { resource, family, variant } = step;
86
+ const issue = typeof family === "string" && typeof variant === "string"
87
+ ? operationUnavailableIssue(contract, { resource, family, variant })
88
+ : validationIssue("V1006", [
89
+ typeof family === "string"
90
+ ? unavailableOperationKey(contract, { resource, family })
91
+ : "family",
92
+ ], `Operation is not available on Resource "${resource}".`);
93
+ return transactionOperationFailure(mapValidationOutcome([issue]), operation);
94
+ }
26
95
  function structuralFailure(rejection, operation) {
27
96
  return operationFailure("A2004", {
28
97
  message: "Transaction plan failed framework validation.",
29
- issues: [rejection],
98
+ issues: [
99
+ operation === undefined || rejection.path === undefined
100
+ ? rejection
101
+ : {
102
+ ...rejection,
103
+ path: [...planStepPath(operation), ...rejection.path],
104
+ },
105
+ ],
30
106
  ...(operation === undefined ? {} : { operation }),
31
107
  });
32
108
  }
33
- function syntheticRequest(origin, requestId, resource, identity, args) {
109
+ function syntheticRequest(origin, request, resource, identity, args) {
34
110
  const common = {
35
- requestId,
111
+ requestId: request.requestId,
112
+ ...(request.state === undefined ? {} : { state: request.state }),
36
113
  resource,
37
114
  ...identity,
38
115
  arguments: args,
39
116
  };
40
- return origin.scope === "application"
41
- ? { ...common, scope: "application" }
117
+ return origin.origin === "application"
118
+ ? { ...common, origin: "application" }
42
119
  : {
43
120
  ...common,
44
- scope: "client",
121
+ origin: origin.origin,
45
122
  protocol: origin.protocol,
46
123
  ...(origin.transport === undefined
47
124
  ? {}
@@ -49,10 +126,10 @@ function syntheticRequest(origin, requestId, resource, identity, args) {
49
126
  };
50
127
  }
51
128
  function requestOrigin(request) {
52
- return request.scope === "application"
53
- ? { scope: "application" }
129
+ return request.origin === "application"
130
+ ? { origin: "application" }
54
131
  : {
55
- scope: "client",
132
+ origin: request.origin,
56
133
  protocol: request.protocol,
57
134
  ...(request.transport === undefined
58
135
  ? {}
@@ -60,55 +137,27 @@ function requestOrigin(request) {
60
137
  };
61
138
  }
62
139
  function originContracts(contracts, origins) {
63
- const layers = new Set(origins.map((origin) => origin.scope));
64
- return [...layers].map((scope) => scope === "application" ? contracts.application : contracts.client);
140
+ const layers = new Set(origins.map(({ origin }) => origin));
141
+ return [...layers].map((origin) => contracts[origin]);
65
142
  }
66
- function collectDataCandidates(contract, resourceName, data, path, candidates) {
67
- if (!isObject(data)) {
68
- return;
69
- }
70
- const resource = lookupResource(contract, resourceName);
71
- for (const [fieldName, value] of Object.entries(data)) {
72
- const field = lookupField(resource, fieldName);
73
- const route = routeTransactionReferenceCandidate(value);
74
- if (field?.kind === "scalar" && route.kind !== "ordinary") {
75
- candidates.push({
76
- path: [...path, fieldName],
77
- field,
78
- candidate: route.candidate,
79
- });
80
- }
81
- }
82
- }
83
- function collectCandidates(contract, request, index, args) {
84
- const candidates = [];
85
- const root = planOperationArgumentsPath(index);
86
- if (request.family === "create") {
87
- const data = lookupOwn(args, "data");
88
- if (request.variant === "many" || request.variant === "count") {
89
- if (Array.isArray(data)) {
90
- data.forEach((entry, dataIndex) => {
91
- collectDataCandidates(contract, request.resource, entry, [...root, "data", dataIndex], candidates);
92
- });
93
- }
94
- }
95
- else {
96
- collectDataCandidates(contract, request.resource, data, [...root, "data"], candidates);
97
- }
98
- }
99
- else if (request.family === "update") {
100
- collectDataCandidates(contract, request.resource, lookupOwn(args, "data"), [...root, "data"], candidates);
101
- }
102
- else if (request.family === "upsert") {
103
- for (const stage of ["create", "update"]) {
104
- collectDataCandidates(contract, request.resource, lookupOwn(args, stage), [...root, stage], candidates);
105
- }
106
- }
107
- return candidates;
143
+ function mixedOriginFailure(origins) {
144
+ const [first] = origins ?? [];
145
+ const other = first === undefined
146
+ ? -1
147
+ : (origins ?? []).findIndex(({ origin }) => origin !== first.origin);
148
+ return other === -1
149
+ ? undefined
150
+ : transactionOperationFailure(operationFailure("A2004", {
151
+ message: "Transaction plan failed framework validation.",
152
+ issues: [
153
+ validationIssue("V1020", [], VALIDATION_CODE_MESSAGES.V1020),
154
+ ],
155
+ }), other);
108
156
  }
109
157
  function* relationTraversals(contract, resourceName, value, path) {
110
158
  const resource = lookupResource(contract, resourceName);
111
- if (resource === undefined) {
159
+ if (resource === undefined ||
160
+ routeTransactionReferenceCandidate(value).kind !== "ordinary") {
112
161
  return;
113
162
  }
114
163
  if (Array.isArray(value)) {
@@ -182,11 +231,15 @@ export function transactionsUnavailableFailure() {
182
231
  issues: [validationIssue("V1006", ["operations"], message)],
183
232
  });
184
233
  }
185
- export async function validateTransactionPlan(dependencies, request, origins) {
234
+ export async function validateTransactionPlan(dependencies, request, origins, planArguments = CALLER_PLAN) {
186
235
  const protocolFailure = validateProtocolIdentity(dependencies.contracts, request);
187
236
  if (protocolFailure !== undefined) {
188
237
  return { ok: false, response: protocolFailure };
189
238
  }
239
+ const mixed = mixedOriginFailure(origins);
240
+ if (mixed !== undefined) {
241
+ return { ok: false, response: mixed };
242
+ }
190
243
  const ownOrigin = requestOrigin(request);
191
244
  const originOf = (index) => origins?.[index] ?? ownOrigin;
192
245
  const planContracts = origins === undefined || origins.length === 0
@@ -229,38 +282,37 @@ export async function validateTransactionPlan(dependencies, request, origins) {
229
282
  }),
230
283
  };
231
284
  }
285
+ const steps = captureSteps(operations, operationCount, planArguments);
286
+ const misuse = createMisuseReporter(dependencies.config.misuse);
232
287
  const validated = [];
233
288
  const cascaded = new Set();
234
289
  for (let index = 0; index < operationCount; index += 1) {
235
- const operationEntry = inspectTransactionOperationEntry(operations, index);
236
- if (!operationEntry.ok) {
237
- return {
238
- ok: false,
239
- response: structuralFailure(operationEntry.issue),
240
- };
290
+ const step = steps[index];
291
+ if (!step.ok) {
292
+ return { ok: false, response: step.response };
241
293
  }
242
- const nodeEnvelope = inspectTransactionEnvelope(operationEntry.value, {
243
- required: OPERATION_KEYS,
244
- invalidContainerPath: ["operation"],
245
- invalidContainerMessage: "Operation node must be an object.",
246
- });
247
- if (!nodeEnvelope.ok) {
248
- return {
249
- ok: false,
250
- response: structuralFailure(nodeEnvelope.issue, index),
251
- };
294
+ if (step.kind === "sql") {
295
+ const statement = validateSqlStatement(step.statement, {
296
+ index,
297
+ earlier: validated,
298
+ available: dependencies.sqlStatements,
299
+ misuse,
300
+ });
301
+ if (!statement.ok) {
302
+ return statement;
303
+ }
304
+ validated.push(statement.statement);
305
+ continue;
252
306
  }
253
- const node = nodeEnvelope.values;
307
+ const node = step.node;
254
308
  const origin = originOf(index);
255
- const contract = origin.scope === "application"
256
- ? dependencies.contracts.application
257
- : dependencies.contracts.client;
309
+ const contract = dependencies.contracts[origin.origin];
258
310
  const resourceValue = node.get("resource");
259
311
  if (typeof resourceValue !== "string") {
260
312
  return {
261
313
  ok: false,
262
314
  response: transactionOperationFailure(operationFailure("A2001", {
263
- message: "Operation Resource is invalid.",
315
+ message: VALIDATION_OUTCOME_MESSAGES.A2001,
264
316
  issues: [
265
317
  validationIssue("V1001", ["resource"], "resource must be a string."),
266
318
  ],
@@ -270,12 +322,7 @@ export async function validateTransactionPlan(dependencies, request, origins) {
270
322
  if (lookupResource(contract, resourceValue) === undefined) {
271
323
  return {
272
324
  ok: false,
273
- response: transactionOperationFailure(operationFailure("A2001", {
274
- message: "Operation arguments failed framework validation.",
275
- issues: [
276
- validationIssue("V1005", ["resource"], `Resource "${resourceValue}" is not available in the active Contract.`),
277
- ],
278
- }), index),
325
+ response: transactionOperationFailure(mapValidationOutcome([resourceUnavailableIssue(resourceValue)]), index),
279
326
  };
280
327
  }
281
328
  const family = node.get("family");
@@ -286,100 +333,136 @@ export async function validateTransactionPlan(dependencies, request, origins) {
286
333
  if (identity === undefined) {
287
334
  return {
288
335
  ok: false,
289
- response: transactionOperationFailure(operationFailure("A2002", {
290
- message: "Operation arguments failed framework validation.",
291
- issues: [
292
- validationIssue("V1006", ["operation"], "Operation is not part of the standard operation grammar."),
293
- ],
294
- }), index),
336
+ response: operationKeyFailure(contract, { resource: resourceValue, family, variant }, index),
295
337
  };
296
338
  }
297
- const operationRequest = syntheticRequest(origin, request.requestId, resourceValue, identity, node.get("args"));
298
- const operationValidation = validateOperationRequest(contract, operationRequest, { transactionReferences: true });
299
- if (!operationValidation.ok) {
339
+ const stepRequest = { resource: resourceValue, ...identity };
340
+ const unavailable = findOperationAvailabilityIssue(contract, stepRequest);
341
+ if (unavailable !== undefined) {
300
342
  return {
301
343
  ok: false,
302
- response: transactionOperationFailure(operationValidation.response, index),
344
+ response: transactionOperationFailure(mapValidationOutcome([unavailable]), index),
303
345
  };
304
346
  }
305
- const candidate = {
306
- index,
307
- request: operationRequest,
308
- arguments: operationValidation.arguments,
309
- projection: planReadOperation(dependencies.contracts.core, contract, (origin.scope === "application"
310
- ? dependencies.config.application
311
- : dependencies.config.client).behaviors, operationRequest, operationValidation.arguments).projection,
312
- declaredFingerprint: node.get("fingerprint"),
313
- candidates: collectCandidates(contract, operationRequest, index, operationValidation.arguments),
314
- };
315
- const referenceValidation = validateTransactionReferences(candidate, validated);
316
- if (!referenceValidation.ok) {
317
- return referenceValidation;
347
+ if (!step.args.ok) {
348
+ return {
349
+ ok: false,
350
+ response: transactionOperationFailure(mapValidationOutcome([
351
+ refuseCallerData(step.args.error, planOperationArgumentsPath(index), {
352
+ ...misuseIdentityOf({
353
+ ...stepRequest,
354
+ origin: origin.origin,
355
+ }),
356
+ operation: index,
357
+ }, misuse),
358
+ ]), index),
359
+ };
318
360
  }
319
- const validatedRequest = {
320
- ...candidate.request,
321
- arguments: referenceValidation.requestArguments,
322
- };
323
- const validatedArguments = referenceValidation.arguments;
324
- const wireArguments = origin.scope === "client"
325
- ? validatedRequest.arguments
326
- : encodeOperationArgumentsForWire(contract, validatedRequest, validatedArguments);
327
- let fingerprint;
328
361
  try {
329
- fingerprint = await computeOperationFingerprint({
330
- resource: validatedRequest.resource,
331
- family: validatedRequest.family,
332
- variant: validatedRequest.variant,
333
- args: wireArguments,
362
+ const operationRequest = syntheticRequest(origin, request, resourceValue, identity, step.args.value);
363
+ const operationValidation = validateOperationRequest(contract, operationRequest, { transactionReferences: true });
364
+ if (!operationValidation.ok) {
365
+ return {
366
+ ok: false,
367
+ response: transactionOperationFailure(operationValidation.response, index),
368
+ };
369
+ }
370
+ const candidate = {
371
+ index,
372
+ request: operationRequest,
373
+ arguments: operationValidation.arguments,
374
+ projection: planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, dependencies.config[origin.origin].compute, operationRequest, operationValidation.arguments).projection,
375
+ declaredFingerprint: node.get("fingerprint"),
376
+ candidates: collectTransactionReferenceCandidates(contract, operationRequest, index, operationValidation.arguments),
377
+ };
378
+ const referenceValidation = validateTransactionReferences(candidate, validated);
379
+ if (!referenceValidation.ok) {
380
+ return referenceValidation;
381
+ }
382
+ const validatedRequest = {
383
+ ...candidate.request,
384
+ arguments: referenceValidation.requestArguments,
385
+ };
386
+ const validatedArguments = referenceValidation.arguments;
387
+ const wireArguments = origin.origin !== "application"
388
+ ? validatedRequest.arguments
389
+ : encodeOperationArgumentsForWire(contract, validatedRequest, validatedArguments);
390
+ let fingerprint;
391
+ try {
392
+ fingerprint = await computeOperationFingerprint({
393
+ resource: validatedRequest.resource,
394
+ family: validatedRequest.family,
395
+ variant: validatedRequest.variant,
396
+ args: wireArguments,
397
+ });
398
+ }
399
+ catch (error) {
400
+ if (!(error instanceof AvCanonicalJsonError)) {
401
+ throw error;
402
+ }
403
+ return {
404
+ ok: false,
405
+ response: structuralFailure(validationIssue("V1001", ["args"], "Invalid runtime/wire type."), index),
406
+ };
407
+ }
408
+ if (!isOperationFingerprint(candidate.declaredFingerprint) ||
409
+ candidate.declaredFingerprint !== fingerprint) {
410
+ return {
411
+ ok: false,
412
+ response: transactionOperationFailure(operationFailure("A2007", {
413
+ message: "Operation fingerprint does not match its arguments.",
414
+ issues: [
415
+ validationIssue("V1017", ["fingerprint"], "Operation fingerprint does not match its arguments."),
416
+ ],
417
+ }), index),
418
+ };
419
+ }
420
+ const dependency = cascadeDependency(contract, validatedRequest, index, cascaded);
421
+ if (dependency !== undefined) {
422
+ return {
423
+ ok: false,
424
+ response: transactionOperationFailure(operationFailure("A2004", {
425
+ message: "Transaction plan failed framework validation.",
426
+ issues: [
427
+ validationIssue("V1019", dependency, VALIDATION_CODE_MESSAGES.V1019),
428
+ ],
429
+ }), index),
430
+ };
431
+ }
432
+ for (const resource of deletedResources(contract, validatedRequest, index)) {
433
+ for (const removed of dependencies.cascades(resource)) {
434
+ cascaded.add(removed);
435
+ }
436
+ }
437
+ validated.push({
438
+ kind: "operation",
439
+ index: candidate.index,
440
+ request: validatedRequest,
441
+ contract,
442
+ arguments: validatedArguments,
443
+ projection: candidate.projection,
444
+ fingerprint,
445
+ references: referenceValidation.references,
334
446
  });
335
447
  }
336
448
  catch (error) {
337
- if (!(error instanceof CanonicalJsonError)) {
449
+ if (!(error instanceof AvCallerDataError)) {
338
450
  throw error;
339
451
  }
340
452
  return {
341
453
  ok: false,
342
- response: structuralFailure(validationIssue("V1001", OPERATION_ARGUMENTS_PATH, "Invalid runtime/wire type."), index),
343
- };
344
- }
345
- if (!isOperationFingerprint(candidate.declaredFingerprint) ||
346
- candidate.declaredFingerprint !== fingerprint) {
347
- return {
348
- ok: false,
349
- response: transactionOperationFailure(operationFailure("A2007", {
350
- message: "Operation fingerprint does not match its arguments.",
351
- issues: [
352
- validationIssue("V1017", ["fingerprint"], "Operation fingerprint does not match its arguments."),
353
- ],
354
- }), index),
355
- };
356
- }
357
- const dependency = cascadeDependency(contract, validatedRequest, index, cascaded);
358
- if (dependency !== undefined) {
359
- return {
360
- ok: false,
361
- response: transactionOperationFailure(operationFailure("A2004", {
362
- message: "Transaction plan failed framework validation.",
363
- issues: [
364
- validationIssue("V1019", dependency, VALIDATION_CODE_MESSAGES.V1019),
365
- ],
366
- }), index),
454
+ response: transactionOperationFailure(mapValidationOutcome([
455
+ refuseCallerData(locateCallerDataError(error, step.args.value), planOperationArgumentsPath(index), {
456
+ ...misuseIdentityOf({
457
+ resource: resourceValue,
458
+ ...identity,
459
+ origin: origin.origin,
460
+ }),
461
+ operation: index,
462
+ }, misuse),
463
+ ]), index),
367
464
  };
368
465
  }
369
- for (const resource of deletedResources(contract, validatedRequest, index)) {
370
- for (const removed of dependencies.cascades(resource)) {
371
- cascaded.add(removed);
372
- }
373
- }
374
- validated.push({
375
- index: candidate.index,
376
- request: validatedRequest,
377
- contract,
378
- arguments: validatedArguments,
379
- projection: candidate.projection,
380
- fingerprint,
381
- references: referenceValidation.references,
382
- });
383
466
  }
384
467
  return { ok: true, plan: { operations: validated } };
385
468
  }
@@ -0,0 +1,30 @@
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvScalarField } from "../contracts/field.js";
3
+ import type { AvOperationIdentity } from "../operations/operation-identity.js";
4
+ import type { SemanticOperationArguments } from "../operations/operation-validator.js";
5
+ import { type TransactionSlotShape } from "./transaction-reference.js";
6
+ type Path = readonly (string | number)[];
7
+ /** One `$ref` candidate found at a reference position, before it is validated. */
8
+ export type TransactionReferenceCandidateSlot = {
9
+ readonly path: Path;
10
+ readonly field: AvScalarField<AvContract>;
11
+ readonly shape: TransactionSlotShape;
12
+ /** The slot is a scalar value of mutation data: what it resolves to is written. */
13
+ readonly written: boolean;
14
+ readonly candidate: unknown;
15
+ };
16
+ /**
17
+ * Every `$ref` candidate at a reference position of one validated operation, with the
18
+ * full wire path, the destination field and the slot's shape. The positions: mutation
19
+ * data (`create`'s `data`, each `data[]` entry of a bulk create, `update`'s `data`,
20
+ * `upsert`'s `create`/`update`) at any depth — its scalar values, the unique keys its
21
+ * relation directives name, the `where` of `$update`/`$delete`/`$upsert`, and the data
22
+ * they nest — the `cursor`, and the step's own `where` at any depth.
23
+ *
24
+ * It reads the validated argument view, whose normalization keeps every key where
25
+ * the caller wrote it, so a slot path names the same member of the wire view.
26
+ */
27
+ export declare function collectTransactionReferenceCandidates(contract: AvContract, request: AvOperationIdentity & {
28
+ readonly resource: string;
29
+ }, index: number, args: SemanticOperationArguments): readonly TransactionReferenceCandidateSlot[];
30
+ export {};