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

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
@@ -1,10 +1,7 @@
1
1
  import { WIRE_SCALAR_PATTERNS } from "../contracts/wire-scalar-format.js";
2
- /** Provider-neutral exact decimal runtime value owned by Aventara. */
3
2
  export class Decimal {
4
3
  #value;
5
4
  constructor(value) {
6
- // `RegExp#test` coerces its argument, so without this guard a number from
7
- // untyped code passed as `"5"` and `toString()` then returned the number.
8
5
  if (typeof value !== "string") {
9
6
  throw new TypeError("Decimal value must be a string.");
10
7
  }
@@ -16,11 +13,6 @@ export class Decimal {
16
13
  toString() {
17
14
  return this.#value;
18
15
  }
19
- /**
20
- * The decimal string, exactly as given: what `JSON.stringify` writes for a
21
- * Decimal (Q16), so a result a developer serializes by hand carries its
22
- * digits rather than `{}`. The protocol's encoders do not rely on it.
23
- */
24
16
  toJSON() {
25
17
  return this.#value;
26
18
  }
@@ -5,12 +5,12 @@ import type { FrameworkOperationRequest } from "./operation-request.js";
5
5
  import type { OperationErrorCode } from "./operation-response.js";
6
6
  /**
7
7
  * One unplanned failure as the framework saw it before sanitization: the raw
8
- * value, the outcome code actually emitted, and enough identity to act on
9
- * it. The code is usually an internal one, because the channel fires for
10
- * unplanned failures; it is the thrower's own code when the framework
11
- * dropped something it could not vouch for from an otherwise honoured
12
- * deliberate outcome (ADR 0008 decision 4), which changes no outcome. Server-side only — a diagnostic is never projected
13
- * onto the wire, which is precisely why it may carry the raw error.
8
+ * value, the outcome code actually emitted, and enough identity to act on it. The
9
+ * code is usually an internal one, because the channel fires for unplanned
10
+ * failures; it is the thrower's own code when the framework dropped something it
11
+ * could not vouch for from an otherwise honoured deliberate outcome, which changes
12
+ * no outcome. Server-side only — a diagnostic is never projected onto the wire,
13
+ * which is precisely why it may carry the raw error.
14
14
  */
15
15
  export type OperationDiagnostic = {
16
16
  readonly kind: "operation";
@@ -1,9 +1,4 @@
1
- /** The default channel: no sink configured, so nothing is observed. */
2
1
  const IGNORE_DIAGNOSTIC = () => undefined;
3
- /**
4
- * A sink may return a promise. Reading `then` off an arbitrary return value
5
- * can itself throw, so this runs inside the reporter's own guard.
6
- */
7
2
  function isThenable(value) {
8
3
  if ((typeof value !== "object" || value === null) &&
9
4
  typeof value !== "function") {
@@ -11,12 +6,6 @@ function isThenable(value) {
11
6
  }
12
7
  return typeof value.then === "function";
13
8
  }
14
- /**
15
- * The channel bound to one diagnostic identity, as the reporters below bind
16
- * it. Exported for `@aventara/core/protocol`, whose binding reports a failure
17
- * only it can meet — a result with no wire form (`A3003`) — under the
18
- * identity it holds; never exported from the main entry.
19
- */
20
9
  export function createReporter(sink, identity) {
21
10
  if (sink === undefined) {
22
11
  return IGNORE_DIAGNOSTIC;
@@ -33,38 +22,15 @@ export function createReporter(sink, identity) {
33
22
  }
34
23
  };
35
24
  }
36
- /**
37
- * The sink each constructed Framework was configured with, keyed by the
38
- * Framework object `createFramework` returned. The protocol's binding
39
- * (`AvProtocol.bind(framework)`, `@aventara/core/protocol`) reads it here, so
40
- * the direction stays one-way — no execution module imports `protocol/` — and
41
- * the public `Framework` type gains no member. A WeakMap: it keeps no
42
- * Framework alive. A Framework built without a sink has no entry.
43
- */
44
25
  const CONFIGURED_SINKS = new WeakMap();
45
- /** Records the sink `framework` was configured with; called once, at construction. */
46
26
  export function recordDiagnosticsSink(framework, sink) {
47
27
  if (sink !== undefined) {
48
28
  CONFIGURED_SINKS.set(framework, sink);
49
29
  }
50
30
  }
51
- /** The sink `framework` was configured with, or `undefined` for none. */
52
31
  export function diagnosticsSinkOf(framework) {
53
32
  return CONFIGURED_SINKS.get(framework);
54
33
  }
55
- /**
56
- * Binds the configured sink to one operation request.
57
- *
58
- * Identity is captured on entry rather than at report time: by the moment a
59
- * failure is reported the request may be exactly what broke, and a diagnostic
60
- * naming no operation is not actionable. A request whose own identity cannot
61
- * be read is past observing, so it silently yields the no-op channel — the
62
- * outermost totality guard still answers with the generic envelope.
63
- *
64
- * The response must be unaffected by observation, so the reporter neither
65
- * awaits the sink nor lets anything the sink does escape: a throw, a rejected
66
- * promise and a booby-trapped thenable all end here.
67
- */
68
34
  export function createDiagnosticsReporter(sink, request, operation) {
69
35
  let identity;
70
36
  try {
@@ -83,7 +49,6 @@ export function createDiagnosticsReporter(sink, request, operation) {
83
49
  }
84
50
  return createReporter(sink, identity);
85
51
  }
86
- /** Binds the configured sink to one transaction request and its plan operations. */
87
52
  export function createTransactionDiagnosticsChannel(sink, request) {
88
53
  let identity;
89
54
  try {
@@ -17,9 +17,9 @@ export declare class AdapterBoundary {
17
17
  originOf(error: unknown): FailureOrigin;
18
18
  }
19
19
  /**
20
- * The one result-serialization text; every A3003 carries it. Its producer is
21
- * the protocol's response encoder (`@aventara/core/protocol`, P1), which
22
- * imports it from here so the code has one text wherever it is emitted.
20
+ * The one result-serialization text; every A3003 carries it. Its producer is the
21
+ * protocol's response encoder, which imports it from here so the code has one text
22
+ * wherever it is emitted.
23
23
  */
24
24
  export declare const SERIALIZATION_FAILURE_MESSAGE = "Result serialization failed.";
25
25
  /** Where a standalone operation's arguments sit in a framework issue path. */
@@ -1,16 +1,10 @@
1
1
  import { VALIDATION_CODE_MESSAGES, VALIDATION_CODES, } from "../operations/validation-code.js";
2
2
  import { FrameworkError } from "./framework-error.js";
3
3
  import { INTERNAL_FAILURE_MESSAGE, internalFailure, OPERATION_CODES, operationFailure, } from "./operation-response.js";
4
- /** The one generic Adapter-failure text; every unexpected A3001 carries it. */
4
+ import { PIPE_OUTPUT_FAILURE_MESSAGE } from "./pipe-output.validator.js";
5
5
  export const ADAPTER_FAILURE_MESSAGE = "Adapter execution failed.";
6
- /**
7
- * Structurally records every value thrown across the Adapter seam so the
8
- * final error boundary can classify origin by identity, never by inspecting
9
- * error text. One boundary instance belongs to one operation execution.
10
- */
11
6
  export class AdapterBoundary {
12
7
  #thrown = new Set();
13
- /** Runs Adapter work, remembering anything it throws before re-throwing it. */
14
8
  async execute(work) {
15
9
  try {
16
10
  return await work();
@@ -24,29 +18,17 @@ export class AdapterBoundary {
24
18
  return this.#thrown.has(error) ? "adapter" : "runtime";
25
19
  }
26
20
  }
27
- /**
28
- * The one result-serialization text; every A3003 carries it. Its producer is
29
- * the protocol's response encoder (`@aventara/core/protocol`, P1), which
30
- * imports it from here so the code has one text wherever it is emitted.
31
- */
32
21
  export const SERIALIZATION_FAILURE_MESSAGE = "Result serialization failed.";
33
- /**
34
- * The framework's own text for each internal-failure code. An A3xxx cause is
35
- * never caller-actionable, so whatever text its thrower supplied is replaced
36
- * by this table — the realistic thrower is a careless Adapter forwarding a
37
- * provider message, and spec 13.5 forbids that text on the wire.
38
- */
39
22
  const INTERNAL_FAILURE_MESSAGES = {
40
23
  A3000: INTERNAL_FAILURE_MESSAGE,
41
24
  A3001: ADAPTER_FAILURE_MESSAGE,
42
25
  A3002: "Transaction failed.",
43
26
  A3003: SERIALIZATION_FAILURE_MESSAGE,
27
+ A3004: PIPE_OUTPUT_FAILURE_MESSAGE,
44
28
  };
45
- /** The internal code an unexpected failure of one origin is emitted under. */
46
29
  function unexpectedCode(origin) {
47
30
  return origin === "adapter" ? "A3001" : "A3000";
48
31
  }
49
- /** The generic, text-free envelope for an unexpected failure of one origin. */
50
32
  function unexpectedFailure(origin) {
51
33
  return origin === "adapter"
52
34
  ? operationFailure("A3001", { message: ADAPTER_FAILURE_MESSAGE })
@@ -58,10 +40,6 @@ function isInternalCode(code) {
58
40
  function isPathSegment(value) {
59
41
  return typeof value === "string" || typeof value === "number";
60
42
  }
61
- /**
62
- * Whether an untrusted value is a list. `Array.isArray` is not itself total:
63
- * it throws on a revoked Proxy, and a thrown value may be one.
64
- */
65
43
  function isList(value) {
66
44
  try {
67
45
  return Array.isArray(value);
@@ -70,15 +48,6 @@ function isList(value) {
70
48
  return false;
71
49
  }
72
50
  }
73
- /**
74
- * Copies an untrusted list into a plain array the framework owns. Traversal,
75
- * not just property reads, is untrusted here: an index accessor, a Proxy
76
- * trap, an overridden `map` and a hijacked `Symbol.species` all run
77
- * thrower-supplied code, and none of it may become the boundary's own
78
- * failure. Elements are read one at a time through {@link readProperty}, so
79
- * an unreadable element is `undefined` — a value every projection below
80
- * already rejects. `undefined` means the value is no list at all.
81
- */
82
51
  function readList(value) {
83
52
  if (!isList(value)) {
84
53
  return undefined;
@@ -93,12 +62,6 @@ function readList(value) {
93
62
  }
94
63
  return items;
95
64
  }
96
- /**
97
- * Projects an issue path onto a plain array of segments the framework owns.
98
- * Copying rather than forwarding is the point: a planted path arrives as a
99
- * live handle to a caller-held array, and its non-index properties would
100
- * otherwise ride into the envelope for every in-memory consumer of it.
101
- */
102
65
  function projectPath(value) {
103
66
  const items = readList(value);
104
67
  if (items === undefined) {
@@ -113,31 +76,13 @@ function projectPath(value) {
113
76
  }
114
77
  return path;
115
78
  }
116
- /** Where a standalone operation's arguments sit in a framework issue path. */
117
79
  export const OPERATION_ARGUMENTS_PATH = [
118
80
  "arguments",
119
81
  ];
120
- /** Where one plan operation's arguments sit in a framework issue path. */
121
82
  export function planOperationArgumentsPath(index) {
122
83
  return ["operations", index, "args"];
123
84
  }
124
- /** A segment that named no own, data-backed member of its container. */
125
85
  const UNRESOLVED = Symbol("unresolved-path-segment");
126
- /**
127
- * Reads one own, data-backed member of an untrusted container.
128
- *
129
- * Own only: satisfying a segment from the prototype chain would let `toString`
130
- * or `constructor` pose as caller data. Data-backed only: the descriptor is
131
- * consulted and only its `value` used, so a getter never runs — running a
132
- * caller's accessor while sanitizing an error is a side effect in the worst
133
- * possible place.
134
- *
135
- * The reflection itself can throw: a revoked Proxy rejects
136
- * `getOwnPropertyDescriptor`. That is not caught here. The whole walk has one
137
- * containment point, in {@link resolvesAgainstArguments}, so there is exactly
138
- * one place where an unwalkable path and an unresolvable one become the same
139
- * answer.
140
- */
141
86
  function readOwnMember(container, key) {
142
87
  if (typeof container !== "object" || container === null) {
143
88
  return UNRESOLVED;
@@ -147,7 +92,6 @@ function readOwnMember(container, key) {
147
92
  ? descriptor.value
148
93
  : UNRESOLVED;
149
94
  }
150
- /** Resolves one path segment; a numeric segment indexes an array and nothing else. */
151
95
  function readSegment(container, segment) {
152
96
  if (typeof segment === "number") {
153
97
  return Number.isInteger(segment) && segment >= 0 && isList(container)
@@ -156,22 +100,6 @@ function readSegment(container, segment) {
156
100
  }
157
101
  return readOwnMember(container, segment);
158
102
  }
159
- /**
160
- * Whether a thrower-supplied path denotes a member of the caller's own
161
- * arguments — the one thing that makes it safe to emit.
162
- *
163
- * A path that resolves echoes back a key sequence the caller already holds;
164
- * anything else is unvouched content on the same channel spec 13.5 closes for
165
- * the rest of `cause` (ADR 0008 decision 4, applied to the third axis). The
166
- * prefix must be the framework's own address for these arguments, and every
167
- * remaining segment must resolve: a resolving prefix does not license the
168
- * rest, so a partial match is no match.
169
- *
170
- * Total, like every step the boundary takes on a thrown value. The walk runs
171
- * over data the framework does not own — a revoked Proxy on it throws from
172
- * reflection alone — so the whole walk sits inside one guard: an unresolvable
173
- * path and an unwalkable one are the same answer.
174
- */
175
103
  function resolvesAgainstArguments(path, view) {
176
104
  try {
177
105
  if (path.length < view.path.length) {
@@ -199,41 +127,16 @@ function resolvesAgainstArguments(path, view) {
199
127
  return false;
200
128
  }
201
129
  }
202
- /**
203
- * Only an allocated Validation code (spec 13.3, amended by ADR 0006 DA-4) may
204
- * be emitted. This is ADR 0005's rule on the axis it did not cover: the union
205
- * is a compile-time promise a separately compiled Adapter or a developer
206
- * filter never made, so the set is tested by identity before emission.
207
- */
208
130
  function isValidationCode(value) {
209
131
  return (typeof value === "string" &&
210
132
  VALIDATION_CODES.includes(value));
211
133
  }
212
- /**
213
- * Projects one issue onto the spec ValidationIssue shape; unknown keys drop.
214
- *
215
- * All three fields are framework-owned by the time they are emitted.
216
- * An unrecognised `code` drops the whole issue rather than riding onto the
217
- * wire in a field the spec defines as a closed set — and rather than being
218
- * rewritten to a plausible neighbour, which would misreport what was wrong.
219
- * The `message` is replaced by the framework's own published text for that
220
- * code, because a thrower-supplied message is the same provider-text channel
221
- * spec 13.5 closes for the rest of `cause`. The `path` is emitted only when
222
- * every segment of it resolves against the caller's own arguments; it is an
223
- * open-ended string channel otherwise, and spec 13.1 makes the field
224
- * optional, so a path that cannot be vouched for is simply absent — the
225
- * issue, its code and the outcome are unchanged. Each dropped value is
226
- * appended to `unvouched`, so the boundary can hand it to the ADR 0004
227
- * diagnostics channel — the only place it still exists.
228
- */
229
134
  function projectIssue(value, unvouched, view) {
230
135
  if (typeof value !== "object" || value === null) {
231
136
  return undefined;
232
137
  }
233
138
  const code = readProperty(value, "code");
234
139
  if (!isValidationCode(code)) {
235
- // `undefined` is an unreadable or absent code, not a supplied one:
236
- // reporting it would be noise, and the issue is malformed either way.
237
140
  if (code !== undefined) {
238
141
  unvouched.push(code);
239
142
  }
@@ -255,18 +158,6 @@ function projectIssue(value, unvouched, view) {
255
158
  }
256
159
  return { path, code, message: owned };
257
160
  }
258
- /**
259
- * Projects a thrower-supplied cause onto the spec 13 `Cause` shape:
260
- * `{ message, issues?, operation? }`. Unknown keys are dropped rather than
261
- * forwarded, so a provider error assigned wholesale as a cause loses its
262
- * `sql`, `stack`, DSN and whatever else it carried. A cause without a string
263
- * message is no cause at all.
264
- *
265
- * Total, like every step the boundary takes on a thrown value: a cause it
266
- * cannot traverse yields the parts it could read, never an exception. A
267
- * throw here would escape the boundary that was sanitizing it and cost the
268
- * thrower the very outcome it deliberately named.
269
- */
270
161
  function projectCause(value, unvouched, view) {
271
162
  const message = readProperty(value, "message");
272
163
  if (typeof message !== "string") {
@@ -279,29 +170,16 @@ function projectCause(value, unvouched, view) {
279
170
  .filter((issue) => issue !== undefined);
280
171
  return {
281
172
  message,
282
- // An empty list is no list: dropping every issue leaves the cause
283
- // without issues rather than fabricating one to fill the field.
284
173
  ...(issues !== undefined && issues.length > 0 ? { issues } : {}),
285
174
  ...(Number.isInteger(rawOperation) && rawOperation >= 0
286
175
  ? { operation: rawOperation }
287
176
  : {}),
288
177
  };
289
178
  }
290
- /**
291
- * Internal failures carry no caller-actionable diagnostics: the message is
292
- * the framework's own and `issues` raised while validating computed/Adapter
293
- * output describe server internals and stay behind the boundary (available
294
- * to filters, never emitted).
295
- */
296
179
  function internalCause(code, cause) {
297
180
  const { issues: _issues, message: _message, ...emitted } = cause;
298
181
  return { ...emitted, message: INTERNAL_FAILURE_MESSAGES[code] };
299
182
  }
300
- /**
301
- * Reads one property of a thrown value. Thrown values are untrusted: a
302
- * getter or Proxy trap may itself throw, and that must never become the
303
- * boundary's own failure.
304
- */
305
183
  function readProperty(value, key) {
306
184
  try {
307
185
  return value[key];
@@ -318,34 +196,16 @@ function isFrameworkErrorInstance(error) {
318
196
  return false;
319
197
  }
320
198
  }
321
- /**
322
- * A {@link FrameworkError} that fails vetting. Its thrower deliberately named
323
- * an outcome the framework cannot honour, so the failure is the broken
324
- * outcome contract itself — an internal error, whatever the origin — and the
325
- * offending value is replaced, never echoed.
326
- */
327
199
  const MALFORMED_OUTCOME = {
328
200
  code: "A3000",
329
201
  cause: { message: INTERNAL_FAILURE_MESSAGE },
330
202
  unvouched: [],
331
203
  };
332
- /**
333
- * Only a recognised error code (spec 13.2) is a deliberate outcome. An
334
- * unknown code, or a success code arriving on the failure path, would break
335
- * the ADR 0003 union on the wire.
336
- */
337
204
  function isOperationErrorCode(value) {
338
205
  return (typeof value === "string" &&
339
206
  OPERATION_CODES.includes(value) &&
340
207
  !value.startsWith("A1"));
341
208
  }
342
- /**
343
- * Vets a value as a deliberate {@link FrameworkError}. `undefined` means it
344
- * is not one at all. Passing the `instanceof` check is not enough:
345
- * `Object.create(FrameworkError.prototype)`, a booby-trapped accessor, an
346
- * unrecognised code or a cause without a message all reach here, and each
347
- * is {@link MALFORMED_OUTCOME} rather than something to dereference or emit.
348
- */
349
209
  function vetDeliberateOutcome(error, view) {
350
210
  if (!isFrameworkErrorInstance(error)) {
351
211
  return undefined;
@@ -361,31 +221,16 @@ function vetDeliberateOutcome(error, view) {
361
221
  const cause = projectCause(rawCause, unvouched, view);
362
222
  return cause === undefined ? MALFORMED_OUTCOME : { code, cause, unvouched };
363
223
  }
364
- /**
365
- * Hands every dropped issue code and issue path to the ADR 0004 channel under
366
- * the outcome actually emitted. Dropping something the framework cannot vouch
367
- * for is no grounds to escalate the thrower's chosen outcome, so the code
368
- * stands and the channel carries the whole consequence. Reporting cannot
369
- * affect the response: the reporter is total and swallows whatever the sink
370
- * does.
371
- */
372
224
  function reportUnvouched(outcome, report) {
373
225
  for (const value of outcome.unvouched) {
374
226
  report(value, outcome.code);
375
227
  }
376
228
  }
377
- /** A deliberate outcome: the stable code and cause its thrower chose. */
378
229
  function deliberateFailure(outcome) {
379
230
  return operationFailure(outcome.code, isInternalCode(outcome.code)
380
231
  ? internalCause(outcome.code, outcome.cause)
381
232
  : outcome.cause);
382
233
  }
383
- /**
384
- * Final framework sanitization, shared by every boundary. A deliberate
385
- * {@link FrameworkError} carries its own stable outcome; anything else is
386
- * replaced by a generic cause so no provider text, stack, path, or secret
387
- * can cross the response boundary. Total: it never throws.
388
- */
389
234
  export function sanitizeOperationFailure(error, origin, report, view) {
390
235
  const outcome = vetDeliberateOutcome(error, view);
391
236
  if (outcome === undefined) {
@@ -398,13 +243,6 @@ export function sanitizeOperationFailure(error, origin, report, view) {
398
243
  reportUnvouched(outcome, report);
399
244
  return deliberateFailure(outcome);
400
245
  }
401
- /**
402
- * Post-validation exception flow (spec 17.3): effective filters are stored as
403
- * `[root..., scoped...]`, so reverse iteration tries scoped filters in reverse
404
- * registration order, then root filters in reverse, then final sanitization.
405
- * A filter handles an error only by returning a {@link FrameworkError};
406
- * returning `undefined` or throwing leaves the original error unhandled.
407
- */
408
246
  export async function resolveOperationFailure(error, filters, context, boundary, report, view) {
409
247
  for (let index = filters.length - 1; index >= 0; index -= 1) {
410
248
  const filter = filters[index];
@@ -413,9 +251,6 @@ export async function resolveOperationFailure(error, filters, context, boundary,
413
251
  }
414
252
  const handled = await attemptFilter(filter, error, context, view);
415
253
  if (handled !== undefined) {
416
- // A filter that names an outcome the framework cannot honour has
417
- // swallowed the original error on the developer's behalf; the
418
- // diagnostics channel is the only place it still exists.
419
254
  if (handled === MALFORMED_OUTCOME) {
420
255
  report(error, "A3000");
421
256
  }
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * The caller's say over an in-process request it does not write by hand: the
3
3
  * second argument of every `framework.application.*` / `framework.client.*` call
4
- * and of `framework.transaction` (Q10 = B, Q14; closes F-833).
4
+ * and of `framework.transaction`.
5
5
  *
6
- * Not "transport options": an in-process call has no transport. A deferred
7
- * handle (`framework.appTx.*` / `framework.clientTx.*`) takes none — a handle is
8
- * not a request, and the id belongs to the run that executes it.
6
+ * Not "transport options": an in-process call has no transport. A deferred handle
7
+ * (`framework.appTx.*` / `framework.clientTx.*`) takes none — a handle is not a
8
+ * request, and the id belongs to the run that executes it.
9
9
  */
10
10
  export type ExecutionOptions = {
11
11
  /**
@@ -8,18 +8,15 @@ import type { PipelineContext } from "./pipeline.js";
8
8
  * What a write-stage compute callback is told about the field it is computing.
9
9
  *
10
10
  * `R` is the Resource the behavior is bound to and `Cfg` the authored
11
- * configuration literal, so `resource` is the literal Resource name and
12
- * `field` — like every other field-key position in the framework — is
13
- * {@link EffectiveFieldKey}: what the adapter discovered plus what the
14
- * configuration added.
11
+ * configuration literal, so `resource` is the literal Resource name and `field` —
12
+ * like every other field-key position in the framework — is {@link
13
+ * EffectiveFieldKey}: what the adapter discovered plus what the configuration
14
+ * added.
15
15
  *
16
- * `data` is keyed on the same set and stays `unknown`-valued. Scalar-to-TS
17
- * *value* typing is `OperationResultFor`'s job in Phase 9 (F-701) and is out
18
- * of scope here by the plan's hard constraints; what this type buys a callback
19
- * author is the key set, not the value.
16
+ * `data` is keyed on the same set and stays `unknown`-valued.
20
17
  *
21
18
  * Under the default `Cfg` the key set degenerates to `string` and this is
22
- * byte-for-byte the shape it was before `Cfg` existed (B4).
19
+ * byte-for-byte the shape it was before `Cfg` existed.
23
20
  */
24
21
  type ComputedWriteContext<M extends AdapterModel, Cfg, R extends FrameworkResourceKey<M>> = {
25
22
  readonly scope: RequestOrigin;
@@ -1,7 +1,3 @@
1
- /**
2
- * Stable typed error used by server-side pipelines, behaviors and Adapters to
3
- * deliberately surface one framework error outcome.
4
- */
5
1
  export class FrameworkError extends Error {
6
2
  code;
7
3
  cause;
@@ -4,12 +4,11 @@ import type { Contract, CoreContract } from "../contracts/contract.js";
4
4
  import type { OperationExecutionRequest } from "./operation-request.js";
5
5
  import type { PipelineContext } from "./pipeline.js";
6
6
  /**
7
- * The two Contracts a write reads (F-829, the write-side twin of D2/F-824). The
8
- * **Core** Contract decides what the Adapter is asked to store; the **active**
9
- * Contract adds the fields its scope declared under `application.fields` /
10
- * `client.fields`, which Core does not carry. Such a field is VIRTUAL by
11
- * construction (`contract.compiler.ts`), so its behaviours run and its value is
12
- * stripped before the Adapter call — never sent.
7
+ * The two Contracts a write reads. The **Core** Contract decides what the Adapter
8
+ * is asked to store; the **active** Contract adds the fields its scope declared
9
+ * under `application.fields` / `client.fields`, which Core does not carry. Such a
10
+ * field is VIRTUAL by construction (`contract.compiler.ts`), so its behaviours run
11
+ * and its value is stripped before the Adapter call — never sent.
13
12
  */
14
13
  export type WriteContracts = {
15
14
  readonly core: CoreContract;
@@ -2,13 +2,6 @@ import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
2
2
  import { FrameworkError } from "./framework-error.js";
3
3
  import { INTERNAL_FAILURE_MESSAGE } from "./operation-response.js";
4
4
  import { normalizeScalarFieldValue } from "./scalar-runtime.js";
5
- /**
6
- * The scalar field `fieldName` names on `resourceName` for a write: Core's own
7
- * field when Core has one — a field the scope hides or narrows is still stored,
8
- * and its behaviours still run — else the scalar the active scope added. Its
9
- * values are normalized against Core's registries either way: a scope adds
10
- * fields, never a scalar or an enum.
11
- */
12
5
  function writeScalarField(contracts, resourceName, fieldName) {
13
6
  const field = lookupField(lookupResource(contracts.core, resourceName), fieldName) ??
14
7
  lookupField(lookupResource(contracts.active, resourceName), fieldName);
@@ -16,15 +9,6 @@ function writeScalarField(contracts, resourceName, fieldName) {
16
9
  ? field
17
10
  : undefined;
18
11
  }
19
- /**
20
- * The sole grammar for relation-mutation record operands. Every write pass
21
- * maps these sites with its own record leaf, leaving identifier-only
22
- * directives untouched. The identifier operands this table deliberately leaves
23
- * empty are described by `RELATION_MUTATION_SELECTOR_SITES` in
24
- * `transactions/operation-arguments-encoder.ts`, the only pass that has to
25
- * encode them; both tables are keyed by `RelationMutationDirective`, so a new
26
- * directive fails to compile in both places.
27
- */
28
12
  export const RELATION_MUTATION_RECORD_SITES = {
29
13
  $create: [{ key: undefined, stage: "create" }],
30
14
  $connect: [],
@@ -38,11 +22,6 @@ export const RELATION_MUTATION_RECORD_SITES = {
38
22
  { key: "update", stage: "update" },
39
23
  ],
40
24
  };
41
- /**
42
- * Narrows a caller-supplied own key to the shared directive vocabulary. Own
43
- * membership, not an assertion: `Object.prototype` members resolve through the
44
- * prototype chain and would otherwise reach a site loop with a non-iterable.
45
- */
46
25
  export function isRelationMutationDirective(key) {
47
26
  return Object.hasOwn(RELATION_MUTATION_RECORD_SITES, key);
48
27
  }
@@ -144,7 +123,6 @@ async function mapRelationMutationRecords(relation, value, leaf) {
144
123
  }
145
124
  return normalized;
146
125
  }
147
- /** Apply effective computed create/update field behavior to post-pipe logical args. */
148
126
  export async function applyWriteFieldBehaviors(contracts, behaviors, request, args, contextFactory) {
149
127
  if (behaviors === undefined || !isRecord(args)) {
150
128
  return args;
@@ -190,7 +168,6 @@ async function stripVirtualRecord(contracts, resourceName, data) {
190
168
  }
191
169
  return persisted;
192
170
  }
193
- /** Strip VIRTUAL scalar input only at the persistence boundary. */
194
171
  export async function stripVirtualMutationInput(contracts, request, args) {
195
172
  if (!isRecord(args)) {
196
173
  return args;
@@ -1,5 +1,5 @@
1
1
  import type { ValidationIssue } from "../operations/validation-code.js";
2
- export declare const OPERATION_CODES: readonly ["A1000", "A1001", "A1002", "A1003", "A1004", "A1005", "A1006", "A1007", "A1008", "A1009", "A2000", "A2001", "A2002", "A2003", "A2004", "A2005", "A2006", "A2007", "A2008", "A2009", "A2010", "A2011", "A2012", "A2013", "A2014", "A3000", "A3001", "A3002", "A3003", "A4000", "A4001", "A4002"];
2
+ export declare const OPERATION_CODES: readonly ["A1000", "A1001", "A1002", "A1003", "A1004", "A1005", "A1006", "A1007", "A1008", "A1009", "A2000", "A2001", "A2002", "A2003", "A2004", "A2005", "A2006", "A2007", "A2008", "A2009", "A2010", "A2011", "A2012", "A2013", "A2014", "A3000", "A3001", "A3002", "A3003", "A3004", "A4000", "A4001", "A4002"];
3
3
  export type OperationCode = (typeof OPERATION_CODES)[number];
4
4
  export type OperationSuccessCode = Extract<OperationCode, `A1${string}`>;
5
5
  export type OperationErrorCode = Exclude<OperationCode, OperationSuccessCode>;
@@ -28,37 +28,21 @@ export const OPERATION_CODES = [
28
28
  "A3001",
29
29
  "A3002",
30
30
  "A3003",
31
+ "A3004",
31
32
  "A4000",
32
33
  "A4001",
33
34
  "A4002",
34
35
  ];
35
- /**
36
- * Builds the success-with-data arm. The only sanctioned way to construct
37
- * one: a runtime-computed `code` (e.g. from a table-driven outcome mapper)
38
- * still yields a well-typed {@link OperationSuccessResponse}.
39
- */
40
36
  export function operationSuccess(data, code) {
41
37
  return { data, code, cause: null };
42
38
  }
43
- /** Builds the no-match success arm (A1001). */
44
39
  export function operationNoMatch() {
45
40
  return { data: null, code: "A1001", cause: null };
46
41
  }
47
- /**
48
- * Builds the failure arm. The only sanctioned way to construct one: a
49
- * runtime-computed error `code` still yields a well-typed
50
- * {@link OperationFailureResponse}.
51
- */
52
42
  export function operationFailure(code, cause) {
53
43
  return { data: null, code, cause };
54
44
  }
55
- /** The one generic internal-failure text; every A3000 carries it. */
56
45
  export const INTERNAL_FAILURE_MESSAGE = "Internal framework error.";
57
- /**
58
- * The generic internal-failure envelope. Nothing about an internal failure is
59
- * caller-actionable, so every A3000 the framework emits is this exact value -
60
- * one constant rather than one restatement per boundary.
61
- */
62
46
  export function internalFailure() {
63
47
  return operationFailure("A3000", { message: INTERNAL_FAILURE_MESSAGE });
64
48
  }