@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
package/CHANGELOG.md ADDED
@@ -0,0 +1,1478 @@
1
+ # @aventara/core
2
+
3
+ ## 1.0.0-rc.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 800123b: New: `framework.appTx.$sql`, a developer SQL step in an application transaction. Write it as a tagged template,
8
+ `` framework.appTx.$sql<Row>`select pgmq.send('jobs', jsonb_build_object('postId', ${post.$ref("id")}))` ``, and put it in
9
+ `framework.transaction([...])` beside the other steps. Every interpolated value is a bound parameter, never SQL text:
10
+ strings, numbers, booleans, `bigint`, `null`, `Date`, `Decimal`, bytes, JSON values (bound as JSON text, so cast them
11
+ with `::jsonb`), and a `$ref` to an earlier step's field, read after that step ran. The statement runs in order in the
12
+ same database transaction, so a failure anywhere rolls everything back, and its rows are that step's entry in the
13
+ result, typed `Row[]` (or `unknown[]`). A plain-string call is refused, a later step cannot `$ref` a SQL step's rows,
14
+ and no pipeline runs around it.
15
+
16
+ It is server-side only: `clientTx` has no `$sql`, the ClientContract and its hash are unchanged, and `/_transactions`
17
+ cannot carry one.
18
+
19
+ The Prisma 7 adapter runs it with `$queryRaw` in its tagged form on the transaction client. A raw query's failure is
20
+ `P2010` on Prisma 7.10.0: a uniqueness or foreign-key violation answers `A2008`, anything else `A3001`. The rule is now
21
+ that Aventara never writes raw SQL itself, and developer SQL only goes through this bound template.
22
+
23
+ Adapter authors: an adapter declares `sqlStatements: true`, has an `executeSql` of its own (a plain statement, outside
24
+ any transaction: a stage's `ctx.$sql` there) and gives its transaction executor one too (`AvAdapter.executeSql`,
25
+ `AvAdapterTransactionExecutor`, `AvAdapterSqlStatement` in `@aventara/core/internal`). Without the declaration, a plan
26
+ with a SQL step is refused with `A2002`. The Prisma 7 adapter runs a statement outside a transaction with `$queryRaw`
27
+ on the base client, and declares `sqlStatements` with every driver.
28
+
29
+ - 8bb1d6a: Breaking: public type and class names take the `Av` prefix. Every public type and class is now `Av` plus what
30
+ it is, with a namespace only where the bare name would be ambiguous: configuration types are `AvConfig…`
31
+ (`AvConfig`, `AvConfigLayer`, `AvConfigResource`, …) and the three Contracts are `AvContract…` (`AvContractCore`,
32
+ `AvContractApplication`, `AvContractClient`). Functions keep their names (`createFramework`, `createFakeAdapter`,
33
+ `createPrismaAdapter`, `defineClientConfig`, `env`), and so do the names that already started with `Av`,
34
+ `AventaraModule`, `AventaraModuleOptions` and `AventaraModuleAsyncOptions`. There are no
35
+ aliases: replace each old name with the new one.
36
+
37
+ Three names merged or left:
38
+
39
+ - `PipelineContext` and `ComputeContext` (which was the same type) are one name, `AvContext`. A compute stage
40
+ now gets its own read-only ctx, `AvComputeContext` (see the ctx entry below).
41
+ - `ComputedRead` is `AvComputeRead`, the one name of a read compute stage: a function, or `{ compute, dependsOn }`.
42
+ `ComputeOnRead`, the bare function type, is no longer exported; `AvComputeRead` accepts the function as it is.
43
+ - `defineFields` and `FrameworkFieldsShape` are removed; `defineResource` replaces them (below).
44
+
45
+ `defineResource` replaces `defineFields`. A Resource's configuration, its root block and its overlay blocks, can
46
+ live in its own module and be spread into each layer's `resources` tree:
47
+
48
+ ```ts
49
+ export const submission = defineResource<Model>()(
50
+ "Submission",
51
+ {
52
+ pipelines: { guards: [signedIn] },
53
+ fields: { title: { pipelines: { pipes: [trim] } } },
54
+ },
55
+ { client: { fields: { title: { pipelines: { validators: [AvZ.maxLength(80)] } } } } },
56
+ );
57
+
58
+ // aventara.config.ts
59
+ resources: { ...submission.root, ...payment.root },
60
+ client: { resources: { ...submission.client } },
61
+ ```
62
+
63
+ It returns `{ root, application?, client? }`, each `{ Submission: block }`; a layer given no block is left out. The
64
+ root block is typed exactly as `resources.Submission` is typed in place: field definitions are checked against what
65
+ the adapter discovered, stages are typed for the Resource, and a key no level admits is a type error at the key.
66
+ Each overlay block is typed as `application.resources.Submission` or `client.resources.Submission` is in place,
67
+ against the root block: it may name a field the root block defines, and a `definition` in it is a type error (and
68
+ `CONFIG_FORBIDDEN_IN_OVERLAY` at startup). Spread, the configuration is the inline one: the same Contracts and
69
+ ClientContract hash. A field `definition` that `defineFields` returned now sits at
70
+ `fields.<field>.definition` inside the block.
71
+
72
+ The generated client's names follow the same rule. Regenerate with `avclient generate`; then rename the
73
+ imports from `AvClient.ts`:
74
+
75
+ | Before | After |
76
+ | ----------------------- | ------------------------- |
77
+ | `AuthError` | `AvAuthError` |
78
+ | `CallOptions` | `AvCallOptions` |
79
+ | `Cause` | `AvCause` |
80
+ | `ConflictError` | `AvConflictError` |
81
+ | `ContractMismatchError` | `AvContractMismatchError` |
82
+ | `Decimal` | `AvDecimal` |
83
+ | `Fetch` | `AvFetch` |
84
+ | `FrameworkError` | `AvError` |
85
+ | `InternalError` | `AvInternalError` |
86
+ | `NotFoundError` | `AvNotFoundError` |
87
+ | `Operation<T>` | `AvOperation<T>` |
88
+ | `OperationCode` | `AvOperationCode` |
89
+ | `ProtocolError` | `AvProtocolError` |
90
+ | `TransportError` | `AvTransportError` |
91
+ | `ValidationCode` | `AvValidationCode` |
92
+ | `ValidationError` | `AvValidationError` |
93
+ | `ValidationIssue` | `AvValidationIssue` |
94
+
95
+ An enum whose name is one of these now walks the rename ladder (`AvDecimal` → `AvDecimalEnum`); an enum named
96
+ `Decimal` is emitted as `Decimal`.
97
+
98
+ `@aventara/core`, every renamed export:
99
+
100
+ | Before | After |
101
+ | ------------------------------------- | ---------------------------------- |
102
+ | `Adapter` | `AvAdapter` |
103
+ | `AdapterDiscoveryDiagnostic` | `AvAdapterDiscoveryDiagnostic` |
104
+ | `AdapterDiscoveryDiagnosticCode` | `AvAdapterDiscoveryDiagnosticCode` |
105
+ | `AdapterModel` | `AvAdapterModel` |
106
+ | `AddedFieldDefinition` | `AvConfigAddedFieldDefinition` |
107
+ | `AfterHook` | `AvAfterHook` |
108
+ | `AnyFrameworkConfig` | `AvConfigAny` |
109
+ | `AnyLayerConfig` | `AvConfigLayerAny` |
110
+ | `AnyResourcesBlock` | `AvConfigResourcesAny` |
111
+ | `ApplicationContract` | `AvContractApplication` |
112
+ | `ApplicationScalarForms` | `AvApplicationScalarForms` |
113
+ | `BeforeHook` | `AvBeforeHook` |
114
+ | `BuiltInScalar` | `AvBuiltInScalar` |
115
+ | `Cause` | `AvCause` |
116
+ | `ClientContract` | `AvContractClient` |
117
+ | `ClientContractProtocol` | `AvContractClientProtocol` |
118
+ | `ComputedRead` | `AvComputeRead` |
119
+ | `ComputeOnCreate` | `AvComputeCreate` |
120
+ | `ComputeOnUpdate` | `AvComputeUpdate` |
121
+ | `ConfigDiagnostic` | `AvConfigDiagnostic` |
122
+ | `ConfigDiagnosticCode` | `AvConfigDiagnosticCode` |
123
+ | `ConfigFieldKey` | `AvConfigFieldKey` |
124
+ | `ConfigLayer` | `AvConfigLayerName` |
125
+ | `Contract` | `AvContract` |
126
+ | `ContractCompilerDiagnostic` | `AvContractCompilerDiagnostic` |
127
+ | `ContractCompilerDiagnosticCode` | `AvContractCompilerDiagnosticCode` |
128
+ | `ContractHash` | `AvContractHash` |
129
+ | `ContractLimits` | `AvContractLimits` |
130
+ | `ContractProtocol` | `AvContractProtocol` |
131
+ | `CoreContract` | `AvContractCore` |
132
+ | `CreateDataInput` | `AvCreateDataInput` |
133
+ | `CursorInput` | `AvCursorInput` |
134
+ | `Decimal` | `AvDecimal` |
135
+ | `DeferredOperationCall` | `AvDeferredOperationCall` |
136
+ | `EffectiveFieldKey` | `AvEffectiveFieldKey` |
137
+ | `EnumDefinition` | `AvEnumDefinition` |
138
+ | `ExactFrameworkConfig` | `AvConfigExact` |
139
+ | `ExecutionOptions` | `AvExecutionOptions` |
140
+ | `Field` | `AvField` |
141
+ | `FieldComputeConfig` | `AvFieldCompute` |
142
+ | `FieldKey` | `AvFieldKey` |
143
+ | `FieldPipe` | `AvFieldPipe` |
144
+ | `FieldWriteGuard` | `AvFieldGuard` |
145
+ | `Filter` | `AvFilter` |
146
+ | `Framework` | `AvFramework` |
147
+ | `FrameworkConfig` | `AvConfig` |
148
+ | `FrameworkConstructionDiagnostic` | `AvConstructionDiagnostic` |
149
+ | `FrameworkConstructionError` | `AvConstructionError` |
150
+ | `FrameworkConstructionStage` | `AvConstructionStage` |
151
+ | `FrameworkContracts` | `AvContracts` |
152
+ | `FrameworkDiagnostic` | `AvDiagnostic` |
153
+ | `FrameworkDiagnosticsSink` | `AvDiagnosticsSink` |
154
+ | `FrameworkError` | `AvError` |
155
+ | `FrameworkExemptionsConfig` | `AvConfigExemptions` |
156
+ | `FrameworkFamilyConfig` | `AvConfigFamily` |
157
+ | `FrameworkFieldDefinition` | `AvConfigFieldDefinition` |
158
+ | `FrameworkFieldLifecycleTrait` | `AvConfigFieldLifecycleTrait` |
159
+ | `FrameworkLayerConfig` | `AvConfigLayer` |
160
+ | `FrameworkLayerKind` | `AvConfigLayerKind` |
161
+ | `FrameworkLimitsConfig` | `AvConfigLimits` |
162
+ | `FrameworkMisuseEvent` | `AvMisuseEvent` |
163
+ | `FrameworkMisuseSink` | `AvMisuseSink` |
164
+ | `FrameworkOperationsConfig` | `AvConfigOperations` |
165
+ | `FrameworkOperationsExemption` | `AvConfigOperationsExemption` |
166
+ | `FrameworkOverlayFieldConfig` | `AvConfigOverlayField` |
167
+ | `FrameworkRelationFieldExemption` | `AvConfigRelationFieldExemption` |
168
+ | `FrameworkResourceConfig` | `AvConfigResource` |
169
+ | `FrameworkResourceExemption` | `AvConfigResourceExemption` |
170
+ | `FrameworkResourceFieldsConfig` | `AvConfigResourceFields` |
171
+ | `FrameworkResourceKey` | `AvConfigResourceKey` |
172
+ | `FrameworkResourcesConfig` | `AvConfigResources` |
173
+ | `FrameworkResourceTransactionsConfig` | `AvConfigResourceTransactions` |
174
+ | `FrameworkRootFieldConfig` | `AvConfigRootField` |
175
+ | `FrameworkScalarFieldExemption` | `AvConfigScalarFieldExemption` |
176
+ | `FrameworkScalarTypeRef` | `AvConfigScalarTypeRef` |
177
+ | `FrameworkVariantConfig` | `AvConfigVariant` |
178
+ | `Guard` | `AvGuard` |
179
+ | `Identifier` | `AvIdentifier` |
180
+ | `IncludeInput` | `AvIncludeInput` |
181
+ | `Interceptor` | `AvInterceptor` |
182
+ | `JsonValue` | `AvJsonValue` |
183
+ | `KnownFieldDefinition` | `AvConfigKnownFieldDefinition` |
184
+ | `LifecycleTrait` | `AvLifecycleTrait` |
185
+ | `NullsOrder` | `AvNullsOrder` |
186
+ | `Operation` | `AvOperation` |
187
+ | `OperationArgumentMap` | `AvOperationArgumentMap` |
188
+ | `OperationArgumentsFor` | `AvOperationArgumentsFor` |
189
+ | `OperationAvailability` | `AvOperationAvailability` |
190
+ | `OperationCall` | `AvOperationCall` |
191
+ | `OperationCode` | `AvOperationCode` |
192
+ | `OperationDiagnostic` | `AvOperationDiagnostic` |
193
+ | `OperationErrorCode` | `AvOperationErrorCode` |
194
+ | `OperationFailureResponse` | `AvOperationFailureResponse` |
195
+ | `OperationFamily` | `AvOperationFamily` |
196
+ | `OperationGrammar` | `AvOperationGrammar` |
197
+ | `OperationIdentity` | `AvOperationIdentity` |
198
+ | `OperationNoMatchResponse` | `AvOperationNoMatchResponse` |
199
+ | `OperationReferenceSurface` | `AvOperationReferenceSurface` |
200
+ | `OperationResponse` | `AvOperationResponse` |
201
+ | `OperationResultFor` | `AvOperationResultFor` |
202
+ | `OperationSlot` | `AvOperationSlot` |
203
+ | `OperationSuccessCode` | `AvOperationSuccessCode` |
204
+ | `OperationSuccessDataCode` | `AvOperationSuccessDataCode` |
205
+ | `OperationSuccessResponse` | `AvOperationSuccessResponse` |
206
+ | `OperationVariant` | `AvOperationVariant` |
207
+ | `OperationVariantScopes` | `AvOperationVariantScopes` |
208
+ | `OrderByEntry` | `AvOrderByEntry` |
209
+ | `OrderByInput` | `AvOrderByInput` |
210
+ | `PaginationCapability` | `AvPaginationCapability` |
211
+ | `Pipe` | `AvPipe` |
212
+ | `PipelineConfig` | `AvPipeline` |
213
+ | `PipelineContext` | `AvContext` |
214
+ | `PipelineTransportContext` | `AvTransportContext` |
215
+ | `ProjectionEntry` | `AvProjectionEntry` |
216
+ | `ProjectionScope` | `AvProjectionScope` |
217
+ | `ProjectionScopes` | `AvProjectionScopes` |
218
+ | `ReferenceableField` | `AvReferenceableField` |
219
+ | `ReferenceBuilder` | `AvReferenceBuilder` |
220
+ | `RelationField` | `AvRelationField` |
221
+ | `RelationFieldCapabilities` | `AvRelationFieldCapabilities` |
222
+ | `RelationFieldCapabilityName` | `AvRelationFieldCapabilityName` |
223
+ | `RelationFieldPipelineConfig` | `AvRelationFieldPipeline` |
224
+ | `RelationFilterCapability` | `AvRelationFilterCapability` |
225
+ | `RelationMutationCapability` | `AvRelationMutationCapability` |
226
+ | `RelationMutationDirective` | `AvRelationMutationDirective` |
227
+ | `RelationProjectionCapability` | `AvRelationProjectionCapability` |
228
+ | `RelationProjectionInput` | `AvRelationProjectionInput` |
229
+ | `RelationReducer` | `AvRelationReducer` |
230
+ | `RelationReducerCapability` | `AvRelationReducerCapability` |
231
+ | `RequestOrigin` | `AvRequestOrigin` |
232
+ | `Resource` | `AvResource` |
233
+ | `ResourceFieldMap` | `AvResourceFieldMap` |
234
+ | `ResourceKey` | `AvResourceKey` |
235
+ | `ResourceOperations` | `AvResourceOperations` |
236
+ | `ScalarDefinition` | `AvScalarDefinition` |
237
+ | `ScalarField` | `AvScalarField` |
238
+ | `ScalarFieldCapabilities` | `AvScalarFieldCapabilities` |
239
+ | `ScalarFieldCapabilityName` | `AvScalarFieldCapabilityName` |
240
+ | `ScalarFieldKey` | `AvScalarFieldKey` |
241
+ | `ScalarFieldPipelineConfig` | `AvScalarFieldPipeline` |
242
+ | `ScalarFilterOperator` | `AvScalarFilterOperator` |
243
+ | `ScalarFormat` | `AvScalarFormat` |
244
+ | `ScalarMutationDirective` | `AvScalarMutationDirective` |
245
+ | `ScalarOrderInput` | `AvScalarOrderInput` |
246
+ | `ScalarRegistry` | `AvScalarRegistry` |
247
+ | `ScalarValueType` | `AvScalarValueType` |
248
+ | `ScopedRelationMutations` | `AvScopedRelationMutations` |
249
+ | `ScopedRelationReducers` | `AvScopedRelationReducers` |
250
+ | `SelectInput` | `AvSelectInput` |
251
+ | `SingleRowResult` | `AvSingleRowResult` |
252
+ | `SortDirection` | `AvSortDirection` |
253
+ | `TransactionAfterHook` | `AvTransactionAfterHook` |
254
+ | `TransactionBeforeHook` | `AvTransactionBeforeHook` |
255
+ | `TransactionCapability` | `AvTransactionCapability` |
256
+ | `TransactionCommittedResponse` | `AvTransactionCommittedResponse` |
257
+ | `TransactionDiagnostic` | `AvTransactionDiagnostic` |
258
+ | `TransactionFilter` | `AvTransactionFilter` |
259
+ | `TransactionGuard` | `AvTransactionGuard` |
260
+ | `TransactionIntegrityError` | `AvTransactionIntegrityError` |
261
+ | `TransactionIntegrityViolation` | `AvTransactionIntegrityViolation` |
262
+ | `TransactionInterceptor` | `AvTransactionInterceptor` |
263
+ | `TransactionPipe` | `AvTransactionPipe` |
264
+ | `TransactionPipelineConfig` | `AvTransactionPipeline` |
265
+ | `TransactionPipelineContext` | `AvTransactionContext` |
266
+ | `TransactionReference` | `AvTransactionReference` |
267
+ | `TransactionResponse` | `AvTransactionResponse` |
268
+ | `TransactionResults` | `AvTransactionResults` |
269
+ | `TransactionRunner` | `AvTransactionRunner` |
270
+ | `TransactionSlotPathError` | `AvTransactionSlotPathError` |
271
+ | `TransactionSlotPathViolation` | `AvTransactionSlotPathViolation` |
272
+ | `UniqueWhereInput` | `AvUniqueWhereInput` |
273
+ | `UpdateDataInput` | `AvUpdateDataInput` |
274
+ | `ValidationCode` | `AvValidationCode` |
275
+ | `ValidationIssue` | `AvValidationIssue` |
276
+ | `WhereInput` | `AvWhereInput` |
277
+ | `WireScalarForms` | `AvWireScalarForms` |
278
+ | `WriteScope` | `AvWriteScope` |
279
+ | `WriteScopes` | `AvWriteScopes` |
280
+
281
+ Error classes whose `name` a log or a test may read:
282
+
283
+ | Before | After |
284
+ | ------------------------ | -------------------------- |
285
+ | `CallerDataError` | `AvCallerDataError` |
286
+ | `ClientConfigError` | `AvClientConfigError` |
287
+ | `ComputedValueError` | `AvComputedValueError` |
288
+ | `ContractProtocolError` | `AvContractProtocolError` |
289
+ | `ContractTransportError` | `AvContractTransportError` |
290
+ | `EnvFileError` | `AvEnvFileError` |
291
+ | `OutputValidationError` | `AvOutputValidationError` |
292
+ | `OutputWriteError` | `AvOutputWriteError` |
293
+ | `PipeOutputError` | `AvPipeOutputError` |
294
+ | `UnmountedRouteError` | `AvUnmountedRouteError` |
295
+
296
+ `@aventara/testing`:
297
+
298
+ | Before | After |
299
+ | ------------------------ | -------------------------- |
300
+ | `AdapterFactory` | `AvAdapterFactory` |
301
+ | `FakeAdapter` | `AvFakeAdapter` |
302
+ | `FakeAdapterExecute` | `AvFakeAdapterExecute` |
303
+ | `FakeAdapterOptions` | `AvFakeAdapterOptions` |
304
+ | `FakeAdapterRollback` | `AvFakeAdapterRollback` |
305
+ | `FakeTransactionOutcome` | `AvFakeTransactionOutcome` |
306
+ | `FakeTransactionTrace` | `AvFakeTransactionTrace` |
307
+
308
+ `@aventara/client` (the `framework.client.ts` config types):
309
+
310
+ | Before | After |
311
+ | ------------------- | --------------------- |
312
+ | `ClientConfigInput` | `AvClientConfigInput` |
313
+ | `ConfigValue` | `AvClientConfigValue` |
314
+ | `EnvReference` | `AvEnvReference` |
315
+
316
+ `@aventara/prisma7-adapter`: its public types and error classes (`createPrismaAdapter` keeps its name):
317
+
318
+ | Before | After |
319
+ | ---------------------------------- | ------------------------------------ |
320
+ | `PrismaAdapterModel` | `AvPrismaAdapterModel` |
321
+ | `PrismaAdapterOptions` | `AvPrismaAdapterOptions` |
322
+ | `PrismaDelegate` | `AvPrismaDelegate` |
323
+ | `PrismaDelegateHost` | `AvPrismaDelegateHost` |
324
+ | `PrismaDelegateIndex` | `AvPrismaDelegateIndex` |
325
+ | `PrismaDiscoveryArtifact` | `AvPrismaDiscoveryArtifact` |
326
+ | `PrismaDriver` | `AvPrismaDriver` |
327
+ | `PrismaIsolationLevel` | `AvPrismaIsolationLevel` |
328
+ | `PrismaProvider` | `AvPrismaProvider` |
329
+ | `PrismaProviderProfile` | `AvPrismaProviderProfile` |
330
+ | `PrismaReferentialAction` | `AvPrismaReferentialAction` |
331
+ | `PrismaReferentialActionTable` | `AvPrismaReferentialActionTable` |
332
+ | `PrismaReferentialEdge` | `AvPrismaReferentialEdge` |
333
+ | `PrismaResourceReferentialActions` | `AvPrismaResourceReferentialActions` |
334
+ | `PrismaTransactionOptions` | `AvPrismaTransactionOptions` |
335
+ | `PrismaCapabilityDerivationError` | `AvPrismaCapabilityDerivationError` |
336
+ | `PrismaDiscoveryArtifactError` | `AvPrismaDiscoveryArtifactError` |
337
+ | `PrismaEmulationError` | `AvPrismaEmulationError` |
338
+ | `PrismaExecutionError` | `AvPrismaExecutionError` |
339
+ | `PrismaExistenceGateError` | `AvPrismaExistenceGateError` |
340
+ | `PrismaFieldProjectionError` | `AvPrismaFieldProjectionError` |
341
+ | `PrismaGenerateCliError` | `AvPrismaGenerateCliError` |
342
+ | `PrismaGenerateStepError` | `AvPrismaGenerateStepError` |
343
+ | `PrismaModelCompositionError` | `AvPrismaModelCompositionError` |
344
+ | `PrismaMutationTranslationError` | `AvPrismaMutationTranslationError` |
345
+ | `PrismaOperationTranslationError` | `AvPrismaOperationTranslationError` |
346
+ | `PrismaOrderTranslationError` | `AvPrismaOrderTranslationError` |
347
+ | `PrismaProjectionTranslationError` | `AvPrismaProjectionTranslationError` |
348
+ | `PrismaResultShapeError` | `AvPrismaResultShapeError` |
349
+ | `PrismaScalarConversionError` | `AvPrismaScalarConversionError` |
350
+ | `PrismaSchemaReaderError` | `AvPrismaSchemaReaderError` |
351
+ | `PrismaTypesReaderError` | `AvPrismaTypesReaderError` |
352
+ | `PrismaWhereTranslationError` | `AvPrismaWhereTranslationError` |
353
+
354
+ - 68d4395: New: the generated client checks field validators before it sends. When the ClientContract carries a field's
355
+ `validators` or a Json Shape's checks, `avclient generate` emits them into the client with the check code that runs
356
+ them, and every call and every transaction checks the values it holds first. A call that breaks a check rejects with
357
+ the same `AvValidationError` the server would answer, `A2004` with the same issues (`code`, `path`, `check`,
358
+ `params`, `message`), and no request is sent:
359
+
360
+ ```ts
361
+ try {
362
+ await avClient.projects.create.one({ data: { id: "p1", name: "no" } });
363
+ } catch (error) {
364
+ // error instanceof AvValidationError, error.code === "A2004", nothing was sent:
365
+ // error.cause.issues[0] → { code: "V1004", path: ["arguments", "data", "name"],
366
+ // message: "Value must be at least 3 characters long.", check: "min_length", params: { minimum: 3 } }
367
+ }
368
+ ```
369
+
370
+ - The server checks every value again. The client checks a value as the caller wrote it and the server checks it
371
+ after its field pipes, so a field pipe that normalizes a value (trims it, lower-cases it) must not turn a value the
372
+ client accepted into one the server refuses.
373
+ - A transaction is checked whole before it is sent: a bad literal value in any step rejects with the server's answer,
374
+ `cause.operation` naming the step. A `$ref` value is checked by the server, at its step.
375
+ - Nested write data, list fields (each entry and the list's length), `$push` entries and Json Shape checks are all
376
+ checked, a Json Shape's checks with the other validators in the order the call wrote the fields, and a plan step
377
+ by step, as the server does. A Json value that does not match its shape is sent, and the server answers it.
378
+ - The check code is `@aventara/core`'s own, copied into the generated output; the client still imports nothing from
379
+ `@aventara/*` or zod at runtime. A contract with no checks generates the same files as before.
380
+ - `AvValidationIssue` declares `check` and `params`, and the client keeps them on the issues a server sends (they
381
+ were dropped before).
382
+ - The server lists validator issues in the order the call wrote the fields (it used the model's field order), and a
383
+ Json Shape's issues in the order of its keys as the Contract lists them, so the client can list the same issues in
384
+ the same order. An issue inside a nested write whose operand is one entry rather than a list no longer names an
385
+ index the request does not have (`[…, "$update", "data", …]`, not `[…, "$update", 0, "data", …]`).
386
+
387
+ - 7e3d06f: Breaking: the configuration has a new shape. Every layer (the root, `application` and `client`) now holds the
388
+ same six keys: `exposed`, `transactionsStyle`, `limits`, `pipelines`, `resources` and `exemptions`. Everything about
389
+ one Resource lives under `resources.<Resource>`: its fields, and each field's `definition` and `pipelines`. The old
390
+ keys are refused when the framework starts, with a message that names where each one moved:
391
+
392
+ | Before (rc.0) | Now (rc.1) |
393
+ | ------------------------------------------------------- | ----------------------------------------------------------------------------------- |
394
+ | `fields: { Post: { url: { type, nullable, … } } }` | `resources: { Post: { fields: { url: { definition: { type, nullable, … } } } } }` |
395
+ | `behaviors: { Post: { fields: { slug: { create } } } }` | `resources: { Post: { fields: { slug: { pipelines: { compute: { create } } } } } }` |
396
+ | `transactions: "none"` | `transactionsStyle: "none"` |
397
+ | `restrictions` | `exposed` + `exemptions` (see below) |
398
+ | `@aventara/core/json` | `@aventara/core/avz` |
399
+
400
+ Before:
401
+
402
+ ```ts
403
+ createFramework({
404
+ api: "/api",
405
+ adapter,
406
+ transactions: "interactive",
407
+ fields: {
408
+ Post: {
409
+ url: {
410
+ type: { scalar: "string" },
411
+ nullable: false,
412
+ list: false,
413
+ lifecycle: ["VIRTUAL"],
414
+ },
415
+ },
416
+ },
417
+ behaviors: {
418
+ Post: {
419
+ fields: {
420
+ url: {
421
+ read: {
422
+ dependsOn: ["slug"],
423
+ compute: ({ record }) => `/p/${record.slug}`,
424
+ },
425
+ },
426
+ },
427
+ },
428
+ },
429
+ });
430
+ ```
431
+
432
+ After:
433
+
434
+ ```ts
435
+ createFramework({
436
+ api: "/api",
437
+ adapter,
438
+ transactionsStyle: "interactive",
439
+ resources: {
440
+ Post: {
441
+ fields: {
442
+ url: {
443
+ definition: {
444
+ type: { scalar: "string" },
445
+ nullable: false,
446
+ list: false,
447
+ lifecycle: ["VIRTUAL"],
448
+ format: "url",
449
+ },
450
+ pipelines: {
451
+ compute: {
452
+ read: {
453
+ dependsOn: ["slug"],
454
+ compute: ({ record }) => `/p/${record.slug}`,
455
+ },
456
+ },
457
+ },
458
+ },
459
+ },
460
+ },
461
+ },
462
+ });
463
+ ```
464
+
465
+ What else changed:
466
+
467
+ - A field is defined at the root only. A `definition` in `application` or `client` is refused
468
+ (`CONFIG_FORBIDDEN_IN_OVERLAY`). Define the field
469
+ at the root; `application` and `client` can still add compute stages to it.
470
+ - Computed values chain. When the root and an overlay both compute a field, the root's stage runs first and the
471
+ overlay's receives its result as `value`. A stage can no longer be turned off with `false`. Returning `undefined`
472
+ keeps the current value. An upsert computes its create branch with `compute.create` and its update branch with
473
+ `compute.update`.
474
+ - A discovered field keeps the adapter's facts. On a field the adapter discovered you may restate its own `type`,
475
+ `nullable` and `list`, and give a Json field its shape (`definition.json`). Setting a different type, any `format`
476
+ or any `capabilities` on it is refused. `format` is for fields you add, and it must be one of zod's named string
477
+ formats (`"email"`, `"url"`, `"uuid"`, …); any other name is a type error and refused at startup.
478
+ - A misplaced key is a type error. In a configuration written inline in `createFramework({ ... })` or
479
+ `AventaraModule.forRoot`, a key that has no place there (a typo, an old key, `compute` on a relation field, a field
480
+ name neither your schema nor the root has) is now a type error at that key, and still refused at startup.
481
+ - A Resource whose name starts with `$` is refused at startup (`$` names are the framework's).
482
+ - The Json shape builder moved from `@aventara/core/json` to `@aventara/core/avz`. Change the import; `AvZ` is
483
+ the same.
484
+
485
+ `exposed` and `exemptions`, which replace `restrictions`, have their own entry.
486
+
487
+ - 1b5d3c0: Breaking: every framework member of a pipeline ctx is `$`-prefixed, and ctx is now the framework's executor.
488
+ The rest of ctx is your Resources: `ctx.<Resource>.<family>.<variant>(args)`, plus `ctx.$sql` and
489
+ `ctx.$transaction`. Because a Resource name can never start with `$` (`COMPILER_RESERVED_RESOURCE_NAME`), a Resource
490
+ never shadows a framework member. The old names are gone with no alias. Reading one is a type error; at runtime it
491
+ is `undefined`.
492
+
493
+ | rc.0 | rc.1 |
494
+ | --------------------------------------------------------- | --------------------------------------------------------------------------- |
495
+ | `ctx.resource`, `ctx.family`, `ctx.variant`, `ctx.nested` | `ctx.$operation.resource`, `.family`, `.variant`, `.nested` |
496
+ | `ctx.args` | `ctx.$args` (a transaction stage: the plan, `readonly AvTransactionStep[]`) |
497
+ | `ctx.origin` | `ctx.$origin` |
498
+ | `ctx.requestId` | `ctx.$requestId` |
499
+ | `ctx.transport` | `ctx.$transport` |
500
+ | `ctx.contract` | `ctx.$contract` |
501
+
502
+ A transaction stage's ctx has no `$operation`. Every ctx also carries `ctx.$state`, the request's writable state (see
503
+ the `$state` entry below).
504
+
505
+ ```ts
506
+ hooks: {
507
+ after: [
508
+ async (post, ctx) => {
509
+ await ctx.User.update.unique({ where: { id: authorId }, data: { postCount: { $increment: 1 } } });
510
+ await ctx.$sql`insert into audit_events (actor, action) values (${actorId}, ${"post.create"})`;
511
+ },
512
+ ],
513
+ },
514
+ ```
515
+
516
+ - A ctx call is raw and application-origin. It runs the Framework Validation Layer against the
517
+ ApplicationContract, plus field pipes, field validators and compute. It runs no developer stage: no guards, pipes,
518
+ hooks, interceptors or filters at any level, no field write guards, no nested target guards, no Resource
519
+ transaction stages, and no `forceTransaction` wrapping. So a hook's call never re-enters the hook that made it.
520
+ The application layer's exposure limits it. The client's does not.
521
+ - A call resolves the operation's data directly (a row, a list, a count, or `null` for a first-style miss). A
522
+ failure throws the `AvError` subclass of its code's class (`AvNotFoundError`, `AvValidationError`, …; see the
523
+ in-process calls entry below) carrying the failure's `code` and `cause`.
524
+ - It joins the current transaction. That covers a plan step's interceptors and hooks, a forced call's, a Resource's
525
+ transaction stages and a `ctx.$transaction` callback. A step's guards and pipes run before the transaction opens,
526
+ so their calls run on their own, as every call outside a transaction does. Under
527
+ `forceTransaction`, an after hook's ctx writes commit with the operation or not at all (the outbox and
528
+ counter-on-another-Resource cases).
529
+ - `ctx.$sql` is the bound tagged template of `appTx.$sql`, run at once. It takes only the tagged-template form,
530
+ binds every value, needs the Adapter's `sqlStatements`, and accepts no `$ref`. It resolves the rows, typed by
531
+ `ctx.$sql<Row>`. Inside a transaction it runs on it; outside one it is a plain statement, with no transaction
532
+ opened around it, and `transactionsStyle: "none"` does not affect it (only `ctx.$transaction` is refused there).
533
+ - `ctx.$transaction(async (tx) => …)` runs the callback in one transaction, with `tx` the ctx bound to it, and
534
+ resolves what the callback returns. A throw rolls it back and is rethrown as it was. Inside an open transaction it
535
+ opens nothing and joins.
536
+ - The executor is typed from the adapter's model, with the application forms and the operation's data
537
+ as the result, like `framework.application`'s success data. A stage typed for any model (`AvGuard` with no model)
538
+ names no Resource.
539
+ - Compute gets a read-only ctx, `AvComputeContext` (new public name). It carries the `$` facts, a read-only view
540
+ of `ctx.$state`, and `ctx.<Resource>.find.*` (`find.count` included), and nothing that writes: no write families, no `$sql`, no
541
+ `$transaction`. This holds at runtime too: reaching one throws, and the operation answers `A3000`. A compute
542
+ stage's input is now `{ field, value, data, ctx }` (`{ field, value, record, ctx }` on read). rc.0's `origin`,
543
+ `resource` and `operation` members are gone: use `ctx.$origin`, `ctx.$operation`, and the stage's placement for
544
+ its Resource.
545
+ - A transaction pipe's returned plan is typed `readonly AvTransactionStep[]` (any model). The runtime holds it to
546
+ the plan it was given, as before.
547
+
548
+ - 6317811: Breaking: `exposed` and `exemptions` replace `restrictions`. Every layer (the root, `application` and `client`)
549
+ says what it exposes with two keys: `exposed`, the layer's default, and `exemptions`, the entries that are the
550
+ opposite of it.
551
+
552
+ - `exposed: true` (the root's default) exposes everything the layer above offers, and `exemptions` lists what to
553
+ hide. `exposed: false` exposes nothing, and `exemptions` lists the only things to expose.
554
+ - In `exemptions`, `true` exempts an entry whole, `false` and `[]` exempt nothing, a list exempts the listed
555
+ entries one level down, and an object goes one level deeper. A Resource takes `true`, `false` or
556
+ `{ operations, fields }`. Operations are nested: `operations: { find: ["many"], update: { unique: true } }`.
557
+ A field takes a list of capability names, or an object per capability whose token lists name filter operators,
558
+ directives, reducers or pagination kinds.
559
+ - A list now always means "exempt these". rc.0's `filter: ["equals"]` meant "keep only `equals`"; under
560
+ `exposed: true` the same intent is the list of the operators to remove.
561
+ - Overlays only narrow. `application` and `client` start from the root's view. An overlay can no longer bring
562
+ back what the root hid (rc.0's `hidden: false`); that is now refused at startup, and the message names the other
563
+ overlay to hide it in instead. Expose an entry at the root and hide it in the overlay that must not see it.
564
+ - An overlay that sets `exemptions` must also set its own `exposed`.
565
+ - Relation positions are the adapter's: an exemption can no longer narrow where a relation is projected or written.
566
+ - A unique operation (`find.unique`, `update.unique`, `delete.unique`, `upsert.unique`) needs an identifier. Picking
567
+ one without the identifier's fields, or hiding every identifier while one stays exposed, is refused at startup
568
+ with `COMPILER_MISSING_IDENTIFIER` instead of the operation silently disappearing.
569
+
570
+ Every name in `exemptions` must exist, in both styles: a Resource, field, family, variant, capability or token the
571
+ adapter does not offer is refused at startup with its path (`COMPILER_UNKNOWN_RESOURCE`, `COMPILER_UNKNOWN_FIELD`,
572
+ `COMPILER_UNAVAILABLE_OPERATION`, `COMPILER_UNAVAILABLE_CAPABILITY`), and in a configuration written inline in
573
+ `createFramework({ ... })` it is a type error first. Under `exposed: true`, hiding in an overlay what the root
574
+ already hid does nothing.
575
+
576
+ Before (rc.0):
577
+
578
+ ```ts
579
+ createFramework({
580
+ api: "/api",
581
+ adapter,
582
+ restrictions: {
583
+ User: {
584
+ fields: {
585
+ passwordHash: { hidden: true },
586
+ email: { capabilities: { filter: ["equals"] } },
587
+ },
588
+ },
589
+ },
590
+ client: {
591
+ restrictions: {
592
+ AuditLog: { hidden: true },
593
+ Post: { operations: { delete: { unique: false } } },
594
+ },
595
+ },
596
+ });
597
+ ```
598
+
599
+ After (rc.1):
600
+
601
+ ```ts
602
+ createFramework({
603
+ api: "/api",
604
+ adapter,
605
+ // The root: `exposed` defaults to true, so these are hidden from every origin.
606
+ exemptions: {
607
+ resources: {
608
+ User: {
609
+ fields: {
610
+ passwordHash: true,
611
+ email: { filter: ["contains", "startsWith"] }, // remove every operator but `equals`
612
+ },
613
+ },
614
+ },
615
+ },
616
+ client: {
617
+ exposed: true,
618
+ exemptions: {
619
+ resources: {
620
+ AuditLog: true,
621
+ Post: { operations: { delete: ["unique"] } },
622
+ },
623
+ },
624
+ },
625
+ });
626
+ ```
627
+
628
+ Or expose only what a frontend calls:
629
+
630
+ ```ts
631
+ client: {
632
+ exposed: false,
633
+ exemptions: {
634
+ resources: {
635
+ Post: {
636
+ operations: { find: ["many", "unique"], create: ["one"] },
637
+ fields: { id: ["select"], title: ["select", "create"], body: ["select", "create"] },
638
+ },
639
+ },
640
+ },
641
+ },
642
+ ```
643
+
644
+ `aventara init` and `aventara new` now write `exposed: true` into `src/aventara.config.ts`, with a comment that
645
+ links the exposure documentation.
646
+
647
+ - 6d0e5d6: New: field validators. `resources.<R>.fields.<f>.pipelines.validators` takes declarative checks written with
648
+ `AvZ` from `@aventara/core/avz`, in zod's check vocabulary:
649
+
650
+ ```ts
651
+ import { AvZ } from "@aventara/core/avz";
652
+
653
+ resources: {
654
+ Project: {
655
+ fields: {
656
+ name: { pipelines: { validators: [AvZ.minLength(3), AvZ.maxLength(80)] } },
657
+ slug: { pipelines: { validators: [AvZ.regex(/^[a-z0-9-]+$/)] } },
658
+ budget: { pipelines: { validators: [AvZ.gte(0), AvZ.multipleOf(100)] } },
659
+ tags: { pipelines: { validators: [AvZ.maxItems(5), AvZ.maxLength(20)] } }, // at most 5 tags of at most 20 characters
660
+ },
661
+ },
662
+ },
663
+ ```
664
+
665
+ - The builders: `lt`, `lte`, `gt`, `gte`, `positive`, `nonnegative`, `negative`, `nonpositive`, `multipleOf`,
666
+ `minLength`, `maxLength`, `length`, `minItems`, `maxItems`, `minSize`, `maxSize`, `size`, `regex`, `includes`,
667
+ `startsWith`, `endsWith`, `lowercase`, `uppercase`, and one per named format: `email`, `url`, `uuid`, `e164`,
668
+ `ipv4`, `ipv6`, `base64`, `nanoid`, `cuid`, `ulid` and the rest, with `AvZ.iso.datetime()`, `.date()`, `.time()`
669
+ and `.duration()`. Each behaves as zod 4's check does.
670
+ - A check has to fit the field's type: `AvZ.maxLength` on an `int` field, or `AvZ.maxItems` on a field that is not a
671
+ list, is a type error and a startup error (`COMPILER_INVALID_VALIDATOR`, naming the path and why). On a list field
672
+ `minItems`/`maxItems` check the list and every other check applies to each entry. A bound is a number, a bigint or a
673
+ `Date`, matching the field.
674
+ - A Json field takes no `validators` key. Its checks go in its `definition.json` shape, written as zod/mini writes
675
+ them: `AvZ.object({ code: AvZ.string().check(AvZ.length(4)), tags: AvZ.array(AvZ.string()).check(AvZ.maxItems(3)) })`.
676
+ - Where they run: once, after every pipe (the guards, then the operation's pipes, then the field pipes) and before
677
+ any interceptor or hook; for a transaction plan or a forced call, on every step's literal values before the
678
+ transaction opens, and on a `$ref` value at its step; on nested write data with the target Resource's checks.
679
+ What they judged is what is written: no later stage can change it. Validators add up across layers: the root's
680
+ apply to both origins, an overlay's to its own.
681
+ - A Json field's shape is one of its validators. Its structure and its checks are judged where validators run, after
682
+ every pipe (rc.0 judged the shape before the pipes), with the same reach: plan literals before the transaction
683
+ opens, a `$ref` value at its step, and nested write data. Its issues come in the order the call wrote the fields,
684
+ with the other validators'. Before the
685
+ pipes the framework only checks that a Json value is plain JSON. A field or operation pipe whose Json output breaks
686
+ the shape is answered `A2004`, as the caller's, not `A3004`. The shape still types the field.
687
+ - A failure answers `A2004` (HTTP 422) with one issue per broken rule, on `V1004` (range, length, size) or `V1003`
688
+ (pattern, format). Each issue now also carries zod's `check` name and the check's `params`, for example
689
+ `{ "code": "V1004", "path": ["arguments", "data", "name"], "check": "max_length", "params": { "maximum": 80 }, "message": "Value must be at most 80 characters long." }`.
690
+ - The checks are in the Contract: a field's `validators` (`AvFieldCheck`, now exported) and a Json Shape node's
691
+ `checks`, only on fields the layer exposes. Adding, removing or changing a client-visible check changes the
692
+ ClientContract hash, so regenerate the client. The generated client runs the same checks before it sends a call.
693
+
694
+ - 7a0cab9: A `where` now offers each field only the filter operators that field allows. The types of `framework.client`,
695
+ `framework.application`, `framework.clientTx`, `framework.appTx` and a generated client read the operators from the
696
+ field's effective `filter` capability, so an operator the server would refuse with `V1006` is now a type error
697
+ instead. That covers an operator the adapter does not offer for the field's type (no `contains` on an Int), an
698
+ operator a layer's exemptions removed (the client layer narrowing `email` to `equals` is refused on
699
+ `framework.client` and still allowed on `framework.application`), and operators inside a nested `not`. A plain
700
+ value, `null` or `$ref` as shorthand is equality, so it is only accepted where the field allows `equals`, and a field
701
+ narrowed to no operators at all can no longer be named in a `where`. Runtime behavior is unchanged.
702
+
703
+ A generated client picks this up when it is regenerated with this version of `@aventara/client`.
704
+
705
+ - eb2a718: New limit `maxJsonDepth` (default 64): how deeply a `json` field's value may nest. Each array or object inside the value
706
+ is one level, counted from the value itself, wherever it is written or filtered on. A value past the limit is refused
707
+ with `A2009` and the new issue code `V1021` at the field's path, before anything else reads it, in single calls,
708
+ transaction steps and over HTTP. It is set like the other limits, at the root or per layer, and appears in the
709
+ Contract's `limits`, so the ClientContract hash changes: regenerate your client. `maxNestingDepth` does not count Json
710
+ values. Before, a value 10,000 levels deep was written and then failed over HTTP with an internal `A3003`, and in a
711
+ transaction failed with `A3000`. The HTTP response encoder and `canonicalizeJson` no longer recurse on a value's depth,
712
+ so a deep value already in your database is read without an error.
713
+ - 03312c5: Fixed a bug where operators inside `not` weren't checked against a field's allowed operators. On a field whose
714
+ `filter` capability allowed only `equals` and `not`, a request like `where: { id: { not: { contains: "a" } } }` passed
715
+ validation and reached the adapter, so a remote caller could use an operator the client layer had removed. Operators
716
+ inside `not` are now checked at every depth, in single calls and transaction steps, under `AND`/`OR`/`NOT` and relation
717
+ filters, and are refused with `A2004`/`V1006` at the nested operator's path. A `not` written as a plain value, `null` or
718
+ `$ref` means "not equal", so it is accepted only where the field allows `equals`; the types now say the same. An empty
719
+ `not: {}` is refused with `V1001`, like an empty filter object.
720
+ - 123f6dc: Breaking: nested writes now run the target's guards. When a create, update or upsert reaches another Resource
721
+ through a relation directive, that target Resource's own guards and field stages now run on the nested data, in
722
+ Node, before the single adapter call (still one call). In rc.0 a nested write ran none of them, so a client could
723
+ create a Category through `Post.create({ data: { category: { $create: … } } })` past a guard that refuses
724
+ `Category.create`. That call is now refused with `A4001`.
725
+
726
+ Which stages a directive runs on its target:
727
+
728
+ | Directive | The target's stages |
729
+ | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
730
+ | `$create`, `$connectOrCreate` | Resource and `create` guards; field stages on the created data |
731
+ | `$update`, `$upsert` | Resource and `update` guards; field stages (an `$upsert`'s `create` branch gets the create field stages and `compute.create`, its `update` branch the update ones) |
732
+ | `$delete` | Resource and `delete` guards |
733
+ | `$connect`, `$disconnect`, `$set` on a to-one whose key the parent holds | None: the parent's relation field write guard covers it |
734
+ | `$connect`, `$disconnect`, `$set` on a to-many, or a to-one whose key the target holds | Resource and `update` guards |
735
+
736
+ - The field stages are the target's field pipes, field validators, field write guards and write compute.
737
+ - Order: each kind runs after the top-level operation's stages of the same kind, for the targets depth first in
738
+ data order: the operation's guards and field write guards, then each target's Resource guards, family guards and
739
+ field write guards; the operation's pipes; the operation's field pipes, then the targets'; the validators; the
740
+ operation's write compute, then the targets'.
741
+ - What a target's stage is told: `ctx.$operation.resource` is the target, `ctx.$operation.family` the family its directive maps to,
742
+ `ctx.$operation.variant` is `"one"`, `ctx.$operation.nested` is `true` and `ctx.$args` is the directive's entry (for example the
743
+ `$create` data, or a `$connect`'s identifier). A family stage's `ctx.$operation.variant` is now typed as the family's
744
+ variants or `"one"`, for `create`, `update` and `delete`.
745
+ - Not run for a target: its layer and variant stages, operation pipes, hooks, interceptors and filters, and its
746
+ Resource transaction stages. A nested write is part of its parent's operation; an error a target's guard throws
747
+ goes through the parent operation's filters.
748
+ - Who holds the key is read from the adapter's referential edges (`AvAdapter.referentialActions`). An adapter
749
+ that states no edge for a to-one relation is read as the target holding it, so the target's `update` guards run.
750
+ - The same holds for a transaction step and a forced call: each step's nested targets' guards, field pipes and
751
+ validators run with the step's own before the transaction opens, and a nested `$ref` value goes through the
752
+ target's field pipes and validators when it resolves at its step.
753
+
754
+ - b65df2e: Fixed a gap where a chain of `not` inside a scalar filter (`{ id: { not: { not: … } } }`) wasn't counted toward
755
+ `maxNestingDepth`. A 50-level chain reached the adapter, and a 5,000-level one failed with an internal `A3000` error
756
+ (a stack overflow) instead of a validation error. Each `not` whose value is an object now counts as one level of
757
+ `where` nesting, like `NOT`, so a chain past the limit is refused with `A2009`/`V1013` before anything runs, in single
758
+ calls, transaction steps and over HTTP. `framework.transaction` no longer overflows on deeply nested arguments either.
759
+ - c6e5010: Breaking: one stage order, and hooks now run inside interceptors. Every operation runs
760
+
761
+ ```
762
+ guards → pipes → validators → interceptors (before) → hooks.before → operation → hooks.after → interceptors (after) → filters
763
+ ```
764
+
765
+ Each stage runs over every level, outer to inner, before the next starts, so every interceptor wraps every hook: all
766
+ interceptors enter, then every `before` hook runs, then the operation, then every `after` hook (inner to outer), then
767
+ the interceptors unwind (inner to outer). In rc.0 every `before` hook ran ahead of every interceptor, every `after`
768
+ hook after every interceptor had unwound, and the overlay's `after` hooks after the root's; now the overlay's run
769
+ before the root's. Filters run inner to outer, and the first filter that handles an error wins. A call that a guard,
770
+ a pipe's output or a validator refuses runs no interceptor and no hook; the filters still see a thrown error. Inside
771
+ a transaction, a step's error its own filters leave unhandled continues to the Resource transaction filters (the
772
+ transaction's outer layer) before it is answered.
773
+
774
+ New: stages at every level of `resources`. `resources.<R>.pipelines`, `resources.<R>.operations.<family>.pipelines`
775
+ and `resources.<R>.operations.<family>.<variant>.pipelines` run now, in both layers, level by level: root layer,
776
+ overlay layer, root Resource, overlay Resource, root family, overlay family, root variant, overlay variant. Nothing
777
+ below removes a stage above. A stage is told the level it sits at: a Resource's `ctx.$operation.resource` is its name, a
778
+ family's `ctx.$operation.family` too, a variant's `ctx.$operation.variant` as well.
779
+
780
+ - Field pipes (`resources.<R>.fields.<f>.pipelines.pipes`) are pure: value in, value out, no `ctx`. They run on
781
+ each value the caller sent in top-level create, update or upsert data, right after the operation's pipes, root's
782
+ then overlay's; guards see the value as sent. In a transaction they run on every step's literal values before the
783
+ transaction opens, and on a `$ref` value when it is resolved at its step. A value a field pipe returns is held to the server's rules
784
+ (`A3004`). A relation field takes no field pipes (`COMPILER_RELATION_FIELD_CONFIG_UNSUPPORTED`).
785
+ - Field write guards (`resources.<R>.fields.<f>.pipelines.guards`) refuse with `A4001` when the caller sends
786
+ the field in create, update or upsert data, a relation field's `$connect` included. They run right after the
787
+ operation's guards, last among the guards.
788
+ - Transactions: every step's guards, pipes and validators run before the transaction opens, in plan order; an
789
+ operation pipe sees a `$ref` as the reference it is. A refused step opens nothing. Then BEGIN, and at each step
790
+ its `$ref`s are resolved, their field pipes and validators run, then the step's interceptors and hooks around its
791
+ adapter call. A forced call runs the same way. A step's guards and pipes no longer run inside the transaction, so
792
+ their ctx calls do not join it.
793
+ - Resource transaction stages (`resources.<R>.transactions.pipelines`) run once per transaction with a
794
+ top-level step on the Resource, inside it: guards and pipes see the whole plan (`ctx.$args`, `$ref`s unresolved),
795
+ interceptors and hooks wrap every step, and the `after` hooks see every step's result before the commit, so a
796
+ throw rolls everything back. Touched Resources run in the order their first step appears; a SQL step touches
797
+ nothing. A transaction pipe may change a step's arguments; they are held to the server's rules and their
798
+ validators at the step.
799
+ - `forceTransaction` on a family or a variant runs a plain call of that operation as a one-step transaction,
800
+ so its after hooks commit with the write or not at all, and the Resource's transaction stages run. It holds when
801
+ any layer sets it. As a step of a plan it is just a step. Under an effective `transactionsStyle: "none"` it is a
802
+ startup error (`CONFIG_INVALID_VALUE`).
803
+
804
+ Breaking: a transaction has one origin. `framework.transaction` refuses a list that mixes `appTx` and
805
+ `clientTx` handles: `A2004` with one new `V1020` issue, "Transaction mixes application and client steps.", at the
806
+ first step of the other origin, before anything runs. An `appTx.$sql` step is application-origin. Run each
807
+ origin's steps as its own transaction. The generated client's error codes include `V1020`.
808
+
809
+ - c1f9389: A forced operation no longer commits a failed step when a Resource transaction interceptor catches the rollback.
810
+ A transaction plan and a plain call of a `forceTransaction` operation now settle through one path, so the check that
811
+ already kept a plan from committing a swallowed failure covers forced calls too.
812
+
813
+ `next()` runs once. A Resource transaction interceptor that calls it a second time, or resolves without calling it,
814
+ rolls the whole transaction back and answers `A3002`, with an `AvTransactionIntegrityError` (`next-called-twice` or
815
+ `steps-not-run`) on the diagnostics channel. An operation interceptor's second `next()` is refused the same way and
816
+ answers `A3000`. Both hold even when the interceptor catches the refusal, and no filter sees it.
817
+
818
+ What a field pipe returns is checked against the server's rules before the transaction opens, for a plan step and
819
+ for a forced call. A refusal (`A3004`) no longer opens a transaction or runs transaction stages first.
820
+
821
+ A `compute.read` `dependsOn` is resolved against the adapter's model, before exposure. A field hidden at the root can
822
+ now be a dependency: it is read for the compute and never returned. A dependency must be a scalar field the adapter
823
+ stores on the same Resource; the type of `dependsOn` now says so.
824
+
825
+ Under `exposed: false`, an exemption object that grants nothing (`{}`, `{ select: false }`, `{ create: [] }`, or a
826
+ Resource object that grants no field and no operation) leaves the field or Resource out of the Contract, exactly as
827
+ leaving the entry out does. Its name no longer reaches the ClientContract, and the hash is the same either way.
828
+
829
+ Compute mistakes are reported once, at the path where they were written. A root mistake is no longer repeated under
830
+ `application` and `client` paths.
831
+
832
+ `forceTransaction: true` is a type error where the types know the effective `transactionsStyle` is `"none"`: the
833
+ adapter's model states `transactions: "none"`, or the layers state a literal `"none"`.
834
+
835
+ Resource transaction stages are told a typed plan. `ctx.$args` is `readonly AvTransactionStep[]`, an operation step
836
+ `{ resource, family, variant, args }` or a SQL step `{ sql }`, and a transaction pipe returns that type or `undefined`.
837
+ `AvTransactionStep` is a new public type.
838
+
839
+ Renamed compiler codes: `COMPILER_MISSING_READ_BEHAVIOR` is now `COMPILER_MISSING_READ_COMPUTE`, and
840
+ `COMPILER_INVALID_BEHAVIOR_DEPENDENCY` is now `COMPILER_INVALID_COMPUTE_DEPENDENCY`.
841
+
842
+ Smaller fixes: a plan with steps of two origins is refused with `V1020` when the plan is validated too, not only by the
843
+ typed runner; a transaction pipe may return a deep copy of a SQL step; `validators: []` is accepted; a `hidden` key on a Resource or field entry is `CONFIG_MOVED_PROPERTY`; and
844
+ an overlay's moved `restrictions` key now names `client.exposed + client.exemptions`.
845
+
846
+ - 9c52482: A `$connect` to a row that does not exist now answers `404 A2003` (not found), the same as reading a missing row.
847
+ Before, it answered `422 A2004`. This covers a to-one `$connect` in `create`, `update` and `upsert`, a to-many
848
+ `$connect`, and the same writes inside a transaction plan, where `cause.operation` names the step. The message is
849
+ unchanged: "The operation's arguments referenced a record that does not exist." On `update.first`, the same mistake
850
+ answered `A2014` before, as if the row had changed underneath; it now answers `A2003` too, and a duplicate unique value
851
+ written through `update.first` answers `409 A2008` instead of `A3001`.
852
+
853
+ Clearer top-level messages for an unknown Resource or operation. `A2001` now says "The requested Resource is not
854
+ available." and `A2002` says "The requested operation is not available on this Resource.", instead of "Operation
855
+ arguments failed framework validation.", which stays the message of `A2004`, `A2007` and `A2009`. A transaction step
856
+ whose operation is outside the standard grammar now carries the same issue message as a single call, naming the
857
+ operation and the Resource (for example `Operation "dance.one" is not available on Resource "posts".`), instead of
858
+ "Operation is not part of the standard operation grammar."
859
+
860
+ A `$ref` with no `fingerprint` is `V1000` (required value missing) and answers `422 A2004`. Before, it was `V1017`
861
+ (fingerprint mismatch) under `A2007`. A fingerprint that is present but wrong is still `V1017`.
862
+
863
+ `aventara init` and `aventara new` link to the documentation at https://aventara-framework.vercel.app. The old
864
+ address redirects, so links already written into projects keep working.
865
+
866
+ - 8396148: Types: a method that returns a call's result without a return type now compiles in a project that emits
867
+ declarations (`declaration: true`, Nest's default). With a shaped Json field, or a `$sql` or `clientTx` handle in
868
+ the result, TypeScript stopped with TS2742 (TS2883 in TypeScript 6) or TS4053, because the declaration had to name
869
+ a type that was not exported. Two type exports are new: `AvZShapedSchema` from `@aventara/core/avz` (a shaped Json
870
+ field's schema in a typed Contract view) and `AvOperationHandle<T, Origin>` from `@aventara/core` (the opaque part of
871
+ a transaction handle).
872
+
873
+ A handle now carries its builder's origin: `framework.transaction([...])` with `appTx` and `clientTx` handles in one
874
+ list is a type error (it was refused only at runtime, `A2004` / `V1020`, which still guards). `AvOperation<T>`
875
+ takes an optional second type argument, `"application"` or `"client"`; a handle typed without it joins either list.
876
+
877
+ A method that returns a façade node without a return type now compiles there too:
878
+ `posts() { return this.framework.application.Post; }`, a whole surface, a Resource, a family, on any of
879
+ `application`, `client`, `appTx` and `clientTx`. The declaration writes the node's name with the Contract view as
880
+ its argument, instead of expanding every call under it, which TypeScript refused (TS4053, then TS7056 "exceeds the
881
+ maximum length the compiler will serialize") from a few Resources up. Twelve type exports are new, one set per
882
+ surface: `AvApplicationFacade`, `AvApplicationResourceFacade`, `AvApplicationFamilyFacade`, and the same for
883
+ `AvClient…`, `AvAppTx…` and `AvClientTx…`. Measured over 50 Resources (Nest 12's `tsconfig`, TypeScript 6): each such
884
+ method emits about 400 KB of declaration and the build peaks at about 370 MB. A variant (`…Post.find.many`)
885
+ is still a call type the declaration cannot name: give that method a return type, or return the call's result.
886
+
887
+ An exported `defineResource(...)` result, and an exported configuration or Framework builder that holds typed
888
+ stages (spread from a `defineResource` result or written inline in `createFramework`), now compile there too. Before,
889
+ one typed variant pipe was enough for TS7056: a declaration wrote each inline stage's parameter types, and with them
890
+ the whole model, once per parameter. The types that carry a configuration onwards now state each stage list by its
891
+ public type for any model (`readonly AvGuard[]`, `readonly AvPipe[]`, …): `defineResource` returns the new
892
+ `AvDefinedResource<R, Block, Overlays>`, and `createFramework`'s `AvFramework<M, Cfg>` carries the configuration that
893
+ way. Every key, field definition, `forceTransaction`, validator and compute phase is kept as written, so a spread
894
+ block is still checked where it is placed and the façades are unchanged; `AvFramework<M, typeof config>` still
895
+ receives `createFramework(config)`. Measured with the scaffold's shape over 2 Resources, the declarations shrink from
896
+ 5.4 MB to 84 KB; over 50 Resources they emit (before: TS7056) and the build peaks under 400 MB.
897
+
898
+ - e8fbb02: Breaking: data is read-only once it is final, and every stage gets `ctx.$state`.
899
+
900
+ Pipes are now the only stage that changes the arguments. A pipe is told frozen arguments and returns new ones (or
901
+ `undefined` to keep them); changing them in place throws a `TypeError`. Guards, interceptors, hooks and filters are
902
+ told frozen arguments too, and an `after` hook a frozen copy of the result. The validators judge what the pipes
903
+ returned, and that is exactly what the adapter writes: a hook or an interceptor can no longer change the write after
904
+ validation. An interceptor may still return a different result after `next()`; the output check holds it. The result a
905
+ caller receives is not frozen. A `Date` or a `Uint8Array` cannot be frozen, so after validation each stage gets its
906
+ own copy of it. Compute fills its fields on the framework's own copy, and its `data` is a frozen snapshot.
907
+
908
+ ```ts
909
+ // rc.1: return new arguments instead of changing them.
910
+ pipes: [(args) => ({ ...args, data: { ...args.data, ownerId: ownerOf(args) } })],
911
+ ```
912
+
913
+ `ctx.$state` is the one writable space per request. Declare what it holds once, then read and write it in any stage:
914
+
915
+ ```ts
916
+ declare module "@aventara/core" {
917
+ interface AvState {
918
+ user?: { id: string; roles: string[] };
919
+ }
920
+ }
921
+
922
+ const signedIn: AvGuard = (ctx) => ctx.$state.user !== undefined;
923
+ ```
924
+
925
+ - One object per request. A transaction's steps and its Resource transaction stages share it, and a ctx call,
926
+ `ctx.$sql` and `ctx.$transaction` inherit the stage's. Compute gets a read-only view; writing through it throws a
927
+ `TypeError`.
928
+ - Seed it per call: `framework.application.Post.create.one(args, { state })`, the same on `framework.client`, and
929
+ `framework.transaction(handles, { state })`. The object is used as it is, so you see what the stages wrote. A call
930
+ that seeds nothing starts with `{}`.
931
+ - `framework.execute` and `executeTransaction` take it as the request's `state` member (not an object: `A2004`,
932
+ `V1001` at `["state"]`). `AvProtocol.bind(framework).handleOperation(request, { state: () => … })` and
933
+ `handleTransaction` take a seed function, called once the request is decoded. A seed that throws an `AvError`
934
+ answers that error; any other throw answers `A3000` and reaches diagnostics.
935
+ - `@aventara/nest` seeds it from the platform request (see its changelog).
936
+
937
+ New public types: `AvState` and `AvDeepReadonly<T>`, the read-only shape to claim when a stage reads
938
+ `ctx.$args` (`ctx.$args as AvDeepReadonly<PostArgs>`). A generated client copies `AvState`'s declaration with the
939
+ rest of core's types; it does nothing there.
940
+
941
+ - 916e5f6: Breaking: in-process calls return data and throw, with the generated client's error classes.
942
+ `framework.application`, `framework.client` and `framework.transaction` now settle the way the generated client
943
+ does: they resolve the data and throw every failure as the `AvError` subclass of its code's class. The subclasses
944
+ are new exports of `@aventara/core`, chosen by one code→class table the generated client reads too:
945
+
946
+ | Class | Codes |
947
+ | ------------------------- | ------------------------------------------- |
948
+ | `AvProtocolError` | A2000, A2001, A2002, A2006, A2010–A2012 |
949
+ | `AvNotFoundError` | A2003 |
950
+ | `AvValidationError` | A2004, A2007, A2009 |
951
+ | `AvContractMismatchError` | A2005 |
952
+ | `AvConflictError` | A2008, A2013, A2014 |
953
+ | `AvInternalError` | A3000–A3004 |
954
+ | `AvAuthError` | A4000–A4002 |
955
+
956
+ `instanceof` works, and `error.code` and `error.cause` are what the envelope carried (a transaction's
957
+ `cause.operation` names the failing step). A stage's ctx calls throw the same subclasses. `framework.execute`,
958
+ `framework.executeTransaction` and the protocol binding still answer the envelope: it is the transport's format.
959
+
960
+ ```ts
961
+ // Before
962
+ const res = await framework.application.Post.find.unique({ where: { id }, select: ["id", "title"] });
963
+ if (res.code !== "A1000") return null;
964
+ return res.data;
965
+ const result = await framework.transaction([user, post]);
966
+ if (result.code === "A1009") use(result.data[1]);
967
+
968
+ // After
969
+ try {
970
+ return await framework.application.Post.find.unique({ where: { id }, select: ["id", "title"] });
971
+ } catch (error) {
972
+ if (error instanceof AvNotFoundError) return null;
973
+ throw error;
974
+ }
975
+ const [created, written] = await framework.transaction([user, post]);
976
+ ```
977
+
978
+ The façades' result types follow: a call resolves the operation's slot (`T`, or `T | null` for a `first`), and
979
+ `framework.transaction` resolves its results tuple. `AvOperationCall` loses its `Settlement` parameter (every direct
980
+ call settles to data), and `AvError` takes its code as a type parameter (`AvError<"A2003">`); `new AvError(code,
981
+ cause)` is unchanged.
982
+
983
+ New: a stage registered at a variant (`resources.<R>.operations.<family>.<variant>.pipelines`) gets its operation's
984
+ arguments typed. `ctx.$args` is that operation's arguments, deep read-only, so a write is a type error and the editor
985
+ completes `data`, `where`, `select`; a pipe there is told that type, deep read-only too, and must return it (or
986
+ `undefined`). The type is read from the model's Application Contract view in the application forms, and a reference
987
+ position also admits a plan step's unresolved `$ref`. Layer, Resource and family stages keep `unknown`. A pipe typed
988
+ for any operation (`AvPipe`) still fits a variant; its output is held to the server's rules at runtime (`A3004`). The
989
+ stage types `AvContext`, `AvGuard`, `AvPipe`, `AvBeforeHook`, `AvAfterHook`, `AvInterceptor`, `AvFilter` and
990
+ `AvPipeline` take the arguments as a new last type parameter, `unknown` by default.
991
+
992
+ Behaviour change: a Resource's transaction filters are the transaction's outer layer, and they run last. An error a
993
+ step throws inside a transaction goes through that step's own filters first, inner to outer; when none handles it,
994
+ the transaction interceptors unwind (their `next()` rejects), and then it goes to the touched Resources' transaction
995
+ filters (the last-touched Resource's first) before it is answered. A transaction interceptor's `next()` rejects with
996
+ the failed step's outcome as the `AvError` a façade would throw for it (`AvNotFoundError` for a unique miss,
997
+ `instanceof` works, `code` and `cause` are set); before, it rejected with an internal rollback object. An error the
998
+ step's filters leave unhandled reaches the interceptor sanitized, as the caller would get it. Catching it still cannot
999
+ commit the failed step. An error a transaction stage throws goes to the
1000
+ transaction filters alone, also after the interceptors have unwound. ROLLBACK follows both. Before, a step's
1001
+ unhandled error was answered without reaching them.
1002
+
1003
+ Behaviour change: a strict unique operation that matches no row (`find.unique`, `update.unique`, `delete.unique`)
1004
+ now fails at the operation, inside the pipeline, as a missing `$connect` target already did. No `after` hook runs
1005
+ for it, an interceptor's `next()` throws the `AvNotFoundError` (it resolved `null` before), the filters see it and
1006
+ may answer another outcome, and a forced call or a transaction step rolls back. Unhandled, it is the same `A2003`
1007
+ as before: the façades throw `AvNotFoundError` and HTTP answers `404`. A `find.first`, `update.first` or
1008
+ `delete.first` that matches no row still resolves `null`, and its `after` hooks run.
1009
+
1010
+ Performance: field write guards and field pipes are dispatched from lists planned at startup, per origin and
1011
+ Resource. A call to a Resource with no field guard reads no record for one, a `create.many` walks its records for
1012
+ guards only when a guarded field is registered, and nested data is walked for guards only when some guard exists.
1013
+
1014
+ - Breaking: required create fields are typed. Each Resource now states what a create cannot do without, and every
1015
+ create payload is typed by it: `framework.application`, `framework.client`, `appTx`/`clientTx`, a stage's `ctx` and
1016
+ typed `args`, and generated clients. Leaving out a required field is a type error, and so is writing a required
1017
+ relation neither way or both ways:
1018
+
1019
+ ```ts
1020
+ await framework.application.Post.create.one({ data: { title: "Hi", authorId } }); // ok
1021
+ await framework.application.Post.create.one({ data: { title: "Hi", author: { $connect: { id } } } }); // ok
1022
+ await framework.application.Post.create.one({ data: { title: "Hi" } }); // type error: `author` or `authorId`
1023
+ await framework.application.Post.create.one({ data: { authorId } }); // type error: `title`
1024
+ ```
1025
+
1026
+ It covers `create.one`'s `data`, every `create.many` and `create.count` record, `upsert`'s `create`, and nested
1027
+ `$create`, `$connectOrCreate` and `$upsert` payloads. A create nested through a relation gets that relation from its
1028
+ parent, so `author: { $create: … }` is not needed inside `Author.posts.$create`. A `$ref` satisfies a field.
1029
+
1030
+ The fact is a new optional member of every Resource in every Contract, `createRequirements`
1031
+ (`AvCreateRequirements`, `AvCreateRequirementGroup`): `required` (fields), `oneOf` (each required to-one relation and
1032
+ the fields holding its reference, `[["author", "authorId"]]`; a composite reference is all of its fields together),
1033
+ and `parentSupplies` (what a nested create gets from its parent). Each layer's Contract states only what that layer
1034
+ lets a caller write: when the layer hides `authorId`, `author` alone is required; when it hides `author`, `authorId`
1035
+ is. A field a `compute.create` stage fills is not required. The Client Contract's hash changes for every schema with a
1036
+ required field or relation, so regenerate your clients.
1037
+
1038
+ Adapter authors: the requirements move from the adapter's own `createRequirements` table, which is removed, onto its
1039
+ model (`AvAdapterResource.createRequirements`, the same shape as the Contract's, before any layer is applied). A name
1040
+ there that is no field of the right kind fails construction with `COMPILER_UNKNOWN_FIELD`.
1041
+
1042
+ The runtime check is unchanged in what it answers (`A2004` with `V1000` at the missing field, or at the relation where
1043
+ the caller may write it; `V1012` for both), and now reads the active Contract's statement. Two consequences: a
1044
+ relation the layer requires alone is reported without naming a reference field the layer hides, and a required
1045
+ relation's reference fields come from the statement, so an adapter that states no referential edges still has a
1046
+ required relation written either way.
1047
+
1048
+ A field an operation pipe fills on the server is now required of the caller. Give it a `compute.create` stage or a
1049
+ database default so callers can leave it out, or have them pass it.
1050
+
1051
+ A layer that still creates a Resource can no longer leave a requirement unwritable. Hiding a required field (or
1052
+ exempting its `create` capability), or a required relation together with a reference field it needs, while the layer
1053
+ keeps a `create` or `upsert` variant or a nested create into the Resource, fails construction with
1054
+ `COMPILER_HIDDEN_REQUIRED_FIELD`. A composite reference is written whole: each of its blocked fields needs a
1055
+ `compute.create`. For example:
1056
+
1057
+ ```text
1058
+ the client layer still creates resource "Post" (create.one, upsert.unique) but hides its required field "tenantId",
1059
+ which every create must write; expose "tenantId", give "tenantId" a compute.create, or exempt the create operation
1060
+ ```
1061
+
1062
+ A pipe that filled the hidden field is not enough. Move the value into a `compute.create` stage on the field (at the
1063
+ root or in that layer), keep the field exposed, or exempt the layer's create operations.
1064
+
1065
+ A `create.many` or `create.count` record cannot write a relation, so a required relation is met there by its
1066
+ reference fields alone. In those records `authorId` is plainly required by the types, and a record without it answers
1067
+ `A2004` with `V1000` at `data.<n>.authorId` (before, a layer that hid `authorId` let it reach the database, which
1068
+ answered `A3001`). A layer that hides `authorId`, even with `author` exposed, while it keeps `create.many` or
1069
+ `create.count` now fails construction with `COMPILER_HIDDEN_REQUIRED_FIELD`:
1070
+
1071
+ ```text
1072
+ the client layer still creates resource "Post" in bulk (create.count, create.many) but hides its reference field
1073
+ "authorId", which every bulk create must write: a bulk record cannot write the relation "author"; expose "authorId",
1074
+ give "authorId" a compute.create, or exempt create.count and create.many
1075
+ ```
1076
+
1077
+ A `compute.create` written inline in `createFramework({ ... })` without parameter types now counts, at the root and in
1078
+ an overlay: the field it fills is no longer required by the types. Before, such a stage made the whole inline
1079
+ configuration's type fall back to the untyped one, so the façades ignored it (and everything else the literal stated).
1080
+ For that, a `compute.create` or `compute.update` stage's `field` and `data` are keyed by `string` now, not by your
1081
+ field names; their values were `unknown` already. `AvComputeCreate` and `AvComputeUpdate` take the model alone
1082
+ (`AvComputeCreate<Model>`).
1083
+
1084
+ - Breaking: the root key `entrypoint` is now `api`, and `framework.entrypoint` is `framework.api`. The value is the
1085
+ same mount path, normalized the same way:
1086
+
1087
+ ```ts
1088
+ createFramework({ api: "/api", adapter });
1089
+ ```
1090
+
1091
+ `entrypoint` is refused with `CONFIG_MOVED_PROPERTY` ("entrypoint moved in rc.1: use api") and is a type error. A
1092
+ generated client still takes `entrypoint` (the server's URL), and so do `defineClientConfig` and
1093
+ `avclient init --entrypoint`: those name where a client points, not where the server mounts.
1094
+
1095
+ - New: the `agent` layer and the Agent Contract, the base for serving AI agents over MCP. `agent` holds the six layer
1096
+ keys an overlay holds, plus `extends`: the layer it starts from, `"client"` (the default), `"application"` or
1097
+ `"root"`. Its view is that layer's final view, narrowed by its own `exposed`/`exemptions`; it never widens it. An
1098
+ exemption that would expose what its parent hid fails construction, and the message names the parent:
1099
+
1100
+ ```text
1101
+ field "Post.body" is hidden by client, the layer agent extends, and the agent layer only narrows that view;
1102
+ expose it in client, or extend a layer that exposes it
1103
+ ```
1104
+
1105
+ Stages run along the chain: the root's, then the parent overlay's, then the agent's, level by level, and every stage
1106
+ is told `ctx.$origin === "agent"` (`AvRequestOrigin` and `AvConfigLayerName` gain `"agent"`). Compute chains the same
1107
+ way. `limits` and `transactionsStyle` are the parent's effective values unless the agent states its own. Left out,
1108
+ the agent layer is its parent's view exactly. `defineResource` takes an `agent` block beside `application` and
1109
+ `client`.
1110
+
1111
+ The layer compiles to `framework.contracts.agent` (`AvContractAgent`), built and identified like the Client Contract:
1112
+ its protocol version and its own hash over its own content, so an agent that exposes what the client exposes has the
1113
+ client's hash. Required create fields, hidden-requirement checks and `forceTransaction` checks apply to it as to any
1114
+ layer, and a refusal names `agent`.
1115
+
1116
+ `AvProtocol.bind(framework, { origin: "agent" })` runs agent calls through the same decoding and validation as HTTP
1117
+ client calls: its surface and `/_contract` are the Agent Contract's, the identity headers must carry the Agent
1118
+ Contract's hash (the Client Contract's is `A2005`), and the calls run under the agent's pipelines. The default
1119
+ binding is unchanged. `framework.execute` and `executeTransaction` take `origin: "agent"` with the Agent Contract's
1120
+ protocol identity.
1121
+
1122
+ - New: the root key `mcp` turns MCP on. It is a mount path (`mcp: "/mcp"`), or `{ path, authorization }` where
1123
+ `authorization` is `{ servers, verify }`: the OAuth authorization servers (https URLs) a caller gets its token from,
1124
+ and `verify(token)`, which resolves the caller or `null`. The path is written as `api` is and must not be `api` itself
1125
+ or inside its `_` namespace. Each mistake is a startup error at its path (`mcp.path`,
1126
+ `mcp.authorization.servers[1]`, …). The resolved endpoint is `framework.mcp` (`AvMcpEndpoint`), for the host that
1127
+ serves it; `undefined` when MCP is off. `agent` without `mcp` is allowed.
1128
+
1129
+ - New: `AvDiagnostic` has a third kind, `AvMcpDiagnostic` (`kind: "mcp"`). When the MCP endpoint itself fails, outside
1130
+ any tool call's operation (the MCP SDK's server or transport), the caller gets a bare `500` and the diagnostics sink
1131
+ gets the raw error with `code: "A3000"`, `origin: "agent"` and a minted `requestId`. A sink that narrows on `kind`
1132
+ now has three arms.
1133
+
1134
+ - Faster startup: each remote Contract (client and agent) is written as canonical JSON once. Its hash, the Contract
1135
+ object and the `/_contract` body all come from that one text instead of four separate passes. The bytes and
1136
+ hashes are unchanged. `createFramework` plus binding the client and agent protocols took 186 ms at 117 Resources and
1137
+ now takes 133 ms (90 to 67 ms at 50, 20 to 15 ms at 6).
1138
+
1139
+ - Smaller edge bundles: `@aventara/core/avz` imports only the zod builders it uses, so a bundler drops the rest of
1140
+ `zod/mini`, its locales included. A minified bundle of the entry went from 453 KB to 48 KB.
1141
+
1142
+ ## 1.0.0-rc.0
1143
+
1144
+ ### Major Changes
1145
+
1146
+ - First release candidate of Aventara 1.0. The public API is now considered stable; changes before 1.0.0 are possible
1147
+ based on feedback.
1148
+
1149
+ ### Minor Changes
1150
+
1151
+ - 24ffbab: A `Json` field can now have a type. Build its shape with `AvZ` from the new entry `@aventara/core/json` and declare it
1152
+ on the field: `fields: { Post: { meta: { json: AvZ.object({ title: AvZ.string() }) } } }`. `framework.application`,
1153
+ `framework.client`, `appTx`/`clientTx` and the generated client then read and write the field as that type instead of
1154
+ generic JSON, and every write to it — create, update, upsert, nested writes and transaction steps, a value taken from
1155
+ an earlier step included — is checked before the database is asked: a value out of shape is refused with `A2004` and
1156
+ one issue per problem at its exact path (`V1000` missing key, `V1001` wrong type, `V1002` outside an enum or literal,
1157
+ `V1004` integer out of range, `V1005` unknown key). Shapes are types only and their objects are closed; reads and
1158
+ filters are never checked. Only a field the adapter discovered as `Json` takes a shape, and a Zod schema is not
1159
+ accepted. The shape is part of the ClientContract (as JSON Schema), so declaring or changing one changes its hash:
1160
+ regenerate the client. `@aventara/core` now depends on `zod` (`^4.6.5`), which only `@aventara/core/json` loads. The
1161
+ shape types `AvZShape`, `AvZObject`, `AvZOptional` and `AvZNullable` are exported too, so a project that emits
1162
+ declarations can export a shape or a configuration holding one.
1163
+ - 24ffbab: Transaction steps can now reference earlier results in `$connect`, `$disconnect`, `$set`, `$connectOrCreate`'s `where`,
1164
+ a `cursor`, a unique `where`, and anywhere in a filter — `AND`/`OR`/`NOT` and relation filters included, with every
1165
+ scalar operator. `framework.appTx` and `framework.clientTx` type each position by what it holds: a filter's value,
1166
+ `equals` and `not` take a source of the field's own type (nullable only where the field is, and a `null` then matches
1167
+ the rows where the field is unset, as a literal `null` does); a unique key, a `cursor`, a comparison or a text operator a
1168
+ non-null source; `in`, `notIn`, `hasEvery` and `hasSome` a list field; `has` one value. The server checks the same rule
1169
+ before anything runs and refuses a mismatch with `A2007`/`V1011`. Nested relation writes take references at any depth
1170
+ too: the values and keys of nested `$create`, `$update` and `$upsert` data, and the `where` of a nested `$update`,
1171
+ `$delete` or `$upsert`. A reference in an ordering or a projection's nested `where` is still refused.
1172
+ - 24ffbab: **Behaviour changes:** server-side calls now copy what you pass them. `framework.application`, `framework.client`,
1173
+ `framework.execute`, `framework.executeTransaction` and the `appTx`/`clientTx` builders read your arguments once, when
1174
+ you call them, into plain data the framework owns; validation, guards, pipes, computed values and the adapter see only
1175
+ that copy, so changing or revoking your object afterwards (an Immer draft after `produce`) no longer affects the
1176
+ operation. A live Proxy (Vue `reactive`, MobX) still works.
1177
+
1178
+ A value that cannot be read — a revoked Proxy, a getter that throws — or that is not plain data — a class instance or a
1179
+ `Map`; `Date`, `Decimal` and `Uint8Array` are fine — is now refused as your request's error: `A2004` with one `V1001` at
1180
+ the value's path (`["arguments", …]`, or `["operations", i, "args", …]` with `cause.operation` in a transaction), before
1181
+ any guard, pipe or adapter runs. Before, it was `A3000` (an internal error) or, from `appTx`/`clientTx`, a `TypeError`
1182
+ thrown at the builder call; a builder now never throws, and `framework.transaction([...])` answers the refusal. The same
1183
+ holds for a `framework.execute` / `executeTransaction` request object that cannot be read. Two answers change for
1184
+ inputs that were never supported: a class instance where an object of arguments belongs (`where`, `data`, …) was
1185
+ accepted or failed as `A3000`, and is now refused; inherited, non-enumerable and symbol keys are dropped, as JSON drops
1186
+ them.
1187
+
1188
+ New optional root setting `misuse` (types `FrameworkMisuseSink`, `FrameworkMisuseEvent`), beside `diagnostics`: it
1189
+ receives one event per refused value — its `kind` (`"unreadable-value"` or `"non-plain-value"`), the `path` the caller
1190
+ received, and the operation's `origin`, `resource`, `family`, `variant` and transaction step (`operation`) when they
1191
+ could be read — never the value itself. It cannot change a response; an error it throws or a promise it rejects is
1192
+ ignored. `diagnostics` keeps receiving only unexpected failures.
1193
+
1194
+ HTTP requests are not copied again: a body the protocol parses from raw content is already plain data.
1195
+
1196
+ The generated client reads your arguments through one guard too: a value that cannot be read is refused with a
1197
+ `TypeError` naming where (`… the value at /where/id could not be read.`) before anything is sent, and a `tx` builder
1198
+ never throws — `transaction([...])` rejects with that error instead. Regenerate the client to pick this up.
1199
+
1200
+ - 24ffbab: A nested `$update` or `$delete` through a to-many relation filters plain fields only on Prisma 7, and Aventara now says
1201
+ so up front: a relation filter in its `where` — `{ posts: { $update: { where: { category: { name: "x" } }, … } } }`, at
1202
+ any depth, under `AND`/`OR`/`NOT` too — is refused with `A2004` / `V1006` before the database is asked, and is a type
1203
+ error in `framework.application`, `framework.client`, `appTx`/`clientTx` and the generated client. Before, it reached
1204
+ Prisma and fail as `A3001`. A to-one relation's nested filter keeps relation filters. The limit is stated by the adapter
1205
+ in the Contract (`nestedWriteFilter: "scalar"`), so the ClientContract hash changes: regenerate the client.
1206
+
1207
+ ### Patch Changes
1208
+
1209
+ - 24ffbab: **Behaviour changes:** `@aventara/core` exports fewer names. Every name it no longer exports was undocumented; every
1210
+ documented name (`createFramework`, `FrameworkConfig`, `defineFields`, `Decimal`, `FrameworkError`, the pipeline types and
1211
+ the rest) is still exported. Types shown in a hover or an error message still resolve; what changes is only which names
1212
+ your own code can import. `OperationScope` was a deprecated alias: use `RequestOrigin`.
1213
+
1214
+ What Aventara's own packages need from core moved to `@aventara/core/internal`. It is not public API: it carries no
1215
+ stability promise, and any of its exports may change or disappear in any release. Applications import from
1216
+ `@aventara/core`.
1217
+
1218
+ Moved to `@aventara/core/internal`: `AdapterField`, `AdapterFieldKey`, `AdapterFieldMap`, `AdapterIdentifier`, `AdapterLifecycleTrait`, `AdapterOperation`, `AdapterOperationExecutor`, `AdapterRelationField`, `AdapterResource`, `AdapterScalarField`, `AdapterScalarFieldKey`, `advertisedDirectives`, `advertisedReducers`, `ApplicationContractView`, `ApplicationOperationRequest`, `ApplicationTransactionRequest`, `AVENTARA_PROTOCOL_VERSION`, `BUILT_IN_SCALARS`, `BuiltinNonRow`, `canonicalizeContract`, `canonicalizeJson`, `CanonicalJsonError`, `ClientContractHashInput`, `ClientOperationRequest`, `ClientProtocolIdentity`, `ClientTransactionRequest`, `compileContracts`, `computeClientContractHash`, `computeOperationFingerprint`, `DEFAULT_CONTRACT_LIMITS`, `FrameworkOperationRequest`, `FrameworkTransactionRequest`, `isOperationVariantAvailable`, `LIFECYCLE_TRAITS`, `OPERATION_CODES`, `OperationFingerprint`, `PROJECTION_SCOPES`, `projectionScopeOf`, `resolveFrameworkConfig`, `SemanticOperationArguments`, `TRANSACTION_CAPABILITIES`, `validateClientContractStructure`, `VALIDATION_CODES`, `verifyClientContractHash`, `WRITE_SCOPES`, `writeScopeOf`.
1219
+
1220
+ No longer exported from any entry: `advertisedDirectivesAt`, `advertisedReducersAt`, `ClientContractStructureVerdict`, `ContractCompilationResult`, `DeferredOperation`, `EffectiveFieldKeyAt`, `holdsAt`, `holdsInAnyScope`, `isOperationFingerprint`, `isTransactionReferenceCandidate`, `isTransactionReferenceObject`, `operationFailure`, `OperationFingerprintNode`, `OperationInternalErrorCode`, `operationNoMatch`, `OperationScope`, `operationSuccess`, `OperationValidationResult`, `RelationMutationAction`, `ResolvedFrameworkConfig`, `ResolvedFrameworkScopeConfig`, `ResolvedPipelineConfig`, `ScalarFilterInput`, `ScalarMutationAction`, `transactionCommitted`, `TransactionCreateDataInput`, `transactionInfrastructureFailure`, `TransactionOperationArgumentsFor`, `transactionOperationFailure`, `TransactionPlan`, `TransactionReferenceCandidate`, `TransactionScalarValue`, `TransactionUpdateDataInput`, `validateFrameworkConfig`, `validateOperationArguments`, `VALIDATION_CODE_MESSAGES`.
1221
+
1222
+ - 24ffbab: Each package ships its `CHANGELOG.md`, so the release notes are in the installed package beside the README.
1223
+ - 24ffbab: A `null` given to a filter operator that has no `null` meaning — `gt`, `contains`, `in`, `has`, `mode`, `isEmpty`,
1224
+ `path`, a JSON `string*` operator and the rest — is now refused as `A2004` / `V1001` at that operator, before the
1225
+ database is asked, and is a type error. Before, it reached the database and failed as `A3001`. `equals: null` and
1226
+ `not: null` still match the rows where a nullable field is unset or set.
1227
+ - 24ffbab: **Diagnostics:** if your own HTTP host mounts only some of `protocol.surface()` and a request for a route it left out
1228
+ reaches `protocol.answerAbsent`, your `diagnostics` sink now receives one `A3000` diagnostic naming the route: an
1229
+ `"operation"` diagnostic with the Resource, family and variant (a `"transaction"` one for `/_transactions`), whose
1230
+ `error` is named `"UnmountedRouteError"` and says which `surface()` entry to mount. The caller's `500 A3000` answer is
1231
+ unchanged, and a route your ClientContract does not offer is still answered without a report. `@aventara/nest` mounts
1232
+ every route, so its applications are not affected.
1233
+ - 24ffbab: **Diagnostics:** a `FrameworkError` you throw on purpose with an `A3xxx` code — from a guard, pipe, hook, interceptor,
1234
+ computed field or adapter, or returned by a filter — now reaches your `diagnostics` sink once, as the error you threw,
1235
+ under its code, with `deliberate: true` on the diagnostic. Before, the caller received the generic `A3000`/`A3001` and
1236
+ your message and issues were reported nowhere. A failure Aventara did not expect carries no `deliberate` field, so a sink
1237
+ can tell the two apart. What the caller receives is unchanged, and `A2xxx`/`A4xxx` outcomes are still not reported.
1238
+ - 24ffbab: **Diagnostics:** a result that does not match its Contract — an adapter row with a wrong value, a missing field, a
1239
+ result of the wrong shape — now reaches your `diagnostics` sink as one `A3000` diagnostic whose `error` (`name`
1240
+ `"OutputValidationError"`) names the operation and lists the problems (`error.issues`). Before, the caller got `A3000`
1241
+ and the sink got nothing unless reading the result threw. The same now holds for a computed field: a read or write
1242
+ behavior that returns a value its field refuses is reported as an error named `"ComputedValueError"` with the issues
1243
+ (before, the sink received only the field's location). What the caller receives is unchanged. A filter that inspects
1244
+ the error now sees that error instead of a `FrameworkError` with code `A3000`.
1245
+
1246
+ The `FrameworkError` documentation now states the message rule: for any code outside `A3xxx`, the message is sent to
1247
+ the caller exactly as written, so it must not carry database text, SQL, a stack, a path or a secret.
1248
+
1249
+ - 24ffbab: **Behaviour changes:** Pipelines and guards read where a request came from as `request.origin` (was `request.scope`).
1250
+ The same property is renamed everywhere it means `"application"` or `"client"`: the pipeline context
1251
+ (`context.origin`), the request objects `framework.execute` and `framework.executeTransaction` take
1252
+ (`{ origin: "client", … }`), the context a computed field's behaviour receives, and every diagnostic the diagnostics
1253
+ sink receives. There is no `scope` alias: replace `scope` with `origin` in those places. Nothing sent over HTTP
1254
+ changes.
1255
+
1256
+ The Nest host's log line for an internal failure now reads `(client origin, request …)` instead of
1257
+ `(client scope, request …)`.
1258
+
1259
+ - 24ffbab: **Types:** a guard, pipe, hook, interceptor or filter typed with `Guard`, `Pipe`, `BeforeHook`, `AfterHook`,
1260
+ `Interceptor` or `Filter` without a model type now type-checks wherever one typed for your model is expected, so you
1261
+ can put it in an `as const` configuration (the shape `aventara init` writes), in `client.pipelines` or
1262
+ `application.pipelines`, and mix it with model-typed callbacks in one list. Before, TypeScript refused it there, and
1263
+ the way around it was a structural parameter type such as `Pick<PipelineContext, "family" | "transport">`, which you no
1264
+ longer need (it keeps working). A callback typed for a different model is still refused.
1265
+ - a973e89: An issue your own code throws now reaches the caller with the message you wrote. When a pipe, guard, hook, interceptor,
1266
+ filter or computed behavior throws `new FrameworkError("A2004", { message, issues: [{ path, code, message }] })`, each
1267
+ issue's `message` is sent as written instead of the generic text for its code — standalone, inside a transaction plan,
1268
+ and over HTTP. The message must have a visible character and be at most 1,000 characters; otherwise the caller receives
1269
+ the generic text for the code and your message goes to the `diagnostics` sink. The rest is unchanged: an issue whose
1270
+ `code` is not a validation code (`V1000` and up) is dropped, a `path` that does not name a member of the request's own
1271
+ arguments is dropped, an `A3xxx` outcome still carries no issues, and an issue an Adapter throws still carries the
1272
+ generic text for its code.
1273
+ - 1e65e9a: `framework.execute(request)` and `framework.executeTransaction(request)` now check the request object itself before
1274
+ running it. A wrong one — not an object, a missing or empty `requestId`, an `origin` other than `"application"` or
1275
+ `"client"`, a client request without a `protocol` of `{ version, hash }`, malformed `transport`, `protocol` or
1276
+ `transport` on an application request, or a missing or non-string `resource`, `family` or `variant` — is answered
1277
+ `A2004` with one issue per wrong member at its own path (`["requestId"]`, `["protocol", "hash"]`, …), and nothing
1278
+ runs: no guard, pipe or hook, no adapter call. Before, most of these answered `A3000` (an internal error) or ran as
1279
+ though the request were well formed. A well-formed request is unchanged, including `A2005`/`A2006` for a stale
1280
+ `protocol` and `A2001` for an unknown Resource.
1281
+ - a973e89: A write that sets an optional relation both ways — its reference field and the relation itself, such as `categoryId`
1282
+ and `category: { $connect: … }` in the same record — is now refused before it reaches the database, exactly like a
1283
+ required relation: `A2004` with a `V1012` issue at the relation, message `Set "categoryId" or "category", not both.`
1284
+ Before, the database refused it and the caller received `A3001`. It applies to `create`, `update` and `upsert`, to
1285
+ nested writes at any depth, and to each step of a transaction.
1286
+
1287
+ The discovery artifact now records, for each relation, the fields that hold its reference (`references` on each edge
1288
+ of `referentialActions`), and a create requirement no longer repeats them. Regenerate your artifact with
1289
+ `npm run aventara:prepare` (or `aventara-prisma7-generate`); an artifact from an earlier version is refused with a
1290
+ message that says so. An adapter's `referentialActions` edges carry the same `references` member.
1291
+
1292
+ - a973e89: With the Prisma adapter, a record that writes one relation through its reference field and another relation directly —
1293
+ such as `authorId` beside `category: { $connect: … }` — is now refused before it reaches the database: `A2004` with a
1294
+ `V1012` issue at the relation write, message
1295
+ `Use relation fields only, or reference fields only, in one record: "authorId" is a reference field and "category" is a relation.`
1296
+ Before, Prisma refused it and the caller received `A3001`. Write the record's relations all as relations
1297
+ (`author: { $connect: … }, category: { $connect: … }`) or all through their fields (`authorId`, `categoryId`). A
1298
+ reference field beside a relation that holds no reference on that side — `mentorId` beside `posts: { $create: … }` on
1299
+ an author — is unchanged and still accepted. It applies to `create`, `update` and `upsert`, to nested writes at any
1300
+ depth, and to each step of a transaction.
1301
+
1302
+ The limit is part of the Contract: a Contract whose data source has it carries `referenceWrites: "uniform"`, so the
1303
+ Contract hash of every Prisma-backed application changes. Regenerate your discovery artifact
1304
+ (`npm run aventara:prepare`) and your generated client (`avclient generate`). An adapter states the limit with
1305
+ `referenceWrites: "uniform"` in its model; without it, nothing changes.
1306
+
1307
+ - 1e65e9a: A write that sets a required relation both ways — its reference field and the relation itself, such as `authorId` and
1308
+ `author: { $connect: … }` in the same `data` — is now refused before it reaches the database: `A2004` with a `V1012`
1309
+ issue at the relation (`["arguments", "data", "author"]`), message `Set "authorId" or "author", not both.` It applies to
1310
+ `create`, `update` and `upsert`, to nested writes at any depth, and to each step of a transaction, and nothing is
1311
+ written. Before, the database refused it and the caller received `A3001`. Writing either one alone is unchanged.
1312
+ - 1e65e9a: A guard, pipe, hook, interceptor or filter typed for any Resource — `Guard`, `Pipe`, `BeforeHook` and the rest without a
1313
+ model argument, or a callback whose context is a `Pick<PipelineContext, …>` — in the root `pipelines` no longer erases
1314
+ `framework.application`, `framework.client`, `framework.appTx` and `framework.clientTx` to an untyped object. They stay
1315
+ typed from your adapter's model with any mix of stage types, at the root and in the `application` and `client`
1316
+ overlays, with or without `as const`, and a callback written inline is still told your Resource names.
1317
+ - 24ffbab: **Behaviour changes, transactions:** an object carrying `$ref` in a step's `args` is now copied when you call
1318
+ `framework.executeTransaction`, like the rest of your arguments. Where a `$ref` belongs (a field value, a filter
1319
+ value, a `$connect` key) it is answered exactly as before; changing it after the call no longer affects the plan.
1320
+ Placed anywhere else — the whole `where`, a whole relation value, the whole `data` — a member of it that cannot be
1321
+ read (a getter that throws, a revoked Proxy) is now your request's error, `A2004` with one `V1001` at that member's
1322
+ path and `cause.operation`, reported to `misuse`; before, it was `A3000`. The framework never runs a getter inside an
1323
+ object that carries `$ref`, wherever it stands, so such a getter is refused unread.
1324
+
1325
+ A value whose first read throws is now refused even if reading it again would succeed: `A2004`/`V1001` at the object
1326
+ or array whose read failed. Before, it was copied from the second read.
1327
+
1328
+ - 2d00ad7: An issue your own code throws from a transaction step now keeps its `path`. A pipe, guard, hook, interceptor,
1329
+ filter or computed behavior does not know where its operation stands in a plan, so it writes the path as it would for
1330
+ a single call — `["arguments", "data", "name"]`. Inside `framework.transaction`, `framework.executeTransaction` and
1331
+ `POST /_transactions` that path is now checked against that step's own arguments and sent as
1332
+ `["operations", i, "args", "data", "name"]` beside `cause.operation`; before, it was dropped and the issue reached the
1333
+ caller without a path. A path written as `["operations", i, "args", …]` with the step's own index is accepted as
1334
+ before, and a path that does not name a member of the step's arguments is still dropped.
1335
+ - 384a50c: **Behaviour changes, transactions:** every issue about a transaction step's arguments now names where it is
1336
+ in the plan, `["operations", i, "args", …]`, beside `cause.operation: i`. Before, the framework's own checks — a wrong
1337
+ type, an unknown field or operator, a structural limit, a Json value out of its `AvZ` shape, a value that is not valid
1338
+ JSON — answered `["arguments", …]` inside a plan while a bad `$ref`, a refused value and a step that depends on a
1339
+ cascaded delete already answered `["operations", i, "args", …]`; now one plan uses one spelling, through
1340
+ `framework.transaction`, `framework.executeTransaction` and `POST /_transactions` alike. A single call is unchanged
1341
+ (`["arguments", …]`). If your code reads `issue.path` from a transaction's answer, drop the `"operations", i, "args"`
1342
+ prefix to get the path inside that step's arguments. `@aventara/testing`'s protocol corpus row "a client-hidden
1343
+ field — /_transactions" and `fixtures/protocol-v1.json` carry the new path.
1344
+ - d43d1cc: **Types:** `diagnostic.deliberate` now type-checks on any `FrameworkDiagnostic`, without checking
1345
+ `diagnostic.kind` first, so a `diagnostics` sink can log it for every report. It is `true` only on an `"operation"`
1346
+ diagnostic for a `FrameworkError` you threw on purpose with an `A3xxx` code, and always absent on a `"transaction"`
1347
+ diagnostic, which reports the transaction's own failure (`A3002`). Before, reading it on the union was a TypeScript
1348
+ error (`TS2339`).
1349
+ - 3f98749: **Types:** `framework.application`, `framework.client`, `framework.appTx` and `framework.clientTx` now follow
1350
+ your `restrictions` the way the generated client does. A field whose capability you turn off — `select`, `filter`,
1351
+ `order`, `create` or `update` — is refused in that position and left out of the result types; an operation you turn
1352
+ off (`operations: { delete: { unique: false } }`) is not on the façade; and a unique operation disappears when its
1353
+ only identifier is hidden. Each façade reads its own layer: `framework.client` the root restrictions with
1354
+ `client.restrictions` over them, `framework.application` the root restrictions with `application.restrictions` over
1355
+ them — so `hidden` now applies to `framework.application` too. Before, only `client`'s `hidden` was reflected, so with
1356
+ `passwordHash: { capabilities: { select: false, … } }` a call such as
1357
+ `framework.client.User.find.many({ select: ["passwordHash"] })` compiled and every result type carried `passwordHash`.
1358
+ Nothing changes at runtime: the server refused those calls before and still does. A restriction value typed as a plain
1359
+ `boolean` rather than `true`/`false` still leaves the field as it was.
1360
+ - 032f792: **Behaviour changes, transactions:** an error about a transaction step itself — rather than its arguments — now
1361
+ names the step too, so every path in a transaction's answer is a path through the request you sent: an unknown or
1362
+ hidden Resource is at `["operations", i, "resource"]`, a fingerprint that does not match at
1363
+ `["operations", i, "fingerprint"]`, a missing or unknown key on the step at `["operations", i, "<key>"]`, and a step
1364
+ that is not an object at `["operations", i]`. An operation the step cannot run points at the key that is wrong:
1365
+ `["operations", i, "family"]` when the family is not a string, not a standard family, or one the Resource offers no
1366
+ variant of; `["operations", i, "variant"]` when the family is right and the variant is not (unknown, not offered or
1367
+ restricted for it). Before, these answered `["resource"]`, `["operation"]`, `["fingerprint"]` and `["<key>"]`.
1368
+ `cause.operation` and the outcome code are unchanged: an unknown Resource is still `A2001`, an unavailable operation
1369
+ `A2002`. `framework.transaction([...])` refuses an entry that is not a handle, or one handle placed twice, at
1370
+ `["operations", i]`. A single call is unchanged. `@aventara/testing`'s protocol corpus and `fixtures/protocol-v1.json`
1371
+ carry the new paths.
1372
+ - dbe6961: **Behaviour changes:** a single call to an operation a Resource does not offer now names the key of the
1373
+ request that is wrong instead of `["operation"]`, which no request has: `["family"]` when the family is not a standard
1374
+ one or the Resource offers none of its operations, `["variant"]` when the family is right and the variant is not. This
1375
+ holds for `framework.execute` and for an HTTP route, whose `/_resources/:resource/:family/:variant` segments are named
1376
+ by those same keys. The code is unchanged (`A2002` / `V1006`), and so is `["resource"]` for an unknown Resource.
1377
+ `@aventara/testing`'s protocol corpus and `fixtures/protocol-v1.json` carry the new paths.
1378
+
1379
+ ## 0.1.0-pilot.4
1380
+
1381
+ ### Patch Changes
1382
+
1383
+ - f37dcd6: The documentation shipped with the package — the comments an editor shows on hover, and the README — now describes
1384
+ what each export does, how to use it, what it returns and what it throws. Notes about how the package was built and
1385
+ why are no longer part of what is published.
1386
+
1387
+ The declarations a generated client copies from `@aventara/core` carry the same documentation.
1388
+
1389
+ ## 0.1.0-pilot.3
1390
+
1391
+ ## 0.1.0-pilot.2
1392
+
1393
+ ### Patch Changes
1394
+
1395
+ - c2a3b7c: A `bigint` value outside the signed 64-bit range is refused as `A2004` with a `V1004` issue at its path, from the wire
1396
+ and from the application alike, before any pipeline or adapter runs. Before this release it reached the database and
1397
+ answered `A3001`.
1398
+ - e69e88d: The published packages are written for the people who use them. The JavaScript ships without comments; the type
1399
+ declarations keep their documentation, and it, the error messages, the protocol fixtures' labels and the comments in a
1400
+ generated client no longer carry the project's internal development notes.
1401
+ - ab58424: A pipe's output is checked against the server's own rules before it reaches the adapter. The request is validated
1402
+ against the caller's Contract; after each pipe, the arguments are validated against the Core Contract (plus fields the
1403
+ caller's scope adds), so a pipe may still write what the caller cannot — a field the client Contract hides, such as a
1404
+ password hash — but not what the server cannot store. A refusal is the new internal code `A3004 PIPE_OUTPUT_INVALID` (HTTP
1405
+ 500). The caller receives only the generic `A server pipeline produced invalid arguments.`, like every internal
1406
+ failure; the pipe (`pipes[i]` and its function name), the operation, the offending field and its V-code go to the
1407
+ diagnostics sink as a `PipeOutputError`, and `@aventara/nest` writes them into its error log line. Nothing reaches the
1408
+ adapter. This holds for operations and transaction steps alike (a plan answers with `cause.operation`). Generated
1409
+ clients map `A3004` to `InternalError`; the protocol fixtures in `@aventara/testing` include an `A3004` row.
1410
+ - 23937f8: A create that lacks a value the database requires is refused as `A2004` with a `V1000` issue at the value's path,
1411
+ instead of reaching the database and answering `A3001`. It covers `create.one`, every row of `create.many`, `upsert`'s
1412
+ `create` branch, nested `$create` (and `$connectOrCreate`/`$upsert` creates) at any depth, and transaction steps
1413
+ (`["operations", i, "args", …]`). A required relation is satisfied by writing it or every scalar that holds its
1414
+ reference; a nested create never needs the relation it is created through. Defaults, `@updatedAt`, autoincrement,
1415
+ optional and list columns are never required. The check runs after pipes and computed behaviours, so a value they
1416
+ supply counts.
1417
+
1418
+ An adapter states the requirements through the new optional `Adapter.createRequirements`; the Prisma 7 adapter reads
1419
+ them from the generated client's create inputs at generate time and records them in the discovery artifact, so the
1420
+ artifact must be regenerated (`aventara:prepare`).
1421
+
1422
+ ## 0.1.0-pilot.1
1423
+
1424
+ ### Patch Changes
1425
+
1426
+ - a45f8a8: The `400 A2000` for a request without its identity headers now says which one: `cause.message` is "The
1427
+ Aventara-Contract-Hash header is missing." (or "The Aventara-Protocol-Version header is missing.", or both, naming both),
1428
+ instead of the generic "The request is malformed and cannot be interpreted." It names headers only and echoes no value.
1429
+ The code, status and every other `A2000` are unchanged. The protocol fixtures in `@aventara/testing` check the new messages, with a row
1430
+ for a request with neither header.
1431
+ - 799346e: The package READMEs (each package's npm page) are rewritten for the people who use the packages. The Prisma 7
1432
+ adapter's README now states the actual behaviour of a to-many relation or `$count` projected on
1433
+ `update.many`/`create.many`: a validation refusal, `A2004` with `V1008`, before any statement runs (it said `A3001`).
1434
+ Every install or run command names the `@pilot` dist-tag.
1435
+
1436
+ ## 0.1.0-pilot.0
1437
+
1438
+ ### Minor Changes
1439
+
1440
+ - First pilot release of `@aventara/core`: the framework itself — configuration, Contracts, validation, operations,
1441
+ pipelines and transactions — independent of any HTTP server or ORM.
1442
+
1443
+ - **`createFramework(config)`** builds a Framework from an adapter and a configuration. The configuration is typed
1444
+ against the adapter's model, so restriction keys, behaviors, `dependsOn` and pipeline `resource` guards are checked
1445
+ against the Resources and fields that exist; `defineFields` declares the fields a configuration adds so the rest of
1446
+ it can name them.
1447
+ - **Contracts.** The adapter's capabilities and your configuration compile into the Core, Application and Client
1448
+ Contracts at startup. The ClientContract is what clients are generated from, and its hash identifies it. A scoped
1449
+ configuration (`application`, `client`) only narrows what the root allows, and a configuration asking for a
1450
+ capability the root or the adapter does not offer fails at startup with `COMPILER_UNAVAILABLE_CAPABILITY` at its
1451
+ path. A value the Contract cannot represent, or an invalid ClientContract (`COMPILER_INVALID_CLIENT_CONTRACT`), also
1452
+ fails at startup.
1453
+ - **Capabilities by argument position.** A relation the database projects or writes only in some operations is
1454
+ advertised only there; asking for it elsewhere is refused with `A2004` (`V1008` for a projection, `V1006` for a
1455
+ write) before any query, and is a type error.
1456
+ - **Typed calls.** `framework.application.<resource>.<family>.<variant>(args)` and `framework.client.…` take arguments
1457
+ and return results typed from the Contract (`OperationResultFor`); an optional second argument, `ExecutionOptions`
1458
+ (`{ requestId }`), sets the request id every pipeline context, adapter call and diagnostic of the call carries.
1459
+ - **Transactions.** `framework.appTx` and `framework.clientTx` build typed plans whose steps can use earlier steps'
1460
+ results through `$ref`; `framework.transaction(steps, options)` runs them. A step that depends on rows an earlier
1461
+ step's cascading delete removed is refused before the plan runs (`A2004`/`V1019`).
1462
+ - **Fields and pipelines.** Computed and virtual fields under `application.fields` and `client.fields`; guards, pipes,
1463
+ before and after hooks, interceptors and filters.
1464
+ - **Scalars.** `Decimal` (string-backed; `toJSON()` writes its digits; a non-string argument throws a `TypeError`),
1465
+ `JsonValue`, and the `ApplicationScalarForms` / `WireScalarForms` maps. A `Date`, `Decimal` or `Uint8Array` at a
1466
+ filter position is shorthand for equality.
1467
+ - **`@aventara/core/protocol`**, a second entry point: the HTTP protocol as data and pure functions a host mounts —
1468
+ `AvProtocol.headers`, `httpStatus`, `scalarFormats`, `normalizeEntrypoint` and `isOperationResponse`, and
1469
+ `AvProtocol.bind(framework)` with `surface()` (the routes to mount), `handleOperation`, `handleTransaction`,
1470
+ `encodeContract` (`GET /_contract`, with `ETag` and `304`), `answerAbsent`, `failure`, and the decoders and encoders
1471
+ under them. A request without an identity header answers `400 A2000`, a wrong protocol version `A2006`, a stale
1472
+ contract hash `A2005`; a body larger than `limits.maxRequestBytes` `413 A2010`, a content type other than
1473
+ `application/json` `415 A2011`; every `405 A2012` carries `Allow`. A malformed request never throws: it answers
1474
+ `400 A2000`.
1475
+ - **The entrypoint** is normalized once: `"api"`, `"/api/"` and `"//api//"` become `"/api"`, `"/"` becomes `""`, and an
1476
+ entrypoint that is not a plain path (whitespace, a scheme, a query, a `..` segment, a `%` and the like) fails at
1477
+ startup with `CONFIG_INVALID_VALUE`.
1478
+ - Every export has a `default` condition, so a CommonJS project can `require()` the package.