@aventara/core 0.1.0-pilot.1 → 0.1.0-pilot.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/adapters/adapter-field.d.ts +4 -4
  2. package/dist/adapters/adapter-resource.d.ts +10 -12
  3. package/dist/adapters/adapter.interface.d.ts +20 -10
  4. package/dist/compiler/contract-compiler-diagnostic.d.ts +3 -4
  5. package/dist/compiler/contract.compiler.d.ts +5 -4
  6. package/dist/compiler/contract.compiler.js +0 -132
  7. package/dist/config/config.resolver.d.ts +2 -2
  8. package/dist/config/config.resolver.js +0 -5
  9. package/dist/config/config.validator.d.ts +3 -3
  10. package/dist/config/config.validator.js +0 -8
  11. package/dist/config/define-fields.d.ts +2 -7
  12. package/dist/config/define-fields.js +0 -15
  13. package/dist/config/effective-fields.d.ts +4 -8
  14. package/dist/config/entrypoint.normalizer.d.ts +7 -7
  15. package/dist/config/entrypoint.normalizer.js +0 -22
  16. package/dist/config/framework-behaviors-config.d.ts +6 -6
  17. package/dist/config/framework-config.d.ts +3 -5
  18. package/dist/config/framework-restrictions-config.d.ts +19 -29
  19. package/dist/config/pipeline-config.d.ts +8 -18
  20. package/dist/contracts/capability.d.ts +18 -21
  21. package/dist/contracts/capability.js +0 -75
  22. package/dist/contracts/client-contract-structure.validator.d.ts +15 -22
  23. package/dist/contracts/client-contract-structure.validator.js +0 -27
  24. package/dist/contracts/contract-canonicalizer.js +0 -96
  25. package/dist/contracts/contract-hash.js +0 -2
  26. package/dist/contracts/contract-limits.js +0 -1
  27. package/dist/contracts/contract-lookup.js +0 -10
  28. package/dist/contracts/contract-protocol.js +0 -10
  29. package/dist/contracts/field.d.ts +23 -26
  30. package/dist/contracts/field.js +0 -107
  31. package/dist/contracts/lifecycle-trait.js +0 -5
  32. package/dist/contracts/resource-operations.d.ts +17 -18
  33. package/dist/contracts/resource-operations.js +0 -63
  34. package/dist/contracts/scalar-value-type.d.ts +12 -22
  35. package/dist/contracts/scalar.js +0 -1
  36. package/dist/contracts/wire-scalar-format.d.ts +20 -20
  37. package/dist/contracts/wire-scalar-format.js +0 -26
  38. package/dist/framework/contract-view.d.ts +7 -8
  39. package/dist/framework/framework-construction.error.js +0 -1
  40. package/dist/framework/framework.d.ts +26 -27
  41. package/dist/framework/framework.factory.js +0 -49
  42. package/dist/framework/operation-facade.js +0 -17
  43. package/dist/operations/operation-arguments.d.ts +36 -46
  44. package/dist/operations/operation-boolean-nodes.js +0 -16
  45. package/dist/operations/operation-call.d.ts +4 -9
  46. package/dist/operations/operation-identity.js +0 -1
  47. package/dist/operations/operation-nesting.js +0 -5
  48. package/dist/operations/operation-result.d.ts +4 -4
  49. package/dist/operations/operation-validator-core.d.ts +2 -2
  50. package/dist/operations/operation-validator-core.js +6 -71
  51. package/dist/operations/operation-validator.d.ts +4 -4
  52. package/dist/operations/operation-validator.js +0 -12
  53. package/dist/operations/projection-scope.resolver.d.ts +8 -10
  54. package/dist/operations/projection-scope.resolver.js +0 -35
  55. package/dist/operations/validation-code.d.ts +11 -18
  56. package/dist/operations/validation-code.js +0 -24
  57. package/dist/operations/write-scope.resolver.d.ts +4 -7
  58. package/dist/operations/write-scope.resolver.js +0 -37
  59. package/dist/protocol/absent-route.responder.d.ts +33 -48
  60. package/dist/protocol/absent-route.responder.js +0 -55
  61. package/dist/protocol/av-protocol.d.ts +6 -6
  62. package/dist/protocol/av-protocol.js +0 -10
  63. package/dist/protocol/contract-document.responder.d.ts +15 -18
  64. package/dist/protocol/contract-document.responder.js +0 -33
  65. package/dist/protocol/http-request.decoder.d.ts +55 -61
  66. package/dist/protocol/http-request.decoder.js +0 -62
  67. package/dist/protocol/http-request.reader.d.ts +12 -13
  68. package/dist/protocol/http-request.reader.js +0 -45
  69. package/dist/protocol/http-response.encoder.d.ts +17 -18
  70. package/dist/protocol/http-response.encoder.js +0 -59
  71. package/dist/protocol/http-status.table.d.ts +7 -11
  72. package/dist/protocol/http-status.table.js +1 -15
  73. package/dist/protocol/index.d.ts +5 -5
  74. package/dist/protocol/index.js +0 -9
  75. package/dist/protocol/operation-response.guard.d.ts +12 -19
  76. package/dist/protocol/operation-response.guard.js +0 -29
  77. package/dist/protocol/protocol-failure.d.ts +21 -26
  78. package/dist/protocol/protocol-failure.js +0 -12
  79. package/dist/protocol/protocol-headers.d.ts +25 -30
  80. package/dist/protocol/protocol-headers.js +0 -66
  81. package/dist/protocol/protocol-surface.d.ts +25 -29
  82. package/dist/protocol/protocol-surface.js +0 -19
  83. package/dist/protocol/protocol.binder.d.ts +58 -71
  84. package/dist/protocol/protocol.binder.js +0 -8
  85. package/dist/protocol/protocol.handler.d.ts +28 -32
  86. package/dist/protocol/protocol.handler.js +0 -43
  87. package/dist/runtime/computed-read-runtime.js +0 -29
  88. package/dist/runtime/create-requirement.d.ts +65 -0
  89. package/dist/runtime/create-requirement.js +141 -0
  90. package/dist/runtime/decimal.d.ts +2 -2
  91. package/dist/runtime/decimal.js +0 -8
  92. package/dist/runtime/diagnostics-reporter.d.ts +6 -6
  93. package/dist/runtime/diagnostics-reporter.js +0 -35
  94. package/dist/runtime/error-boundary.d.ts +3 -3
  95. package/dist/runtime/error-boundary.js +2 -167
  96. package/dist/runtime/execution-options.d.ts +4 -4
  97. package/dist/runtime/field-behavior.d.ts +6 -9
  98. package/dist/runtime/framework-error.js +0 -4
  99. package/dist/runtime/mutation-planner.d.ts +5 -6
  100. package/dist/runtime/mutation-planner.js +0 -23
  101. package/dist/runtime/operation-response.d.ts +1 -1
  102. package/dist/runtime/operation-response.js +1 -17
  103. package/dist/runtime/operation-runtime.d.ts +24 -22
  104. package/dist/runtime/operation-runtime.js +18 -52
  105. package/dist/runtime/outcome-mapper.js +0 -22
  106. package/dist/runtime/output-validator.js +0 -1
  107. package/dist/runtime/pipe-output.validator.d.ts +48 -0
  108. package/dist/runtime/pipe-output.validator.js +79 -0
  109. package/dist/runtime/pipeline.d.ts +20 -26
  110. package/dist/runtime/referential-action.d.ts +14 -19
  111. package/dist/runtime/referential-action.js +0 -23
  112. package/dist/runtime/request-id.js +0 -21
  113. package/dist/runtime/scalar-runtime.d.ts +14 -16
  114. package/dist/runtime/scalar-runtime.js +12 -57
  115. package/dist/transactions/deferred-operation.d.ts +9 -14
  116. package/dist/transactions/operation-arguments-encoder.d.ts +0 -1
  117. package/dist/transactions/operation-arguments-encoder.js +0 -14
  118. package/dist/transactions/operation-fingerprint.js +0 -1
  119. package/dist/transactions/transaction-envelope.js +0 -14
  120. package/dist/transactions/transaction-integrity-error.d.ts +10 -11
  121. package/dist/transactions/transaction-integrity-error.js +0 -5
  122. package/dist/transactions/transaction-plan-assembler.d.ts +0 -1
  123. package/dist/transactions/transaction-plan-assembler.js +0 -35
  124. package/dist/transactions/transaction-plan-validator.d.ts +5 -5
  125. package/dist/transactions/transaction-plan-validator.js +0 -63
  126. package/dist/transactions/transaction-reference-resolver.d.ts +12 -13
  127. package/dist/transactions/transaction-reference-resolver.js +0 -16
  128. package/dist/transactions/transaction-reference-validator.js +0 -8
  129. package/dist/transactions/transaction-reference.d.ts +19 -43
  130. package/dist/transactions/transaction-reference.js +0 -11
  131. package/dist/transactions/transaction-request.d.ts +4 -5
  132. package/dist/transactions/transaction-response.d.ts +1 -1
  133. package/dist/transactions/transaction-runtime.d.ts +2 -3
  134. package/dist/transactions/transaction-runtime.js +5 -44
  135. package/dist/transactions/transaction-slot-path-error.d.ts +10 -11
  136. package/dist/transactions/transaction-slot-path-error.js +0 -7
  137. package/dist/transactions/transaction-slot-writer.d.ts +12 -12
  138. package/dist/transactions/transaction-slot-writer.js +0 -34
  139. package/package.json +2 -2
@@ -6,38 +6,32 @@ import { type AvProtocolResponse } from "./http-response.encoder.js";
6
6
  import { transportFailure } from "./protocol-failure.js";
7
7
  import { type SurfaceRoute } from "./protocol-surface.js";
8
8
  /**
9
- * The protocol bound to ONE Framework instance — what `AvProtocol.bind`
10
- * returns (§5.9; the type's name ruled 2026-10-05). A host binds once, at
11
- * startup, and calls these members per request; none takes a Contract, an
12
- * entrypoint or a limit, because the binding already read them.
13
- *
14
- * Grows one member per slice (§7); the exact set is pinned in
15
- * `index.test-d.ts`.
9
+ * The protocol bound to ONE Framework instance — what `AvProtocol.bind` returns. A
10
+ * host binds once, at startup, and calls these members per request; none takes a
11
+ * Contract, an entrypoint or a limit, because the binding already read them.
16
12
  */
17
13
  export type AvProtocolBinding = {
18
14
  /**
19
- * Every route a host mounts for the bound ClientContract, from one list,
20
- * each tagged by `kind` (ADR 0007 DA-13; the architect's ruling,
21
- * 2026-10-05): one `POST` `operation` route per `(resource, family,
22
- * variant)` it advertises — nothing it does not — then the `contract` route
23
- * `GET /_contract` (always), then the `transactions` route
24
- * `POST /_transactions` exactly when its `transactions` is `"interactive"`.
25
- * Each path is relative to `framework.entrypoint`. Read once at bind time:
26
- * every call answers the same deep-frozen list, which is passive data a
27
- * host may serialize.
15
+ * Every route a host mounts for the bound ClientContract, from one list, each
16
+ * tagged by `kind`: one `POST` `operation` route per `(resource, family, variant)`
17
+ * it advertises — nothing it does not — then the `contract` route `GET /_contract`
18
+ * (always), then the `transactions` route `POST /_transactions` exactly when its
19
+ * `transactions` is `"interactive"`. Each path is relative to
20
+ * `framework.entrypoint`. Read once at bind time: every call answers the same
21
+ * deep-frozen list, which is passive data a host may serialize.
28
22
  *
29
- * A host that mounts one route per entry still needs a fallback for the
30
- * paths it did not mount: that is the absence responder's, not a catch-all
31
- * into framework handling.
23
+ * A host that mounts one route per entry still needs a fallback for the paths it
24
+ * did not mount: that is the absence responder's, not a catch-all into framework
25
+ * handling.
32
26
  */
33
27
  readonly surface: () => readonly SurfaceRoute[];
34
28
  /**
35
29
  * An operation route's HTTP request → the client-origin request
36
- * `framework.execute` takes, or the framework response that answers it
37
- * instead, with the request id either way (Q13). Answers absence for an
38
- * unadvertised triple without executing it (Q12), so a catch-all host is
39
- * safe. Raw body: size, content type, JSON and shape enforced; parsed body:
40
- * shape only — the rest was the host's parser's (Q11).
30
+ * `framework.execute` takes, or the framework response that answers it instead,
31
+ * with the request id either way. Answers absence for an unadvertised triple
32
+ * without executing it, so a catch-all host is safe. Raw body: size, content type,
33
+ * JSON and shape enforced; parsed body: shape only — the rest was the host's
34
+ * parser's.
41
35
  */
42
36
  readonly decodeOperation: (request: AvProtocolRequest) => DecodedOperation;
43
37
  /**
@@ -47,77 +41,70 @@ export type AvProtocolBinding = {
47
41
  */
48
42
  readonly decodeTransaction: (request: AvProtocolRequest) => DecodedTransaction;
49
43
  /**
50
- * One operation's framework response — what `framework.execute` answered —
51
- * as the HTTP response a host writes: the code's status (§13.2), `data` in
52
- * wire forms (P1), `Aventara-Request-Id` echoed (Q13). A result with no wire
53
- * form answers `A3003` → 500. A diagnostic of one operation names it
54
- * (`resource`, `family`, `variant`), so the `A3003` reaches the diagnostics
55
- * sink only when the host passes `decoded` — `decodeOperation`'s success
56
- * value — as `handleOperation` does (the architect, 2026-10-05); without
57
- * it the answer is the same and nothing is reported.
44
+ * One operation's framework response — what `framework.execute` answered — as the
45
+ * HTTP response a host writes: the code's status, `data` in wire forms,
46
+ * `Aventara-Request-Id` echoed. A result with no wire form answers `A3003` → 500.
47
+ * A diagnostic of one operation names it (`resource`, `family`, `variant`), so the
48
+ * `A3003` reaches the diagnostics sink only when the host passes `decoded` —
49
+ * `decodeOperation`'s success value — as `handleOperation` does; without it the
50
+ * answer is the same and nothing is reported.
58
51
  */
59
52
  readonly encodeOperation: (response: OperationResponse, requestId: string, decoded?: DecodedOperationRequest) => AvProtocolResponse;
60
53
  /**
61
- * The same for `/_transactions` — what `framework.executeTransaction`
62
- * answered. A second encoder by the architect's choice (§5.9); both share
63
- * the one status table and the one wire walker. An `A3003` is reported to
64
- * the Framework's diagnostics sink as a `"transaction"` diagnostic — client
65
- * scope, this `requestId`, the step it blames as `operation` — with the
66
- * value that had no wire form (or what its getter threw) as `error`.
54
+ * The same for `/_transactions` — what `framework.executeTransaction` answered. An
55
+ * `A3003` is reported to the Framework's diagnostics sink as a `"transaction"`
56
+ * diagnostic — client scope, this `requestId`, the step it blames as `operation` —
57
+ * with the value that had no wire form (or what its getter threw) as `error`.
67
58
  */
68
59
  readonly encodeTransaction: (response: TransactionResponse, requestId: string) => AvProtocolResponse;
69
60
  /**
70
61
  * A transport code — `A2000`, `A2010`, `A2011` or `A2012` — as the complete
71
- * framework response, with framework-authored text (ruled 2026-10-05). For a
72
- * host that parses the body itself and must answer its parser's failure.
73
- * `A2012` requires the methods its route allows, so every 405 carries
74
- * `Allow` (the director, 2026-10-05).
62
+ * framework response, with framework-authored text (ruled 2026-10-05). For a host
63
+ * that parses the body itself and must answer its parser's failure. `A2012`
64
+ * requires the methods its route allows, so every 405 carries `Allow`.
75
65
  */
76
66
  readonly failure: typeof transportFailure;
77
67
  /**
78
- * The shortcut (R2): `decodeOperation` → `framework.execute` →
79
- * `encodeOperation`, resolving the response the host writes for an
80
- * operation route. A decode failure is answered without executing; an
81
- * `A3003` is reported to the diagnostics sink with the operation's
82
- * identity and request id. Total over any value an untyped host hands it:
83
- * one that is not an `AvProtocolRequest` answers `400 A2000`; it never
84
- * rejects.
68
+ * The shortcut: `decodeOperation` → `framework.execute` → `encodeOperation`,
69
+ * resolving the response the host writes for an operation route. A decode failure
70
+ * is answered without executing; an `A3003` is reported to the diagnostics sink
71
+ * with the operation's identity and request id. Total over any value an untyped
72
+ * host hands it: one that is not an `AvProtocolRequest` answers `400 A2000`; it
73
+ * never rejects.
85
74
  */
86
75
  readonly handleOperation: (request: AvProtocolRequest) => Promise<AvProtocolResponse>;
87
76
  /**
88
77
  * The same for `/_transactions`: `decodeTransaction` →
89
- * `framework.executeTransaction` → `encodeTransaction`. Every step runs
90
- * under ClientContract rules (R1); a committed plan is `200 A1009`, a
91
- * rolled-back one its failing step's own status.
78
+ * `framework.executeTransaction` → `encodeTransaction`. Every step runs under
79
+ * ClientContract rules; a committed plan is `200 A1009`, a rolled-back one its
80
+ * failing step's own status.
92
81
  */
93
82
  readonly handleTransaction: (request: AvProtocolRequest) => Promise<AvProtocolResponse>;
94
83
  /**
95
- * The `GET /_contract` responder (Q8): the bound ClientContract's
96
- * JCS-canonical bytes, `ETag` its quoted hash, `Cache-Control: no-cache`,
97
- * and `304` with no body when `If-None-Match` matches (weak comparison, a
98
- * list, `*`). Requires no identity header; any other method is `405
99
- * A2012` with `Allow: GET`. The bytes are written once, at bind time.
84
+ * The `GET /_contract` responder: the bound ClientContract's JCS-canonical bytes,
85
+ * `ETag` its quoted hash, `Cache-Control: no-cache`, and `304` with no body when
86
+ * `If-None-Match` matches (weak comparison, a list, `*`). Requires no identity
87
+ * header; any other method is `405 A2012` with `Allow: GET`. The bytes are written
88
+ * once, at bind time.
100
89
  */
101
90
  readonly encodeContract: (request: AvProtocolRequest) => AvProtocolResponse;
102
91
  /**
103
- * The absence responder (Q2's O3): the fallback a host mounts for every
104
- * path it did not mount from `surface()` — never a catch-all into framework
105
- * handling (it reads no body, runs no pipeline, calls no Adapter). Answers
106
- * what the catch-all decoder answers before a body — `A2000`, `A2006`,
107
- * `A2005`, `A2001`, `A2002`, `A2012` with `Allow` — byte for byte; a route
108
- * that exists reached with its own method as `500 A3000` (a host that
109
- * mounted only part of the surface); and `undefined` for a path outside the
110
- * protocol's namespace, which the host answers itself (the architect,
111
- * 2026-10-05).
92
+ * The absence responder: the fallback a host mounts for every path it did not
93
+ * mount from `surface()` — never a catch-all into framework handling (it reads no
94
+ * body, runs no pipeline, calls no Adapter). Answers what the catch-all decoder
95
+ * answers before a body — `A2000`, `A2006`, `A2005`, `A2001`, `A2002`, `A2012`
96
+ * with `Allow` — byte for byte; a route that exists reached with its own method as
97
+ * `500 A3000` (a host that mounted only part of the surface); and `undefined` for
98
+ * a path outside the protocol's namespace, which the host answers itself.
112
99
  */
113
100
  readonly answerAbsent: (request: AvProtocolRequest) => AvProtocolResponse | undefined;
114
101
  };
115
102
  /**
116
- * `AvProtocol.bind(framework)`: reads the instance's compiled ClientContract
117
- * once and returns the bound members, frozen.
103
+ * `AvProtocol.bind(framework)`: reads the instance's compiled ClientContract once
104
+ * and returns the bound members, frozen.
118
105
  *
119
- * It validates nothing construction did not: `createFramework` already refused
120
- * a bad entrypoint (R4) and compiled the ClientContract this reads, so binding
121
- * cannot fail.
106
+ * It validates nothing construction did not: `createFramework` already refused a
107
+ * bad entrypoint and compiled the ClientContract this reads, so binding cannot
108
+ * fail.
122
109
  */
123
110
  export declare function bind(framework: Framework): AvProtocolBinding;
@@ -6,14 +6,6 @@ import { encodeOperationResponse, encodeTransactionResponse, } from "./http-resp
6
6
  import { handleOperationRequest, handleTransactionRequest, operationUnencodableReport, planUnencodableReport, } from "./protocol.handler.js";
7
7
  import { transportFailure } from "./protocol-failure.js";
8
8
  import { surfaceOf } from "./protocol-surface.js";
9
- /**
10
- * `AvProtocol.bind(framework)`: reads the instance's compiled ClientContract
11
- * once and returns the bound members, frozen.
12
- *
13
- * It validates nothing construction did not: `createFramework` already refused
14
- * a bad entrypoint (R4) and compiled the ClientContract this reads, so binding
15
- * cannot fail.
16
- */
17
9
  export function bind(framework) {
18
10
  const { contracts } = framework;
19
11
  const surface = surfaceOf(contracts.client);
@@ -16,48 +16,44 @@ export type HandlerContext = {
16
16
  };
17
17
  /**
18
18
  * Where a plan's `A3003` goes: the Framework's diagnostics sink, as a
19
- * `"transaction"` diagnostic — client scope (the protocol has no other
20
- * origin, P4), the request id the plan ran under, and the step the encoder
21
- * blames as `operation` when it blames one. One spelling for both
22
- * `protocol.encodeTransaction` and `protocol.handleTransaction`.
19
+ * `"transaction"` diagnostic — client scope, the request id the plan ran under,
20
+ * and the step the encoder blames as `operation` when it blames one. One spelling
21
+ * for both `protocol.encodeTransaction` and `protocol.handleTransaction`.
23
22
  */
24
23
  export declare function planUnencodableReport(sink: FrameworkDiagnosticsSink | undefined, requestId: string): UnencodableReport;
25
24
  /**
26
25
  * Where one operation's `A3003` goes: the Framework's diagnostics sink, as an
27
- * `"operation"` diagnostic carrying the decoded request's identity and id —
28
- * the shape the public `OperationDiagnostic` already has. One spelling for
29
- * `protocol.handleOperation` and for `protocol.encodeOperation` given the
30
- * decoded request (the architect, 2026-10-05).
26
+ * `"operation"` diagnostic carrying the decoded request's identity and id — the
27
+ * shape the public `OperationDiagnostic` already has. One spelling for
28
+ * `protocol.handleOperation` and for `protocol.encodeOperation` given the decoded
29
+ * request.
31
30
  */
32
31
  export declare function operationUnencodableReport(sink: FrameworkDiagnosticsSink | undefined, request: ClientOperationRequest): UnencodableReport;
33
32
  /**
34
- * `protocol.handleOperation(request)` (§5.9, R2; S8): the three steps a host
35
- * would otherwise spell out — `decodeOperation` → `framework.execute` →
36
- * `encodeOperation` — in one call, resolving the `AvProtocolResponse` the host
37
- * writes. A request the decoder answers itself (a transport failure, an
38
- * identity mismatch, an unadvertised route) is answered without executing.
33
+ * `protocol.handleOperation(request)`: the three steps a host would otherwise
34
+ * spell out — `decodeOperation` → `framework.execute` → `encodeOperation` — in one
35
+ * call, resolving the `AvProtocolResponse` the host writes. A request the decoder
36
+ * answers itself (a transport failure, an identity mismatch, an unadvertised
37
+ * route) is answered without executing.
39
38
  *
40
- * Total over ANY value, never rejecting: the decoder answers every value (one
41
- * that is not an `AvProtocolRequest` as `400 A2000`; the director,
42
- * 2026-10-05), `execute` resolves for every request it is handed, and the
43
- * encoder answers every response — a result with no wire form as `A3003` →
44
- * 500. That `A3003`
45
- * reaches the Framework's diagnostics sink as an `"operation"` diagnostic
46
- * carrying the decoded request's identity and id (the director, 2026-10-05),
47
- * which only this shortcut holds: the bare `encodeOperation` is given the
48
- * response and the request id alone.
39
+ * Total over ANY value, never rejecting: the decoder answers every value,
40
+ * `execute` resolves for every request it is handed, and the encoder answers every
41
+ * response — a result with no wire form as `A3003` →
42
+ * 500. That `A3003` reaches the Framework's diagnostics sink as an `"operation"`
43
+ * diagnostic carrying the decoded request's identity and id, which only this
44
+ * shortcut holds: the bare `encodeOperation` is given the response and the
45
+ * request id alone.
49
46
  */
50
47
  export declare function handleOperationRequest(context: HandlerContext, request: AvProtocolRequest): Promise<AvProtocolResponse>;
51
48
  /**
52
- * `protocol.handleTransaction(request)` (§5.9, R2; S9): the same shortcut for
53
- * `/_transactions` — `decodeTransaction` → `framework.executeTransaction` →
54
- * `encodeTransaction`. The decoded plan is client origin and cannot say
55
- * otherwise, so every step runs under ClientContract rules (R1): a
56
- * client-hidden field, a client-restricted variant or a client-hidden
57
- * Resource is refused as through its single-operation route, plus
58
- * `cause.operation`. A committed plan is `200 A1009` (P3); a rolled-back one
59
- * answers its failing step's code at that code's status (Q4). Total over any
60
- * value, as {@link handleOperationRequest} is; an `A3003` is
61
- * reported through {@link planUnencodableReport}.
49
+ * `protocol.handleTransaction(request)`: the same shortcut for `/_transactions` —
50
+ * `decodeTransaction` → `framework.executeTransaction` → `encodeTransaction`. The
51
+ * decoded plan is client origin and cannot say otherwise, so every step runs under
52
+ * ClientContract rules: a client-hidden field, a client-restricted variant or a
53
+ * client-hidden Resource is refused as through its single-operation route, plus
54
+ * `cause.operation`. A committed plan is `200 A1009`; a rolled-back one answers
55
+ * its failing step's code at that code's status. Total over any value, as {@link
56
+ * handleOperationRequest} is; an `A3003` is reported through {@link
57
+ * planUnencodableReport}.
62
58
  */
63
59
  export declare function handleTransactionRequest(context: HandlerContext, request: AvProtocolRequest): Promise<AvProtocolResponse>;
@@ -1,13 +1,6 @@
1
1
  import { createDiagnosticsReporter, createReporter, } from "../runtime/diagnostics-reporter.js";
2
2
  import { decodeOperationRequest, decodeTransactionRequest, } from "./http-request.decoder.js";
3
3
  import { encodeOperationResponse, encodeTransactionResponse, } from "./http-response.encoder.js";
4
- /**
5
- * Where a plan's `A3003` goes: the Framework's diagnostics sink, as a
6
- * `"transaction"` diagnostic — client scope (the protocol has no other
7
- * origin, P4), the request id the plan ran under, and the step the encoder
8
- * blames as `operation` when it blames one. One spelling for both
9
- * `protocol.encodeTransaction` and `protocol.handleTransaction`.
10
- */
11
4
  export function planUnencodableReport(sink, requestId) {
12
5
  return (error, operation) => createReporter(sink, {
13
6
  kind: "transaction",
@@ -16,33 +9,9 @@ export function planUnencodableReport(sink, requestId) {
16
9
  ...(operation === undefined ? {} : { operation }),
17
10
  })(error, "A3003");
18
11
  }
19
- /**
20
- * Where one operation's `A3003` goes: the Framework's diagnostics sink, as an
21
- * `"operation"` diagnostic carrying the decoded request's identity and id —
22
- * the shape the public `OperationDiagnostic` already has. One spelling for
23
- * `protocol.handleOperation` and for `protocol.encodeOperation` given the
24
- * decoded request (the architect, 2026-10-05).
25
- */
26
12
  export function operationUnencodableReport(sink, request) {
27
13
  return (error) => createDiagnosticsReporter(sink, request)(error, "A3003");
28
14
  }
29
- /**
30
- * `protocol.handleOperation(request)` (§5.9, R2; S8): the three steps a host
31
- * would otherwise spell out — `decodeOperation` → `framework.execute` →
32
- * `encodeOperation` — in one call, resolving the `AvProtocolResponse` the host
33
- * writes. A request the decoder answers itself (a transport failure, an
34
- * identity mismatch, an unadvertised route) is answered without executing.
35
- *
36
- * Total over ANY value, never rejecting: the decoder answers every value (one
37
- * that is not an `AvProtocolRequest` as `400 A2000`; the director,
38
- * 2026-10-05), `execute` resolves for every request it is handed, and the
39
- * encoder answers every response — a result with no wire form as `A3003` →
40
- * 500. That `A3003`
41
- * reaches the Framework's diagnostics sink as an `"operation"` diagnostic
42
- * carrying the decoded request's identity and id (the director, 2026-10-05),
43
- * which only this shortcut holds: the bare `encodeOperation` is given the
44
- * response and the request id alone.
45
- */
46
15
  export async function handleOperationRequest(context, request) {
47
16
  const decoded = decodeOperationRequest(context.contracts, request);
48
17
  if (!decoded.ok) {
@@ -51,18 +20,6 @@ export async function handleOperationRequest(context, request) {
51
20
  const response = await context.execute(decoded.request);
52
21
  return encodeOperationResponse(response, decoded.requestId, operationUnencodableReport(context.sink, decoded.request));
53
22
  }
54
- /**
55
- * `protocol.handleTransaction(request)` (§5.9, R2; S9): the same shortcut for
56
- * `/_transactions` — `decodeTransaction` → `framework.executeTransaction` →
57
- * `encodeTransaction`. The decoded plan is client origin and cannot say
58
- * otherwise, so every step runs under ClientContract rules (R1): a
59
- * client-hidden field, a client-restricted variant or a client-hidden
60
- * Resource is refused as through its single-operation route, plus
61
- * `cause.operation`. A committed plan is `200 A1009` (P3); a rolled-back one
62
- * answers its failing step's code at that code's status (Q4). Total over any
63
- * value, as {@link handleOperationRequest} is; an `A3003` is
64
- * reported through {@link planUnencodableReport}.
65
- */
66
23
  export async function handleTransactionRequest(context, request) {
67
24
  const decoded = decodeTransactionRequest(context.contracts, request);
68
25
  if (!decoded.ok) {
@@ -35,17 +35,6 @@ function supportsProjection(request) {
35
35
  }
36
36
  return request.variant !== "count";
37
37
  }
38
- /**
39
- * Plan one scalar of the read. Two Contracts answer two different questions:
40
- * the **active** Contract decides what the read RETURNS, and the **Core**
41
- * Contract decides what the Adapter is ASKED for — only a field it stores.
42
- *
43
- * A field added at a scope (`application.fields`) exists in that scope's
44
- * Contract and not in Core, and is VIRTUAL by construction
45
- * (`contract.compiler.ts`), so it is returned and computed, never requested.
46
- * Resolving the returned field against Core instead dropped it from the default
47
- * read and sent an explicit `select` of it to the Adapter as a column (D2).
48
- */
49
38
  function addScalarProjection(core, active, behaviors, resourceName, fieldName, adapterSelect, requested, computed) {
50
39
  const activeField = lookupField(lookupResource(active, resourceName), fieldName);
51
40
  if (activeField?.kind !== "scalar") {
@@ -253,13 +242,6 @@ function replaceWithInternalSelect(args, select) {
253
242
  internal.select = select;
254
243
  return internal;
255
244
  }
256
- /**
257
- * Clone the caller projection into the internal Adapter projection: the read
258
- * set the Adapter is asked for, always explicit for a projecting variant, plus
259
- * whatever computed scalar fields need to materialize. Caller-visible arguments
260
- * are never mutated and hidden dependencies are resolved through the Core
261
- * Contract.
262
- */
263
245
  export function planReadOperation(core, active, behaviors, request, args) {
264
246
  if (!isRecord(args) || !supportsProjection(request)) {
265
247
  return { arguments: args, projection: undefined, materialize: false };
@@ -285,11 +267,6 @@ export function planReadOperation(core, active, behaviors, request, args) {
285
267
  materialize: true,
286
268
  };
287
269
  }
288
- // No caller projection: the read set is the default projection, issued
289
- // explicitly and unconditionally. Leaving it unspecified would mean "whatever
290
- // the Adapter's provider reads by default", which is every stored column —
291
- // including one the active scope has removed from reads, fetched into server
292
- // memory before the output validator could refuse it (D1).
293
270
  const defaults = defaultProjectionLevel(core, active, behaviors, request.resource);
294
271
  return {
295
272
  arguments: { ...args, select: defaults.select },
@@ -319,8 +296,6 @@ async function materializeRecord(active, behaviors, request, plan, value, contex
319
296
  if (!isRecord(value)) {
320
297
  return value;
321
298
  }
322
- // The active Contract planned this read, so it is the one that knows every
323
- // computed field in it — a field added at its scope included (D2).
324
299
  const resource = lookupResource(active, plan.resource);
325
300
  if (resource === undefined) {
326
301
  return value;
@@ -359,10 +334,6 @@ async function materializeRecord(active, behaviors, request, plan, value, contex
359
334
  .filter((fieldName) => Object.hasOwn(record, fieldName))
360
335
  .map((fieldName) => [fieldName, record[fieldName]]));
361
336
  }
362
- /**
363
- * Materialize computed scalar reads and remove internal dependency fields,
364
- * against `active` — the Contract `planReadOperation` was given as `active`.
365
- */
366
337
  export async function materializeReadOperation(active, behaviors, request, plan, value, contextFactory) {
367
338
  const projection = plan.projection;
368
339
  if (!plan.materialize || projection === undefined) {
@@ -0,0 +1,65 @@
1
+ import type { Contract } from "../contracts/contract.js";
2
+ import type { OperationIdentity } from "../operations/operation-identity.js";
3
+ import type { ValidationIssue } from "../operations/validation-code.js";
4
+ /**
5
+ * Core's create-requirement vocabulary, and the check that reads it.
6
+ *
7
+ * **The facts are an Adapter's.** Which values a store cannot create a row
8
+ * without is a property of the store's schema — a column with no default, a
9
+ * reference that must point somewhere — and only the Adapter can read it. The
10
+ * words are Aventara's, so an Adapter translates its provider's facts into them,
11
+ * and the reasoning over them is core's, so no Adapter re-implements it.
12
+ *
13
+ * None of this enters a Contract. A Contract carries no foreign-key detail and
14
+ * no knowledge of which relation is the other end of which, and a requirement
15
+ * needs both; it is a server-side fact, read once when the Framework is
16
+ * constructed, like the referential actions.
17
+ *
18
+ * **When the check runs.** After guards, pipes and computed write behaviours —
19
+ * the moment the arguments are what the Adapter will be handed — and before
20
+ * any `before` hook or Adapter work. Earlier would refuse a value a pipe or a
21
+ * computed behaviour was about to supply; later is the store's own refusal,
22
+ * which reaches the caller as an internal failure. A missing value is the
23
+ * caller's to fix, so it answers `A2004` with a `V1000` issue at the path where
24
+ * the value belongs.
25
+ */
26
+ /** A relation edge, named by the Resource that holds it and its field there. */
27
+ export type CreateRequirementEdge = {
28
+ readonly resource: string;
29
+ readonly relation: string;
30
+ };
31
+ /**
32
+ * One value a create of a Resource cannot do without.
33
+ *
34
+ * - `field` — a scalar with no default, generated value or other source: it
35
+ * must be written.
36
+ * - `relation` — a required to-one relation: it must be written (connected or
37
+ * created), or every one of `orFields` must be — the scalar fields that hold
38
+ * the reference. When the row is created **through** the relation's other end
39
+ * (`inverse`), the parent supplies it, and it is not required.
40
+ */
41
+ export type CreateRequirement = {
42
+ readonly kind: "field";
43
+ readonly field: string;
44
+ } | {
45
+ readonly kind: "relation";
46
+ readonly relation: string;
47
+ readonly orFields: readonly string[];
48
+ readonly inverse?: CreateRequirementEdge;
49
+ };
50
+ /**
51
+ * Every Resource's create requirements, keyed by Resource. A Resource that is
52
+ * absent, or carries an empty list, requires nothing core can check.
53
+ */
54
+ export type CreateRequirementTable = Readonly<Record<string, readonly CreateRequirement[]>>;
55
+ type Path = readonly (string | number)[];
56
+ /**
57
+ * The `V1000` issues for every create position in one operation's arguments
58
+ * that lacks a value the Adapter requires — `create.*`'s `data`, `upsert`'s
59
+ * `create`, and every nested create under any write — in argument order.
60
+ * Empty when nothing is missing. Total over malformed input.
61
+ */
62
+ export declare function missingCreateValues(contract: Contract, table: CreateRequirementTable, request: OperationIdentity & {
63
+ readonly resource: string;
64
+ }, args: unknown, argumentsPath: Path): readonly ValidationIssue[];
65
+ export {};
@@ -0,0 +1,141 @@
1
+ import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
+ import { advertisedDirectivesAt } from "../contracts/field.js";
3
+ import { NESTED_WRITE_SCOPE, resolveWriteScope, } from "../operations/write-scope.resolver.js";
4
+ import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "./mutation-planner.js";
5
+ function isRecord(value) {
6
+ return value !== null && typeof value === "object" && !Array.isArray(value);
7
+ }
8
+ function written(record, key) {
9
+ return Object.hasOwn(record, key) && record[key] !== undefined;
10
+ }
11
+ function requirementsOf(table, resource) {
12
+ const listed = Object.hasOwn(table, resource) ? table[resource] : undefined;
13
+ return Array.isArray(listed) ? listed : [];
14
+ }
15
+ function creatableScalar(contract, resource, field) {
16
+ const found = lookupField(lookupResource(contract, resource), field);
17
+ return found?.kind === "scalar" && found.capabilities.create !== undefined;
18
+ }
19
+ function creatableRelation(contract, resource, relation, scope) {
20
+ const found = lookupField(lookupResource(contract, resource), relation);
21
+ return (found?.kind === "relation" &&
22
+ advertisedDirectivesAt(found.capabilities.create, scope) !== undefined);
23
+ }
24
+ function checkCreateRecord(context, resource, record, path, scope, via) {
25
+ if (!isRecord(record)) {
26
+ return;
27
+ }
28
+ const { contract, issues } = context;
29
+ for (const requirement of requirementsOf(context.table, resource)) {
30
+ if (requirement.kind === "field") {
31
+ if (!written(record, requirement.field) &&
32
+ creatableScalar(contract, resource, requirement.field)) {
33
+ issues.push({
34
+ code: "V1000",
35
+ path: [...path, requirement.field],
36
+ message: `Field "${requirement.field}" is required to create ${resource}.`,
37
+ });
38
+ }
39
+ continue;
40
+ }
41
+ if (via !== undefined &&
42
+ requirement.inverse?.resource === via.resource &&
43
+ requirement.inverse.relation === via.relation) {
44
+ continue;
45
+ }
46
+ const orFields = Array.isArray(requirement.orFields)
47
+ ? requirement.orFields
48
+ : [];
49
+ if (written(record, requirement.relation) ||
50
+ (orFields.length > 0 && orFields.every((field) => written(record, field)))) {
51
+ continue;
52
+ }
53
+ if (creatableRelation(contract, resource, requirement.relation, scope)) {
54
+ issues.push({
55
+ code: "V1000",
56
+ path: [...path, requirement.relation],
57
+ message: `Relation "${requirement.relation}" is required to create ${resource}${orFields.length > 0 ? `: write it, or ${orFields.map((field) => `"${field}"`).join(" and ")}` : ""}.`,
58
+ });
59
+ continue;
60
+ }
61
+ const missing = orFields.find((field) => !written(record, field) && creatableScalar(contract, resource, field));
62
+ if (missing !== undefined) {
63
+ issues.push({
64
+ code: "V1000",
65
+ path: [...path, missing],
66
+ message: `Field "${missing}" is required to create ${resource}.`,
67
+ });
68
+ }
69
+ }
70
+ walkNestedCreates(context, resource, record, path);
71
+ }
72
+ function walkNestedCreates(context, resource, record, path) {
73
+ if (!isRecord(record)) {
74
+ return;
75
+ }
76
+ const owner = lookupResource(context.contract, resource);
77
+ for (const [key, value] of Object.entries(record)) {
78
+ const field = lookupField(owner, key);
79
+ if (field?.kind !== "relation" || !isRecord(value)) {
80
+ continue;
81
+ }
82
+ const via = { resource, relation: key };
83
+ for (const [directive, operand] of Object.entries(value)) {
84
+ if (!isRelationMutationDirective(directive)) {
85
+ continue;
86
+ }
87
+ const entries = Array.isArray(operand)
88
+ ? operand.map((entry, index) => ({ entry, at: [index] }))
89
+ : [{ entry: operand, at: [] }];
90
+ for (const { entry, at } of entries) {
91
+ const entryPath = [...path, key, directive, ...at];
92
+ for (const site of RELATION_MUTATION_RECORD_SITES[directive]) {
93
+ const siteRecord = site.key === undefined
94
+ ? entry
95
+ : isRecord(entry)
96
+ ? entry[site.key]
97
+ : undefined;
98
+ const sitePath = site.key === undefined ? entryPath : [...entryPath, site.key];
99
+ if (site.stage === "create") {
100
+ checkCreateRecord(context, field.target, siteRecord, sitePath, NESTED_WRITE_SCOPE, via);
101
+ }
102
+ else {
103
+ walkNestedCreates(context, field.target, siteRecord, sitePath);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ export function missingCreateValues(contract, table, request, args, argumentsPath) {
111
+ if (!isRecord(args)) {
112
+ return [];
113
+ }
114
+ const context = { contract, table, issues: [] };
115
+ const scope = resolveWriteScope(lookupResource(contract, request.resource), request);
116
+ if (request.family === "create" && written(args, "data")) {
117
+ const data = args.data;
118
+ if (Array.isArray(data)) {
119
+ data.forEach((entry, index) => {
120
+ checkCreateRecord(context, request.resource, entry, [...argumentsPath, "data", index], scope, undefined);
121
+ });
122
+ }
123
+ else {
124
+ checkCreateRecord(context, request.resource, data, [...argumentsPath, "data"], scope, undefined);
125
+ }
126
+ }
127
+ if (request.family === "upsert") {
128
+ checkCreateRecord(context, request.resource, args.create, [...argumentsPath, "create"], scope, undefined);
129
+ walkNestedCreates(context, request.resource, args.update, [
130
+ ...argumentsPath,
131
+ "update",
132
+ ]);
133
+ }
134
+ if (request.family === "update") {
135
+ walkNestedCreates(context, request.resource, args.data, [
136
+ ...argumentsPath,
137
+ "data",
138
+ ]);
139
+ }
140
+ return context.issues;
141
+ }
@@ -5,8 +5,8 @@ export declare class Decimal {
5
5
  toString(): string;
6
6
  /**
7
7
  * The decimal string, exactly as given: what `JSON.stringify` writes for a
8
- * Decimal (Q16), so a result a developer serializes by hand carries its
9
- * digits rather than `{}`. The protocol's encoders do not rely on it.
8
+ * Decimal, so a result a developer serializes by hand carries its digits rather
9
+ * than `{}`. The protocol's encoders do not rely on it.
10
10
  */
11
11
  toJSON(): string;
12
12
  }