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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/CHANGELOG.md +1140 -0
  2. package/README.md +224 -57
  3. package/dist/adapters/adapter-discovery-diagnostic.d.ts +4 -4
  4. package/dist/adapters/adapter-field.d.ts +11 -11
  5. package/dist/adapters/adapter-identifier.d.ts +6 -6
  6. package/dist/adapters/adapter-model.d.ts +9 -9
  7. package/dist/adapters/adapter-operation-executor.interface.d.ts +4 -4
  8. package/dist/adapters/adapter-operation.d.ts +3 -3
  9. package/dist/adapters/adapter-resource.d.ts +18 -9
  10. package/dist/adapters/adapter-sql-statement.d.ts +19 -0
  11. package/dist/adapters/adapter-transaction-executor.interface.d.ts +19 -0
  12. package/dist/adapters/adapter.interface.d.ts +49 -29
  13. package/dist/avz/avz-check.factory.d.ts +83 -0
  14. package/dist/avz/avz-check.factory.js +116 -0
  15. package/dist/avz/avz-check.registry.d.ts +35 -0
  16. package/dist/avz/avz-check.registry.js +9 -0
  17. package/dist/avz/avz.d.ts +203 -0
  18. package/dist/{json → avz}/avz.js +150 -8
  19. package/dist/{json → avz}/index.d.ts +2 -1
  20. package/dist/{json → avz}/json-shape.registry.d.ts +7 -7
  21. package/dist/{json → avz}/zod-issue.translator.d.ts +8 -2
  22. package/dist/{json → avz}/zod-issue.translator.js +7 -0
  23. package/dist/compiler/contract-compiler-diagnostic.d.ts +31 -5
  24. package/dist/compiler/contract.compiler.d.ts +18 -18
  25. package/dist/compiler/contract.compiler.js +548 -441
  26. package/dist/compiler/create-requirements.projector.d.ts +49 -0
  27. package/dist/compiler/create-requirements.projector.js +423 -0
  28. package/dist/compiler/field-validator.compiler.d.ts +47 -0
  29. package/dist/compiler/field-validator.compiler.js +238 -0
  30. package/dist/config/any-framework-config.d.ts +19 -12
  31. package/dist/config/config-diagnostic.d.ts +11 -4
  32. package/dist/config/config-layer.d.ts +15 -6
  33. package/dist/config/config.resolver.d.ts +74 -31
  34. package/dist/config/config.resolver.js +108 -44
  35. package/dist/config/config.validator.d.ts +7 -7
  36. package/dist/config/config.validator.js +581 -72
  37. package/dist/config/define-resource.d.ts +57 -0
  38. package/dist/config/define-resource.js +14 -0
  39. package/dist/config/effective-fields.d.ts +19 -23
  40. package/dist/config/entrypoint.normalizer.d.ts +1 -1
  41. package/dist/config/exact-framework-config.d.ts +280 -0
  42. package/dist/config/field-compute.resolver.d.ts +19 -0
  43. package/dist/config/field-compute.resolver.js +115 -0
  44. package/dist/config/field-pipeline-config.d.ts +47 -0
  45. package/dist/config/forced-operation.validator.d.ts +10 -0
  46. package/dist/config/forced-operation.validator.js +66 -0
  47. package/dist/config/framework-config.d.ts +110 -39
  48. package/dist/config/framework-exemptions-config.d.ts +91 -0
  49. package/dist/config/framework-exemptions-config.js +1 -0
  50. package/dist/config/framework-field-definition.d.ts +78 -0
  51. package/dist/config/framework-field-definition.js +28 -0
  52. package/dist/config/framework-resources-config.d.ts +116 -0
  53. package/dist/config/framework-resources-config.js +1 -0
  54. package/dist/config/pipeline-config.d.ts +56 -20
  55. package/dist/config/pipeline-tree.resolver.d.ts +79 -0
  56. package/dist/config/pipeline-tree.resolver.js +220 -0
  57. package/dist/config/stage-type.eraser.d.ts +65 -0
  58. package/dist/config/stage-type.eraser.js +1 -0
  59. package/dist/contracts/capability.d.ts +11 -11
  60. package/dist/contracts/client-contract-structure.validator.d.ts +323 -28
  61. package/dist/contracts/client-contract-structure.validator.js +152 -8
  62. package/dist/contracts/contract-canonicalizer.d.ts +19 -3
  63. package/dist/contracts/contract-canonicalizer.js +141 -28
  64. package/dist/contracts/contract-hash.d.ts +12 -7
  65. package/dist/contracts/contract-hash.js +3 -2
  66. package/dist/contracts/contract-limits.d.ts +4 -1
  67. package/dist/contracts/contract-limits.js +1 -0
  68. package/dist/contracts/contract-lookup.d.ts +5 -5
  69. package/dist/contracts/contract-protocol.d.ts +4 -4
  70. package/dist/contracts/contract.d.ts +24 -16
  71. package/dist/contracts/create-requirements.d.ts +35 -0
  72. package/dist/contracts/create-requirements.js +1 -0
  73. package/dist/contracts/enum-definition.d.ts +1 -1
  74. package/dist/contracts/field-check.d.ts +101 -0
  75. package/dist/contracts/field-check.js +1 -0
  76. package/dist/contracts/field.d.ts +52 -42
  77. package/dist/contracts/identifier.d.ts +4 -4
  78. package/dist/contracts/json-shape.d.ts +12 -1
  79. package/dist/contracts/lifecycle-trait.d.ts +2 -2
  80. package/dist/contracts/resource-operations.d.ts +28 -28
  81. package/dist/contracts/resource.d.ts +15 -9
  82. package/dist/contracts/scalar-value-type.d.ts +15 -15
  83. package/dist/contracts/scalar.d.ts +3 -3
  84. package/dist/contracts/transaction-capability.d.ts +1 -1
  85. package/dist/contracts/wire-scalar-format.d.ts +4 -4
  86. package/dist/framework/contract-view.d.ts +213 -147
  87. package/dist/framework/framework-construction.error.d.ts +10 -10
  88. package/dist/framework/framework-construction.error.js +2 -2
  89. package/dist/framework/framework.d.ts +47 -23
  90. package/dist/framework/framework.factory.d.ts +8 -6
  91. package/dist/framework/framework.factory.js +40 -20
  92. package/dist/framework/operation-facade.d.ts +123 -52
  93. package/dist/framework/operation-facade.js +9 -1
  94. package/dist/index.d.ts +55 -50
  95. package/dist/index.js +6 -6
  96. package/dist/internal.d.ts +15 -10
  97. package/dist/internal.js +3 -1
  98. package/dist/operations/operation-arguments.d.ts +267 -202
  99. package/dist/operations/operation-call.d.ts +27 -28
  100. package/dist/operations/operation-identity.d.ts +10 -10
  101. package/dist/operations/operation-result.d.ts +21 -21
  102. package/dist/operations/operation-validator-core.d.ts +6 -6
  103. package/dist/operations/operation-validator-core.js +13 -2
  104. package/dist/operations/operation-validator.d.ts +9 -9
  105. package/dist/operations/projection-scope.resolver.d.ts +6 -6
  106. package/dist/operations/structural-limits.walker.d.ts +6 -6
  107. package/dist/operations/structural-limits.walker.js +145 -0
  108. package/dist/operations/validation-code.d.ts +11 -6
  109. package/dist/operations/validation-code.js +4 -0
  110. package/dist/operations/write-scope.resolver.d.ts +6 -6
  111. package/dist/protocol/absent-route.responder.d.ts +13 -12
  112. package/dist/protocol/absent-route.responder.js +19 -19
  113. package/dist/protocol/contract-document.responder.d.ts +3 -3
  114. package/dist/protocol/contract-document.responder.js +2 -2
  115. package/dist/protocol/http-request.decoder.d.ts +17 -13
  116. package/dist/protocol/http-request.decoder.js +10 -10
  117. package/dist/protocol/http-request.reader.d.ts +3 -3
  118. package/dist/protocol/http-response.encoder.d.ts +4 -4
  119. package/dist/protocol/http-response.encoder.js +94 -55
  120. package/dist/protocol/http-status.table.d.ts +2 -2
  121. package/dist/protocol/operation-response.guard.d.ts +2 -2
  122. package/dist/protocol/protocol-surface.d.ts +4 -4
  123. package/dist/protocol/protocol.binder.d.ts +50 -27
  124. package/dist/protocol/protocol.binder.js +12 -9
  125. package/dist/protocol/protocol.handler.d.ts +22 -13
  126. package/dist/protocol/protocol.handler.js +44 -9
  127. package/dist/protocol/unmounted-route.error.d.ts +4 -4
  128. package/dist/protocol/unmounted-route.error.js +2 -2
  129. package/dist/runtime/caller-data.copier.d.ts +5 -5
  130. package/dist/runtime/caller-data.copier.js +13 -13
  131. package/dist/runtime/caller-data.door.d.ts +6 -6
  132. package/dist/runtime/caller-data.door.js +6 -4
  133. package/dist/runtime/computed-read-runtime.d.ts +7 -6
  134. package/dist/runtime/computed-read-runtime.js +61 -48
  135. package/dist/runtime/computed-value.error.d.ts +6 -6
  136. package/dist/runtime/computed-value.error.js +3 -3
  137. package/dist/runtime/context-executor.runtime.d.ts +59 -0
  138. package/dist/runtime/context-executor.runtime.js +275 -0
  139. package/dist/runtime/create-requirement.d.ts +10 -81
  140. package/dist/runtime/create-requirement.js +80 -57
  141. package/dist/runtime/decimal.d.ts +2 -2
  142. package/dist/runtime/decimal.js +1 -1
  143. package/dist/runtime/diagnostics-reporter.d.ts +53 -27
  144. package/dist/runtime/diagnostics-reporter.js +24 -0
  145. package/dist/runtime/error-boundary.d.ts +65 -8
  146. package/dist/runtime/error-boundary.js +45 -19
  147. package/dist/runtime/execution-options.d.ts +10 -2
  148. package/dist/runtime/field-check.evaluator.d.ts +29 -0
  149. package/dist/runtime/field-check.evaluator.js +521 -0
  150. package/dist/runtime/field-compute.d.ts +64 -0
  151. package/dist/runtime/field-compute.js +1 -0
  152. package/dist/runtime/field-stage.plan.d.ts +15 -0
  153. package/dist/runtime/field-stage.plan.js +27 -0
  154. package/dist/runtime/field-stage.runtime.d.ts +35 -0
  155. package/dist/runtime/field-stage.runtime.js +143 -0
  156. package/dist/runtime/field-validator.runtime.d.ts +11 -0
  157. package/dist/runtime/field-validator.runtime.js +87 -0
  158. package/dist/runtime/framework-error-class.table.d.ts +33 -0
  159. package/dist/runtime/framework-error-class.table.js +25 -0
  160. package/dist/runtime/framework-error.d.ts +68 -8
  161. package/dist/runtime/framework-error.factory.d.ts +4 -0
  162. package/dist/runtime/framework-error.factory.js +15 -0
  163. package/dist/runtime/framework-error.js +23 -2
  164. package/dist/runtime/interceptor-next.error.d.ts +5 -0
  165. package/dist/runtime/interceptor-next.error.js +6 -0
  166. package/dist/runtime/json-value.d.ts +3 -3
  167. package/dist/runtime/level-lifecycle.runtime.d.ts +25 -0
  168. package/dist/runtime/level-lifecycle.runtime.js +42 -0
  169. package/dist/runtime/misuse-reporter.d.ts +12 -12
  170. package/dist/runtime/mutation-planner.d.ts +19 -10
  171. package/dist/runtime/mutation-planner.js +54 -30
  172. package/dist/runtime/nested-write.walker.d.ts +32 -0
  173. package/dist/runtime/nested-write.walker.js +73 -0
  174. package/dist/runtime/operation-request.d.ts +33 -6
  175. package/dist/runtime/operation-response.d.ts +17 -17
  176. package/dist/runtime/operation-runtime.d.ts +113 -25
  177. package/dist/runtime/operation-runtime.js +395 -74
  178. package/dist/runtime/outcome-mapper.d.ts +16 -5
  179. package/dist/runtime/outcome-mapper.js +23 -6
  180. package/dist/runtime/output-validator.d.ts +10 -10
  181. package/dist/runtime/output-validator.js +3 -3
  182. package/dist/runtime/owned-execution.registry.d.ts +6 -6
  183. package/dist/runtime/pipe-output.validator.d.ts +33 -18
  184. package/dist/runtime/pipe-output.validator.js +12 -12
  185. package/dist/runtime/pipeline.d.ts +196 -34
  186. package/dist/runtime/readonly-value.d.ts +32 -0
  187. package/dist/runtime/readonly-value.js +141 -0
  188. package/dist/runtime/request-envelope.validator.d.ts +3 -3
  189. package/dist/runtime/request-envelope.validator.js +12 -7
  190. package/dist/runtime/request-id.d.ts +1 -1
  191. package/dist/runtime/request-state.d.ts +14 -0
  192. package/dist/runtime/request-state.js +1 -0
  193. package/dist/runtime/request-state.resolver.d.ts +12 -0
  194. package/dist/runtime/request-state.resolver.js +20 -0
  195. package/dist/runtime/scalar-runtime.d.ts +31 -16
  196. package/dist/runtime/scalar-runtime.js +16 -18
  197. package/dist/transactions/deferred-operation.d.ts +35 -20
  198. package/dist/transactions/operation-arguments-encoder.d.ts +3 -3
  199. package/dist/transactions/operation-arguments-encoder.js +2 -2
  200. package/dist/transactions/sql-statement.d.ts +77 -0
  201. package/dist/transactions/sql-statement.js +47 -0
  202. package/dist/transactions/sql-statement.validator.d.ts +44 -0
  203. package/dist/transactions/sql-statement.validator.js +134 -0
  204. package/dist/transactions/transaction-envelope.d.ts +4 -4
  205. package/dist/transactions/transaction-integrity-error.d.ts +6 -6
  206. package/dist/transactions/transaction-integrity-error.js +5 -2
  207. package/dist/transactions/transaction-plan-assembler.d.ts +21 -11
  208. package/dist/transactions/transaction-plan-assembler.js +148 -34
  209. package/dist/transactions/transaction-plan-validator.d.ts +29 -20
  210. package/dist/transactions/transaction-plan-validator.js +70 -38
  211. package/dist/transactions/transaction-reference-collector.d.ts +5 -5
  212. package/dist/transactions/transaction-reference-resolver.d.ts +19 -2
  213. package/dist/transactions/transaction-reference-resolver.js +26 -14
  214. package/dist/transactions/transaction-reference-validator.d.ts +34 -4
  215. package/dist/transactions/transaction-reference-validator.js +58 -26
  216. package/dist/transactions/transaction-reference.d.ts +13 -13
  217. package/dist/transactions/transaction-request.d.ts +18 -5
  218. package/dist/transactions/transaction-response.d.ts +6 -6
  219. package/dist/transactions/transaction-runtime.d.ts +8 -7
  220. package/dist/transactions/transaction-runtime.js +166 -50
  221. package/dist/transactions/transaction-settlement.runtime.d.ts +51 -0
  222. package/dist/transactions/transaction-settlement.runtime.js +120 -0
  223. package/dist/transactions/transaction-slot-path-error.d.ts +4 -4
  224. package/dist/transactions/transaction-slot-path-error.js +2 -2
  225. package/dist/transactions/transaction-slot-writer.js +2 -2
  226. package/dist/transactions/transaction-stage.runtime.d.ts +81 -0
  227. package/dist/transactions/transaction-stage.runtime.js +123 -0
  228. package/package.json +6 -5
  229. package/src/runtime/field-check.evaluator.ts +720 -0
  230. package/dist/config/define-fields.d.ts +0 -42
  231. package/dist/config/define-fields.js +0 -3
  232. package/dist/config/framework-behaviors-config.d.ts +0 -30
  233. package/dist/config/framework-fields-config.d.ts +0 -42
  234. package/dist/config/framework-restrictions-config.d.ts +0 -142
  235. package/dist/json/avz.d.ts +0 -96
  236. package/dist/runtime/field-behavior.d.ts +0 -48
  237. /package/dist/{config/framework-behaviors-config.js → adapters/adapter-sql-statement.js} +0 -0
  238. /package/dist/{config/framework-fields-config.js → adapters/adapter-transaction-executor.interface.js} +0 -0
  239. /package/dist/{json → avz}/index.js +0 -0
  240. /package/dist/{json → avz}/json-shape.registry.js +0 -0
  241. /package/dist/config/{framework-restrictions-config.js → exact-framework-config.js} +0 -0
  242. /package/dist/{runtime/field-behavior.js → config/field-pipeline-config.js} +0 -0
@@ -1,101 +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";
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
4
  import type { ReferentialActionTable } from "./referential-action.js";
5
- /**
6
- * Core's create-requirement vocabulary, and the check that reads it.
7
- *
8
- * **The facts are an Adapter's.** Which values a store cannot create a row
9
- * without is a property of the store's schema — a column with no default, a
10
- * reference that must point somewhere — and only the Adapter can read it. The
11
- * words are Aventara's, so an Adapter translates its provider's facts into them,
12
- * and the reasoning over them is core's, so no Adapter re-implements it.
13
- *
14
- * None of this enters a Contract. A Contract carries no foreign-key detail and
15
- * no knowledge of which relation is the other end of which, and a requirement
16
- * needs both; it is a server-side fact, read once when the Framework is
17
- * constructed, like the referential actions.
18
- *
19
- * **When the check runs.** After guards, pipes and computed write behaviours —
20
- * the moment the arguments are what the Adapter will be handed — and before
21
- * any `before` hook or Adapter work. Earlier would refuse a value a pipe or a
22
- * computed behaviour was about to supply; later is the store's own refusal,
23
- * which reaches the caller as an internal failure. A missing value is the
24
- * caller's to fix, so it answers `A2004` with a `V1000` issue at the path where
25
- * the value belongs.
26
- *
27
- * **One value, two spellings.** A relation that holds a reference has scalar
28
- * fields that hold it too — the Adapter states which, on the relation's
29
- * referential edge (`ReferentialEdge.references`), for every such relation,
30
- * required or optional. A write that sets both — `authorId` and
31
- * `author: { $connect: … }` in one record, at create or update — names the
32
- * reference twice. No store can honour both, and which one the caller meant is
33
- * not the framework's to guess, so it is the caller's `A2004` too: a `V1012`
34
- * issue at the relation, in every record the check walks, before any Adapter
35
- * work. The same edge is what a required relation may instead be written
36
- * through, so the pairing has one source.
37
- *
38
- * **One store, one spelling per record.** A store may take a record's
39
- * references only one way at a time — every relation that holds one written as
40
- * a relation, or every one through its fields — and state it as the Contract's
41
- * `referenceWrites: "uniform"`. Under it, a record that writes a relation
42
- * holding a reference beside another relation's reference field is the caller's
43
- * `A2004` as well: a `V1012` issue at the relation write.
44
- */
45
- /** A relation edge, named by the Resource that holds it and its field there. */
46
- export type CreateRequirementEdge = {
47
- readonly resource: string;
48
- readonly relation: string;
49
- };
50
- /**
51
- * One value a create of a Resource cannot do without.
52
- *
53
- * - `field` — a scalar with no default, generated value or other source: it
54
- * must be written.
55
- * - `relation` — a required to-one relation: it must be written (connected or
56
- * created), or every field that holds its reference must be — the
57
- * `references` of the relation's referential edge, less any the store fills
58
- * itself (`DEFAULTED` or `GENERATED_ON_CREATE`). When the row is created
59
- * **through** the relation's other end (`inverse`), the parent supplies it,
60
- * and it is not required.
61
- */
62
- export type CreateRequirement = {
63
- readonly kind: "field";
64
- readonly field: string;
65
- } | {
66
- readonly kind: "relation";
67
- readonly relation: string;
68
- readonly inverse?: CreateRequirementEdge;
69
- };
70
- /**
71
- * Every Resource's create requirements, keyed by Resource. A Resource that is
72
- * absent, or carries an empty list, requires nothing core can check.
73
- */
74
- export type CreateRequirementTable = Readonly<Record<string, readonly CreateRequirement[]>>;
75
5
  type Path = readonly (string | number)[];
76
6
  /**
77
- * What the Adapter stated that the check reads: its create requirements, and
78
- * its referential edges for the fields that hold each reference. Read once when
79
- * the Framework is constructed.
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.
80
11
  */
81
12
  export type RecordWriteFacts = {
82
- readonly requirements: CreateRequirementTable;
83
13
  readonly references: ReferentialActionTable;
84
14
  };
85
15
  /** The facts an Adapter stated, read off it once; an absent table states nothing. */
86
16
  export declare function recordWriteFactsOf(adapter: {
87
- readonly createRequirements?: CreateRequirementTable;
88
17
  readonly referentialActions?: ReferentialActionTable;
89
18
  }): RecordWriteFacts;
90
19
  /**
91
20
  * The `V1000` issues for every create position in one operation's arguments
92
- * that lacks a value the Adapter requires — `create.*`'s `data`, `upsert`'s
21
+ * that lacks a value the active Contract requires — `create.*`'s `data`, `upsert`'s
93
22
  * `create`, and every nested create under any write — and the `V1012` issues
94
23
  * for every write record, create or update, that sets a relation and its
95
24
  * reference both, in argument order. Empty when there are none. Total over
96
25
  * malformed input.
97
26
  */
98
- export declare function createRequirementIssues(contract: Contract, facts: RecordWriteFacts, request: OperationIdentity & {
27
+ export declare function createRequirementIssues(contract: AvContract, facts: RecordWriteFacts, request: AvOperationIdentity & {
99
28
  readonly resource: string;
100
- }, args: unknown, argumentsPath: Path): readonly ValidationIssue[];
29
+ }, args: unknown, argumentsPath: Path): readonly AvValidationIssue[];
101
30
  export {};
@@ -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,6 +24,41 @@ 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;
@@ -45,46 +66,52 @@ function checkCreateRecord(context, resource, record, path, scope, via) {
45
66
  const { contract, issues } = context;
46
67
  const conflicted = referenceConflicts(context, resource, record, path);
47
68
  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
- });
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
+ }
57
89
  }
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
90
  }
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
- });
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
+ }
88
115
  }
89
116
  }
90
117
  walkNestedCreates(context, resource, record, path);
@@ -177,10 +204,7 @@ function walkNestedCreates(context, resource, record, path) {
177
204
  }
178
205
  }
179
206
  export function recordWriteFactsOf(adapter) {
180
- return {
181
- requirements: adapter.createRequirements ?? {},
182
- references: adapter.referentialActions ?? {},
183
- };
207
+ return { references: adapter.referentialActions ?? {} };
184
208
  }
185
209
  export function createRequirementIssues(contract, facts, request, args, argumentsPath) {
186
210
  if (!isRecord(args)) {
@@ -188,7 +212,6 @@ export function createRequirementIssues(contract, facts, request, args, argument
188
212
  }
189
213
  const context = {
190
214
  contract,
191
- requirements: facts.requirements,
192
215
  references: facts.references,
193
216
  issues: [],
194
217
  };
@@ -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,74 @@ 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.
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;
50
67
  /**
51
68
  * Receives a diagnostic for every unplanned failure. Set once, as the root
52
69
  * configuration's `diagnostics`.
53
70
  */
54
- export type FrameworkDiagnosticsSink = (diagnostic: FrameworkDiagnostic) => void | Promise<void>;
71
+ export type AvDiagnosticsSink = (diagnostic: AvDiagnostic) => void | Promise<void>;
55
72
  /**
56
73
  * The channel as the runtime holds it: bound to one request, told the raw
57
74
  * error and the code being emitted. Total by construction — it returns
58
75
  * before the sink has finished and swallows everything the sink does.
59
76
  */
60
- export type DiagnosticsReporter = (error: unknown, code: OperationErrorCode, marks?: DiagnosticMarks) => void;
77
+ export type DiagnosticsReporter = (error: unknown, code: AvOperationErrorCode, marks?: DiagnosticMarks) => void;
61
78
  /** What a report states about its error beyond the code: today, whether it was deliberate. */
62
- export type DiagnosticMarks = Pick<OperationDiagnostic, "deliberate">;
79
+ export type DiagnosticMarks = Pick<AvOperationDiagnostic, "deliberate">;
63
80
  /** The identifying half of a diagnostic, captured once per request. */
64
- type OperationDiagnosticIdentity = Omit<OperationDiagnostic, "error" | "code">;
65
- type TransactionDiagnosticIdentity = Omit<TransactionDiagnostic, "error" | "code">;
81
+ type OperationDiagnosticIdentity = Omit<AvOperationDiagnostic, "error" | "code">;
82
+ type TransactionDiagnosticIdentity = Omit<AvTransactionDiagnostic, "error" | "code">;
66
83
  /** The diagnostics channel bound to one diagnostic identity. */
67
- 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;
68
94
  /** Records the sink `framework` was configured with; called once, at construction. */
69
- export declare function recordDiagnosticsSink(framework: object, sink: FrameworkDiagnosticsSink | undefined): void;
95
+ export declare function recordDiagnosticsSink(framework: object, sink: AvDiagnosticsSink | undefined): void;
70
96
  /** The sink `framework` was configured with, or `undefined` for none. */
71
- export declare function diagnosticsSinkOf(framework: object): FrameworkDiagnosticsSink | undefined;
97
+ export declare function diagnosticsSinkOf(framework: object): AvDiagnosticsSink | undefined;
72
98
  /**
73
99
  * Binds the configured sink to one operation request. The sink is not awaited,
74
100
  * and nothing it throws or rejects with reaches the response.
75
101
  */
76
- 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;
77
103
  /** The diagnostics channel of one transaction request. */
78
104
  export type TransactionDiagnosticsChannel = {
79
105
  /** A plan-level report; `operation` attributes it to a recorded failing index. */
@@ -82,5 +108,5 @@ export type TransactionDiagnosticsChannel = {
82
108
  readonly operation: (request: FrameworkOperationRequest, operation: number) => DiagnosticsReporter;
83
109
  };
84
110
  /** Binds the configured sink to one transaction request and its plan operations. */
85
- export declare function createTransactionDiagnosticsChannel(sink: FrameworkDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
111
+ export declare function createTransactionDiagnosticsChannel(sink: AvDiagnosticsSink | undefined, request: FrameworkTransactionRequest): TransactionDiagnosticsChannel;
86
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) &&
@@ -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 {};