@aventara/core 1.0.0-rc.0 → 1.0.0-rc.2

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 (267) hide show
  1. package/CHANGELOG.md +1434 -0
  2. package/ERRORS.md +142 -0
  3. package/README.md +247 -57
  4. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  5. package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
  6. package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
  7. package/dist/adapters/adapter-field.d.ts +25 -11
  8. package/dist/adapters/adapter-identifier.d.ts +6 -6
  9. package/dist/adapters/adapter-model.d.ts +18 -9
  10. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  11. package/dist/adapters/adapter-operation.d.ts +3 -3
  12. package/dist/adapters/adapter-resource.d.ts +18 -9
  13. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  14. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  15. package/dist/adapters/adapter.interface.d.ts +59 -29
  16. package/dist/avz/avz-check.factory.d.ts +83 -0
  17. package/dist/avz/avz-check.factory.js +116 -0
  18. package/dist/avz/avz-check.registry.d.ts +35 -0
  19. package/dist/avz/avz-check.registry.js +9 -0
  20. package/dist/avz/avz.d.ts +203 -0
  21. package/dist/{json → avz}/avz.js +150 -8
  22. package/dist/{json → avz}/index.d.ts +2 -1
  23. package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
  24. package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
  25. package/dist/{json → avz}/zod-issue.translator.js +7 -0
  26. package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
  27. package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
  28. package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
  29. package/dist/compiler/contract.compiler.d.ts +18 -18
  30. package/dist/compiler/contract.compiler.js +637 -442
  31. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  32. package/dist/compiler/create-requirements.projector.js +423 -0
  33. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  34. package/dist/compiler/field-validator.compiler.js +238 -0
  35. package/dist/config/any-framework-config.d.ts +19 -12
  36. package/dist/config/computed-fields.d.ts +62 -0
  37. package/dist/config/computed-fields.js +80 -0
  38. package/dist/config/config-diagnostic.d.ts +11 -4
  39. package/dist/config/config-diagnostic.guidance.d.ts +6 -0
  40. package/dist/config/config-diagnostic.guidance.js +32 -0
  41. package/dist/config/config-layer.d.ts +15 -6
  42. package/dist/config/config.resolver.d.ts +74 -31
  43. package/dist/config/config.resolver.js +108 -44
  44. package/dist/config/config.validator.d.ts +7 -7
  45. package/dist/config/config.validator.js +581 -72
  46. package/dist/config/define-resource.d.ts +57 -0
  47. package/dist/config/define-resource.js +14 -0
  48. package/dist/config/effective-fields.d.ts +19 -23
  49. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  50. package/dist/config/exact-framework-config.d.ts +308 -0
  51. package/dist/config/field-compute.resolver.d.ts +21 -0
  52. package/dist/config/field-compute.resolver.js +123 -0
  53. package/dist/config/field-pipeline-config.d.ts +47 -0
  54. package/dist/config/forced-operation.validator.d.ts +10 -0
  55. package/dist/config/forced-operation.validator.js +66 -0
  56. package/dist/config/framework-config.d.ts +111 -39
  57. package/dist/config/framework-exemptions-config.d.ts +91 -0
  58. package/dist/config/framework-exemptions-config.js +1 -0
  59. package/dist/config/framework-field-definition.d.ts +78 -0
  60. package/dist/config/framework-field-definition.js +28 -0
  61. package/dist/config/framework-resources-config.d.ts +122 -0
  62. package/dist/config/framework-resources-config.js +1 -0
  63. package/dist/config/pipeline-config.d.ts +56 -20
  64. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  65. package/dist/config/pipeline-tree.resolver.js +220 -0
  66. package/dist/config/stage-type.eraser.d.ts +65 -0
  67. package/dist/config/stage-type.eraser.js +1 -0
  68. package/dist/contracts/capability.d.ts +21 -12
  69. package/dist/contracts/capability.js +2 -0
  70. package/dist/contracts/client-contract-structure.validator.d.ts +388 -63
  71. package/dist/contracts/client-contract-structure.validator.js +156 -10
  72. package/dist/contracts/contract-canonicalizer.d.ts +26 -3
  73. package/dist/contracts/contract-canonicalizer.js +156 -29
  74. package/dist/contracts/contract-hash.d.ts +12 -7
  75. package/dist/contracts/contract-hash.js +3 -2
  76. package/dist/contracts/contract-limits.d.ts +4 -1
  77. package/dist/contracts/contract-limits.js +1 -0
  78. package/dist/contracts/contract-lookup.d.ts +5 -5
  79. package/dist/contracts/contract-protocol.d.ts +4 -4
  80. package/dist/contracts/contract.d.ts +24 -16
  81. package/dist/contracts/create-requirements.d.ts +35 -0
  82. package/dist/contracts/create-requirements.js +1 -0
  83. package/dist/contracts/enum-definition.d.ts +1 -1
  84. package/dist/contracts/field-check.d.ts +101 -0
  85. package/dist/contracts/field-check.js +1 -0
  86. package/dist/contracts/field.d.ts +81 -42
  87. package/dist/contracts/identifier.d.ts +4 -4
  88. package/dist/contracts/json-shape.d.ts +12 -1
  89. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  90. package/dist/contracts/resource-operations.d.ts +28 -28
  91. package/dist/contracts/resource.d.ts +15 -9
  92. package/dist/contracts/scalar-value-type.d.ts +15 -15
  93. package/dist/contracts/scalar.d.ts +3 -3
  94. package/dist/contracts/transaction-capability.d.ts +1 -1
  95. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  96. package/dist/framework/contract-view.d.ts +213 -147
  97. package/dist/framework/framework-construction.error.d.ts +19 -10
  98. package/dist/framework/framework-construction.error.js +7 -3
  99. package/dist/framework/framework.d.ts +47 -23
  100. package/dist/framework/framework.factory.d.ts +8 -6
  101. package/dist/framework/framework.factory.js +49 -22
  102. package/dist/framework/operation-facade.d.ts +123 -52
  103. package/dist/framework/operation-facade.js +9 -1
  104. package/dist/index.d.ts +57 -50
  105. package/dist/index.js +7 -6
  106. package/dist/internal.d.ts +17 -10
  107. package/dist/internal.js +4 -1
  108. package/dist/operations/database-refusal.d.ts +51 -0
  109. package/dist/operations/database-refusal.js +45 -0
  110. package/dist/operations/operation-arguments.d.ts +343 -207
  111. package/dist/operations/operation-call.d.ts +27 -28
  112. package/dist/operations/operation-identity.d.ts +10 -10
  113. package/dist/operations/operation-result.d.ts +21 -21
  114. package/dist/operations/operation-validator-core.d.ts +6 -6
  115. package/dist/operations/operation-validator-core.js +99 -6
  116. package/dist/operations/operation-validator.d.ts +9 -9
  117. package/dist/operations/projection-scope.resolver.d.ts +6 -6
  118. package/dist/operations/structural-limits.walker.d.ts +6 -6
  119. package/dist/operations/structural-limits.walker.js +145 -0
  120. package/dist/operations/validation-code.d.ts +11 -6
  121. package/dist/operations/validation-code.guidance.d.ts +6 -0
  122. package/dist/operations/validation-code.guidance.js +90 -0
  123. package/dist/operations/validation-code.js +4 -0
  124. package/dist/operations/write-scope.resolver.d.ts +10 -6
  125. package/dist/operations/write-scope.resolver.js +2 -0
  126. package/dist/protocol/absent-route.responder.d.ts +13 -12
  127. package/dist/protocol/absent-route.responder.js +19 -19
  128. package/dist/protocol/contract-document.responder.d.ts +3 -3
  129. package/dist/protocol/contract-document.responder.js +2 -2
  130. package/dist/protocol/http-request.decoder.d.ts +17 -13
  131. package/dist/protocol/http-request.decoder.js +10 -10
  132. package/dist/protocol/http-request.reader.d.ts +3 -3
  133. package/dist/protocol/http-response.encoder.d.ts +4 -4
  134. package/dist/protocol/http-response.encoder.js +94 -55
  135. package/dist/protocol/http-status.table.d.ts +2 -2
  136. package/dist/protocol/operation-response.guard.d.ts +2 -2
  137. package/dist/protocol/protocol-surface.d.ts +4 -4
  138. package/dist/protocol/protocol.binder.d.ts +50 -27
  139. package/dist/protocol/protocol.binder.js +12 -9
  140. package/dist/protocol/protocol.handler.d.ts +22 -13
  141. package/dist/protocol/protocol.handler.js +91 -17
  142. package/dist/protocol/unmounted-route.error.d.ts +4 -4
  143. package/dist/protocol/unmounted-route.error.js +2 -2
  144. package/dist/runtime/caller-data.copier.d.ts +22 -5
  145. package/dist/runtime/caller-data.copier.js +31 -14
  146. package/dist/runtime/caller-data.door.d.ts +17 -11
  147. package/dist/runtime/caller-data.door.js +6 -4
  148. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  149. package/dist/runtime/computed-read-runtime.js +76 -50
  150. package/dist/runtime/computed-value.error.d.ts +7 -6
  151. package/dist/runtime/computed-value.error.js +5 -4
  152. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  153. package/dist/runtime/context-executor.runtime.js +275 -0
  154. package/dist/runtime/create-requirement.d.ts +44 -79
  155. package/dist/runtime/create-requirement.js +213 -73
  156. package/dist/runtime/decimal.d.ts +2 -2
  157. package/dist/runtime/decimal.js +1 -1
  158. package/dist/runtime/diagnostics-reporter.d.ts +54 -27
  159. package/dist/runtime/diagnostics-reporter.js +24 -0
  160. package/dist/runtime/error-boundary.d.ts +65 -8
  161. package/dist/runtime/error-boundary.js +49 -19
  162. package/dist/runtime/error-guidance.d.ts +12 -0
  163. package/dist/runtime/error-guidance.js +1 -0
  164. package/dist/runtime/error.catalog.d.ts +49 -0
  165. package/dist/runtime/error.catalog.js +49 -0
  166. package/dist/runtime/execution-options.d.ts +10 -2
  167. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  168. package/dist/runtime/field-check.evaluator.js +521 -0
  169. package/dist/runtime/field-compute.d.ts +64 -0
  170. package/dist/runtime/field-compute.js +1 -0
  171. package/dist/runtime/field-stage.plan.d.ts +15 -0
  172. package/dist/runtime/field-stage.plan.js +27 -0
  173. package/dist/runtime/field-stage.runtime.d.ts +37 -0
  174. package/dist/runtime/field-stage.runtime.js +147 -0
  175. package/dist/runtime/field-validator.runtime.d.ts +19 -0
  176. package/dist/runtime/field-validator.runtime.js +92 -0
  177. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  178. package/dist/runtime/framework-error-class.table.js +25 -0
  179. package/dist/runtime/framework-error.d.ts +68 -8
  180. package/dist/runtime/framework-error.factory.d.ts +4 -0
  181. package/dist/runtime/framework-error.factory.js +15 -0
  182. package/dist/runtime/framework-error.js +23 -2
  183. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  184. package/dist/runtime/interceptor-next.error.js +6 -0
  185. package/dist/runtime/json-value.d.ts +11 -6
  186. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  187. package/dist/runtime/level-lifecycle.runtime.js +39 -0
  188. package/dist/runtime/misuse-reporter.d.ts +12 -12
  189. package/dist/runtime/mutation-planner.d.ts +19 -10
  190. package/dist/runtime/mutation-planner.js +48 -35
  191. package/dist/runtime/nested-write.walker.d.ts +32 -0
  192. package/dist/runtime/nested-write.walker.js +73 -0
  193. package/dist/runtime/operation-code.guidance.d.ts +6 -0
  194. package/dist/runtime/operation-code.guidance.js +167 -0
  195. package/dist/runtime/operation-request.d.ts +33 -6
  196. package/dist/runtime/operation-response.d.ts +17 -17
  197. package/dist/runtime/operation-runtime.d.ts +127 -25
  198. package/dist/runtime/operation-runtime.js +441 -78
  199. package/dist/runtime/outcome-mapper.d.ts +16 -5
  200. package/dist/runtime/outcome-mapper.js +23 -6
  201. package/dist/runtime/output-validator.d.ts +10 -10
  202. package/dist/runtime/output-validator.js +3 -3
  203. package/dist/runtime/owned-execution.registry.d.ts +16 -6
  204. package/dist/runtime/pipe-output.validator.d.ts +43 -18
  205. package/dist/runtime/pipe-output.validator.js +15 -13
  206. package/dist/runtime/pipeline.d.ts +223 -34
  207. package/dist/runtime/readonly-value.d.ts +43 -0
  208. package/dist/runtime/readonly-value.js +150 -0
  209. package/dist/runtime/request-envelope.validator.d.ts +3 -3
  210. package/dist/runtime/request-envelope.validator.js +12 -7
  211. package/dist/runtime/request-id.d.ts +1 -1
  212. package/dist/runtime/request-state.d.ts +14 -0
  213. package/dist/runtime/request-state.js +1 -0
  214. package/dist/runtime/request-state.resolver.d.ts +12 -0
  215. package/dist/runtime/request-state.resolver.js +20 -0
  216. package/dist/runtime/scalar-runtime.d.ts +35 -16
  217. package/dist/runtime/scalar-runtime.js +102 -34
  218. package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
  219. package/dist/runtime/unsent-value.normalizer.js +128 -0
  220. package/dist/transactions/deferred-operation.d.ts +35 -20
  221. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  222. package/dist/transactions/operation-arguments-encoder.js +2 -2
  223. package/dist/transactions/operation-fingerprint.js +2 -2
  224. package/dist/transactions/sql-statement.d.ts +85 -0
  225. package/dist/transactions/sql-statement.js +47 -0
  226. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  227. package/dist/transactions/sql-statement.validator.js +167 -0
  228. package/dist/transactions/transaction-envelope.d.ts +4 -4
  229. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  230. package/dist/transactions/transaction-integrity-error.js +5 -2
  231. package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
  232. package/dist/transactions/transaction-plan-assembler.js +169 -32
  233. package/dist/transactions/transaction-plan-validator.d.ts +45 -20
  234. package/dist/transactions/transaction-plan-validator.js +96 -38
  235. package/dist/transactions/transaction-reference-collector.d.ts +5 -5
  236. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  237. package/dist/transactions/transaction-reference-resolver.js +26 -14
  238. package/dist/transactions/transaction-reference-validator.d.ts +76 -4
  239. package/dist/transactions/transaction-reference-validator.js +129 -71
  240. package/dist/transactions/transaction-reference.d.ts +13 -13
  241. package/dist/transactions/transaction-reference.js +5 -0
  242. package/dist/transactions/transaction-request.d.ts +18 -5
  243. package/dist/transactions/transaction-response.d.ts +6 -6
  244. package/dist/transactions/transaction-runtime.d.ts +8 -7
  245. package/dist/transactions/transaction-runtime.js +191 -50
  246. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  247. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  248. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  249. package/dist/transactions/transaction-slot-path-error.js +2 -2
  250. package/dist/transactions/transaction-slot-writer.js +2 -2
  251. package/dist/transactions/transaction-stage.runtime.d.ts +82 -0
  252. package/dist/transactions/transaction-stage.runtime.js +126 -0
  253. package/package.json +9 -7
  254. package/src/runtime/field-check.evaluator.ts +720 -0
  255. package/dist/config/define-fields.d.ts +0 -42
  256. package/dist/config/define-fields.js +0 -3
  257. package/dist/config/framework-behaviors-config.d.ts +0 -30
  258. package/dist/config/framework-fields-config.d.ts +0 -42
  259. package/dist/config/framework-restrictions-config.d.ts +0 -142
  260. package/dist/json/avz.d.ts +0 -96
  261. package/dist/runtime/field-behavior.d.ts +0 -48
  262. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  263. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  264. /package/dist/{json → avz}/index.js +0 -0
  265. /package/dist/{json → avz}/json-shape.registry.js +0 -0
  266. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  267. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
2
  import { advertisedDirectivesAt } from "../contracts/field.js";
3
- import { NESTED_WRITE_SCOPE, resolveWriteScope, } from "../operations/write-scope.resolver.js";
3
+ import { LOOPBACK_WRITE_SCOPE, NESTED_WRITE_SCOPE, resolveWriteScope, } from "../operations/write-scope.resolver.js";
4
4
  import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "./mutation-planner.js";
5
5
  function isRecord(value) {
6
6
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -8,10 +8,6 @@ function isRecord(value) {
8
8
  function written(record, key) {
9
9
  return Object.hasOwn(record, key) && record[key] !== undefined;
10
10
  }
11
- function requirementsOf(table, resource) {
12
- const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
13
- return Array.isArray(listed) ? listed : [];
14
- }
15
11
  function edgesOf(table, resource) {
16
12
  const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
17
13
  return Array.isArray(listed) ? listed : [];
@@ -19,16 +15,6 @@ function edgesOf(table, resource) {
19
15
  function referencesOf(edge) {
20
16
  return Array.isArray(edge.references) ? edge.references : [];
21
17
  }
22
- function referenceFieldsOf(table, resource, relation) {
23
- const edge = edgesOf(table, resource).find((candidate) => candidate.field === relation);
24
- return edge === undefined ? [] : referencesOf(edge);
25
- }
26
- function storeSupplied(contract, resource, field) {
27
- const found = lookupField(lookupResource(contract, resource), field);
28
- return (found?.kind === "scalar" &&
29
- (found.lifecycle.includes("DEFAULTED") ||
30
- found.lifecycle.includes("GENERATED_ON_CREATE")));
31
- }
32
18
  function creatableScalar(contract, resource, field) {
33
19
  const found = lookupField(lookupResource(contract, resource), field);
34
20
  return found?.kind === "scalar" && found.capabilities.create !== undefined;
@@ -38,53 +24,104 @@ function creatableRelation(contract, resource, relation, scope) {
38
24
  return (found?.kind === "relation" &&
39
25
  advertisedDirectivesAt(found.capabilities.create, scope) !== undefined);
40
26
  }
27
+ function blockedByPosition(contract, resource, relation, scope) {
28
+ return (scope !== NESTED_WRITE_SCOPE &&
29
+ creatableRelation(contract, resource, relation, NESTED_WRITE_SCOPE) &&
30
+ !creatableRelation(contract, resource, relation, scope));
31
+ }
32
+ function requirementsOf(contract, resource) {
33
+ const found = lookupResource(contract, resource)?.createRequirements;
34
+ return isRecord(found) ? found : undefined;
35
+ }
36
+ function namesOf(value) {
37
+ return Array.isArray(value)
38
+ ? value.filter((name) => typeof name === "string")
39
+ : [];
40
+ }
41
+ function suppliedThrough(requirements, via) {
42
+ if (via === undefined || !isRecord(requirements.parentSupplies)) {
43
+ return new Set();
44
+ }
45
+ const byRelation = Object.hasOwn(requirements.parentSupplies, via.resource)
46
+ ? requirements.parentSupplies[via.resource]
47
+ : undefined;
48
+ if (!isRecord(byRelation) || !Object.hasOwn(byRelation, via.relation)) {
49
+ return new Set();
50
+ }
51
+ return new Set(namesOf(byRelation[via.relation]));
52
+ }
53
+ function missingIssue(path, resource, field, relation, or = []) {
54
+ return {
55
+ code: "V1000",
56
+ path: [...path, field],
57
+ message: relation
58
+ ? `Relation "${field}" is required to create ${resource}${or.length > 0 ? `: write it, or ${or.map((name) => `"${name}"`).join(" and ")}` : ""}.`
59
+ : `Field "${field}" is required to create ${resource}.`,
60
+ };
61
+ }
41
62
  function checkCreateRecord(context, resource, record, path, scope, via) {
42
63
  if (!isRecord(record)) {
43
64
  return;
44
65
  }
66
+ if (context.computed !== undefined) {
67
+ computedRequirementGaps(context, resource, record, path, via);
68
+ walkNestedCreates(context, resource, record, path);
69
+ return;
70
+ }
45
71
  const { contract, issues } = context;
46
- const conflicted = referenceConflicts(context, resource, record, path);
47
- mixedReferenceWrites(context, resource, record, path, conflicted);
48
- for (const requirement of requirementsOf(context.requirements, resource)) {
49
- if (requirement.kind === "field") {
50
- if (!written(record, requirement.field) &&
51
- creatableScalar(contract, resource, requirement.field)) {
52
- issues.push({
53
- code: "V1000",
54
- path: [...path, requirement.field],
55
- message: `Field "${requirement.field}" is required to create ${resource}.`,
56
- });
72
+ const looped = loopbackWrites(context, resource, record, path, via, "create");
73
+ const conflicted = looped.size > 0
74
+ ? looped
75
+ : referenceConflicts(context, resource, record, path);
76
+ if (looped.size === 0) {
77
+ mixedReferenceWrites(context, resource, record, path, conflicted);
78
+ }
79
+ const requirements = requirementsOf(contract, resource);
80
+ if (requirements !== undefined) {
81
+ const supplied = suppliedThrough(requirements, via);
82
+ for (const field of namesOf(requirements.required)) {
83
+ if (supplied.has(field) || written(record, field)) {
84
+ continue;
85
+ }
86
+ if (creatableScalar(contract, resource, field)) {
87
+ issues.push(missingIssue(path, resource, field, false));
88
+ }
89
+ else if (!conflicted.has(field) &&
90
+ creatableRelation(contract, resource, field, scope)) {
91
+ issues.push(missingIssue(path, resource, field, true));
92
+ }
93
+ else if (blockedByPosition(contract, resource, field, scope)) {
94
+ const edge = edgesOf(context.references, resource).find((candidate) => candidate.field === field);
95
+ const references = edge === undefined ? [] : referencesOf(edge);
96
+ if (!references.some((name) => written(record, name))) {
97
+ issues.push(missingIssue(path, resource, references[0] ?? field, false));
98
+ }
57
99
  }
58
- continue;
59
- }
60
- if (conflicted.has(requirement.relation)) {
61
- continue;
62
- }
63
- if (via !== undefined &&
64
- requirement.inverse?.resource === via.resource &&
65
- requirement.inverse.relation === via.relation) {
66
- continue;
67
- }
68
- const orFields = referenceFieldsOf(context.references, resource, requirement.relation).filter((field) => !storeSupplied(contract, resource, field));
69
- if (written(record, requirement.relation) ||
70
- (orFields.length > 0 && orFields.every((field) => written(record, field)))) {
71
- continue;
72
- }
73
- if (creatableRelation(contract, resource, requirement.relation, scope)) {
74
- issues.push({
75
- code: "V1000",
76
- path: [...path, requirement.relation],
77
- message: `Relation "${requirement.relation}" is required to create ${resource}${orFields.length > 0 ? `: write it, or ${orFields.map((field) => `"${field}"`).join(" and ")}` : ""}.`,
78
- });
79
- continue;
80
100
  }
81
- const missing = orFields.find((field) => !written(record, field) && creatableScalar(contract, resource, field));
82
- if (missing !== undefined) {
83
- issues.push({
84
- code: "V1000",
85
- path: [...path, missing],
86
- message: `Field "${missing}" is required to create ${resource}.`,
87
- });
101
+ const groups = Array.isArray(requirements.oneOf) ? requirements.oneOf : [];
102
+ for (const group of groups) {
103
+ const [relation, ...references] = namesOf(group);
104
+ if (relation === undefined ||
105
+ references.length === 0 ||
106
+ conflicted.has(relation) ||
107
+ supplied.has(relation) ||
108
+ references.some((field) => supplied.has(field)) ||
109
+ written(record, relation) ||
110
+ references.every((field) => written(record, field))) {
111
+ continue;
112
+ }
113
+ if (creatableRelation(contract, resource, relation, scope)) {
114
+ issues.push(missingIssue(path, resource, relation, true, references));
115
+ continue;
116
+ }
117
+ const missing = references.find((field) => !written(record, field) &&
118
+ creatableScalar(contract, resource, field)) ??
119
+ (blockedByPosition(contract, resource, relation, scope)
120
+ ? references.find((field) => !written(record, field))
121
+ : undefined);
122
+ if (missing !== undefined) {
123
+ issues.push(missingIssue(path, resource, missing, false));
124
+ }
88
125
  }
89
126
  }
90
127
  walkNestedCreates(context, resource, record, path);
@@ -130,14 +167,93 @@ function mixedReferenceWrites(context, resource, record, path, conflicted) {
130
167
  });
131
168
  }
132
169
  }
133
- function checkUpdateRecord(context, resource, record, path) {
170
+ function checkUpdateRecord(context, resource, record, path, via) {
134
171
  if (!isRecord(record)) {
135
172
  return;
136
173
  }
137
- const conflicted = referenceConflicts(context, resource, record, path);
138
- mixedReferenceWrites(context, resource, record, path, conflicted);
174
+ if (context.computed === undefined &&
175
+ loopbackWrites(context, resource, record, path, via, "update").size === 0) {
176
+ const conflicted = referenceConflicts(context, resource, record, path);
177
+ mixedReferenceWrites(context, resource, record, path, conflicted);
178
+ }
139
179
  walkNestedCreates(context, resource, record, path);
140
180
  }
181
+ function loopbackWrites(context, resource, record, path, via, stage) {
182
+ const refused = new Set();
183
+ if (via === undefined) {
184
+ return refused;
185
+ }
186
+ const { contract } = context;
187
+ const edge = lookupField(lookupResource(contract, via.resource), via.relation);
188
+ if (edge?.kind !== "relation" || typeof edge.inverse !== "string") {
189
+ return refused;
190
+ }
191
+ const inverse = edge.inverse;
192
+ const other = lookupField(lookupResource(contract, resource), inverse);
193
+ if (other?.kind === "relation" &&
194
+ advertisedDirectivesAt(other.capabilities[stage], LOOPBACK_WRITE_SCOPE) !==
195
+ undefined) {
196
+ return refused;
197
+ }
198
+ const references = edgesOf(context.references, resource).find((candidate) => candidate.field === inverse) ?? undefined;
199
+ for (const field of [
200
+ inverse,
201
+ ...(references === undefined ? [] : referencesOf(references)),
202
+ ]) {
203
+ if (!written(record, field)) {
204
+ continue;
205
+ }
206
+ refused.add(field);
207
+ context.issues.push({
208
+ code: "V1012",
209
+ path: [...path, field],
210
+ message: field === inverse
211
+ ? `Relation "${field}" is the relation this ${resource} is written through, from its other end ("${via.resource}.${via.relation}"): the write it sits in supplies it.`
212
+ : `Field "${field}" holds the reference of "${inverse}", the relation this ${resource} is written through ("${via.resource}.${via.relation}"): the write it sits in supplies it.`,
213
+ });
214
+ }
215
+ return refused;
216
+ }
217
+ function computedRequirementGaps(context, resource, record, path, via) {
218
+ const reader = context.computed;
219
+ const computed = reader?.computed(resource);
220
+ const stated = reader?.stated(resource);
221
+ if (computed === undefined || computed.size === 0 || stated === undefined) {
222
+ return;
223
+ }
224
+ const supplied = suppliedThrough(stated, via);
225
+ const gap = (field) => {
226
+ context.gaps?.push({
227
+ resource,
228
+ field,
229
+ issue: {
230
+ code: "V1000",
231
+ path: [...path, field],
232
+ message: `compute.create on ${resource}.${field} returned undefined for a required field.`,
233
+ },
234
+ });
235
+ };
236
+ for (const field of namesOf(stated.required)) {
237
+ if (computed.has(field) &&
238
+ !supplied.has(field) &&
239
+ !written(record, field)) {
240
+ gap(field);
241
+ }
242
+ }
243
+ const groups = Array.isArray(stated.oneOf) ? stated.oneOf : [];
244
+ for (const group of groups) {
245
+ const [relation, ...references] = namesOf(group);
246
+ const left = references.find((field) => computed.has(field) && !written(record, field));
247
+ if (relation === undefined ||
248
+ left === undefined ||
249
+ supplied.has(relation) ||
250
+ references.some((field) => supplied.has(field)) ||
251
+ written(record, relation)) {
252
+ continue;
253
+ }
254
+ gap(left);
255
+ }
256
+ }
141
257
  function walkNestedCreates(context, resource, record, path) {
142
258
  if (!isRecord(record)) {
143
259
  return;
@@ -169,7 +285,7 @@ function walkNestedCreates(context, resource, record, path) {
169
285
  checkCreateRecord(context, field.target, siteRecord, sitePath, NESTED_WRITE_SCOPE, via);
170
286
  }
171
287
  else {
172
- checkUpdateRecord(context, field.target, siteRecord, sitePath);
288
+ checkUpdateRecord(context, field.target, siteRecord, sitePath, via);
173
289
  }
174
290
  }
175
291
  }
@@ -177,21 +293,52 @@ function walkNestedCreates(context, resource, record, path) {
177
293
  }
178
294
  }
179
295
  export function recordWriteFactsOf(adapter) {
296
+ const resources = adapter.model?.resources ?? {};
180
297
  return {
181
- requirements: adapter.createRequirements ?? {},
182
298
  references: adapter.referentialActions ?? {},
299
+ stated: (resource) => {
300
+ const found = Object.hasOwn(resources, resource)
301
+ ? resources[resource]
302
+ : undefined;
303
+ const stated = isRecord(found) ? found.createRequirements : undefined;
304
+ return isRecord(stated) ? stated : undefined;
305
+ },
183
306
  };
184
307
  }
185
308
  export function createRequirementIssues(contract, facts, request, args, argumentsPath) {
186
- if (!isRecord(args)) {
187
- return [];
188
- }
189
309
  const context = {
190
310
  contract,
191
- requirements: facts.requirements,
192
311
  references: facts.references,
193
312
  issues: [],
194
313
  };
314
+ walkOperation(context, request, args, argumentsPath);
315
+ return context.issues;
316
+ }
317
+ export function preliminaryRecordIssues(contract, facts, request, args, argumentsPath) {
318
+ const context = {
319
+ contract,
320
+ references: facts.references,
321
+ issues: [],
322
+ };
323
+ walkOperation(context, request, args, argumentsPath);
324
+ return context.issues;
325
+ }
326
+ export function computedRequirementGapsOf(contract, facts, request, args, argumentsPath, computed) {
327
+ const gaps = [];
328
+ walkOperation({
329
+ contract,
330
+ references: facts.references,
331
+ issues: [],
332
+ computed: { stated: facts.stated, computed },
333
+ gaps,
334
+ }, request, args, argumentsPath);
335
+ return gaps;
336
+ }
337
+ function walkOperation(context, request, args, argumentsPath) {
338
+ if (!isRecord(args)) {
339
+ return;
340
+ }
341
+ const contract = context.contract;
195
342
  const scope = resolveWriteScope(lookupResource(contract, request.resource), request);
196
343
  if (request.family === "create" && written(args, "data")) {
197
344
  const data = args.data;
@@ -206,16 +353,9 @@ export function createRequirementIssues(contract, facts, request, args, argument
206
353
  }
207
354
  if (request.family === "upsert") {
208
355
  checkCreateRecord(context, request.resource, args.create, [...argumentsPath, "create"], scope, undefined);
209
- checkUpdateRecord(context, request.resource, args.update, [
210
- ...argumentsPath,
211
- "update",
212
- ]);
356
+ checkUpdateRecord(context, request.resource, args.update, [...argumentsPath, "update"], undefined);
213
357
  }
214
358
  if (request.family === "update") {
215
- checkUpdateRecord(context, request.resource, args.data, [
216
- ...argumentsPath,
217
- "data",
218
- ]);
359
+ checkUpdateRecord(context, request.resource, args.data, [...argumentsPath, "data"], undefined);
219
360
  }
220
- return context.issues;
221
361
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * An exact decimal value, independent of any database driver's decimal class.
3
- * Results carry `decimal` fields as `Decimal`.
3
+ * Results carry `decimal` fields as `AvDecimal`.
4
4
  */
5
- export declare class Decimal {
5
+ export declare class AvDecimal {
6
6
  #private;
7
7
  constructor(value: string);
8
8
  toString(): string;
@@ -1,5 +1,5 @@
1
1
  import { WIRE_SCALAR_PATTERNS } from "../contracts/wire-scalar-format.js";
2
- export class Decimal {
2
+ export class AvDecimal {
3
3
  #value;
4
4
  constructor(value) {
5
5
  if (typeof value !== "string") {
@@ -1,27 +1,27 @@
1
- import type { RequestOrigin } from "../config/config-layer.js";
2
- import type { OperationFamily } from "../operations/operation-identity.js";
1
+ import type { AvRequestOrigin } from "../config/config-layer.js";
2
+ import type { AvOperationFamily } from "../operations/operation-identity.js";
3
3
  import type { FrameworkTransactionRequest } from "../transactions/transaction-request.js";
4
4
  import type { FrameworkOperationRequest } from "./operation-request.js";
5
- import type { OperationErrorCode } from "./operation-response.js";
5
+ import { type AvOperationErrorCode, type AvOperationFailureResponse } from "./operation-response.js";
6
6
  /**
7
7
  * One unplanned failure of an operation: the raw error, the code the caller
8
- * received, and the operation and request it happened in — or a developer's
9
- * deliberate internal failure, marked `deliberate`. Server-side only:
8
+ * received, and the operation and request it happened in. It can also be a
9
+ * developer's deliberate internal failure, marked `deliberate`. Server-side only:
10
10
  * diagnostics are never sent to the caller.
11
11
  */
12
- export type OperationDiagnostic = {
12
+ export type AvOperationDiagnostic = {
13
13
  readonly kind: "operation";
14
14
  readonly error: unknown;
15
- readonly code: OperationErrorCode;
16
- readonly origin: RequestOrigin;
15
+ readonly code: AvOperationErrorCode;
16
+ readonly origin: AvRequestOrigin;
17
17
  readonly resource: string;
18
- readonly family: OperationFamily;
18
+ readonly family: AvOperationFamily;
19
19
  readonly variant: string;
20
20
  readonly requestId: string;
21
21
  readonly operation?: number;
22
22
  /**
23
- * `true` when `error` is a `FrameworkError` its thrower — a pipeline
24
- * callback, a behavior, a filter or an Adapter — raised deliberately with an
23
+ * `true` when `error` is an `AvError` its thrower (a pipeline
24
+ * callback, a compute stage, a filter or an Adapter) raised deliberately with an
25
25
  * internal (`A3xxx`) code: the developer's own failure, whose message and
26
26
  * issues the caller never receives. Absent for a failure the framework did not
27
27
  * expect.
@@ -32,48 +32,75 @@ export type OperationDiagnostic = {
32
32
  * One unplanned failure of a transaction: the raw error, the code the caller
33
33
  * received, and the step it is blamed on (`operation`) when there is one.
34
34
  */
35
- export type TransactionDiagnostic = {
35
+ export type AvTransactionDiagnostic = {
36
36
  readonly kind: "transaction";
37
37
  readonly error: unknown;
38
- readonly code: OperationErrorCode;
39
- readonly origin: RequestOrigin;
38
+ readonly code: AvOperationErrorCode;
39
+ readonly origin: AvRequestOrigin;
40
40
  readonly requestId: string;
41
41
  readonly operation?: number;
42
42
  /**
43
43
  * Never present: only an operation diagnostic is marked `deliberate`. Declared
44
- * so the mark can be read on any {@link FrameworkDiagnostic}.
44
+ * so the mark can be read on any {@link AvDiagnostic}.
45
45
  */
46
46
  readonly deliberate?: never;
47
47
  };
48
- /** One diagnostic: of an operation, or of a transaction as a whole. */
49
- export type FrameworkDiagnostic = OperationDiagnostic | TransactionDiagnostic;
48
+ /**
49
+ * One unplanned failure of the MCP endpoint itself, outside any tool call's
50
+ * operation: the raw error, answered `500` with no detail, or `401` when it is
51
+ * the throw of `mcp.authorization.verify`.
52
+ */
53
+ export type AvMcpDiagnostic = {
54
+ readonly kind: "mcp";
55
+ readonly error: unknown;
56
+ /** Always `A3000`: an internal failure, with nothing more specific to say. */
57
+ readonly code: "A3000";
58
+ readonly origin: "agent";
59
+ /** Minted for the report: the MCP request carries no Aventara request id. */
60
+ readonly requestId: string;
61
+ /** Never present: no operation of a plan is involved. */
62
+ readonly operation?: never;
63
+ /** Never present: only an operation diagnostic is marked `deliberate`. */
64
+ readonly deliberate?: never;
65
+ };
66
+ /** One diagnostic: of an operation, of a transaction as a whole, or of the MCP endpoint. */
67
+ export type AvDiagnostic = AvOperationDiagnostic | AvTransactionDiagnostic | AvMcpDiagnostic;
50
68
  /**
51
69
  * Receives a diagnostic for every unplanned failure. Set once, as the root
52
70
  * configuration's `diagnostics`.
53
71
  */
54
- export type FrameworkDiagnosticsSink = (diagnostic: FrameworkDiagnostic) => void | Promise<void>;
72
+ export type AvDiagnosticsSink = (diagnostic: AvDiagnostic) => void | Promise<void>;
55
73
  /**
56
74
  * The channel as the runtime holds it: bound to one request, told the raw
57
75
  * error and the code being emitted. Total by construction — it returns
58
76
  * before the sink has finished and swallows everything the sink does.
59
77
  */
60
- export type DiagnosticsReporter = (error: unknown, code: OperationErrorCode, marks?: DiagnosticMarks) => void;
78
+ export type DiagnosticsReporter = (error: unknown, code: AvOperationErrorCode, marks?: DiagnosticMarks) => void;
61
79
  /** What a report states about its error beyond the code: today, whether it was deliberate. */
62
- export type DiagnosticMarks = Pick<OperationDiagnostic, "deliberate">;
80
+ export type DiagnosticMarks = Pick<AvOperationDiagnostic, "deliberate">;
63
81
  /** The identifying half of a diagnostic, captured once per request. */
64
- type OperationDiagnosticIdentity = Omit<OperationDiagnostic, "error" | "code">;
65
- type TransactionDiagnosticIdentity = Omit<TransactionDiagnostic, "error" | "code">;
82
+ type OperationDiagnosticIdentity = Omit<AvOperationDiagnostic, "error" | "code">;
83
+ type TransactionDiagnosticIdentity = Omit<AvTransactionDiagnostic, "error" | "code">;
66
84
  /** The diagnostics channel bound to one diagnostic identity. */
67
- export declare function createReporter(sink: FrameworkDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity): DiagnosticsReporter;
85
+ export declare function createReporter(sink: AvDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity): DiagnosticsReporter;
86
+ /**
87
+ * The MCP endpoint's failure channel for `framework`: each call reports one
88
+ * {@link AvMcpDiagnostic} to its configured sink, under a minted request id, and
89
+ * answers the response the caller receives instead: the generic `A3000`, which
90
+ * carries nothing of the error. Total: it returns before the sink has finished
91
+ * and swallows everything the sink does. A Framework without a sink gets a
92
+ * channel that observes nothing and still answers the `A3000`.
93
+ */
94
+ export declare function mcpFailureReporterOf(framework: object): (error: unknown) => AvOperationFailureResponse;
68
95
  /** Records the sink `framework` was configured with; called once, at construction. */
69
- export declare function recordDiagnosticsSink(framework: object, sink: FrameworkDiagnosticsSink | undefined): void;
96
+ export declare function recordDiagnosticsSink(framework: object, sink: AvDiagnosticsSink | undefined): void;
70
97
  /** The sink `framework` was configured with, or `undefined` for none. */
71
- export declare function diagnosticsSinkOf(framework: object): FrameworkDiagnosticsSink | undefined;
98
+ export declare function diagnosticsSinkOf(framework: object): AvDiagnosticsSink | undefined;
72
99
  /**
73
100
  * Binds the configured sink to one operation request. The sink is not awaited,
74
101
  * and nothing it throws or rejects with reaches the response.
75
102
  */
76
- export declare function createDiagnosticsReporter(sink: FrameworkDiagnosticsSink | undefined, request: FrameworkOperationRequest, operation?: number): DiagnosticsReporter;
103
+ export declare function createDiagnosticsReporter(sink: AvDiagnosticsSink | undefined, request: FrameworkOperationRequest, operation?: number): DiagnosticsReporter;
77
104
  /** The diagnostics channel of one transaction request. */
78
105
  export type TransactionDiagnosticsChannel = {
79
106
  /** A plan-level report; `operation` attributes it to a recorded failing index. */
@@ -82,5 +109,5 @@ export type TransactionDiagnosticsChannel = {
82
109
  readonly operation: (request: FrameworkOperationRequest, operation: number) => DiagnosticsReporter;
83
110
  };
84
111
  /** Binds the configured sink to one transaction request and its plan operations. */
85
- export declare function createTransactionDiagnosticsChannel(sink: FrameworkDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
112
+ export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
86
113
  export {};
@@ -1,3 +1,5 @@
1
+ import { internalFailure, } from "./operation-response.js";
2
+ import { requestIdOf } from "./request-id.js";
1
3
  const IGNORE_DIAGNOSTIC = () => undefined;
2
4
  function isThenable(value) {
3
5
  if ((typeof value !== "object" || value === null) &&
@@ -30,6 +32,28 @@ export function createReporter(sink, identity) {
30
32
  };
31
33
  }
32
34
  const CONFIGURED_SINKS = new WeakMap();
35
+ export function mcpFailureReporterOf(framework) {
36
+ const sink = CONFIGURED_SINKS.get(framework);
37
+ return (error) => {
38
+ if (sink !== undefined) {
39
+ try {
40
+ const settled = sink({
41
+ kind: "mcp",
42
+ error,
43
+ code: "A3000",
44
+ origin: "agent",
45
+ requestId: requestIdOf(undefined),
46
+ });
47
+ if (isThenable(settled)) {
48
+ settled.then(undefined, () => undefined);
49
+ }
50
+ }
51
+ catch {
52
+ }
53
+ }
54
+ return internalFailure();
55
+ };
56
+ }
33
57
  export function recordDiagnosticsSink(framework, sink) {
34
58
  if (sink !== undefined) {
35
59
  CONFIGURED_SINKS.set(framework, sink);
@@ -1,6 +1,7 @@
1
1
  import type { DiagnosticsReporter } from "./diagnostics-reporter.js";
2
- import type { OperationFailureResponse } from "./operation-response.js";
3
- import type { Filter, PipelineContext } from "./pipeline.js";
2
+ import { AvError } from "./framework-error.js";
3
+ import type { AvCause, AvOperationErrorCode, AvOperationFailureResponse } from "./operation-response.js";
4
+ import type { AvContext } from "./pipeline.js";
4
5
  /** Where an unexpected post-validation exception originated. */
5
6
  export type FailureOrigin = "adapter" | "runtime";
6
7
  /** The one generic Adapter-failure text; every unexpected A3001 carries it. */
@@ -39,18 +40,74 @@ export type CallerArgumentsView = {
39
40
  * framework's text for its code and reported to the diagnostics channel.
40
41
  */
41
42
  export declare const MAX_DEVELOPER_ISSUE_MESSAGE_LENGTH = 1000;
43
+ /** The stable outcome a thrower chose, once the boundary has vetted it. */
44
+ type DeliberateOutcome = {
45
+ readonly code: AvOperationErrorCode;
46
+ readonly cause: AvCause;
47
+ /**
48
+ * Every issue code, issue path and developer issue message the boundary could
49
+ * not vouch for, raw and in supplied order.
50
+ */
51
+ readonly unvouched: readonly unknown[];
52
+ };
42
53
  /**
43
54
  * Final framework sanitization, shared by every boundary. A deliberate
44
- * {@link FrameworkError} carries its own stable outcome; anything else is
55
+ * {@link AvError} carries its own stable outcome; anything else is
45
56
  * replaced by a generic cause so no provider text, stack, path, or secret
46
57
  * can cross the response boundary. Total: it never throws.
47
58
  */
48
- export declare function sanitizeOperationFailure(error: unknown, origin: FailureOrigin, report: DiagnosticsReporter, view: CallerArgumentsView): OperationFailureResponse;
59
+ export declare function sanitizeOperationFailure(error: unknown, origin: FailureOrigin, report: DiagnosticsReporter, view: CallerArgumentsView): AvOperationFailureResponse;
60
+ /**
61
+ * A filter over the context its stage is told: an operation's `AvFilter`,
62
+ * or a Resource transaction filter, whose context is the plan.
63
+ */
64
+ type FilterOf<Context> = (error: unknown, context: Context) => AvError | undefined | Promise<AvError | undefined>;
49
65
  /**
50
66
  * Post-validation exception flow: effective filters are stored as `[root...,
51
67
  * scoped...]`, so reverse iteration tries scoped filters in reverse registration
52
- * order, then root filters in reverse, then final sanitization. A filter handles an
53
- * error only by returning a {@link FrameworkError}; returning `undefined` or throwing
54
- * leaves the original error unhandled.
68
+ * order, then root filters in reverse. An error they leave unhandled goes to
69
+ * `outer` when there is one (a transaction step's: its Resource transaction
70
+ * filters, run once the transaction interceptors have unwound), else to final
71
+ * sanitization. A filter handles an error only by returning a {@link AvError};
72
+ * returning `undefined` or throwing leaves the original error unhandled.
73
+ */
74
+ export declare function resolveOperationFailure<Context = AvContext>(error: unknown, filters: readonly FilterOf<Context>[], context: Context, boundary: AdapterBoundary, report: DiagnosticsReporter, view: CallerArgumentsView, outer?: OuterFailureLayer): Promise<AvOperationFailureResponse>;
75
+ /**
76
+ * An error a step's own filters left unhandled, with what answering it later
77
+ * needs: the caller's arguments as the step held them, the step's Adapter
78
+ * boundary (whose identity says whose words the error is) and its reporter.
79
+ */
80
+ export type UnhandledFailure = {
81
+ readonly error: unknown;
82
+ readonly view: CallerArgumentsView;
83
+ readonly boundary: AdapterBoundary;
84
+ readonly report: DiagnosticsReporter;
85
+ };
86
+ /**
87
+ * Where a transaction step hands an error its own filters left unhandled. It
88
+ * records the error and answers a provisional failure, which fails the step; the
89
+ * transaction replaces it with the transaction filters' answer.
55
90
  */
56
- export declare function resolveOperationFailure(error: unknown, filters: readonly Filter[], context: PipelineContext, boundary: AdapterBoundary, report: DiagnosticsReporter, view: CallerArgumentsView): Promise<OperationFailureResponse>;
91
+ export type OuterFailureLayer = {
92
+ readonly defer: (failure: UnhandledFailure) => AvOperationFailureResponse;
93
+ };
94
+ /**
95
+ * An unhandled step error through `chain` (the transaction filters, the first
96
+ * that handles it wins), then final sanitization.
97
+ */
98
+ export declare function resolveUnhandledFailure(failure: UnhandledFailure, chain: FilterChain): Promise<AvOperationFailureResponse>;
99
+ /**
100
+ * A chain of filters and the context they are told, tried in reverse: the first
101
+ * that returns an {@link AvError} handles the error.
102
+ */
103
+ export type FilterChain = {
104
+ readonly attempt: (error: unknown, view: CallerArgumentsView, boundary: AdapterBoundary) => Promise<FilteredOutcome | undefined>;
105
+ };
106
+ /** The chain of `filters` (stored outer to inner, tried in reverse), told `context`. */
107
+ export declare function filterChain<Context>(filters: readonly FilterOf<Context>[], context: Context): FilterChain;
108
+ /** What a filter returned, and the deliberate outcome it vets as. */
109
+ type FilteredOutcome = {
110
+ readonly returned: unknown;
111
+ readonly outcome: DeliberateOutcome;
112
+ };
113
+ export {};