@aventara/core 1.0.0-rc.0 → 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 (242) hide show
  1. package/CHANGELOG.md +1140 -0
  2. package/README.md +224 -57
  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 +9 -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 -29
  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/{json → avz}/avz.js +150 -8
  19. package/dist/{json → avz}/index.d.ts +2 -1
  20. package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
  21. package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
  22. package/dist/{json → avz}/zod-issue.translator.js +7 -0
  23. package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
  24. package/dist/compiler/contract.compiler.d.ts +18 -18
  25. package/dist/compiler/contract.compiler.js +548 -441
  26. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  27. package/dist/compiler/create-requirements.projector.js +423 -0
  28. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  29. package/dist/compiler/field-validator.compiler.js +238 -0
  30. package/dist/config/any-framework-config.d.ts +19 -12
  31. package/dist/config/config-diagnostic.d.ts +11 -4
  32. package/dist/config/config-layer.d.ts +15 -6
  33. package/dist/config/config.resolver.d.ts +74 -31
  34. package/dist/config/config.resolver.js +108 -44
  35. package/dist/config/config.validator.d.ts +7 -7
  36. package/dist/config/config.validator.js +581 -72
  37. package/dist/config/define-resource.d.ts +57 -0
  38. package/dist/config/define-resource.js +14 -0
  39. package/dist/config/effective-fields.d.ts +19 -23
  40. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  41. package/dist/config/exact-framework-config.d.ts +280 -0
  42. package/dist/config/field-compute.resolver.d.ts +19 -0
  43. package/dist/config/field-compute.resolver.js +115 -0
  44. package/dist/config/field-pipeline-config.d.ts +47 -0
  45. package/dist/config/forced-operation.validator.d.ts +10 -0
  46. package/dist/config/forced-operation.validator.js +66 -0
  47. package/dist/config/framework-config.d.ts +110 -39
  48. package/dist/config/framework-exemptions-config.d.ts +91 -0
  49. package/dist/config/framework-exemptions-config.js +1 -0
  50. package/dist/config/framework-field-definition.d.ts +78 -0
  51. package/dist/config/framework-field-definition.js +28 -0
  52. package/dist/config/framework-resources-config.d.ts +116 -0
  53. package/dist/config/framework-resources-config.js +1 -0
  54. package/dist/config/pipeline-config.d.ts +56 -20
  55. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  56. package/dist/config/pipeline-tree.resolver.js +220 -0
  57. package/dist/config/stage-type.eraser.d.ts +65 -0
  58. package/dist/config/stage-type.eraser.js +1 -0
  59. package/dist/contracts/capability.d.ts +11 -11
  60. package/dist/contracts/client-contract-structure.validator.d.ts +323 -28
  61. package/dist/contracts/client-contract-structure.validator.js +152 -8
  62. package/dist/contracts/contract-canonicalizer.d.ts +19 -3
  63. package/dist/contracts/contract-canonicalizer.js +141 -28
  64. package/dist/contracts/contract-hash.d.ts +12 -7
  65. package/dist/contracts/contract-hash.js +3 -2
  66. package/dist/contracts/contract-limits.d.ts +4 -1
  67. package/dist/contracts/contract-limits.js +1 -0
  68. package/dist/contracts/contract-lookup.d.ts +5 -5
  69. package/dist/contracts/contract-protocol.d.ts +4 -4
  70. package/dist/contracts/contract.d.ts +24 -16
  71. package/dist/contracts/create-requirements.d.ts +35 -0
  72. package/dist/contracts/create-requirements.js +1 -0
  73. package/dist/contracts/enum-definition.d.ts +1 -1
  74. package/dist/contracts/field-check.d.ts +101 -0
  75. package/dist/contracts/field-check.js +1 -0
  76. package/dist/contracts/field.d.ts +52 -42
  77. package/dist/contracts/identifier.d.ts +4 -4
  78. package/dist/contracts/json-shape.d.ts +12 -1
  79. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  80. package/dist/contracts/resource-operations.d.ts +28 -28
  81. package/dist/contracts/resource.d.ts +15 -9
  82. package/dist/contracts/scalar-value-type.d.ts +15 -15
  83. package/dist/contracts/scalar.d.ts +3 -3
  84. package/dist/contracts/transaction-capability.d.ts +1 -1
  85. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  86. package/dist/framework/contract-view.d.ts +213 -147
  87. package/dist/framework/framework-construction.error.d.ts +10 -10
  88. package/dist/framework/framework-construction.error.js +2 -2
  89. package/dist/framework/framework.d.ts +47 -23
  90. package/dist/framework/framework.factory.d.ts +8 -6
  91. package/dist/framework/framework.factory.js +40 -20
  92. package/dist/framework/operation-facade.d.ts +123 -52
  93. package/dist/framework/operation-facade.js +9 -1
  94. package/dist/index.d.ts +55 -50
  95. package/dist/index.js +6 -6
  96. package/dist/internal.d.ts +15 -10
  97. package/dist/internal.js +3 -1
  98. package/dist/operations/operation-arguments.d.ts +267 -202
  99. package/dist/operations/operation-call.d.ts +27 -28
  100. package/dist/operations/operation-identity.d.ts +10 -10
  101. package/dist/operations/operation-result.d.ts +21 -21
  102. package/dist/operations/operation-validator-core.d.ts +6 -6
  103. package/dist/operations/operation-validator-core.js +13 -2
  104. package/dist/operations/operation-validator.d.ts +9 -9
  105. package/dist/operations/projection-scope.resolver.d.ts +6 -6
  106. package/dist/operations/structural-limits.walker.d.ts +6 -6
  107. package/dist/operations/structural-limits.walker.js +145 -0
  108. package/dist/operations/validation-code.d.ts +11 -6
  109. package/dist/operations/validation-code.js +4 -0
  110. package/dist/operations/write-scope.resolver.d.ts +6 -6
  111. package/dist/protocol/absent-route.responder.d.ts +13 -12
  112. package/dist/protocol/absent-route.responder.js +19 -19
  113. package/dist/protocol/contract-document.responder.d.ts +3 -3
  114. package/dist/protocol/contract-document.responder.js +2 -2
  115. package/dist/protocol/http-request.decoder.d.ts +17 -13
  116. package/dist/protocol/http-request.decoder.js +10 -10
  117. package/dist/protocol/http-request.reader.d.ts +3 -3
  118. package/dist/protocol/http-response.encoder.d.ts +4 -4
  119. package/dist/protocol/http-response.encoder.js +94 -55
  120. package/dist/protocol/http-status.table.d.ts +2 -2
  121. package/dist/protocol/operation-response.guard.d.ts +2 -2
  122. package/dist/protocol/protocol-surface.d.ts +4 -4
  123. package/dist/protocol/protocol.binder.d.ts +50 -27
  124. package/dist/protocol/protocol.binder.js +12 -9
  125. package/dist/protocol/protocol.handler.d.ts +22 -13
  126. package/dist/protocol/protocol.handler.js +44 -9
  127. package/dist/protocol/unmounted-route.error.d.ts +4 -4
  128. package/dist/protocol/unmounted-route.error.js +2 -2
  129. package/dist/runtime/caller-data.copier.d.ts +5 -5
  130. package/dist/runtime/caller-data.copier.js +13 -13
  131. package/dist/runtime/caller-data.door.d.ts +6 -6
  132. package/dist/runtime/caller-data.door.js +6 -4
  133. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  134. package/dist/runtime/computed-read-runtime.js +61 -48
  135. package/dist/runtime/computed-value.error.d.ts +6 -6
  136. package/dist/runtime/computed-value.error.js +3 -3
  137. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  138. package/dist/runtime/context-executor.runtime.js +275 -0
  139. package/dist/runtime/create-requirement.d.ts +10 -81
  140. package/dist/runtime/create-requirement.js +80 -57
  141. package/dist/runtime/decimal.d.ts +2 -2
  142. package/dist/runtime/decimal.js +1 -1
  143. package/dist/runtime/diagnostics-reporter.d.ts +53 -27
  144. package/dist/runtime/diagnostics-reporter.js +24 -0
  145. package/dist/runtime/error-boundary.d.ts +65 -8
  146. package/dist/runtime/error-boundary.js +45 -19
  147. package/dist/runtime/execution-options.d.ts +10 -2
  148. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  149. package/dist/runtime/field-check.evaluator.js +521 -0
  150. package/dist/runtime/field-compute.d.ts +64 -0
  151. package/dist/runtime/field-compute.js +1 -0
  152. package/dist/runtime/field-stage.plan.d.ts +15 -0
  153. package/dist/runtime/field-stage.plan.js +27 -0
  154. package/dist/runtime/field-stage.runtime.d.ts +35 -0
  155. package/dist/runtime/field-stage.runtime.js +143 -0
  156. package/dist/runtime/field-validator.runtime.d.ts +11 -0
  157. package/dist/runtime/field-validator.runtime.js +87 -0
  158. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  159. package/dist/runtime/framework-error-class.table.js +25 -0
  160. package/dist/runtime/framework-error.d.ts +68 -8
  161. package/dist/runtime/framework-error.factory.d.ts +4 -0
  162. package/dist/runtime/framework-error.factory.js +15 -0
  163. package/dist/runtime/framework-error.js +23 -2
  164. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  165. package/dist/runtime/interceptor-next.error.js +6 -0
  166. package/dist/runtime/json-value.d.ts +3 -3
  167. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  168. package/dist/runtime/level-lifecycle.runtime.js +42 -0
  169. package/dist/runtime/misuse-reporter.d.ts +12 -12
  170. package/dist/runtime/mutation-planner.d.ts +19 -10
  171. package/dist/runtime/mutation-planner.js +54 -30
  172. package/dist/runtime/nested-write.walker.d.ts +32 -0
  173. package/dist/runtime/nested-write.walker.js +73 -0
  174. package/dist/runtime/operation-request.d.ts +33 -6
  175. package/dist/runtime/operation-response.d.ts +17 -17
  176. package/dist/runtime/operation-runtime.d.ts +113 -25
  177. package/dist/runtime/operation-runtime.js +395 -74
  178. package/dist/runtime/outcome-mapper.d.ts +16 -5
  179. package/dist/runtime/outcome-mapper.js +23 -6
  180. package/dist/runtime/output-validator.d.ts +10 -10
  181. package/dist/runtime/output-validator.js +3 -3
  182. package/dist/runtime/owned-execution.registry.d.ts +6 -6
  183. package/dist/runtime/pipe-output.validator.d.ts +33 -18
  184. package/dist/runtime/pipe-output.validator.js +12 -12
  185. package/dist/runtime/pipeline.d.ts +196 -34
  186. package/dist/runtime/readonly-value.d.ts +32 -0
  187. package/dist/runtime/readonly-value.js +141 -0
  188. package/dist/runtime/request-envelope.validator.d.ts +3 -3
  189. package/dist/runtime/request-envelope.validator.js +12 -7
  190. package/dist/runtime/request-id.d.ts +1 -1
  191. package/dist/runtime/request-state.d.ts +14 -0
  192. package/dist/runtime/request-state.js +1 -0
  193. package/dist/runtime/request-state.resolver.d.ts +12 -0
  194. package/dist/runtime/request-state.resolver.js +20 -0
  195. package/dist/runtime/scalar-runtime.d.ts +31 -16
  196. package/dist/runtime/scalar-runtime.js +16 -18
  197. package/dist/transactions/deferred-operation.d.ts +35 -20
  198. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  199. package/dist/transactions/operation-arguments-encoder.js +2 -2
  200. package/dist/transactions/sql-statement.d.ts +77 -0
  201. package/dist/transactions/sql-statement.js +47 -0
  202. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  203. package/dist/transactions/sql-statement.validator.js +134 -0
  204. package/dist/transactions/transaction-envelope.d.ts +4 -4
  205. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  206. package/dist/transactions/transaction-integrity-error.js +5 -2
  207. package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
  208. package/dist/transactions/transaction-plan-assembler.js +148 -34
  209. package/dist/transactions/transaction-plan-validator.d.ts +29 -20
  210. package/dist/transactions/transaction-plan-validator.js +70 -38
  211. package/dist/transactions/transaction-reference-collector.d.ts +5 -5
  212. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  213. package/dist/transactions/transaction-reference-resolver.js +26 -14
  214. package/dist/transactions/transaction-reference-validator.d.ts +34 -4
  215. package/dist/transactions/transaction-reference-validator.js +58 -26
  216. package/dist/transactions/transaction-reference.d.ts +13 -13
  217. package/dist/transactions/transaction-request.d.ts +18 -5
  218. package/dist/transactions/transaction-response.d.ts +6 -6
  219. package/dist/transactions/transaction-runtime.d.ts +8 -7
  220. package/dist/transactions/transaction-runtime.js +166 -50
  221. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  222. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  223. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  224. package/dist/transactions/transaction-slot-path-error.js +2 -2
  225. package/dist/transactions/transaction-slot-writer.js +2 -2
  226. package/dist/transactions/transaction-stage.runtime.d.ts +81 -0
  227. package/dist/transactions/transaction-stage.runtime.js +123 -0
  228. package/package.json +6 -5
  229. package/src/runtime/field-check.evaluator.ts +720 -0
  230. package/dist/config/define-fields.d.ts +0 -42
  231. package/dist/config/define-fields.js +0 -3
  232. package/dist/config/framework-behaviors-config.d.ts +0 -30
  233. package/dist/config/framework-fields-config.d.ts +0 -42
  234. package/dist/config/framework-restrictions-config.d.ts +0 -142
  235. package/dist/json/avz.d.ts +0 -96
  236. package/dist/runtime/field-behavior.d.ts +0 -48
  237. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  238. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  239. /package/dist/{json → avz}/index.js +0 -0
  240. /package/dist/{json → avz}/json-shape.registry.js +0 -0
  241. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  242. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -1,38 +1,146 @@
1
+ import { hasFieldValidators } from "../compiler/field-validator.compiler.js";
2
+ import { fieldStagesOf, isForcedOperation, nestedTargetLevels, operationLevels, rawPipelineTree, transactionLevelsOf, } from "../config/pipeline-tree.resolver.js";
1
3
  import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
2
4
  import { findOperationAvailabilityIssue, validateOperationArguments, } from "../operations/operation-validator.js";
5
+ import { transactionInfrastructureFailure } from "../transactions/transaction-response.js";
6
+ import { settleTransaction } from "../transactions/transaction-settlement.runtime.js";
7
+ import { TRANSACTION_PIPES, transactionFacts, } from "../transactions/transaction-stage.runtime.js";
3
8
  import { copyAtDoor, misuseIdentityOf, refuseCallerData, } from "./caller-data.door.js";
4
9
  import { materializeReadOperation, planReadOperation, } from "./computed-read-runtime.js";
10
+ import { createContextExecutor, } from "./context-executor.runtime.js";
5
11
  import { createRequirementIssues, recordWriteFactsOf, } from "./create-requirement.js";
12
+ import { createDiagnosticsReporter, } from "./diagnostics-reporter.js";
6
13
  import { AdapterBoundary, OPERATION_ARGUMENTS_PATH, resolveOperationFailure, sanitizeOperationFailure, } from "./error-boundary.js";
14
+ import { planFieldStages } from "./field-stage.plan.js";
15
+ import { guardSentFields, pipeSentFields, valueAt, writeRecordPathsOf, } from "./field-stage.runtime.js";
16
+ import { fieldValidatorIssues } from "./field-validator.runtime.js";
17
+ import { thrownFailure } from "./framework-error.factory.js";
18
+ import { AvInterceptorNextError } from "./interceptor-next.error.js";
19
+ import { runLevelLifecycle, } from "./level-lifecycle.runtime.js";
7
20
  import { createMisuseReporter, } from "./misuse-reporter.js";
8
- import { applyWriteFieldBehaviors, stripVirtualMutationInput, } from "./mutation-planner.js";
21
+ import { applyNestedWriteCompute, applyWriteCompute, stripVirtualMutationInput, } from "./mutation-planner.js";
22
+ import { nestedWriteTargetsOf, } from "./nested-write.walker.js";
9
23
  import { internalFailure, operationFailure } from "./operation-response.js";
10
- import { mapOperationOutcome, mapValidationOutcome } from "./outcome-mapper.js";
11
- import { OutputValidationError, validateOperationOutput, } from "./output-validator.js";
12
- import { refusePipeOutput } from "./pipe-output.validator.js";
24
+ import { mapOperationOutcome, mapValidationOutcome, uniqueMissFailure, } from "./outcome-mapper.js";
25
+ import { AvOutputValidationError, validateOperationOutput, } from "./output-validator.js";
26
+ import { refusePipeOutput, refuseStageOutput, } from "./pipe-output.validator.js";
27
+ import { deepFreeze, frozenCopy } from "./readonly-value.js";
28
+ import { requestStateOf } from "./request-state.resolver.js";
13
29
  import { normalizeOperationScalarValues, } from "./scalar-runtime.js";
30
+ function scopeOf(request, binding) {
31
+ return {
32
+ requestId: request.requestId,
33
+ transaction: binding?.kind === "transaction" ? binding.executor : undefined,
34
+ state: request.state,
35
+ };
36
+ }
37
+ export function withRequestState(request) {
38
+ return { ...request, state: requestStateOf(request.state) };
39
+ }
40
+ export function createPipelineDependencies(dependencies, model) {
41
+ const misuse = createMisuseReporter(dependencies.config.misuse);
42
+ const recordWrites = recordWriteFactsOf(dependencies.adapter);
43
+ const contexts = createContextExecutor({
44
+ model,
45
+ adapter: dependencies.adapter,
46
+ application: dependencies.contracts.application,
47
+ diagnostics: dependencies.config.diagnostics,
48
+ misuse,
49
+ run: (request, transaction) => executeContextCall(raw, dependencies, request, transaction, misuse),
50
+ });
51
+ const { contracts, config } = dependencies;
52
+ const pipeline = {
53
+ contracts,
54
+ config,
55
+ recordWrites,
56
+ contexts,
57
+ fieldStages: {
58
+ application: planFieldStages(config.application.pipelines, contracts.application),
59
+ client: planFieldStages(config.client.pipelines, contracts.client),
60
+ agent: planFieldStages(config.agent.pipelines, contracts.agent),
61
+ },
62
+ };
63
+ const rawTree = rawPipelineTree(config.application.pipelines);
64
+ const raw = {
65
+ ...pipeline,
66
+ config: {
67
+ ...config,
68
+ application: { ...config.application, pipelines: rawTree },
69
+ },
70
+ fieldStages: {
71
+ ...pipeline.fieldStages,
72
+ application: planFieldStages(rawTree, contracts.application),
73
+ },
74
+ };
75
+ return pipeline;
76
+ }
77
+ async function executeContextCall(raw, dependencies, request, transaction, misuse) {
78
+ const report = createDiagnosticsReporter(dependencies.config.diagnostics, request);
79
+ try {
80
+ let validated;
81
+ try {
82
+ validated = validateOperation(dependencies, request, "caller", misuse);
83
+ }
84
+ catch (error) {
85
+ return sanitizeOperationFailure(error, "runtime", report, {
86
+ path: OPERATION_ARGUMENTS_PATH,
87
+ arguments: request.arguments,
88
+ });
89
+ }
90
+ if (!validated.ok) {
91
+ return validated.response;
92
+ }
93
+ const stateful = withRequestState(request);
94
+ const admitted = await admitOperation(raw, stateful, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, report, {
95
+ requestId: request.requestId,
96
+ transaction,
97
+ state: stateful.state,
98
+ });
99
+ if (!admitted.ok) {
100
+ return admitted.response;
101
+ }
102
+ return await executeAdmittedOperation(raw, stateful, validated.contract, admitted.args, OPERATION_ARGUMENTS_PATH, transaction === undefined
103
+ ? { kind: "standalone", executor: dependencies.adapter }
104
+ : { kind: "transaction", executor: transaction }, report);
105
+ }
106
+ catch (error) {
107
+ report(error, "A3000");
108
+ return internalFailure();
109
+ }
110
+ }
14
111
  export function activeContract(contracts, request) {
15
- return request.origin === "application"
16
- ? contracts.application
17
- : contracts.client;
112
+ return contracts[request.origin];
18
113
  }
19
114
  function activeScopeConfig(config, request) {
20
- return request.origin === "application" ? config.application : config.client;
115
+ return config[request.origin];
21
116
  }
22
- function pipelineContext(contract, request, args) {
117
+ function operationFacts(contract, request, args) {
23
118
  return {
24
- contract,
25
- origin: request.origin,
26
- resource: request.resource,
27
- family: request.family,
28
- variant: request.variant,
29
- args,
30
- requestId: request.requestId,
31
- ...(request.origin === "client" && request.transport !== undefined
32
- ? { transport: request.transport }
119
+ $operation: {
120
+ resource: request.resource,
121
+ family: request.family,
122
+ variant: request.variant,
123
+ },
124
+ $args: args,
125
+ $origin: request.origin,
126
+ $requestId: request.requestId,
127
+ $contract: contract,
128
+ ...(request.origin !== "application" && request.transport !== undefined
129
+ ? { $transport: request.transport }
33
130
  : {}),
34
131
  };
35
132
  }
133
+ function nestedFacts(contract, request, target, payload) {
134
+ return {
135
+ ...operationFacts(contract, request, payload),
136
+ $operation: {
137
+ resource: target.resource,
138
+ family: target.family,
139
+ variant: "one",
140
+ nested: true,
141
+ },
142
+ };
143
+ }
36
144
  function forbidden() {
37
145
  return operationFailure("A4001", {
38
146
  message: "Operation denied by a framework guard.",
@@ -48,16 +156,11 @@ function outputAccepted(contract, request, projection, data, report) {
48
156
  return false;
49
157
  }
50
158
  if (!validation.ok) {
51
- report(new OutputValidationError(request, validation.issues), "A3000");
159
+ report(new AvOutputValidationError(request, validation.issues), "A3000");
52
160
  }
53
161
  return validation.ok;
54
162
  }
55
- export function createOperationRuntime(dependencies) {
56
- const pipelineDependencies = {
57
- contracts: dependencies.contracts,
58
- config: dependencies.config,
59
- recordWrites: recordWriteFactsOf(dependencies.adapter),
60
- };
163
+ export function createOperationRuntime(dependencies, pipelineDependencies) {
61
164
  const misuse = createMisuseReporter(dependencies.config.misuse);
62
165
  return async (request, report, source) => {
63
166
  let validated;
@@ -73,7 +176,19 @@ export function createOperationRuntime(dependencies) {
73
176
  if (!validated.ok) {
74
177
  return validated.response;
75
178
  }
76
- return executeValidatedOperation(pipelineDependencies, request, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, dependencies.adapter, report);
179
+ const stateful = withRequestState(request);
180
+ const admitted = await admitOperation(pipelineDependencies, stateful, validated.contract, validated.arguments, OPERATION_ARGUMENTS_PATH, report, {
181
+ requestId: request.requestId,
182
+ transaction: undefined,
183
+ state: stateful.state,
184
+ });
185
+ if (!admitted.ok) {
186
+ return admitted.response;
187
+ }
188
+ if (isForcedOperation(activeScopeConfig(dependencies.config, request).pipelines, request)) {
189
+ return executeForcedOperation(pipelineDependencies, dependencies.adapter, stateful, validated.contract, admitted.args, report);
190
+ }
191
+ return executeAdmittedOperation(pipelineDependencies, stateful, validated.contract, admitted.args, OPERATION_ARGUMENTS_PATH, { kind: "standalone", executor: dependencies.adapter }, report);
77
192
  };
78
193
  }
79
194
  function validateOperation(dependencies, request, source, misuse) {
@@ -100,19 +215,21 @@ function validateOperation(dependencies, request, source, misuse) {
100
215
  return { ok: true, contract, arguments: validation.arguments };
101
216
  }
102
217
  export function validateProtocolIdentity(contracts, request) {
103
- return request.origin === "client"
104
- ? protocolIdentityFailure(contracts, request.protocol)
105
- : undefined;
218
+ return request.origin === "application"
219
+ ? undefined
220
+ : protocolIdentityFailure(contracts, request.protocol, request.origin);
106
221
  }
107
- export function protocolIdentityFailure(contracts, protocol) {
222
+ export function protocolIdentityFailure(contracts, protocol, origin) {
108
223
  if (protocol.version !== AVENTARA_PROTOCOL_VERSION) {
109
224
  return operationFailure("A2006", {
110
225
  message: "Aventara protocol version does not match the server.",
111
226
  });
112
227
  }
113
- if (protocol.hash !== contracts.client.protocol.hash) {
228
+ if (protocol.hash !== contracts[origin].protocol.hash) {
114
229
  return operationFailure("A2005", {
115
- message: "Generated client contract does not match the server. Regenerate the client.",
230
+ message: origin === "client"
231
+ ? "Generated client contract does not match the server. Regenerate the client."
232
+ : "Agent contract does not match the server. Rebuild the agent's tools from the current Agent Contract.",
116
233
  });
117
234
  }
118
235
  return undefined;
@@ -133,76 +250,280 @@ export function validateOperationRequest(contract, request, options, write = "co
133
250
  function rejected(response) {
134
251
  return { ok: false, response };
135
252
  }
136
- export async function executeValidatedOperation(dependencies, request, contract, validatedArguments, argumentsPath, executor, report) {
137
- const scopeConfig = activeScopeConfig(dependencies.config, request);
138
- const pipelines = scopeConfig.pipelines;
139
- const adapterBoundary = new AdapterBoundary();
140
- let args = validatedArguments;
253
+ const FIELD_PIPES = "Field pipes";
254
+ const STEP_PIPES = "Pipes";
255
+ export const EVERY_FIELD = () => true;
256
+ function filtersOf(levels) {
257
+ return levels.flatMap((level) => level.filters);
258
+ }
259
+ const SINGLE_CALL = { select: EVERY_FIELD };
260
+ export async function admitOperation(dependencies, request, contract, args, argumentsPath, report, scope, admission = SINGLE_CALL) {
261
+ const contexts = dependencies.contexts;
262
+ const tree = activeScopeConfig(dependencies.config, request).pipelines;
263
+ const levels = operationLevels(tree, request);
264
+ const planned = dependencies.fieldStages[request.origin];
265
+ const guarded = planned.guarded(request.resource);
266
+ const contracts = { core: dependencies.contracts.core, active: contract };
267
+ let current = deepFreeze(args);
268
+ const context = () => contexts.operation(scope, operationFacts(contract, request, current));
269
+ const admit = async () => {
270
+ for (const level of levels) {
271
+ for (const guard of level.guards) {
272
+ if ((await guard(context())) === false) {
273
+ return { ok: false, response: forbidden() };
274
+ }
275
+ }
276
+ }
277
+ if (guarded.length > 0 &&
278
+ !(await guardSentFields(fieldStagesOf(tree, request.resource), guarded, writeRecordPathsOf(request.family, current), current, context))) {
279
+ return { ok: false, response: forbidden() };
280
+ }
281
+ for (const target of planned.nestedGuards
282
+ ? nestedWriteTargetsOf(contract, dependencies.recordWrites.references, request, current)
283
+ : []) {
284
+ const told = () => contexts.operation(scope, nestedFacts(contract, request, target, valueAt(current, target.path)));
285
+ for (const level of nestedTargetLevels(tree, target.resource, target.family)) {
286
+ for (const guard of level.guards) {
287
+ if ((await guard(told())) === false) {
288
+ return { ok: false, response: forbidden() };
289
+ }
290
+ }
291
+ }
292
+ const targetGuarded = planned.guarded(target.resource);
293
+ if (targetGuarded.length > 0 &&
294
+ !(await guardSentFields(fieldStagesOf(tree, target.resource), targetGuarded, target.records.map((site) => site.path), current, told))) {
295
+ return { ok: false, response: forbidden() };
296
+ }
297
+ }
298
+ let piped = false;
299
+ let pipeIndex = 0;
300
+ for (const level of levels) {
301
+ for (const pipe of level.pipes) {
302
+ const returned = await pipe(current, context());
303
+ if (returned !== undefined && returned !== current) {
304
+ const refused = refusePipeOutput(contracts, request, returned, pipe, pipeIndex, admission.validation);
305
+ if (refused !== undefined) {
306
+ report(refused.error, "A3004");
307
+ return { ok: false, response: refused.response };
308
+ }
309
+ current = deepFreeze(returned);
310
+ piped = true;
311
+ }
312
+ pipeIndex += 1;
313
+ }
314
+ }
315
+ const fields = await runFieldInputStages(dependencies, request, contract, current, argumentsPath, report, admission);
316
+ if (!fields.ok) {
317
+ return fields;
318
+ }
319
+ return {
320
+ ok: true,
321
+ args: deepFreeze(fields.args),
322
+ piped: piped || fields.piped,
323
+ };
324
+ };
141
325
  try {
142
- return await runLifecycle();
326
+ return await admit();
143
327
  }
144
328
  catch (error) {
145
- return resolveOperationFailure(error, pipelines.filters, pipelineContext(contract, request, args), adapterBoundary, report, { path: argumentsPath, arguments: args });
329
+ return {
330
+ ok: false,
331
+ response: await resolveOperationFailure(error, filtersOf(levels), context(), new AdapterBoundary(), report, { path: argumentsPath, arguments: current }),
332
+ };
146
333
  }
147
- async function runLifecycle() {
148
- for (const guard of pipelines.guards) {
149
- const allowed = await guard(pipelineContext(contract, request, args));
150
- if (allowed === false) {
151
- return forbidden();
334
+ }
335
+ async function runFieldInputStages(dependencies, request, contract, args, argumentsPath, report, admission) {
336
+ const tree = activeScopeConfig(dependencies.config, request).pipelines;
337
+ const planned = dependencies.fieldStages[request.origin];
338
+ const pipes = planned.anyPipes;
339
+ if (!pipes && !hasFieldValidators(contract)) {
340
+ return { ok: true, args, piped: false };
341
+ }
342
+ let current = args;
343
+ let changed = false;
344
+ if (pipes) {
345
+ const pipedFields = planned.piped(request.resource);
346
+ let piped = pipedFields.length === 0
347
+ ? { args: current, changed: false }
348
+ : await pipeSentFields(fieldStagesOf(tree, request.resource), pipedFields, writeRecordPathsOf(request.family, current), current, admission.select);
349
+ changed = piped.changed;
350
+ for (const target of nestedWriteTargetsOf(contract, dependencies.recordWrites.references, request, piped.args)) {
351
+ const targetPiped = planned.piped(target.resource);
352
+ if (targetPiped.length === 0) {
353
+ continue;
152
354
  }
355
+ piped = await pipeSentFields(fieldStagesOf(tree, target.resource), targetPiped, target.records.map((site) => site.path), piped.args, admission.select);
356
+ changed ||= piped.changed;
153
357
  }
154
- for (const [index, pipe] of pipelines.pipes.entries()) {
155
- const nextArgs = await pipe(args, pipelineContext(contract, request, args));
156
- if (nextArgs !== undefined) {
157
- args = nextArgs;
358
+ current = piped.args;
359
+ if (changed) {
360
+ const refused = refuseStageOutput({ core: dependencies.contracts.core, active: contract }, request, current, FIELD_PIPES, admission.validation);
361
+ if (refused !== undefined) {
362
+ report(refused.error, "A3004");
363
+ return { ok: false, response: refused.response };
158
364
  }
159
- const refused = refusePipeOutput({ core: dependencies.contracts.core, active: contract }, request, args, pipe, index);
365
+ }
366
+ }
367
+ const broken = fieldValidatorIssues(contract, dependencies.recordWrites.references, request, current, argumentsPath, admission.select);
368
+ if (broken.length > 0) {
369
+ return { ok: false, response: mapValidationOutcome(broken) };
370
+ }
371
+ return { ok: true, args: current, piped: changed };
372
+ }
373
+ export async function prepareStep(dependencies, request, contract, args, argumentsPath, report, executor, changes, outer) {
374
+ let current = deepFreeze(args);
375
+ const scope = {
376
+ requestId: request.requestId,
377
+ transaction: executor,
378
+ state: request.state,
379
+ };
380
+ try {
381
+ const resolved = await runFieldInputStages(dependencies, request, contract, current, argumentsPath, report, { select: changes.written });
382
+ if (!resolved.ok) {
383
+ return resolved;
384
+ }
385
+ current = resolved.args;
386
+ const subject = changes.transactionPiped
387
+ ? TRANSACTION_PIPES
388
+ : changes.pipedAroundReferences
389
+ ? STEP_PIPES
390
+ : undefined;
391
+ if (subject !== undefined) {
392
+ const refused = refuseStageOutput({ core: dependencies.contracts.core, active: contract }, request, current, subject);
160
393
  if (refused !== undefined) {
161
394
  report(refused.error, "A3004");
162
- return refused.response;
395
+ return { ok: false, response: refused.response };
396
+ }
397
+ }
398
+ if (changes.transactionPiped) {
399
+ const broken = fieldValidatorIssues(contract, dependencies.recordWrites.references, request, current, argumentsPath, EVERY_FIELD);
400
+ if (broken.length > 0) {
401
+ return { ok: false, response: mapValidationOutcome(broken) };
402
+ }
403
+ }
404
+ return { ok: true, args: deepFreeze(current), piped: resolved.piped };
405
+ }
406
+ catch (error) {
407
+ return {
408
+ ok: false,
409
+ response: await resolveOperationFailure(error, filtersOf(operationLevels(activeScopeConfig(dependencies.config, request).pipelines, request)), dependencies.contexts.operation(scope, operationFacts(contract, request, current)), new AdapterBoundary(), report, { path: argumentsPath, arguments: current }, outer),
410
+ };
411
+ }
412
+ }
413
+ async function executeForcedOperation(dependencies, adapter, request, contract, args, report) {
414
+ const plan = [
415
+ {
416
+ resource: request.resource,
417
+ family: request.family,
418
+ variant: request.variant,
419
+ args,
420
+ },
421
+ ];
422
+ const settled = await settleTransaction({
423
+ adapter,
424
+ levels: transactionLevelsOf(activeScopeConfig(dependencies.config, request).pipelines, request.resource),
425
+ plan,
426
+ contextOf: (current, executor) => dependencies.contexts.transaction({
427
+ requestId: request.requestId,
428
+ transaction: executor,
429
+ state: request.state,
430
+ }, transactionFacts(contract, request, current)),
431
+ failureView: { path: OPERATION_ARGUMENTS_PATH, arguments: args },
432
+ report,
433
+ runStep: async (_index, step, piped, executor, _results, outer) => {
434
+ let stepArguments = step.args;
435
+ if (piped) {
436
+ const prepared = await prepareStep(dependencies, request, contract, stepArguments, OPERATION_ARGUMENTS_PATH, report, executor, {
437
+ written: () => false,
438
+ transactionPiped: true,
439
+ pipedAroundReferences: false,
440
+ }, outer);
441
+ if (!prepared.ok) {
442
+ return prepared.response;
443
+ }
444
+ stepArguments = prepared.args;
163
445
  }
446
+ return executeAdmittedOperation(dependencies, request, contract, stepArguments, OPERATION_ARGUMENTS_PATH, { kind: "transaction", executor, outer }, report);
447
+ },
448
+ });
449
+ switch (settled.kind) {
450
+ case "committed":
451
+ return settled.responses[0] ?? internalFailure();
452
+ case "rolled-back":
453
+ return settled.response;
454
+ case "broken":
455
+ report(settled.error, "A3002");
456
+ return transactionInfrastructureFailure();
457
+ }
458
+ }
459
+ export async function executeAdmittedOperation(dependencies, request, contract, admittedArguments, argumentsPath, binding, report) {
460
+ const { executor } = binding;
461
+ const scope = scopeOf(request, binding);
462
+ const contexts = dependencies.contexts;
463
+ const scopeConfig = activeScopeConfig(dependencies.config, request);
464
+ const levels = operationLevels(scopeConfig.pipelines, request);
465
+ const adapterBoundary = new AdapterBoundary();
466
+ const contracts = { core: dependencies.contracts.core, active: contract };
467
+ let args = deepFreeze(admittedArguments);
468
+ let told;
469
+ const view = () => {
470
+ if (told === undefined || told.of !== args) {
471
+ told = { of: args, view: frozenCopy(args) };
164
472
  }
165
- args = await applyWriteFieldBehaviors({ core: dependencies.contracts.core, active: contract }, scopeConfig.behaviors, request, args, () => pipelineContext(contract, request, args));
166
- const missing = createRequirementIssues(contract, dependencies.recordWrites, request, args, argumentsPath);
473
+ return told.view;
474
+ };
475
+ const context = () => contexts.operation(scope, operationFacts(contract, request, view()));
476
+ const computeContext = () => contexts.compute(scope, operationFacts(contract, request, view()));
477
+ const reuse = { refusal: undefined };
478
+ const refusedReuse = (refusal) => {
479
+ report(refusal, "A3000");
480
+ return internalFailure();
481
+ };
482
+ let response;
483
+ try {
484
+ response = await runLifecycle();
485
+ }
486
+ catch (error) {
487
+ if (reuse.refusal !== undefined) {
488
+ return refusedReuse(reuse.refusal);
489
+ }
490
+ return resolveOperationFailure(error, filtersOf(levels), context(), adapterBoundary, report, { path: argumentsPath, arguments: args }, binding.kind === "transaction" ? binding.outer : undefined);
491
+ }
492
+ return reuse.refusal === undefined ? response : refusedReuse(reuse.refusal);
493
+ async function runLifecycle() {
494
+ let computed = await applyWriteCompute(contracts, scopeConfig.compute, request, args, computeContext);
495
+ computed = await applyNestedWriteCompute(contracts, scopeConfig.compute, computed, nestedWriteTargetsOf(contract, dependencies.recordWrites.references, request, computed), (target, payload) => contexts.compute(scope, nestedFacts(contract, request, target, payload)));
496
+ const missing = createRequirementIssues(contract, dependencies.recordWrites, request, computed, argumentsPath);
167
497
  if (missing.length > 0) {
168
498
  return mapValidationOutcome(missing);
169
499
  }
170
- for (const hook of pipelines.hooks.before) {
171
- await hook(pipelineContext(contract, request, args));
172
- }
500
+ args = deepFreeze(computed);
173
501
  let readMaterialized = false;
174
502
  let executedReadPlan;
175
503
  const materialize = async (data, plan) => {
176
504
  readMaterialized = true;
177
505
  executedReadPlan = plan;
178
- return materializeReadOperation(contract, scopeConfig.behaviors, request, plan, data, () => pipelineContext(contract, request, args));
506
+ return materializeReadOperation(contract, scopeConfig.compute, request, plan, data, computeContext);
179
507
  };
180
- let invoke = async () => {
181
- const readPlan = planReadOperation(dependencies.contracts.core, contract, scopeConfig.behaviors, request, args);
182
- const adapterArguments = await stripVirtualMutationInput({ core: dependencies.contracts.core, active: contract }, request, readPlan.arguments);
508
+ const invoke = async () => {
509
+ const readPlan = planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, scopeConfig.compute, request, args);
510
+ const adapterArguments = await stripVirtualMutationInput(contracts, request, readPlan.arguments);
183
511
  const identity = request;
184
512
  const adapterData = await adapterBoundary.execute(() => executor.execute({
185
513
  ...identity,
186
514
  resource: request.resource,
187
515
  arguments: adapterArguments,
188
516
  }));
517
+ const miss = uniqueMissFailure(request, adapterData);
518
+ if (miss !== undefined) {
519
+ throw thrownFailure(miss);
520
+ }
189
521
  return materialize(adapterData, readPlan);
190
522
  };
191
- for (let index = pipelines.interceptors.length - 1; index >= 0; index -= 1) {
192
- const interceptor = pipelines.interceptors[index];
193
- if (interceptor === undefined) {
194
- continue;
195
- }
196
- const next = invoke;
197
- invoke = () => interceptor(pipelineContext(contract, request, args), next);
198
- }
199
- let data = await invoke();
200
- if (!readMaterialized) {
201
- data = await materialize(data, planReadOperation(dependencies.contracts.core, contract, scopeConfig.behaviors, request, args));
202
- }
203
- for (const hook of pipelines.hooks.after) {
204
- await hook(data, pipelineContext(contract, request, args));
205
- }
523
+ const materialized = async (data) => readMaterialized
524
+ ? data
525
+ : materialize(data, planReadOperation(dependencies.contracts.core, dependencies.config.adapter.model, contract, scopeConfig.compute, request, args));
526
+ const data = await materialized(await runLevelLifecycle(levels, context, invoke, materialized, reuse, () => new AvInterceptorNextError()));
206
527
  if (!outputAccepted(contract, request, executedReadPlan?.projection, data, report)) {
207
528
  return internalFailure();
208
529
  }
@@ -1,11 +1,22 @@
1
- import type { OperationIdentity } from "../operations/operation-identity.js";
2
- import type { ValidationIssue } from "../operations/validation-code.js";
3
- import type { OperationFailureResponse, OperationResponse } from "./operation-response.js";
1
+ import type { AvOperationIdentity } from "../operations/operation-identity.js";
2
+ import type { AvValidationIssue } from "../operations/validation-code.js";
3
+ import type { AvOperationFailureResponse, AvOperationResponse } from "./operation-response.js";
4
+ /**
5
+ * The failure a strict unique operation's miss raises inside the pipeline, or
6
+ * `undefined` when `data` is a row, or the variant answers a miss with `null`.
7
+ */
8
+ export declare function uniqueMissFailure(operation: AvOperationIdentity, data: unknown): AvOperationFailureResponse | undefined;
4
9
  /**
5
10
  * Maps one validated operation result to its stable outcome envelope. The
6
11
  * result must already have passed output validation, so `null` can only
7
12
  * reach a variant whose cardinality admits it.
8
13
  */
9
- export declare function mapOperationOutcome(operation: OperationIdentity, data: unknown): OperationResponse;
14
+ export declare function mapOperationOutcome(operation: AvOperationIdentity, data: unknown): AvOperationResponse;
15
+ /** The A-codes a set of Framework Validation Layer issues can roll up to. */
16
+ export type ValidationOutcomeCode = "A2001" | "A2002" | "A2004" | "A2007" | "A2009";
17
+ /** The framework's top-level `cause.message` for each validation outcome code. */
18
+ export declare const VALIDATION_OUTCOME_MESSAGES: {
19
+ readonly [K in ValidationOutcomeCode]: string;
20
+ };
10
21
  /** Maps framework validation issues to their stable failure envelope. */
11
- export declare function mapValidationOutcome(issues: readonly ValidationIssue[]): OperationFailureResponse;
22
+ export declare function mapValidationOutcome(issues: readonly AvValidationIssue[]): AvOperationFailureResponse;
@@ -21,18 +21,26 @@ function outcomeRule(operation) {
21
21
  const table = OUTCOME_TABLE;
22
22
  return table[`${operation.family}.${operation.variant}`];
23
23
  }
24
+ function notFound() {
25
+ return operationFailure("A2003", {
26
+ message: "No record matched the unique selector.",
27
+ });
28
+ }
24
29
  function absenceOutcome(absence) {
25
30
  switch (absence) {
26
31
  case "no-match":
27
32
  return operationNoMatch();
28
33
  case "not-found":
29
- return operationFailure("A2003", {
30
- message: "No record matched the unique selector.",
31
- });
34
+ return notFound();
32
35
  case undefined:
33
36
  return internalFailure();
34
37
  }
35
38
  }
39
+ export function uniqueMissFailure(operation, data) {
40
+ return data === null && outcomeRule(operation)?.absence === "not-found"
41
+ ? notFound()
42
+ : undefined;
43
+ }
36
44
  export function mapOperationOutcome(operation, data) {
37
45
  const rule = outcomeRule(operation);
38
46
  if (rule === undefined) {
@@ -52,6 +60,13 @@ function namesUnavailableOperation(issue) {
52
60
  const head = stepRelativeHead(issue);
53
61
  return issue.code === "V1006" && (head === "family" || head === "variant");
54
62
  }
63
+ export const VALIDATION_OUTCOME_MESSAGES = {
64
+ A2001: "The requested Resource is not available.",
65
+ A2002: "The requested operation is not available on this Resource.",
66
+ A2004: "Operation arguments failed framework validation.",
67
+ A2007: "Operation arguments failed framework validation.",
68
+ A2009: "Operation arguments failed framework validation.",
69
+ };
55
70
  function validationCode(issues) {
56
71
  if (issues.some((issue) => issue.code !== "V1019" && stepRelativeHead(issue) === "resource")) {
57
72
  return "A2001";
@@ -68,14 +83,16 @@ function validationCode(issues) {
68
83
  }
69
84
  if (issues.some((issue) => issue.code === "V1013" ||
70
85
  issue.code === "V1014" ||
71
- issue.code === "V1015")) {
86
+ issue.code === "V1015" ||
87
+ issue.code === "V1021")) {
72
88
  return "A2009";
73
89
  }
74
90
  return "A2004";
75
91
  }
76
92
  export function mapValidationOutcome(issues) {
77
- return operationFailure(validationCode(issues), {
78
- message: "Operation arguments failed framework validation.",
93
+ const code = validationCode(issues);
94
+ return operationFailure(code, {
95
+ message: VALIDATION_OUTCOME_MESSAGES[code],
79
96
  issues,
80
97
  });
81
98
  }