@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
@@ -30,16 +30,16 @@ export type AdapterScalarField<M extends AdapterModel> = {
30
30
  * qualifier included, and that sharing is the point: the ADAPTER is the only party
31
31
  * that can measure which argument positions a relation is reachable in, because
32
32
  * the answer depends on which provider call each operation variant is routed to.
33
- * Core tabulating it would be a tabulated provider fact (D-802) and would be wrong
34
- * for the next adapter.
33
+ * Core tabulating it would be a tabulated provider fact and would be wrong for the
34
+ * next adapter.
35
35
  *
36
36
  * The qualifier is OPTIONAL at this boundary, as it is in the Contract: an adapter
37
37
  * that has not measured the axis states the unqualified answer and is believed,
38
38
  * which is what keeps a surface that predates the measurement meaningful rather
39
39
  * than silently narrowed.
40
40
  *
41
- * **A scope qualifies the TOP LEVEL of an argument only** — the measurement and the
42
- * reason are recorded on `ProjectionScope`, and a discoverer that narrows
41
+ * **A scope qualifies the TOP LEVEL of an argument only** — the measurement and
42
+ * the reason are recorded on `ProjectionScope`, and a discoverer that narrows
43
43
  * recursively would advertise less than the provider accepts.
44
44
  */
45
45
  export type AdapterRelationField<M extends AdapterModel> = {
@@ -21,20 +21,18 @@ export type AdapterFieldKey<M extends AdapterModel, R extends Extract<keyof M["r
21
21
  * Provider-discovered facts for one Aventara Resource candidate.
22
22
  *
23
23
  * `TFields` is never supplied by a caller — every in-repo site writes
24
- * `AdapterResource<M>` — but it is **load-bearing and must not be inlined**.
25
- * It is the indirection that keeps `M` out of this type's body.
24
+ * `AdapterResource<M>` — but it is **load-bearing and must not be inlined**. It is
25
+ * the indirection that keeps `M` out of this type's body.
26
26
  *
27
- * `AdapterField<M>` is invariant in `M` (it reads `keyof M["scalars"]` and
28
- * `keyof M["resources"]`). If `M` reached the body, `AdapterResource` would
29
- * acquire an invariant variance marker, and every concrete model would stop
30
- * satisfying the self-typed `AdapterModel.resources: Readonly<Record<string,
31
- * AdapterResource<this>>>` constraint. Measured: 43 type errors across the
32
- * adapter and index type tests, and identically 43 whether the parameter is
33
- * deleted or merely bypassed — so it is the body occurrence that matters,
34
- * not the arity.
27
+ * `AdapterField<M>` is invariant in `M` (it reads `keyof M["scalars"]` and `keyof
28
+ * M["resources"]`). If `M` reached the body, `AdapterResource` would acquire an
29
+ * invariant variance marker, and every concrete model would stop satisfying the
30
+ * self-typed `AdapterModel.resources: Readonly<Record<string,
31
+ * AdapterResource<this>>>` constraint. Measured: 43 type errors across the adapter
32
+ * and index type tests, and identically 43 whether the parameter is deleted or
33
+ * merely bypassed — so it is the body occurrence that matters, not the arity.
35
34
  *
36
- * This is why F-601 ("the second type parameter is dead") was closed as
37
- * mistaken rather than actioned. Deleting it is not a cleanup.
35
+ * Deleting it is not a cleanup.
38
36
  */
39
37
  export type AdapterResource<M extends AdapterModel, TFields extends AdapterFieldMap<M> = AdapterFieldMap<M>> = {
40
38
  readonly fields: TFields;
@@ -1,3 +1,4 @@
1
+ import type { CreateRequirementTable } from "../runtime/create-requirement.js";
1
2
  import type { ReferentialActionTable } from "../runtime/referential-action.js";
2
3
  import type { AdapterModel } from "./adapter-model.js";
3
4
  import type { AdapterOperationExecutor } from "./adapter-operation-executor.interface.js";
@@ -25,17 +26,26 @@ export interface Adapter<M extends AdapterModel = AdapterModel> extends AdapterO
25
26
  */
26
27
  readonly referentialActions?: ReferentialActionTable;
27
28
  /**
28
- * Optional callback transaction capability, required exactly when the
29
- * discovered model declares `transactions: "interactive"`. The callback
30
- * receives only a transaction-scoped operation executor, never the provider
31
- * client itself, and every operation of a plan executes through it.
29
+ * Optional create requirements: for each Resource, the values its store
30
+ * cannot create a row without, in Aventara's words
31
+ * (`runtime/create-requirement.ts`). Read once at framework construction,
32
+ * like `model`, and never part of a Contract or its hash.
33
+ *
34
+ * Optional so an Adapter that cannot state them is believed: core then checks
35
+ * nothing, and a missing value reaches the store as before.
36
+ */
37
+ readonly createRequirements?: CreateRequirementTable;
38
+ /**
39
+ * Optional callback transaction capability, required exactly when the discovered
40
+ * model declares `transactions: "interactive"`. The callback receives only a
41
+ * transaction-scoped operation executor, never the provider client itself, and
42
+ * every operation of a plan executes through it.
32
43
  *
33
- * The implementation MUST reject with the exact value `work` threw — by
34
- * identity, never a wrapper — and MUST NOT resolve after `work` rejected;
35
- * rollback is implied by that rejection. Framework guards, pipes, hooks and
36
- * interceptors of every plan operation run inside `work` while the provider
37
- * transaction is open, so they must not perform network I/O or unrelated
38
- * slow work (spec §14.5).
44
+ * The implementation MUST reject with the exact value `work` threw — by identity,
45
+ * never a wrapper — and MUST NOT resolve after `work` rejected; rollback is
46
+ * implied by that rejection. Framework guards, pipes, hooks and interceptors of
47
+ * every plan operation run inside `work` while the provider transaction is open,
48
+ * so they must not perform network I/O or unrelated slow work.
39
49
  */
40
50
  transaction?<T>(work: (executor: AdapterOperationExecutor<M>) => Promise<T>): Promise<T>;
41
51
  }
@@ -1,10 +1,9 @@
1
1
  export type ContractCompilerDiagnosticCode = "COMPILER_UNKNOWN_RESOURCE" | "COMPILER_UNKNOWN_FIELD" | "COMPILER_RELATION_FIELD_CONFIG_UNSUPPORTED" | "COMPILER_INCOMPLETE_FIELD" | "COMPILER_STRUCTURAL_FIELD_OVERRIDE" | "COMPILER_MISSING_SCALAR" | "COMPILER_MISSING_ENUM" | "COMPILER_DANGLING_RELATION" | "COMPILER_UNAVAILABLE_OPERATION" | "COMPILER_UNAVAILABLE_CAPABILITY" | "COMPILER_INVALID_LIFECYCLE" | "COMPILER_MISSING_READ_BEHAVIOR" | "COMPILER_INVALID_BEHAVIOR_DEPENDENCY"
2
2
  /**
3
3
  * The finished, hashed client projection is not a structurally valid
4
- * `ClientContract` (`validateClientContractStructure`; Phase 10 R3, the
5
- * architect's code, 2026-10-05). A framework-bug guard: the server never
6
- * serves what its own generator would refuse. `path` is the JSONPath
7
- * inside the ClientContract (`$.enums.status.values[1]`).
4
+ * `ClientContract`. A framework-bug guard: the server never serves what its own
5
+ * generator would refuse. `path` is the JSONPath inside the ClientContract
6
+ * (`$.enums.status.values[1]`).
8
7
  */
9
8
  | "COMPILER_INVALID_CLIENT_CONTRACT";
10
9
  export type ContractCompilerDiagnostic = {
@@ -17,7 +17,7 @@ export type ContractCompilationResult = {
17
17
  /**
18
18
  * Whether writing `configured` VERBATIM as capability member `key` would advertise
19
19
  * something `baseline` does not — the question the `fields` walk asks before it
20
- * copies a value onto an adapter field (F-817).
20
+ * copies a value onto an adapter field.
21
21
  *
22
22
  * Answered on the member's AXIS, off the same `satisfies`-pinned table the
23
23
  * restriction walk and the output gate read, and the baseline is read through the
@@ -29,11 +29,12 @@ export type ContractCompilationResult = {
29
29
  *
30
30
  * The unqualified forms keep their meaning: `true` and a bare token list claim
31
31
  * every position on the axis, so either one over a qualified baseline is an
32
- * addition — writing it verbatim would widen the member (C-855).
32
+ * addition — writing it verbatim would widen the member.
33
33
  *
34
34
  * A key no axis covers, and a value its axis does not admit, are not additions;
35
- * they are unrepresentable, and the output gate ({@link validateCapabilityRepresentation})
36
- * is the one place that says so. So is a position off the axis.
35
+ * they are unrepresentable, and the output gate ({@link
36
+ * validateCapabilityRepresentation}) is the one place that says so. So is a
37
+ * position off the axis.
37
38
  *
38
39
  * Exported for its unit test only; it is not part of the package surface.
39
40
  */
@@ -150,36 +150,11 @@ function addConfiguredScalarField(config, path, diagnostics) {
150
150
  },
151
151
  };
152
152
  }
153
- /**
154
- * Whether writing `configured` VERBATIM as capability member `key` would advertise
155
- * something `baseline` does not — the question the `fields` walk asks before it
156
- * copies a value onto an adapter field (F-817).
157
- *
158
- * Answered on the member's AXIS, off the same `satisfies`-pinned table the
159
- * restriction walk and the output gate read, and the baseline is read through the
160
- * shape's own owners: {@link holdsAt} for a position list, the `…At` readers for a
161
- * scope-qualified token arm. Never off the runtime shape of the value: an
162
- * object-shaped arm used to match no branch and pass unexamined, and `true` was
163
- * compared to the baseline with `!== true`, which reads a qualified baseline as
164
- * *not advertised* even where it holds in every position.
165
- *
166
- * The unqualified forms keep their meaning: `true` and a bare token list claim
167
- * every position on the axis, so either one over a qualified baseline is an
168
- * addition — writing it verbatim would widen the member (C-855).
169
- *
170
- * A key no axis covers, and a value its axis does not admit, are not additions;
171
- * they are unrepresentable, and the output gate ({@link validateCapabilityRepresentation})
172
- * is the one place that says so. So is a position off the axis.
173
- *
174
- * Exported for its unit test only; it is not part of the package surface.
175
- */
176
153
  export function capabilityAddsBaseline(fieldKind, baseline, key, configured) {
177
154
  const axis = capabilityAxisFor(fieldKind, key);
178
155
  if (axis === undefined) {
179
156
  return false;
180
157
  }
181
- // Every arm below answers `false` for a denial (`false`) and for no value at
182
- // all: neither claims a token or a position.
183
158
  const baselineValue = baseline[key];
184
159
  switch (axis.kind) {
185
160
  case "flag":
@@ -216,12 +191,6 @@ export function capabilityAddsBaseline(fieldKind, baseline, key, configured) {
216
191
  }
217
192
  }
218
193
  }
219
- /**
220
- * The tokens a scope-qualified member value claims, and the positions it claims
221
- * them in: a bare token list claims every position on the axis, a
222
- * `{ <tokenKey>, scopes }` arm the positions it names. `undefined` for any other
223
- * shape, which is the output gate's to refuse.
224
- */
225
194
  function scopedTokenClaim(axis, configured) {
226
195
  if (isTokenList(configured)) {
227
196
  return { tokens: configured, positions: axis.axis };
@@ -236,11 +205,6 @@ function scopedTokenClaim(axis, configured) {
236
205
  }
237
206
  return undefined;
238
207
  }
239
- /**
240
- * What a scope-qualified baseline member advertises at one position, through the
241
- * shape's own `…At` owner for its token key. A baseline that is neither arm
242
- * advertises nothing — the same answer an absent member gives.
243
- */
244
208
  function advertisedTokensAt(tokenKey, baselineValue, position) {
245
209
  if (!isTokenList(baselineValue) && !isRecord(baselineValue)) {
246
210
  return undefined;
@@ -406,12 +370,6 @@ function applyBehaviors(projection, scope, config, diagnostics, allowRestrictedM
406
370
  }
407
371
  }
408
372
  }
409
- /**
410
- * Pinned against the restriction type AND the Contract member type, so a capability
411
- * member added to either surface fails to compile HERE rather than reaching the
412
- * restriction walk with no axis and being skipped, or reaching the output gate with
413
- * no axis and being refused.
414
- */
415
373
  const SCALAR_CAPABILITY_AXES = {
416
374
  select: { kind: "flag" },
417
375
  filter: { kind: "tokens" },
@@ -420,7 +378,6 @@ const SCALAR_CAPABILITY_AXES = {
420
378
  create: { kind: "tokens" },
421
379
  update: { kind: "tokens" },
422
380
  };
423
- /** @see SCALAR_CAPABILITY_AXES — the same pin, on the relation surface. */
424
381
  const RELATION_CAPABILITY_AXES = {
425
382
  select: { kind: "scopes", axis: PROJECTION_SCOPES },
426
383
  include: { kind: "scopes", axis: PROJECTION_SCOPES },
@@ -437,8 +394,6 @@ const RELATION_CAPABILITY_AXES = {
437
394
  };
438
395
  function capabilityAxisFor(kind, key) {
439
396
  const axes = kind === "scalar" ? SCALAR_CAPABILITY_AXES : RELATION_CAPABILITY_AXES;
440
- // An OWN key: the table is a plain object, and `axes["toString"]` would answer
441
- // with a prototype method rather than with "no axis".
442
397
  return Object.hasOwn(axes, key) ? axes[key] : undefined;
443
398
  }
444
399
  function unavailableCapability(path, message, diagnostics) {
@@ -456,10 +411,6 @@ function narrowedScopes(axis, holdsAtScope, requested, key, path, diagnostics) {
456
411
  if (requested.length === 0) {
457
412
  return { outcome: "denied" };
458
413
  }
459
- // Membership of the axis is asked first, and of the axis ARRAY rather than of a
460
- // literal: the unqualified baseline holds at every position, so a position that
461
- // is not a position at all would pass the `holdsAt` read and be written into the
462
- // Contract. The type forbids it; a configuration assembled at runtime does not.
463
414
  const unavailable = requested.filter((scope) => !axis.includes(scope) || !holdsAtScope(scope));
464
415
  if (unavailable.length > 0) {
465
416
  unavailableCapability(path, `capability "${key}" requested unavailable scopes: ${unavailable.join(", ")}`, diagnostics);
@@ -467,12 +418,6 @@ function narrowedScopes(axis, holdsAtScope, requested, key, path, diagnostics) {
467
418
  }
468
419
  return { outcome: "narrowed", scopes: [...requested] };
469
420
  }
470
- /**
471
- * A projection member narrowed by position. The baseline is consulted through
472
- * {@link holdsAt} rather than by inspecting the member's arm, so the unqualified
473
- * baseline keeps meaning *holds in every position* and a narrowing against it is a
474
- * narrowing rather than a mismatch.
475
- */
476
421
  function applyScopeRestriction(axis, baselineValue, current, key, requested, path, diagnostics) {
477
422
  const baseline = baselineValue;
478
423
  const narrowing = narrowedScopes(axis, (scope) => holdsAt(baseline, scope), requested, key, path, diagnostics);
@@ -485,19 +430,6 @@ function applyScopeRestriction(axis, baselineValue, current, key, requested, pat
485
430
  }
486
431
  current[key] = narrowing.scopes;
487
432
  }
488
- /**
489
- * A scope-qualified token member narrowed on either axis, or both. The tokens and
490
- * the positions are read through the shape owners — {@link advertisedDirectives} /
491
- * {@link advertisedReducers} for the token list, and the `…At` pair for the
492
- * positions — so the two arms of the Contract member are never destructured here.
493
- *
494
- * A token-only narrowing **keeps the qualifier the baseline carries**: narrowing
495
- * what may be written is not a statement about where it may be written, and
496
- * dropping the qualifier would widen the member to every position (C-855).
497
- *
498
- * Answers whether the restriction was a shape this member admits at all. `false`
499
- * leaves the diagnostic to the caller, which owns the one message for every axis.
500
- */
501
433
  function applyScopedTokenRestriction(tokenKey, axis, baselineValue, current, key, value, path, diagnostics) {
502
434
  const requestedTokens = Array.isArray(value)
503
435
  ? value
@@ -546,18 +478,11 @@ function applyScopedTokenRestriction(tokenKey, axis, baselineValue, current, key
546
478
  return true;
547
479
  }
548
480
  function applyCapabilityRestriction(fieldKind, inherited, restoration, current, key, value, path, diagnostics) {
549
- // Denial needs no baseline: a layer may always refuse to carry a capability
550
- // forward, including one an earlier layer already removed.
551
481
  if (value === false) {
552
482
  delete current[key];
553
483
  return;
554
484
  }
555
485
  const axis = capabilityAxisFor(fieldKind, key);
556
- // The member is measured against what this layer INHERITED when it inherited
557
- // one, and against the root baseline only when it inherited none — the one
558
- // split, by role, that every arm below reads through (F-815, LayerBaselines).
559
- // The operations axis draws the same line: an advertised variant keeps what it
560
- // carries, an absent one is restored.
561
486
  const baselineValue = inherited?.[key] ?? restoration[key];
562
487
  if (axis === undefined ||
563
488
  baselineValue === undefined ||
@@ -565,13 +490,6 @@ function applyCapabilityRestriction(fieldKind, inherited, restoration, current,
565
490
  unavailableCapability(path, `capability "${key}" is not available in the canonical baseline`, diagnostics);
566
491
  return;
567
492
  }
568
- // `true` takes the measured answer VERBATIM, qualifier included: what this layer
569
- // inherited when there is one — *available, as narrowed above me* — and the
570
- // root baseline's answer when the member is being restored. Preserving a
571
- // qualified capability is not widening it — the distinction the operations axis
572
- // draws between preserving a descriptor and replacing it with the unqualified
573
- // arm — and the clone is of the ceiling this layer is measured against, so it
574
- // can never exceed it.
575
493
  if (value === true) {
576
494
  current[key] = cloneValue(baselineValue);
577
495
  return;
@@ -640,11 +558,6 @@ function applyOperationRestrictions(restoration, current, restrictions, path, di
640
558
  diagnostics.push(diagnostic("COMPILER_UNAVAILABLE_OPERATION", `${path}.${family}.${variant}`, `operation "${family}.${variant}" is not available in the canonical baseline`));
641
559
  continue;
642
560
  }
643
- // An already-advertised variant keeps the availability this projection
644
- // carries: an earlier layer may have narrowed `true` to a descriptor, and
645
- // later layers only narrow (C-858). Only a variant this scope restores
646
- // takes the baseline's availability, cloned so that no two projections
647
- // share one descriptor object.
648
561
  const target = currentFamily;
649
562
  if (!isOperationVariantAvailable(target[variant])) {
650
563
  target[variant] = cloneValue(baselineAvailability);
@@ -742,9 +655,6 @@ function reconcileIdentifiers(resource, baseline, restrictions) {
742
655
  : undefined;
743
656
  if (isOperationVariantAvailable(baselineAvailability)) {
744
657
  const targetFamily = isRecord(currentFamily) ? currentFamily : {};
745
- // Restoring the variant must not restate its availability: a variant this
746
- // projection still advertises keeps the descriptor it carries, and one
747
- // identifiers bring back takes the baseline's, cloned per projection.
748
658
  if (!isOperationVariantAvailable(targetFamily[variant])) {
749
659
  targetFamily[variant] = cloneValue(baselineAvailability);
750
660
  }
@@ -799,11 +709,6 @@ function validateFieldLifecycle(field, path, diagnostics) {
799
709
  }
800
710
  }
801
711
  if (lifecycle.includes("VIRTUAL") &&
802
- // Not `=== true`: a projection member may carry the scopes it holds in, and a
803
- // field selectable in one scope needs an effective read behavior exactly as
804
- // much as one selectable in every scope. The question is scope-blind because
805
- // this check has no scope — `holdsInAnyScope` is the shape owner's name for
806
- // that, so there is no hand-rolled comparison here either.
807
712
  holdsInAnyScope(capabilities.select) &&
808
713
  !lifecycle.includes("COMPUTED_ON_READ")) {
809
714
  diagnostics.push(diagnostic("COMPILER_MISSING_READ_BEHAVIOR", path, "selectable VIRTUAL field requires an effective read behavior"));
@@ -812,13 +717,6 @@ function validateFieldLifecycle(field, path, diagnostics) {
812
717
  function isTokenList(value) {
813
718
  return (Array.isArray(value) && value.every((entry) => typeof entry === "string"));
814
719
  }
815
- /**
816
- * Why a position list is not one the Contract can carry on this axis, or
817
- * `undefined` when it is. Empty is refused for the reason `ProjectionScopes` and
818
- * `WriteScopes` give — absent is already the one encoding of unavailable (C-843) —
819
- * and membership is asked of the axis ARRAY, so a position from the other axis is
820
- * as off-axis as a string that is no position at all.
821
- */
822
720
  function positionListFault(axis, positions) {
823
721
  if (positions.length === 0) {
824
722
  return "an empty position list";
@@ -828,17 +726,6 @@ function positionListFault(axis, positions) {
828
726
  ? `positions not on its axis: ${offAxis.join(", ")}`
829
727
  : undefined;
830
728
  }
831
- /**
832
- * Why a member value is not a shape its axis admits, or `undefined` when it is —
833
- * each arm the Contract type declares for that axis, and nothing else.
834
- *
835
- * Shape only. Whether the value is NARROWER than the layer it derives from is
836
- * C-858's question, and the restriction walk already answers it against
837
- * {@link LayerBaselines} (F-815); asking it again here would be the same rule in a
838
- * second place. Token vocabularies are not checked either: the token unions are
839
- * types with no runtime registry, and inventing one here would be a second source
840
- * of truth for them.
841
- */
842
729
  function representationFault(axis, value) {
843
730
  switch (axis.kind) {
844
731
  case "flag":
@@ -867,21 +754,8 @@ function representationFault(axis, value) {
867
754
  }
868
755
  }
869
756
  }
870
- /**
871
- * The output gate (F-816): every capability member a finished projection carries
872
- * is checked against the member-to-axis table before the projection can be hashed.
873
- *
874
- * The projection is assembled from configuration that may be built at runtime and
875
- * from an adapter model that is a runtime value, and two of the walks that assemble
876
- * it copy a member verbatim; the canonicalizer orders what it is handed and
877
- * deliberately rewrites nothing it does not recognise. So the type is not the
878
- * guard, the producers are not the guard, and without this the compiler emits —
879
- * and hashes — whatever its walks assembled.
880
- */
881
757
  function validateCapabilityRepresentation(field, path, diagnostics) {
882
758
  for (const [key, value] of Object.entries(field.capabilities)) {
883
- // No `undefined` skip: an own property holding no value is not canonical JSON,
884
- // and skipping it here hands the canonicalizer a throw instead of a diagnostic.
885
759
  const axis = capabilityAxisFor(field.kind, key);
886
760
  const fault = axis === undefined
887
761
  ? "no capability axis covers it"
@@ -953,7 +827,6 @@ function projectDerivedScope(model, scopeName, core, scope, diagnostics) {
953
827
  validateProjection(projection, baseline, scopeName, scope.restrictions, diagnostics);
954
828
  return projection;
955
829
  }
956
- /** Compile Core first, then derive Application and Client from the Core compilation lineage. */
957
830
  export async function compileContracts(model, config) {
958
831
  const compilerConfig = config;
959
832
  const diagnostics = [];
@@ -974,11 +847,6 @@ export async function compileContracts(model, config) {
974
847
  ...clientHashInput,
975
848
  protocol: { version: AVENTARA_PROTOCOL_VERSION, hash },
976
849
  });
977
- // R3 (Phase 10): the server checks its own ClientContract before serving
978
- // it — here, so construction fails before listen, and every consumer
979
- // (`framework.client`, `/_transactions`, `/_contract`, the generator)
980
- // reads a value that passed. A refusal is a framework bug or an Adapter
981
- // defect the projection copied through, never a caller's.
982
850
  const structure = validateClientContractStructure(client);
983
851
  if (!structure.valid) {
984
852
  return {
@@ -28,8 +28,8 @@ export type ResolvedFrameworkScopeConfig<M extends AdapterModel = AdapterModel>
28
28
  };
29
29
  export type ResolvedFrameworkConfig<M extends AdapterModel = AdapterModel> = {
30
30
  /**
31
- * The mount path in its canonical form (R4, F-822): `""` at the root,
32
- * otherwise `/seg(/seg)*`. Normalized once, here; every reader sees this.
31
+ * The mount path in its canonical form: `""` at the root, otherwise `/seg(/seg)*`.
32
+ * Normalized once, here; every reader sees this.
33
33
  */
34
34
  readonly entrypoint: string;
35
35
  readonly adapter: Adapter<M>;
@@ -77,10 +77,6 @@ function resolveScope(root, scoped) {
77
77
  pipelines: resolvePipelines(root.pipelines, scoped?.pipelines),
78
78
  };
79
79
  }
80
- /**
81
- * The entrypoint's canonical mount path. Validation refuses a non-canonical one
82
- * first; a caller that resolves without validating meets the same diagnostic.
83
- */
84
80
  function resolveEntrypoint(entrypoint) {
85
81
  const normalized = normalizeEntrypoint(entrypoint);
86
82
  if (!normalized.ok) {
@@ -90,7 +86,6 @@ function resolveEntrypoint(entrypoint) {
90
86
  }
91
87
  return normalized.path;
92
88
  }
93
- /** Resolve root, application, and client configuration without compiling Contracts. */
94
89
  export function resolveFrameworkConfig(config) {
95
90
  const root = {
96
91
  ...(hasOwn(config, "fields") ? { fields: config.fields } : {}),
@@ -1,8 +1,8 @@
1
1
  import type { ConfigDiagnostic } from "./config-diagnostic.js";
2
2
  /**
3
- * The refusal of an entrypoint whose mount path is not canonical (R4, F-822,
4
- * Q15), from the normalizer's message: it names the defect and the rule —
5
- * never the value, which may carry credentials.
3
+ * The refusal of an entrypoint whose mount path is not canonical, from the
4
+ * normalizer's message: it names the defect and the rule — never the value, which
5
+ * may carry credentials.
6
6
  */
7
7
  export declare function entrypointRefusalDiagnostic(message: string): ConfigDiagnostic;
8
8
  /** Validate framework-owned authoring structure; later semantic leaves remain opaque. */
@@ -47,11 +47,6 @@ function isPlainRecord(value) {
47
47
  function diagnostic(code, path, message) {
48
48
  return { code, path, message };
49
49
  }
50
- /**
51
- * The refusal of an entrypoint whose mount path is not canonical (R4, F-822,
52
- * Q15), from the normalizer's message: it names the defect and the rule —
53
- * never the value, which may carry credentials.
54
- */
55
50
  export function entrypointRefusalDiagnostic(message) {
56
51
  return diagnostic("CONFIG_INVALID_VALUE", "entrypoint", `entrypoint ${message}`);
57
52
  }
@@ -151,8 +146,6 @@ function validateAdapter(value, diagnostics) {
151
146
  return;
152
147
  }
153
148
  const adapter = value;
154
- // One property read, not two: `adapter.model` is a property of the
155
- // adapter, so validation must not observe it more times than it needs.
156
149
  const model = adapter.model;
157
150
  if (model === null || typeof model !== "object") {
158
151
  diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "adapter.model", "adapter.model must be an object"));
@@ -165,7 +158,6 @@ function validateAdapter(value, diagnostics) {
165
158
  diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "adapter.transaction", "adapter.transaction must be a function when provided"));
166
159
  }
167
160
  }
168
- /** Validate framework-owned authoring structure; later semantic leaves remain opaque. */
169
161
  export function validateFrameworkConfig(value) {
170
162
  const diagnostics = [];
171
163
  if (!isPlainRecord(value)) {
@@ -28,13 +28,8 @@ export type AddedScalarFieldConfig<M extends AdapterModel = AdapterModel> = Omit
28
28
  /**
29
29
  * The shape one authored field name admits, by what the adapter knows of it.
30
30
  *
31
- * `string extends AdapterFieldKey<M, R>` is the wide default, and is
32
- * load-bearing for B4 exactly as it is in `FieldRestrictionsFor`: against an
33
- * abstract `AdapterModel` the discovered key set is erased to `string`, so
34
- * every name would otherwise land in the adapter-known bucket and every
35
- * added field would be rejected for carrying a `type`. Where there is no
36
- * discovered key set to discriminate on, the answer is today's undivided
37
- * {@link FrameworkScalarFieldConfig}.
31
+ * Where there is no discovered key set to discriminate on, the answer is today's
32
+ * undivided {@link FrameworkScalarFieldConfig}.
38
33
  */
39
34
  type ScalarFieldConfigFor<M extends AdapterModel, R extends FrameworkResourceKey<M>, F> = string extends AdapterFieldKey<M, R> ? FrameworkScalarFieldConfig<M> : F extends AdapterFieldKey<M, R> ? M["resources"][R]["fields"][F] extends {
40
35
  readonly kind: "relation";
@@ -1,18 +1,3 @@
1
- /**
2
- * Authors stage 1 of a configuration: the `fields` block, checked against
3
- * what the adapter discovered and returned unwidened.
4
- *
5
- * The returned literal is stage 2's `Cfg` fields block, so the names it adds
6
- * are nameable from `restrictions`, `behaviors` and `dependsOn`.
7
- *
8
- * `M` is bound by the **model value**, not a type argument: TypeScript has
9
- * no partial type-argument inference, so `defineFields<M>({ … })` would
10
- * force `Self` to be written out by hand. The model is already a value at
11
- * the authoring site, so binding it there costs nothing.
12
- *
13
- * The model argument is type-level only — the returned block is the authored
14
- * one, unchanged.
15
- */
16
1
  export function defineFields(_model, fields) {
17
2
  return fields;
18
3
  }
@@ -26,9 +26,8 @@ type FieldsBlockKey<Block, R extends string> = [Block] extends [never] ? never :
26
26
  * The field names `Cfg`'s own root `fields` block adds for `R`.
27
27
  *
28
28
  * Under the default `Cfg` this degenerates to `string`: `AnyFieldsBlock` maps
29
- * every resource name to an open record, so the effective key set widens back
30
- * to an index-signature-compatible `string` and today's wide acceptance is
31
- * preserved (B4).
29
+ * every resource name to an open record, so the effective key set widens back to
30
+ * an index-signature-compatible `string` and today's wide acceptance is preserved.
32
31
  */
33
32
  export type ConfigFieldKey<M extends AdapterModel, Cfg, R extends FrameworkResourceKey<M>> = FieldsBlockKey<FieldsBlockOf<Cfg>, R>;
34
33
  /**
@@ -37,11 +36,8 @@ export type ConfigFieldKey<M extends AdapterModel, Cfg, R extends FrameworkResou
37
36
  * Nothing else in the framework may compute a field-key set; `restrictions`,
38
37
  * `behaviors` and `dependsOn` all key on this type.
39
38
  *
40
- * There is deliberately no subtraction here. A field hidden by
41
- * `restrictions` stays present in the narrowed key set, per ADR 0009's
42
- * Consequences: restriction is projection policy applied at compilation, not
43
- * a change to the resource's field identity. A `HiddenFieldKey` subtraction
44
- * would contradict the Accepted ADR and must not be reintroduced.
39
+ * There is deliberately no subtraction here. A `HiddenFieldKey` subtraction would
40
+ * contradict the Accepted ADR and must not be reintroduced.
45
41
  */
46
42
  export type EffectiveFieldKey<M extends AdapterModel, Cfg, R extends FrameworkResourceKey<M>> = AdapterFieldKey<M, R> | ConfigFieldKey<M, Cfg, R>;
47
43
  /** The overlay `Cfg` carries for `Origin`, or `never` when it declares none. */
@@ -1,8 +1,8 @@
1
1
  /**
2
- * The framework entrypoint's mount path, in its one canonical form (R4, F-822,
3
- * Q15): `""` at the root, otherwise `/seg(/seg)*` — one leading slash, no
4
- * trailing slash, no empty segment. Root is the empty string, not `"/"`, so a
5
- * route joins onto it by concatenation with no special case.
2
+ * The framework entrypoint's mount path, in its one canonical form: `""` at the
3
+ * root, otherwise `/seg(/seg)*` — one leading slash, no trailing slash, no empty
4
+ * segment. Root is the empty string, not `"/"`, so a route joins onto it by
5
+ * concatenation with no special case.
6
6
  */
7
7
  export type EntrypointPath = "" | `/${string}`;
8
8
  /**
@@ -27,7 +27,7 @@ export type EntrypointNormalization = {
27
27
  };
28
28
  /**
29
29
  * `AvProtocol.normalizeEntrypoint` — a mount path, as written, to its canonical
30
- * form or a refusal (R4, F-822, Q15).
30
+ * form or a refusal.
31
31
  *
32
32
  * The one source of the rule: config resolution stores the canonical form as
33
33
  * `framework.entrypoint`, config validation turns a refusal into a `CONFIG_`
@@ -36,8 +36,8 @@ export type EntrypointNormalization = {
36
36
  * resolved or percent-encoded anything. Execution code reads it from here;
37
37
  * `@aventara/core/protocol` re-exports it, and the main entry does not.
38
38
  *
39
- * Checked in order, so each value has one reason: whitespace, a scheme (`://`),
40
- * a query, a fragment, a `..` or `.` segment (either separator, `%2e` spelling
39
+ * Checked in order, so each value has one reason: whitespace, a scheme (`://`), a
40
+ * query, a fragment, a `..` or `.` segment (either separator, `%2e` spelling
41
41
  * included), a backslash, a non-ASCII character, a `%`, and finally any other
42
42
  * character outside RFC 3986's `pchar`.
43
43
  */
@@ -1,4 +1,3 @@
1
- /** What a canonical segment is, stated once for every refusal's message. */
2
1
  const MOUNT_PATH_RULE = "a mount path is /-separated segments of ASCII letters, digits and -._~!$&'()*+,;=:@ only";
3
2
  const DEFECTS = {
4
3
  whitespace: "contains whitespace",
@@ -12,12 +11,7 @@ const DEFECTS = {
12
11
  "percent-encoding": "contains a percent sign, and percent-encoding is refused",
13
12
  character: "contains a character a path segment may not carry unencoded",
14
13
  };
15
- /**
16
- * RFC 3986 `pchar` without `%` (Q15): unreserved, sub-delims, `:` and `@`. A
17
- * canonical segment is one or more of these and nothing else.
18
- */
19
14
  const CANONICAL_SEGMENT = /^[A-Za-z0-9\-._~!$&'()*+,;=:@]+$/u;
20
- /** `.` or `..`, spelled as URL resolution recognises it: `.` or `%2e`, any case. */
21
15
  const DOT_SEGMENT = /^(?:\.|%2e)$/iu;
22
16
  const DOT_DOT_SEGMENT = /^(?:\.|%2e){2}$/iu;
23
17
  function refusal(reason) {
@@ -27,22 +21,6 @@ function refusal(reason) {
27
21
  message: `${DEFECTS[reason]}; ${MOUNT_PATH_RULE}`,
28
22
  };
29
23
  }
30
- /**
31
- * `AvProtocol.normalizeEntrypoint` — a mount path, as written, to its canonical
32
- * form or a refusal (R4, F-822, Q15).
33
- *
34
- * The one source of the rule: config resolution stores the canonical form as
35
- * `framework.entrypoint`, config validation turns a refusal into a `CONFIG_`
36
- * diagnostic, and the client generator's `resolveEntrypoint` hands it the mount
37
- * path of the URL it is given — as written, before a URL parser has trimmed,
38
- * resolved or percent-encoded anything. Execution code reads it from here;
39
- * `@aventara/core/protocol` re-exports it, and the main entry does not.
40
- *
41
- * Checked in order, so each value has one reason: whitespace, a scheme (`://`),
42
- * a query, a fragment, a `..` or `.` segment (either separator, `%2e` spelling
43
- * included), a backslash, a non-ASCII character, a `%`, and finally any other
44
- * character outside RFC 3986's `pchar`.
45
- */
46
24
  export function normalizeEntrypoint(value) {
47
25
  if (/\s/u.test(value))
48
26
  return refusal("whitespace");
@@ -10,13 +10,13 @@ export type FrameworkFieldBehaviorConfig<M extends AdapterModel = AdapterModel,
10
10
  readonly read?: false | FrameworkReadBehavior<M, Cfg, R>;
11
11
  };
12
12
  /**
13
- * Executable behavior bindings for one Resource, keyed on the single
14
- * effective field-key answer.
13
+ * Executable behavior bindings for one Resource, keyed on the single effective
14
+ * field-key answer.
15
15
  *
16
- * `Partial` is required, not cosmetic: a mapped type over a literal key set
17
- * would otherwise demand a binding for every field of the Resource. Under the
18
- * default `Cfg` the key set is `string`, the mapped half collapses to one
19
- * index signature and today's wide acceptance is preserved (B4).
16
+ * `Partial` is required, not cosmetic: a mapped type over a literal key set would
17
+ * otherwise demand a binding for every field of the Resource. Under the default
18
+ * `Cfg` the key set is `string`, the mapped half collapses to one index signature
19
+ * and today's wide acceptance is preserved.
20
20
  */
21
21
  export type FrameworkResourceBehaviorsConfig<M extends AdapterModel = AdapterModel, Cfg = AnyFrameworkConfig, R extends FrameworkResourceKey<M> = FrameworkResourceKey<M>> = {
22
22
  readonly fields: Readonly<Partial<{