@aventara/core 0.1.0-pilot.4 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/CHANGELOG.md +1478 -0
  2. package/README.md +275 -11
  3. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  4. package/dist/adapters/adapter-field.d.ts +11 -11
  5. package/dist/adapters/adapter-identifier.d.ts +6 -6
  6. package/dist/adapters/adapter-model.d.ts +17 -9
  7. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  8. package/dist/adapters/adapter-operation.d.ts +3 -3
  9. package/dist/adapters/adapter-resource.d.ts +18 -9
  10. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  11. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  12. package/dist/adapters/adapter.interface.d.ts +49 -25
  13. package/dist/avz/avz-check.factory.d.ts +83 -0
  14. package/dist/avz/avz-check.factory.js +116 -0
  15. package/dist/avz/avz-check.registry.d.ts +35 -0
  16. package/dist/avz/avz-check.registry.js +9 -0
  17. package/dist/avz/avz.d.ts +203 -0
  18. package/dist/avz/avz.js +354 -0
  19. package/dist/avz/index.d.ts +7 -0
  20. package/dist/avz/index.js +1 -0
  21. package/dist/avz/json-shape.registry.d.ts +22 -0
  22. package/dist/avz/json-shape.registry.js +16 -0
  23. package/dist/avz/zod-issue.translator.d.ts +57 -0
  24. package/dist/avz/zod-issue.translator.js +149 -0
  25. package/dist/compiler/contract-compiler-diagnostic.d.ts +37 -5
  26. package/dist/compiler/contract.compiler.d.ts +18 -18
  27. package/dist/compiler/contract.compiler.js +595 -421
  28. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  29. package/dist/compiler/create-requirements.projector.js +423 -0
  30. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  31. package/dist/compiler/field-validator.compiler.js +238 -0
  32. package/dist/config/any-framework-config.d.ts +19 -12
  33. package/dist/config/config-diagnostic.d.ts +11 -4
  34. package/dist/config/config-layer.d.ts +15 -6
  35. package/dist/config/config.resolver.d.ts +75 -29
  36. package/dist/config/config.resolver.js +109 -44
  37. package/dist/config/config.validator.d.ts +7 -7
  38. package/dist/config/config.validator.js +586 -71
  39. package/dist/config/define-resource.d.ts +57 -0
  40. package/dist/config/define-resource.js +14 -0
  41. package/dist/config/effective-fields.d.ts +19 -23
  42. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  43. package/dist/config/exact-framework-config.d.ts +280 -0
  44. package/dist/config/field-compute.resolver.d.ts +19 -0
  45. package/dist/config/field-compute.resolver.js +115 -0
  46. package/dist/config/field-pipeline-config.d.ts +47 -0
  47. package/dist/config/forced-operation.validator.d.ts +10 -0
  48. package/dist/config/forced-operation.validator.js +66 -0
  49. package/dist/config/framework-config.d.ts +111 -37
  50. package/dist/config/framework-exemptions-config.d.ts +91 -0
  51. package/dist/config/framework-exemptions-config.js +1 -0
  52. package/dist/config/framework-field-definition.d.ts +78 -0
  53. package/dist/config/framework-field-definition.js +28 -0
  54. package/dist/config/framework-resources-config.d.ts +116 -0
  55. package/dist/config/framework-resources-config.js +1 -0
  56. package/dist/config/pipeline-config.d.ts +56 -20
  57. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  58. package/dist/config/pipeline-tree.resolver.js +220 -0
  59. package/dist/config/stage-type.eraser.d.ts +65 -0
  60. package/dist/config/stage-type.eraser.js +1 -0
  61. package/dist/contracts/capability.d.ts +11 -11
  62. package/dist/contracts/client-contract-structure.validator.d.ts +344 -29
  63. package/dist/contracts/client-contract-structure.validator.js +248 -7
  64. package/dist/contracts/contract-canonicalizer.d.ts +19 -3
  65. package/dist/contracts/contract-canonicalizer.js +172 -27
  66. package/dist/contracts/contract-hash.d.ts +12 -7
  67. package/dist/contracts/contract-hash.js +3 -2
  68. package/dist/contracts/contract-limits.d.ts +4 -1
  69. package/dist/contracts/contract-limits.js +1 -0
  70. package/dist/contracts/contract-lookup.d.ts +5 -5
  71. package/dist/contracts/contract-protocol.d.ts +4 -4
  72. package/dist/contracts/contract.d.ts +31 -16
  73. package/dist/contracts/create-requirements.d.ts +35 -0
  74. package/dist/contracts/create-requirements.js +1 -0
  75. package/dist/contracts/enum-definition.d.ts +1 -1
  76. package/dist/contracts/field-check.d.ts +101 -0
  77. package/dist/contracts/field-check.js +1 -0
  78. package/dist/contracts/field.d.ts +61 -41
  79. package/dist/contracts/identifier.d.ts +4 -4
  80. package/dist/contracts/json-shape.d.ts +76 -0
  81. package/dist/contracts/json-shape.js +1 -0
  82. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  83. package/dist/contracts/reference-write-limit.d.ts +7 -0
  84. package/dist/contracts/reference-write-limit.js +1 -0
  85. package/dist/contracts/resource-operations.d.ts +28 -28
  86. package/dist/contracts/resource.d.ts +15 -9
  87. package/dist/contracts/scalar-value-type.d.ts +25 -14
  88. package/dist/contracts/scalar.d.ts +3 -3
  89. package/dist/contracts/transaction-capability.d.ts +1 -1
  90. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  91. package/dist/framework/contract-view.d.ts +234 -63
  92. package/dist/framework/framework-construction.error.d.ts +10 -10
  93. package/dist/framework/framework-construction.error.js +2 -2
  94. package/dist/framework/framework.d.ts +50 -24
  95. package/dist/framework/framework.factory.d.ts +8 -6
  96. package/dist/framework/framework.factory.js +95 -32
  97. package/dist/framework/operation-facade.d.ts +123 -52
  98. package/dist/framework/operation-facade.js +9 -1
  99. package/dist/index.d.ts +55 -82
  100. package/dist/index.js +6 -26
  101. package/dist/internal.d.ts +40 -0
  102. package/dist/internal.js +18 -0
  103. package/dist/operations/operation-arguments.d.ts +316 -201
  104. package/dist/operations/operation-call.d.ts +27 -28
  105. package/dist/operations/operation-identity.d.ts +12 -10
  106. package/dist/operations/operation-identity.js +3 -0
  107. package/dist/operations/operation-result.d.ts +21 -21
  108. package/dist/operations/operation-validator-core.d.ts +6 -6
  109. package/dist/operations/operation-validator-core.js +41 -12
  110. package/dist/operations/operation-validator.d.ts +24 -9
  111. package/dist/operations/operation-validator.js +26 -10
  112. package/dist/operations/projection-scope.resolver.d.ts +7 -7
  113. package/dist/operations/structural-limits.walker.d.ts +19 -0
  114. package/dist/operations/structural-limits.walker.js +489 -0
  115. package/dist/operations/validation-code.d.ts +11 -6
  116. package/dist/operations/validation-code.js +4 -0
  117. package/dist/operations/write-scope.resolver.d.ts +6 -6
  118. package/dist/protocol/absent-route.responder.d.ts +13 -11
  119. package/dist/protocol/absent-route.responder.js +42 -16
  120. package/dist/protocol/contract-document.responder.d.ts +3 -3
  121. package/dist/protocol/contract-document.responder.js +2 -2
  122. package/dist/protocol/http-request.decoder.d.ts +23 -13
  123. package/dist/protocol/http-request.decoder.js +19 -11
  124. package/dist/protocol/http-request.reader.d.ts +3 -3
  125. package/dist/protocol/http-response.encoder.d.ts +4 -4
  126. package/dist/protocol/http-response.encoder.js +94 -55
  127. package/dist/protocol/http-status.table.d.ts +2 -2
  128. package/dist/protocol/operation-response.guard.d.ts +2 -2
  129. package/dist/protocol/protocol-surface.d.ts +4 -4
  130. package/dist/protocol/protocol.binder.d.ts +52 -27
  131. package/dist/protocol/protocol.binder.js +14 -9
  132. package/dist/protocol/protocol.handler.d.ts +28 -15
  133. package/dist/protocol/protocol.handler.js +55 -10
  134. package/dist/protocol/unmounted-route.error.d.ts +19 -0
  135. package/dist/protocol/unmounted-route.error.js +10 -0
  136. package/dist/runtime/caller-data.copier.d.ts +59 -0
  137. package/dist/runtime/caller-data.copier.js +470 -0
  138. package/dist/runtime/caller-data.door.d.ts +56 -0
  139. package/dist/runtime/caller-data.door.js +67 -0
  140. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  141. package/dist/runtime/computed-read-runtime.js +61 -55
  142. package/dist/runtime/computed-value.error.d.ts +13 -0
  143. package/dist/runtime/computed-value.error.js +9 -0
  144. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  145. package/dist/runtime/context-executor.runtime.js +275 -0
  146. package/dist/runtime/create-requirement.d.ts +22 -57
  147. package/dist/runtime/create-requirement.js +140 -37
  148. package/dist/runtime/decimal.d.ts +2 -2
  149. package/dist/runtime/decimal.js +1 -1
  150. package/dist/runtime/diagnostics-reporter.d.ts +64 -22
  151. package/dist/runtime/diagnostics-reporter.js +35 -4
  152. package/dist/runtime/error-boundary.d.ts +73 -8
  153. package/dist/runtime/error-boundary.js +104 -48
  154. package/dist/runtime/execution-options.d.ts +10 -2
  155. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  156. package/dist/runtime/field-check.evaluator.js +521 -0
  157. package/dist/runtime/field-compute.d.ts +64 -0
  158. package/dist/runtime/field-compute.js +1 -0
  159. package/dist/runtime/field-stage.plan.d.ts +15 -0
  160. package/dist/runtime/field-stage.plan.js +27 -0
  161. package/dist/runtime/field-stage.runtime.d.ts +35 -0
  162. package/dist/runtime/field-stage.runtime.js +143 -0
  163. package/dist/runtime/field-validator.runtime.d.ts +11 -0
  164. package/dist/runtime/field-validator.runtime.js +87 -0
  165. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  166. package/dist/runtime/framework-error-class.table.js +25 -0
  167. package/dist/runtime/framework-error.d.ts +79 -7
  168. package/dist/runtime/framework-error.factory.d.ts +4 -0
  169. package/dist/runtime/framework-error.factory.js +15 -0
  170. package/dist/runtime/framework-error.js +23 -2
  171. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  172. package/dist/runtime/interceptor-next.error.js +6 -0
  173. package/dist/runtime/json-value.d.ts +3 -3
  174. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  175. package/dist/runtime/level-lifecycle.runtime.js +42 -0
  176. package/dist/runtime/misuse-reporter.d.ts +32 -0
  177. package/dist/runtime/misuse-reporter.js +19 -0
  178. package/dist/runtime/mutation-planner.d.ts +19 -10
  179. package/dist/runtime/mutation-planner.js +62 -36
  180. package/dist/runtime/nested-write.walker.d.ts +32 -0
  181. package/dist/runtime/nested-write.walker.js +73 -0
  182. package/dist/runtime/operation-request.d.ts +35 -15
  183. package/dist/runtime/operation-response.d.ts +17 -17
  184. package/dist/runtime/operation-runtime.d.ts +125 -30
  185. package/dist/runtime/operation-runtime.js +423 -83
  186. package/dist/runtime/outcome-mapper.d.ts +16 -5
  187. package/dist/runtime/outcome-mapper.js +35 -8
  188. package/dist/runtime/output-validator.d.ts +16 -6
  189. package/dist/runtime/output-validator.js +12 -1
  190. package/dist/runtime/owned-execution.registry.d.ts +13 -0
  191. package/dist/runtime/owned-execution.registry.js +7 -0
  192. package/dist/runtime/pipe-output.validator.d.ts +33 -18
  193. package/dist/runtime/pipe-output.validator.js +12 -12
  194. package/dist/runtime/pipeline.d.ts +202 -28
  195. package/dist/runtime/readonly-value.d.ts +32 -0
  196. package/dist/runtime/readonly-value.js +141 -0
  197. package/dist/runtime/referential-action.d.ts +7 -0
  198. package/dist/runtime/request-envelope.validator.d.ts +5 -0
  199. package/dist/runtime/request-envelope.validator.js +123 -0
  200. package/dist/runtime/request-id.d.ts +1 -1
  201. package/dist/runtime/request-state.d.ts +14 -0
  202. package/dist/runtime/request-state.js +1 -0
  203. package/dist/runtime/request-state.resolver.d.ts +12 -0
  204. package/dist/runtime/request-state.resolver.js +20 -0
  205. package/dist/runtime/scalar-runtime.d.ts +56 -13
  206. package/dist/runtime/scalar-runtime.js +167 -86
  207. package/dist/transactions/deferred-operation.d.ts +35 -20
  208. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  209. package/dist/transactions/operation-arguments-encoder.js +2 -2
  210. package/dist/transactions/sql-statement.d.ts +77 -0
  211. package/dist/transactions/sql-statement.js +47 -0
  212. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  213. package/dist/transactions/sql-statement.validator.js +134 -0
  214. package/dist/transactions/transaction-envelope.d.ts +4 -4
  215. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  216. package/dist/transactions/transaction-integrity-error.js +5 -2
  217. package/dist/transactions/transaction-plan-assembler.d.ts +23 -9
  218. package/dist/transactions/transaction-plan-assembler.js +195 -82
  219. package/dist/transactions/transaction-plan-validator.d.ts +53 -21
  220. package/dist/transactions/transaction-plan-validator.js +246 -163
  221. package/dist/transactions/transaction-reference-collector.d.ts +30 -0
  222. package/dist/transactions/transaction-reference-collector.js +204 -0
  223. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  224. package/dist/transactions/transaction-reference-resolver.js +27 -10
  225. package/dist/transactions/transaction-reference-validator.d.ts +34 -4
  226. package/dist/transactions/transaction-reference-validator.js +82 -43
  227. package/dist/transactions/transaction-reference.d.ts +30 -58
  228. package/dist/transactions/transaction-request.d.ts +20 -7
  229. package/dist/transactions/transaction-response.d.ts +12 -7
  230. package/dist/transactions/transaction-response.js +24 -1
  231. package/dist/transactions/transaction-runtime.d.ts +11 -8
  232. package/dist/transactions/transaction-runtime.js +167 -50
  233. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  234. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  235. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  236. package/dist/transactions/transaction-slot-path-error.js +2 -2
  237. package/dist/transactions/transaction-slot-writer.js +2 -2
  238. package/dist/transactions/transaction-stage.runtime.d.ts +81 -0
  239. package/dist/transactions/transaction-stage.runtime.js +123 -0
  240. package/package.json +18 -3
  241. package/src/runtime/field-check.evaluator.ts +720 -0
  242. package/dist/config/define-fields.d.ts +0 -35
  243. package/dist/config/define-fields.js +0 -3
  244. package/dist/config/framework-behaviors-config.d.ts +0 -30
  245. package/dist/config/framework-fields-config.d.ts +0 -36
  246. package/dist/config/framework-restrictions-config.d.ts +0 -142
  247. package/dist/operations/operation-boolean-nodes.d.ts +0 -11
  248. package/dist/operations/operation-boolean-nodes.js +0 -283
  249. package/dist/operations/operation-nesting.d.ts +0 -8
  250. package/dist/operations/operation-nesting.js +0 -307
  251. package/dist/runtime/field-behavior.d.ts +0 -48
  252. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  253. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  254. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  255. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -1,65 +1,30 @@
1
- import type { Contract } from "../contracts/contract.js";
2
- import type { OperationIdentity } from "../operations/operation-identity.js";
3
- import type { ValidationIssue } from "../operations/validation-code.js";
4
- /**
5
- * Core's create-requirement vocabulary, and the check that reads it.
6
- *
7
- * **The facts are an Adapter's.** Which values a store cannot create a row
8
- * without is a property of the store's schema — a column with no default, a
9
- * reference that must point somewhere — and only the Adapter can read it. The
10
- * words are Aventara's, so an Adapter translates its provider's facts into them,
11
- * and the reasoning over them is core's, so no Adapter re-implements it.
12
- *
13
- * None of this enters a Contract. A Contract carries no foreign-key detail and
14
- * no knowledge of which relation is the other end of which, and a requirement
15
- * needs both; it is a server-side fact, read once when the Framework is
16
- * constructed, like the referential actions.
17
- *
18
- * **When the check runs.** After guards, pipes and computed write behaviours —
19
- * the moment the arguments are what the Adapter will be handed — and before
20
- * any `before` hook or Adapter work. Earlier would refuse a value a pipe or a
21
- * computed behaviour was about to supply; later is the store's own refusal,
22
- * which reaches the caller as an internal failure. A missing value is the
23
- * caller's to fix, so it answers `A2004` with a `V1000` issue at the path where
24
- * the value belongs.
25
- */
26
- /** A relation edge, named by the Resource that holds it and its field there. */
27
- export type CreateRequirementEdge = {
28
- readonly resource: string;
29
- readonly relation: string;
30
- };
1
+ import type { AvContract } from "../contracts/contract.js";
2
+ import type { AvOperationIdentity } from "../operations/operation-identity.js";
3
+ import type { AvValidationIssue } from "../operations/validation-code.js";
4
+ import type { ReferentialActionTable } from "./referential-action.js";
5
+ type Path = readonly (string | number)[];
31
6
  /**
32
- * One value a create of a Resource cannot do without.
33
- *
34
- * - `field` — a scalar with no default, generated value or other source: it
35
- * must be written.
36
- * - `relation` — a required to-one relation: it must be written (connected or
37
- * created), or every one of `orFields` must be — the scalar fields that hold
38
- * the reference. When the row is created **through** the relation's other end
39
- * (`inverse`), the parent supplies it, and it is not required.
7
+ * What the Adapter stated beside its model that the check reads: its
8
+ * referential edges, for the fields that hold each reference. Read once when
9
+ * the Framework is constructed. The requirements themselves are the active
10
+ * Contract's.
40
11
  */
41
- export type CreateRequirement = {
42
- readonly kind: "field";
43
- readonly field: string;
44
- } | {
45
- readonly kind: "relation";
46
- readonly relation: string;
47
- readonly orFields: readonly string[];
48
- readonly inverse?: CreateRequirementEdge;
12
+ export type RecordWriteFacts = {
13
+ readonly references: ReferentialActionTable;
49
14
  };
50
- /**
51
- * Every Resource's create requirements, keyed by Resource. A Resource that is
52
- * absent, or carries an empty list, requires nothing core can check.
53
- */
54
- export type CreateRequirementTable = Readonly<Record<string, readonly CreateRequirement[]>>;
55
- type Path = readonly (string | number)[];
15
+ /** The facts an Adapter stated, read off it once; an absent table states nothing. */
16
+ export declare function recordWriteFactsOf(adapter: {
17
+ readonly referentialActions?: ReferentialActionTable;
18
+ }): RecordWriteFacts;
56
19
  /**
57
20
  * The `V1000` issues for every create position in one operation's arguments
58
- * that lacks a value the Adapter requires — `create.*`'s `data`, `upsert`'s
59
- * `create`, and every nested create under any write — in argument order.
60
- * Empty when nothing is missing. Total over malformed input.
21
+ * that lacks a value the active Contract requires — `create.*`'s `data`, `upsert`'s
22
+ * `create`, and every nested create under any write — and the `V1012` issues
23
+ * for every write record, create or update, that sets a relation and its
24
+ * reference both, in argument order. Empty when there are none. Total over
25
+ * malformed input.
61
26
  */
62
- export declare function missingCreateValues(contract: Contract, table: CreateRequirementTable, request: OperationIdentity & {
27
+ export declare function createRequirementIssues(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
63
28
  readonly resource: string;
64
- }, args: unknown, argumentsPath: Path): readonly ValidationIssue[];
29
+ }, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
65
30
  export {};
@@ -8,10 +8,13 @@ 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) {
11
+ function edgesOf(table, resource) {
12
12
  const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
13
13
  return Array.isArray(listed) ? listed : [];
14
14
  }
15
+ function referencesOf(edge) {
16
+ return Array.isArray(edge.references) ? edge.references : [];
17
+ }
15
18
  function creatableScalar(contract, resource, field) {
16
19
  const found = lookupField(lookupResource(contract, resource), field);
17
20
  return found?.kind === "scalar" && found.capabilities.create !== undefined;
@@ -21,52 +24,145 @@ function creatableRelation(contract, resource, relation, scope) {
21
24
  return (found?.kind === "relation" &&
22
25
  advertisedDirectivesAt(found.capabilities.create, scope) !== undefined);
23
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
+ }
24
62
  function checkCreateRecord(context, resource, record, path, scope, via) {
25
63
  if (!isRecord(record)) {
26
64
  return;
27
65
  }
28
66
  const { contract, issues } = context;
29
- for (const requirement of requirementsOf(context.table, resource)) {
30
- if (requirement.kind === "field") {
31
- if (!written(record, requirement.field) &&
32
- creatableScalar(contract, resource, requirement.field)) {
33
- issues.push({
34
- code: "V1000",
35
- path: [...path, requirement.field],
36
- message: `Field "${requirement.field}" is required to create ${resource}.`,
37
- });
67
+ const conflicted = referenceConflicts(context, resource, record, path);
68
+ mixedReferenceWrites(context, resource, record, path, conflicted);
69
+ const requirements = requirementsOf(contract, resource);
70
+ if (requirements !== undefined) {
71
+ const supplied = suppliedThrough(requirements, via);
72
+ for (const field of namesOf(requirements.required)) {
73
+ if (supplied.has(field) || written(record, field)) {
74
+ continue;
75
+ }
76
+ if (creatableScalar(contract, resource, field)) {
77
+ issues.push(missingIssue(path, resource, field, false));
78
+ }
79
+ else if (!conflicted.has(field) &&
80
+ creatableRelation(contract, resource, field, scope)) {
81
+ issues.push(missingIssue(path, resource, field, true));
82
+ }
83
+ else if (blockedByPosition(contract, resource, field, scope)) {
84
+ const edge = edgesOf(context.references, resource).find((candidate) => candidate.field === field);
85
+ const references = edge === undefined ? [] : referencesOf(edge);
86
+ if (!references.some((name) => written(record, name))) {
87
+ issues.push(missingIssue(path, resource, references[0] ?? field, false));
88
+ }
38
89
  }
39
- continue;
40
90
  }
41
- if (via !== undefined &&
42
- requirement.inverse?.resource === via.resource &&
43
- requirement.inverse.relation === via.relation) {
91
+ const groups = Array.isArray(requirements.oneOf) ? requirements.oneOf : [];
92
+ for (const group of groups) {
93
+ const [relation, ...references] = namesOf(group);
94
+ if (relation === undefined ||
95
+ references.length === 0 ||
96
+ conflicted.has(relation) ||
97
+ supplied.has(relation) ||
98
+ references.some((field) => supplied.has(field)) ||
99
+ written(record, relation) ||
100
+ references.every((field) => written(record, field))) {
101
+ continue;
102
+ }
103
+ if (creatableRelation(contract, resource, relation, scope)) {
104
+ issues.push(missingIssue(path, resource, relation, true, references));
105
+ continue;
106
+ }
107
+ const missing = references.find((field) => !written(record, field) &&
108
+ creatableScalar(contract, resource, field)) ??
109
+ (blockedByPosition(contract, resource, relation, scope)
110
+ ? references.find((field) => !written(record, field))
111
+ : undefined);
112
+ if (missing !== undefined) {
113
+ issues.push(missingIssue(path, resource, missing, false));
114
+ }
115
+ }
116
+ }
117
+ walkNestedCreates(context, resource, record, path);
118
+ }
119
+ function referenceConflicts(context, resource, record, path) {
120
+ const conflicted = new Set();
121
+ for (const edge of edgesOf(context.references, resource)) {
122
+ if (!written(record, edge.field)) {
44
123
  continue;
45
124
  }
46
- const orFields = Array.isArray(requirement.orFields)
47
- ? requirement.orFields
48
- : [];
49
- if (written(record, requirement.relation) ||
50
- (orFields.length > 0 && orFields.every((field) => written(record, field)))) {
125
+ const fields = referencesOf(edge).filter((field) => written(record, field));
126
+ if (fields.length === 0) {
51
127
  continue;
52
128
  }
53
- if (creatableRelation(contract, resource, requirement.relation, scope)) {
54
- issues.push({
55
- code: "V1000",
56
- path: [...path, requirement.relation],
57
- message: `Relation "${requirement.relation}" is required to create ${resource}${orFields.length > 0 ? `: write it, or ${orFields.map((field) => `"${field}"`).join(" and ")}` : ""}.`,
58
- });
129
+ conflicted.add(edge.field);
130
+ context.issues.push({
131
+ code: "V1012",
132
+ path: [...path, edge.field],
133
+ message: `Set ${fields.map((field) => `"${field}"`).join(" and ")} or "${edge.field}", not both.`,
134
+ });
135
+ }
136
+ return conflicted;
137
+ }
138
+ function mixedReferenceWrites(context, resource, record, path, conflicted) {
139
+ if (context.contract.referenceWrites !== "uniform") {
140
+ return;
141
+ }
142
+ const edges = edgesOf(context.references, resource);
143
+ const referenceFields = [...new Set(edges.flatMap(referencesOf))];
144
+ for (const edge of edges) {
145
+ if (!written(record, edge.field) || conflicted.has(edge.field)) {
59
146
  continue;
60
147
  }
61
- const missing = orFields.find((field) => !written(record, field) && creatableScalar(contract, resource, field));
62
- if (missing !== undefined) {
63
- issues.push({
64
- code: "V1000",
65
- path: [...path, missing],
66
- message: `Field "${missing}" is required to create ${resource}.`,
67
- });
148
+ const fields = referenceFields.filter((field) => written(record, field));
149
+ if (fields.length === 0) {
150
+ continue;
68
151
  }
152
+ const named = fields.map((field) => `"${field}"`).join(" and ");
153
+ context.issues.push({
154
+ code: "V1012",
155
+ path: [...path, edge.field],
156
+ message: `Use relation fields only, or reference fields only, in one record: ${named} ${fields.length === 1 ? "is a reference field" : "are reference fields"} and "${edge.field}" is a relation.`,
157
+ });
158
+ }
159
+ }
160
+ function checkUpdateRecord(context, resource, record, path) {
161
+ if (!isRecord(record)) {
162
+ return;
69
163
  }
164
+ const conflicted = referenceConflicts(context, resource, record, path);
165
+ mixedReferenceWrites(context, resource, record, path, conflicted);
70
166
  walkNestedCreates(context, resource, record, path);
71
167
  }
72
168
  function walkNestedCreates(context, resource, record, path) {
@@ -100,18 +196,25 @@ function walkNestedCreates(context, resource, record, path) {
100
196
  checkCreateRecord(context, field.target, siteRecord, sitePath, NESTED_WRITE_SCOPE, via);
101
197
  }
102
198
  else {
103
- walkNestedCreates(context, field.target, siteRecord, sitePath);
199
+ checkUpdateRecord(context, field.target, siteRecord, sitePath);
104
200
  }
105
201
  }
106
202
  }
107
203
  }
108
204
  }
109
205
  }
110
- export function missingCreateValues(contract, table, request, args, argumentsPath) {
206
+ export function recordWriteFactsOf(adapter) {
207
+ return { references: adapter.referentialActions ?? {} };
208
+ }
209
+ export function createRequirementIssues(contract, facts, request, args, argumentsPath) {
111
210
  if (!isRecord(args)) {
112
211
  return [];
113
212
  }
114
- const context = { contract, table, issues: [] };
213
+ const context = {
214
+ contract,
215
+ references: facts.references,
216
+ issues: [],
217
+ };
115
218
  const scope = resolveWriteScope(lookupResource(contract, request.resource), request);
116
219
  if (request.family === "create" && written(args, "data")) {
117
220
  const data = args.data;
@@ -126,13 +229,13 @@ export function missingCreateValues(contract, table, request, args, argumentsPat
126
229
  }
127
230
  if (request.family === "upsert") {
128
231
  checkCreateRecord(context, request.resource, args.create, [...argumentsPath, "create"], scope, undefined);
129
- walkNestedCreates(context, request.resource, args.update, [
232
+ checkUpdateRecord(context, request.resource, args.update, [
130
233
  ...argumentsPath,
131
234
  "update",
132
235
  ]);
133
236
  }
134
237
  if (request.family === "update") {
135
- walkNestedCreates(context, request.resource, args.data, [
238
+ checkUpdateRecord(context, request.resource, args.data, [
136
239
  ...argumentsPath,
137
240
  "data",
138
241
  ]);
@@ -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,63 +1,105 @@
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. 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:
9
10
  * diagnostics are never sent to the caller.
10
11
  */
11
- export type OperationDiagnostic = {
12
+ export type AvOperationDiagnostic = {
12
13
  readonly kind: "operation";
13
14
  readonly error: unknown;
14
- readonly code: OperationErrorCode;
15
- readonly scope: RequestOrigin;
15
+ readonly code: AvOperationErrorCode;
16
+ readonly origin: AvRequestOrigin;
16
17
  readonly resource: string;
17
- readonly family: OperationFamily;
18
+ readonly family: AvOperationFamily;
18
19
  readonly variant: string;
19
20
  readonly requestId: string;
20
21
  readonly operation?: number;
22
+ /**
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
+ * internal (`A3xxx`) code: the developer's own failure, whose message and
26
+ * issues the caller never receives. Absent for a failure the framework did not
27
+ * expect.
28
+ */
29
+ readonly deliberate?: true;
21
30
  };
22
31
  /**
23
32
  * One unplanned failure of a transaction: the raw error, the code the caller
24
33
  * received, and the step it is blamed on (`operation`) when there is one.
25
34
  */
26
- export type TransactionDiagnostic = {
35
+ export type AvTransactionDiagnostic = {
27
36
  readonly kind: "transaction";
28
37
  readonly error: unknown;
29
- readonly code: OperationErrorCode;
30
- readonly scope: RequestOrigin;
38
+ readonly code: AvOperationErrorCode;
39
+ readonly origin: AvRequestOrigin;
31
40
  readonly requestId: string;
32
41
  readonly operation?: number;
42
+ /**
43
+ * Never present: only an operation diagnostic is marked `deliberate`. Declared
44
+ * so the mark can be read on any {@link AvDiagnostic}.
45
+ */
46
+ readonly deliberate?: never;
33
47
  };
34
- /** One diagnostic: of an operation, or of a transaction as a whole. */
35
- 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.
51
+ */
52
+ export type AvMcpDiagnostic = {
53
+ readonly kind: "mcp";
54
+ readonly error: unknown;
55
+ /** Always `A3000`: an internal failure, with nothing more specific to say. */
56
+ readonly code: "A3000";
57
+ readonly origin: "agent";
58
+ /** Minted for the report: the MCP request carries no Aventara request id. */
59
+ readonly requestId: string;
60
+ /** Never present: no operation of a plan is involved. */
61
+ readonly operation?: never;
62
+ /** Never present: only an operation diagnostic is marked `deliberate`. */
63
+ readonly deliberate?: never;
64
+ };
65
+ /** One diagnostic: of an operation, of a transaction as a whole, or of the MCP endpoint. */
66
+ export type AvDiagnostic = AvOperationDiagnostic | AvTransactionDiagnostic | AvMcpDiagnostic;
36
67
  /**
37
68
  * Receives a diagnostic for every unplanned failure. Set once, as the root
38
69
  * configuration's `diagnostics`.
39
70
  */
40
- export type FrameworkDiagnosticsSink = (diagnostic: FrameworkDiagnostic) => void | Promise<void>;
71
+ export type AvDiagnosticsSink = (diagnostic: AvDiagnostic) => void | Promise<void>;
41
72
  /**
42
73
  * The channel as the runtime holds it: bound to one request, told the raw
43
74
  * error and the code being emitted. Total by construction — it returns
44
75
  * before the sink has finished and swallows everything the sink does.
45
76
  */
46
- export type DiagnosticsReporter = (error: unknown, code: OperationErrorCode) => void;
77
+ export type DiagnosticsReporter = (error: unknown, code: AvOperationErrorCode, marks?: DiagnosticMarks) => void;
78
+ /** What a report states about its error beyond the code: today, whether it was deliberate. */
79
+ export type DiagnosticMarks = Pick<AvOperationDiagnostic, "deliberate">;
47
80
  /** The identifying half of a diagnostic, captured once per request. */
48
- type OperationDiagnosticIdentity = Omit<OperationDiagnostic, "error" | "code">;
49
- type TransactionDiagnosticIdentity = Omit<TransactionDiagnostic, "error" | "code">;
81
+ type OperationDiagnosticIdentity = Omit<AvOperationDiagnostic, "error" | "code">;
82
+ type TransactionDiagnosticIdentity = Omit<AvTransactionDiagnostic, "error" | "code">;
50
83
  /** The diagnostics channel bound to one diagnostic identity. */
51
- export declare function createReporter(sink: FrameworkDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity): DiagnosticsReporter;
84
+ export declare function createReporter(sink: AvDiagnosticsSink | undefined, identity: OperationDiagnosticIdentity | TransactionDiagnosticIdentity): DiagnosticsReporter;
85
+ /**
86
+ * The MCP endpoint's failure channel for `framework`: each call reports one
87
+ * {@link AvMcpDiagnostic} to its configured sink, under a minted request id, and
88
+ * answers the response the caller receives instead: the generic `A3000`, which
89
+ * carries nothing of the error. Total: it returns before the sink has finished
90
+ * and swallows everything the sink does. A Framework without a sink gets a
91
+ * channel that observes nothing and still answers the `A3000`.
92
+ */
93
+ export declare function mcpFailureReporterOf(framework: object): (error: unknown) => AvOperationFailureResponse;
52
94
  /** Records the sink `framework` was configured with; called once, at construction. */
53
- export declare function recordDiagnosticsSink(framework: object, sink: FrameworkDiagnosticsSink | undefined): void;
95
+ export declare function recordDiagnosticsSink(framework: object, sink: AvDiagnosticsSink | undefined): void;
54
96
  /** The sink `framework` was configured with, or `undefined` for none. */
55
- export declare function diagnosticsSinkOf(framework: object): FrameworkDiagnosticsSink | undefined;
97
+ export declare function diagnosticsSinkOf(framework: object): AvDiagnosticsSink | undefined;
56
98
  /**
57
99
  * Binds the configured sink to one operation request. The sink is not awaited,
58
100
  * and nothing it throws or rejects with reaches the response.
59
101
  */
60
- export declare function createDiagnosticsReporter(sink: FrameworkDiagnosticsSink | undefined, request: FrameworkOperationRequest, operation?: number): DiagnosticsReporter;
102
+ export declare function createDiagnosticsReporter(sink: AvDiagnosticsSink | undefined, request: FrameworkOperationRequest, operation?: number): DiagnosticsReporter;
61
103
  /** The diagnostics channel of one transaction request. */
62
104
  export type TransactionDiagnosticsChannel = {
63
105
  /** A plan-level report; `operation` attributes it to a recorded failing index. */
@@ -66,5 +108,5 @@ export type TransactionDiagnosticsChannel = {
66
108
  readonly operation: (request: FrameworkOperationRequest, operation: number) => DiagnosticsReporter;
67
109
  };
68
110
  /** Binds the configured sink to one transaction request and its plan operations. */
69
- export declare function createTransactionDiagnosticsChannel(sink: FrameworkDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
111
+ export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
70
112
  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) &&
@@ -10,9 +12,16 @@ export function createReporter(sink, identity) {
10
12
  if (sink === undefined) {
11
13
  return IGNORE_DIAGNOSTIC;
12
14
  }
13
- return (error, code) => {
15
+ return (error, code, marks) => {
14
16
  try {
15
- const settled = sink({ ...identity, error, code });
17
+ const settled = sink(identity.kind === "operation"
18
+ ? {
19
+ ...identity,
20
+ error,
21
+ code,
22
+ ...(marks?.deliberate === true ? { deliberate: true } : {}),
23
+ }
24
+ : { ...identity, error, code });
16
25
  if (isThenable(settled)) {
17
26
  settled.then(undefined, () => undefined);
18
27
  }
@@ -23,6 +32,28 @@ export function createReporter(sink, identity) {
23
32
  };
24
33
  }
25
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
+ }
26
57
  export function recordDiagnosticsSink(framework, sink) {
27
58
  if (sink !== undefined) {
28
59
  CONFIGURED_SINKS.set(framework, sink);
@@ -36,7 +67,7 @@ export function createDiagnosticsReporter(sink, request, operation) {
36
67
  try {
37
68
  identity = {
38
69
  kind: "operation",
39
- scope: request.scope,
70
+ origin: request.origin,
40
71
  resource: request.resource,
41
72
  family: request.family,
42
73
  variant: request.variant,
@@ -54,7 +85,7 @@ export function createTransactionDiagnosticsChannel(sink, request) {
54
85
  try {
55
86
  identity = {
56
87
  kind: "transaction",
57
- scope: request.scope,
88
+ origin: request.origin,
58
89
  requestId: request.requestId,
59
90
  };
60
91
  }
@@ -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. */
@@ -20,6 +21,8 @@ export declare class AdapterBoundary {
20
21
  export declare const SERIALIZATION_FAILURE_MESSAGE = "Result serialization failed.";
21
22
  /** Where a standalone operation's arguments sit in a framework issue path. */
22
23
  export declare const OPERATION_ARGUMENTS_PATH: readonly (string | number)[];
24
+ /** Where one plan step sits in a framework issue path: its node in the request. */
25
+ export declare function planStepPath(index: number): readonly (string | number)[];
23
26
  /** Where one plan operation's arguments sit in a framework issue path. */
24
27
  export declare function planOperationArgumentsPath(index: number): readonly (string | number)[];
25
28
  /**
@@ -31,18 +34,80 @@ export type CallerArgumentsView = {
31
34
  readonly path: readonly (string | number)[];
32
35
  readonly arguments: unknown;
33
36
  };
37
+ /**
38
+ * The longest issue message a developer's code may send to the caller, in UTF-16
39
+ * code units. A longer one, or one with no visible character, is replaced by the
40
+ * framework's text for its code and reported to the diagnostics channel.
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
+ };
34
53
  /**
35
54
  * Final framework sanitization, shared by every boundary. A deliberate
36
- * {@link FrameworkError} carries its own stable outcome; anything else is
55
+ * {@link AvError} carries its own stable outcome; anything else is
37
56
  * replaced by a generic cause so no provider text, stack, path, or secret
38
57
  * can cross the response boundary. Total: it never throws.
39
58
  */
40
- 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>;
41
65
  /**
42
66
  * Post-validation exception flow: effective filters are stored as `[root...,
43
67
  * scoped...]`, so reverse iteration tries scoped filters in reverse registration
44
- * order, then root filters in reverse, then final sanitization. A filter handles an
45
- * error only by returning a {@link FrameworkError}; returning `undefined` or throwing
46
- * 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.
47
73
  */
48
- export declare function resolveOperationFailure(error: unknown, filters: readonly Filter[], context: PipelineContext, boundary: AdapterBoundary, report: DiagnosticsReporter, view: CallerArgumentsView): Promise<OperationFailureResponse>;
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.
90
+ */
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 {};