@aventara/core 1.0.0-rc.10 → 1.0.0-rc.11

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 (110) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/ERRORS.md +82 -82
  3. package/README.md +57 -1
  4. package/dist/compiler/contract-compiler-diagnostic.guidance.js +1 -1
  5. package/dist/compiler/contract.compiler.js +56 -9
  6. package/dist/compiler/create-requirements.projector.js +1 -3
  7. package/dist/compiler/field-validator.compiler.js +1 -3
  8. package/dist/compiler/managed-elsewhere.projector.js +5 -5
  9. package/dist/config/cache-stage.factory.d.ts +24 -0
  10. package/dist/config/cache-stage.factory.js +3 -0
  11. package/dist/config/config.resolver.js +1 -7
  12. package/dist/config/config.validator.js +61 -13
  13. package/dist/config/exact-framework-config.d.ts +6 -0
  14. package/dist/config/field-compute.resolver.js +1 -3
  15. package/dist/config/pipeline-config.d.ts +16 -0
  16. package/dist/config/pipeline-tree.resolver.js +2 -3
  17. package/dist/contracts/canonical-json.writer.d.ts +7 -0
  18. package/dist/contracts/canonical-json.writer.js +55 -0
  19. package/dist/contracts/client-contract-structure.validator.d.ts +64 -0
  20. package/dist/contracts/client-contract-structure.validator.js +12 -0
  21. package/dist/contracts/contract-canonicalizer.js +5 -0
  22. package/dist/contracts/contract-limits.d.ts +6 -0
  23. package/dist/contracts/contract-limits.js +2 -0
  24. package/dist/contracts/contract.d.ts +15 -0
  25. package/dist/contracts/json-schema.projector.js +1 -3
  26. package/dist/framework/access-facade.js +1 -3
  27. package/dist/framework/framework.factory.js +42 -13
  28. package/dist/framework/operation-facade.d.ts +67 -6
  29. package/dist/framework/operation-facade.js +7 -0
  30. package/dist/framework/operation-set.runner.d.ts +47 -0
  31. package/dist/framework/operation-set.runner.js +168 -0
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.js +2 -0
  34. package/dist/internal.d.ts +2 -0
  35. package/dist/internal.js +2 -0
  36. package/dist/operations/operation-validator-core.js +2 -4
  37. package/dist/operations/structural-limits.walker.js +1 -3
  38. package/dist/policy/access-question.runtime.js +1 -3
  39. package/dist/policy/policy-admission.js +1 -3
  40. package/dist/policy/policy-after-update.runtime.js +1 -3
  41. package/dist/policy/policy-nested-write.runtime.js +3 -12
  42. package/dist/policy/policy-read.runtime.js +1 -3
  43. package/dist/policy/policy-reference-write.runtime.js +2 -11
  44. package/dist/policy/policy-request.d.ts +31 -0
  45. package/dist/policy/policy-request.js +69 -17
  46. package/dist/policy/policy-session.js +1 -3
  47. package/dist/policy/policy-write.runtime.js +1 -3
  48. package/dist/prebuilt/core-version.generated.d.ts +1 -1
  49. package/dist/prebuilt/core-version.generated.js +1 -1
  50. package/dist/prebuilt/prebuilt-changes.js +1 -3
  51. package/dist/prebuilt/prebuilt-contracts.loader.js +1 -3
  52. package/dist/prebuilt/prebuilt-inputs.fingerprint.js +1 -3
  53. package/dist/protocol/absent-route.responder.d.ts +69 -16
  54. package/dist/protocol/absent-route.responder.js +75 -31
  55. package/dist/protocol/contract-document.responder.d.ts +7 -0
  56. package/dist/protocol/contract-document.responder.js +3 -2
  57. package/dist/protocol/http-request.decoder.d.ts +33 -0
  58. package/dist/protocol/http-request.decoder.js +23 -7
  59. package/dist/protocol/http-request.reader.d.ts +4 -0
  60. package/dist/protocol/http-request.reader.js +11 -2
  61. package/dist/protocol/http-response.encoder.d.ts +12 -0
  62. package/dist/protocol/http-response.encoder.js +15 -1
  63. package/dist/protocol/operation-response.guard.js +1 -3
  64. package/dist/protocol/operation-set.decoder.d.ts +48 -0
  65. package/dist/protocol/operation-set.decoder.js +185 -0
  66. package/dist/protocol/operation-set.handler.d.ts +27 -0
  67. package/dist/protocol/operation-set.handler.js +179 -0
  68. package/dist/protocol/protocol-headers.d.ts +9 -0
  69. package/dist/protocol/protocol-headers.js +12 -5
  70. package/dist/protocol/protocol-surface.d.ts +12 -4
  71. package/dist/protocol/protocol-surface.js +34 -1
  72. package/dist/protocol/protocol.binder.d.ts +37 -1
  73. package/dist/protocol/protocol.binder.js +2 -0
  74. package/dist/protocol/protocol.handler.d.ts +35 -2
  75. package/dist/protocol/protocol.handler.js +84 -8
  76. package/dist/protocol/read-cache.responder.d.ts +26 -0
  77. package/dist/protocol/read-cache.responder.js +47 -0
  78. package/dist/protocol/read-query.codec.d.ts +34 -0
  79. package/dist/protocol/read-query.codec.js +125 -0
  80. package/dist/runtime/computed-read-runtime.js +2 -8
  81. package/dist/runtime/create-requirement.js +1 -3
  82. package/dist/runtime/diagnostics-reporter.d.ts +6 -1
  83. package/dist/runtime/diagnostics-reporter.js +3 -8
  84. package/dist/runtime/error.catalog.d.ts +2 -2
  85. package/dist/runtime/error.catalog.js +1 -1
  86. package/dist/runtime/field-stage.runtime.d.ts +0 -2
  87. package/dist/runtime/field-stage.runtime.js +1 -7
  88. package/dist/runtime/field-validator.runtime.js +2 -1
  89. package/dist/runtime/mutation-planner.js +1 -3
  90. package/dist/runtime/nested-write.walker.js +2 -1
  91. package/dist/runtime/output-validator.js +1 -3
  92. package/dist/runtime/owned-execution.registry.d.ts +22 -2
  93. package/dist/runtime/pipeline.d.ts +5 -1
  94. package/dist/runtime/record.guard.d.ts +14 -0
  95. package/dist/runtime/record.guard.js +10 -0
  96. package/dist/runtime/request-envelope.validator.js +13 -10
  97. package/dist/runtime/scalar-runtime.d.ts +0 -10
  98. package/dist/runtime/scalar-runtime.js +1 -10
  99. package/dist/runtime/thenable.guard.d.ts +7 -0
  100. package/dist/runtime/thenable.guard.js +5 -0
  101. package/dist/runtime/unsent-value.normalizer.js +2 -1
  102. package/dist/transactions/operation-arguments-encoder.js +1 -7
  103. package/dist/transactions/sql-statement.validator.js +2 -1
  104. package/dist/transactions/transaction-plan-assembler.js +1 -7
  105. package/dist/transactions/transaction-plan-validator.js +4 -6
  106. package/dist/transactions/transaction-reference-collector.js +8 -10
  107. package/dist/transactions/transaction-reference-resolver.js +1 -3
  108. package/dist/transactions/transaction-runtime.js +31 -2
  109. package/dist/transactions/transaction-stage.runtime.js +1 -3
  110. package/package.json +1 -1
@@ -8,6 +8,7 @@ import { createReporter, } from "../runtime/diagnostics-reporter.js";
8
8
  import { ADAPTER_FAILURE_MESSAGE, deliberateRefusalCode, } from "../runtime/error-boundary.js";
9
9
  import { internalFailure, operationFailure, operationSuccess, } from "../runtime/operation-response.js";
10
10
  import { VALIDATION_OUTCOME_MESSAGES } from "../runtime/outcome-mapper.js";
11
+ import { isRecord } from "../runtime/record.guard.js";
11
12
  import { requestStateOf } from "../runtime/request-state.resolver.js";
12
13
  import { normalizeOperationScalarValues } from "../runtime/scalar-runtime.js";
13
14
  import { admitByPolicy } from "./policy-admission.js";
@@ -21,9 +22,6 @@ const QUESTION_KEYS = new Set([
21
22
  "action",
22
23
  "where",
23
24
  ]);
24
- function isRecord(value) {
25
- return typeof value === "object" && value !== null && !Array.isArray(value);
26
- }
27
25
  const LIMIT_CODES = new Set([
28
26
  "V1013",
29
27
  "V1014",
@@ -3,6 +3,7 @@ import { defaultProjectionFields } from "../runtime/computed-read-runtime.js";
3
3
  import { valueAt, writeRecordPathsOf } from "../runtime/field-stage.runtime.js";
4
4
  import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "../runtime/mutation-planner.js";
5
5
  import { operationFailure } from "../runtime/operation-response.js";
6
+ import { isRecord } from "../runtime/record.guard.js";
6
7
  import { everyOf, noneOf, someOf, } from "./policy-condition.js";
7
8
  import { fieldAccess, } from "./policy-session.js";
8
9
  export function policyRefusal(message) {
@@ -22,9 +23,6 @@ function policyActionsOf(family) {
22
23
  return ["create", "update"];
23
24
  }
24
25
  }
25
- function isRecord(value) {
26
- return value !== null && typeof value === "object" && !Array.isArray(value);
27
- }
28
26
  class FieldWalk {
29
27
  active;
30
28
  used = new Map();
@@ -1,12 +1,10 @@
1
1
  import { adapterPrimaryIdentifier } from "../adapters/adapter-identifier.js";
2
2
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
3
3
  import { frozenCopy } from "../runtime/readonly-value.js";
4
+ import { isRecord } from "../runtime/record.guard.js";
4
5
  import { policyRefusal } from "./policy-admission.js";
5
6
  import { allOf, everyOf, someOf, whereOf, } from "./policy-condition.js";
6
7
  import { identifiedRows } from "./policy-read.runtime.js";
7
- function isRecord(value) {
8
- return value !== null && typeof value === "object" && !Array.isArray(value);
9
- }
10
8
  const fieldLists = new WeakMap();
11
9
  function listOf(core, key, make) {
12
10
  let lists = fieldLists.get(core);
@@ -3,6 +3,7 @@ import { toOneRelinkWithRewrite } from "../contracts/capability.js";
3
3
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
4
4
  import { isRelationMutationDirective } from "../runtime/mutation-planner.js";
5
5
  import { frozenCopy } from "../runtime/readonly-value.js";
6
+ import { isPlainRecord, isRecord } from "../runtime/record.guard.js";
6
7
  import { policyRefusal } from "./policy-admission.js";
7
8
  import { afterUpdate, beforeFields, checkChanged, coveredBefore, rowFieldsOf, unchangedSince, } from "./policy-after-update.runtime.js";
8
9
  import { allOf, noneOf, someOf, whereOf, } from "./policy-condition.js";
@@ -10,16 +11,6 @@ import { NamedRows } from "./policy-named-rows.js";
10
11
  import { identifiedRows } from "./policy-read.runtime.js";
11
12
  import { isHeldTarget } from "./policy-reference-write.runtime.js";
12
13
  import { fieldAccess } from "./policy-session.js";
13
- function isRecord(value) {
14
- return value !== null && typeof value === "object" && !Array.isArray(value);
15
- }
16
- function isPlainObject(value) {
17
- if (!isRecord(value)) {
18
- return false;
19
- }
20
- const prototype = Object.getPrototypeOf(value);
21
- return prototype === Object.prototype || prototype === null;
22
- }
23
14
  function namesReference(selector, references) {
24
15
  if (references === undefined) {
25
16
  return false;
@@ -32,7 +23,7 @@ function namesReference(selector, references) {
32
23
  return (value !== undefined &&
33
24
  value !== null &&
34
25
  !Array.isArray(value) &&
35
- !isPlainObject(value));
26
+ !isPlainRecord(value));
36
27
  }));
37
28
  }
38
29
  const DROPPED = Symbol("dropped");
@@ -46,7 +37,7 @@ function rewritten(value, replaced) {
46
37
  ? value
47
38
  : entries.filter((entry) => entry !== DROPPED);
48
39
  }
49
- if (!isPlainObject(value)) {
40
+ if (!isPlainRecord(value)) {
50
41
  return value;
51
42
  }
52
43
  let changed = false;
@@ -1,11 +1,9 @@
1
1
  import { adapterPrimaryIdentifier } from "../adapters/adapter-identifier.js";
2
2
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
3
+ import { isRecord } from "../runtime/record.guard.js";
3
4
  import { policyRefusal } from "./policy-admission.js";
4
5
  import { allOf, anyOf, everyOf, noneOf, someOf, } from "./policy-condition.js";
5
6
  import { fieldAccess } from "./policy-session.js";
6
- function isRecord(value) {
7
- return value !== null && typeof value === "object" && !Array.isArray(value);
8
- }
9
7
  function relationOf(core, resource, name) {
10
8
  const field = lookupField(lookupResource(core, resource), name);
11
9
  return field?.kind === "relation"
@@ -2,19 +2,10 @@ import { lookupResource } from "../contracts/contract-lookup.js";
2
2
  import { advertisedDirectivesAt, } from "../contracts/field.js";
3
3
  import { writeScopeOf } from "../contracts/resource-operations.js";
4
4
  import { LOOPBACK_WRITE_SCOPE, NESTED_WRITE_SCOPE, TO_MANY_UPDATE_WRITE_SCOPE, } from "../operations/write-scope.resolver.js";
5
+ import { isPlainRecord, isRecord } from "../runtime/record.guard.js";
5
6
  import { policyRefusal } from "./policy-admission.js";
6
7
  import { allOf, everyOf, noneOf, someOf, whereOf, } from "./policy-condition.js";
7
8
  import { NamedRows } from "./policy-named-rows.js";
8
- function isRecord(value) {
9
- return value !== null && typeof value === "object" && !Array.isArray(value);
10
- }
11
- function isPlainObject(value) {
12
- if (!isRecord(value)) {
13
- return false;
14
- }
15
- const prototype = Object.getPrototypeOf(value);
16
- return prototype === Object.prototype || prototype === null;
17
- }
18
9
  const ownedOf = new WeakMap();
19
10
  function resourceOf(model, resource) {
20
11
  return Object.hasOwn(model.resources, resource)
@@ -149,7 +140,7 @@ function writtenReferences(model, record, resource) {
149
140
  written.length !== owned.fields.length ||
150
141
  references === undefined ||
151
142
  references.length !== owned.fields.length ||
152
- values.some(isPlainObject)
143
+ values.some(isPlainRecord)
153
144
  ? { kind: "unstated" }
154
145
  : { kind: "value", values },
155
146
  ],
@@ -30,6 +30,37 @@ export declare function openRequestPolicy(policy: ResolvedPolicyConfig | undefin
30
30
  }, caller: PolicyCaller | undefined, adapter: AvAdapterOperationExecutor & {
31
31
  readonly model: AvAdapterModel;
32
32
  }): PolicySession | undefined | Promise<PolicySession | undefined>;
33
+ /**
34
+ * The principal a remote request runs as, derived once from its state, or
35
+ * `undefined` when no policy checks it; a promise of it when the principal
36
+ * arrives as one. A throw, or a rejection, is the caller's to answer as the
37
+ * server's defect. Under a held state ({@link holdRequestPrincipal}) it is the
38
+ * principal derived the first time, however often it is asked.
39
+ */
40
+ export declare function derivePolicyCaller(policy: ResolvedPolicyConfig | undefined, request: {
41
+ readonly origin: AvRequestOrigin;
42
+ readonly state: AvState;
43
+ }): PolicyCaller | undefined | Promise<PolicyCaller>;
44
+ /**
45
+ * Derives and holds `request`'s origin's principal from a held state that
46
+ * holds none yet; nothing for a state no host held, or for an origin the
47
+ * policy derives no principal for. Never throws and never rejects: the
48
+ * request that names its principal is not answered by it. A throw holds
49
+ * nothing; a rejection is held, observed here, and answers the requests that
50
+ * later read it.
51
+ */
52
+ export declare function holdFirstPrincipal(policy: ResolvedPolicyConfig | undefined, request: {
53
+ readonly origin: AvRequestOrigin;
54
+ readonly state: AvState;
55
+ }): void;
56
+ /**
57
+ * Holds `state` as one request's: every request run under this object reads
58
+ * its principal once, the first time one is derived from it, until the state
59
+ * is held again. A host calls it once per request, on the state it seeds once
60
+ * and shares between that request's calls, before any of them runs. Anything
61
+ * that is not an object is ignored: no request runs under it.
62
+ */
63
+ export declare function holdRequestPrincipal(state: unknown): void;
33
64
  /**
34
65
  * Policy admission inside its own boundary, as the Framework Validation Layer's
35
66
  * is: a refusal, a defect of the engine or its answers (`A3000`), or an adapter
@@ -1,4 +1,5 @@
1
1
  import { AdapterBoundary, sanitizeOperationFailure, } from "../runtime/error-boundary.js";
2
+ import { isThenable } from "../runtime/thenable.guard.js";
2
3
  import { admitByPolicy, admitWriteByPolicy } from "./policy-admission.js";
3
4
  import { openPolicySession } from "./policy-session.js";
4
5
  export function callerOf(options) {
@@ -14,32 +15,83 @@ export function callerOf(options) {
14
15
  }
15
16
  return principal === undefined ? undefined : { principal };
16
17
  }
17
- function isThenable(value) {
18
- return (value !== null &&
19
- (typeof value === "object" || typeof value === "function") &&
20
- typeof value.then === "function");
21
- }
22
18
  export function openRequestPolicy(policy, core, request, caller, adapter) {
23
19
  if (policy === undefined) {
24
20
  return undefined;
25
21
  }
26
- let principal;
27
22
  if (caller !== undefined) {
28
- principal = caller.principal;
23
+ holdFirstPrincipal(policy, request);
29
24
  }
30
- else if (request.origin === "application") {
25
+ const settled = caller ?? derivePolicyCaller(policy, request);
26
+ if (settled === undefined) {
31
27
  return undefined;
32
28
  }
33
- else {
34
- principal = policy.principal({
35
- $state: request.state,
36
- $origin: request.origin,
37
- });
38
- if (isThenable(principal)) {
39
- return Promise.resolve(principal).then((settled) => sessionOf(policy, core, request.origin, adapter, settled));
40
- }
29
+ return settled instanceof Promise
30
+ ? settled.then(({ principal }) => sessionOf(policy, core, request.origin, adapter, principal))
31
+ : sessionOf(policy, core, request.origin, adapter, settled.principal);
32
+ }
33
+ export function derivePolicyCaller(policy, request) {
34
+ if (policy === undefined || request.origin === "application") {
35
+ return undefined;
36
+ }
37
+ const held = heldOf(policy, request.state);
38
+ if (held === undefined) {
39
+ return principalOf(policy, request);
40
+ }
41
+ const known = held.get(request.origin);
42
+ if (known !== undefined) {
43
+ return known;
44
+ }
45
+ const derived = principalOf(policy, request);
46
+ held.set(request.origin, derived);
47
+ return derived;
48
+ }
49
+ export function holdFirstPrincipal(policy, request) {
50
+ if (policy === undefined || request.origin === "application") {
51
+ return;
52
+ }
53
+ const held = heldOf(policy, request.state);
54
+ if (held === undefined || held.has(request.origin)) {
55
+ return;
56
+ }
57
+ let derived;
58
+ try {
59
+ derived = principalOf(policy, request);
60
+ }
61
+ catch {
62
+ return;
63
+ }
64
+ if (derived instanceof Promise) {
65
+ derived.catch(() => undefined);
66
+ }
67
+ held.set(request.origin, derived);
68
+ }
69
+ function heldOf(policy, state) {
70
+ const held = HELD_PRINCIPALS.get(state);
71
+ if (held === undefined) {
72
+ return undefined;
73
+ }
74
+ let byOrigin = held.get(policy);
75
+ if (byOrigin === undefined) {
76
+ byOrigin = new Map();
77
+ held.set(policy, byOrigin);
78
+ }
79
+ return byOrigin;
80
+ }
81
+ function principalOf(policy, request) {
82
+ const principal = policy.principal({
83
+ $state: request.state,
84
+ $origin: request.origin,
85
+ });
86
+ return isThenable(principal)
87
+ ? Promise.resolve(principal).then((settled) => ({ principal: settled }))
88
+ : { principal };
89
+ }
90
+ const HELD_PRINCIPALS = new WeakMap();
91
+ export function holdRequestPrincipal(state) {
92
+ if (typeof state === "object" && state !== null) {
93
+ HELD_PRINCIPALS.set(state, new Map());
41
94
  }
42
- return sessionOf(policy, core, request.origin, adapter, principal);
43
95
  }
44
96
  function sessionOf(policy, core, origin, adapter, principal) {
45
97
  return openPolicySession(policy, core, adapter.model, principal, origin, {
@@ -1,6 +1,7 @@
1
1
  import { adapterPrimaryIdentifier } from "../adapters/adapter-identifier.js";
2
2
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
3
3
  import { validateOperationArguments } from "../operations/operation-validator-core.js";
4
+ import { isRecord } from "../runtime/record.guard.js";
4
5
  import { normalizeOperationScalarValues } from "../runtime/scalar-runtime.js";
5
6
  import { encodeOperationArgumentsForWire } from "../transactions/operation-arguments-encoder.js";
6
7
  class PolicyDefectError extends Error {
@@ -12,9 +13,6 @@ function isEmptyRecord(value) {
12
13
  !Array.isArray(value) &&
13
14
  Object.keys(value).length === 0);
14
15
  }
15
- function isRecord(value) {
16
- return value !== null && typeof value === "object" && !Array.isArray(value);
17
- }
18
16
  const FRAGMENT_WIRE_ORIGIN = "client";
19
17
  function checkedFragment(core, resource, where, what) {
20
18
  if (!isRecord(where)) {
@@ -2,6 +2,7 @@ import { adapterPrimaryIdentifier } from "../adapters/adapter-identifier.js";
2
2
  import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
3
3
  import { uniqueMissFailure } from "../runtime/outcome-mapper.js";
4
4
  import { frozenCopy } from "../runtime/readonly-value.js";
5
+ import { isRecord } from "../runtime/record.guard.js";
5
6
  import { policyRefusal } from "./policy-admission.js";
6
7
  import { afterCheckFields, afterUpdate, beforeFields, beforeUnreadable, checkChanged, coveredBefore, rowsBefore, unchangedSince, } from "./policy-after-update.runtime.js";
7
8
  import { allOf, everyOf, noneOf, someOf, whereOf, } from "./policy-condition.js";
@@ -38,9 +39,6 @@ function fewerChanged(resource, checks, before, changed) {
38
39
  : undefined;
39
40
  }
40
41
  const UNVERIFIABLE = "cannot be verified on this database: it has no interactive transaction to roll the write back in";
41
- function isRecord(value) {
42
- return value !== null && typeof value === "object" && !Array.isArray(value);
43
- }
44
42
  function refused(message) {
45
43
  return { kind: "refused", response: policyRefusal(message) };
46
44
  }
@@ -1,2 +1,2 @@
1
1
  /** The version of this `@aventara/core`. */
2
- export declare const CORE_VERSION = "1.0.0-rc.10";
2
+ export declare const CORE_VERSION = "1.0.0-rc.11";
@@ -1 +1 @@
1
- export const CORE_VERSION = "1.0.0-rc.10";
1
+ export const CORE_VERSION = "1.0.0-rc.11";
@@ -1,6 +1,4 @@
1
- function isRecord(value) {
2
- return value !== null && typeof value === "object" && !Array.isArray(value);
3
- }
1
+ import { isRecord } from "../runtime/record.guard.js";
4
2
  export function listedNames(names) {
5
3
  return names.length < 2
6
4
  ? names.join("")
@@ -2,14 +2,12 @@ import { bindPrebuiltContracts, } from "../compiler/contract.compiler.js";
2
2
  import { recordCanonicalContractText } from "../contracts/contract-canonicalizer.js";
3
3
  import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
4
4
  import { emitFrameworkWarning } from "../runtime/framework-warning.emitter.js";
5
+ import { isRecord } from "../runtime/record.guard.js";
5
6
  import { CORE_VERSION } from "./core-version.generated.js";
6
7
  import { listedNames, prebuiltHeaderChanges, prebuiltInputChanges, } from "./prebuilt-changes.js";
7
8
  import { PREBUILT_FORMAT } from "./prebuilt-contracts.js";
8
9
  import { prebuiltInputsFingerprint, prebuiltPartFingerprints, } from "./prebuilt-inputs.fingerprint.js";
9
10
  const PREBUILT_STALE_WARNING = "AVENTARA_PREBUILT_STALE";
10
- function isRecord(value) {
11
- return value !== null && typeof value === "object" && !Array.isArray(value);
12
- }
13
11
  async function changedInputs(stored, model, config) {
14
12
  const changes = prebuiltInputChanges(stored, await prebuiltPartFingerprints(model, config));
15
13
  return changes.length === 0
@@ -2,14 +2,12 @@ import { avzCheckOf } from "../avz/avz-check.registry.js";
2
2
  import { jsonShapeOf } from "../avz/json-shape.registry.js";
3
3
  import { hashCanonicalContractText } from "../contracts/contract-hash.js";
4
4
  import { AVENTARA_PROTOCOL_VERSION } from "../contracts/contract-protocol.js";
5
+ import { isRecord } from "../runtime/record.guard.js";
5
6
  import { CORE_VERSION } from "./core-version.generated.js";
6
7
  import { PREBUILT_FORMAT } from "./prebuilt-contracts.js";
7
8
  const LAYERS = ["root", "application", "client", "agent"];
8
9
  const NOT_INPUTS = new Set(["adapter", "prebuilt"]);
9
10
  const PER_RESOURCE = "#resources";
10
- function isRecord(value) {
11
- return value !== null && typeof value === "object" && !Array.isArray(value);
12
- }
13
11
  function sortedRecord(record) {
14
12
  const keys = Object.keys(record);
15
13
  const prototype = Object.getPrototypeOf(record);
@@ -1,11 +1,14 @@
1
1
  import type { AvContracts } from "../compiler/contract.compiler.js";
2
2
  import type { RemoteRequestOrigin } from "../config/config-layer.js";
3
+ import type { AvContractClient } from "../contracts/contract.js";
3
4
  import { type AvOperationIdentity } from "../operations/operation-identity.js";
4
5
  import { type AvDiagnosticsSink } from "../runtime/diagnostics-reporter.js";
5
6
  import type { AvRequestProtocol } from "../runtime/operation-request.js";
7
+ import { type AvOperationFailureResponse } from "../runtime/operation-response.js";
6
8
  import type { AvProtocolRequest } from "./http-request.decoder.js";
7
9
  import { type ReadRequest } from "./http-request.reader.js";
8
10
  import { type AvProtocolResponse } from "./http-response.encoder.js";
11
+ import { type ReadQuery } from "./read-query.codec.js";
9
12
  /**
10
13
  * The absence answers: the checks a framework route makes before it reads a body, runs
11
14
  * a pipeline or reaches an Adapter — the protocol version (`A2006`), the
@@ -20,6 +23,43 @@ export type OperationRouteSegments = {
20
23
  readonly family: string;
21
24
  readonly variant: string;
22
25
  };
26
+ /** What a route check resolves to: the operation it names, or the answer that refuses it. */
27
+ type OperationRouteResolution = {
28
+ readonly ok: true;
29
+ readonly operation: AvOperationIdentity;
30
+ } | {
31
+ readonly ok: false;
32
+ readonly failure: AvOperationFailureResponse;
33
+ };
34
+ /**
35
+ * An operation route `/_resources/<resource>/<family>/<variant>` under one client
36
+ * protocol identity: version → hash → Resource → operation. A Resource key is matched
37
+ * exactly and only as the ClientContract's own key; a family/variant pair only when it
38
+ * is a standard operation the Resource advertises, read through
39
+ * `isOperationVariantAvailable` alone.
40
+ */
41
+ export declare function resolveOperationRoute(contracts: AvContracts, protocol: AvRequestProtocol, route: OperationRouteSegments, origin?: RemoteRequestOrigin): OperationRouteResolution;
42
+ /**
43
+ * The `/_transactions` route under one client protocol identity: version → hash → the
44
+ * ClientContract's transaction capability. The route exists only when that capability
45
+ * is `"interactive"` — tested against the value itself, as `protocol.surface()` tests
46
+ * it — and is otherwise absent with core's own refusal of a plan. `undefined` when the
47
+ * route is there.
48
+ */
49
+ declare function transactionsRouteFailure(contracts: AvContracts, protocol: AvRequestProtocol, origin?: RemoteRequestOrigin): AvOperationFailureResponse | undefined;
50
+ /**
51
+ * The `/_access/can` route under one client protocol identity: version → hash →
52
+ * the Contract's `access` section. The route exists only when the section is
53
+ * there — tested as `protocol.surface()` tests it — and is otherwise absent.
54
+ * `undefined` when the route is there.
55
+ */
56
+ declare function accessCanRouteFailure(contracts: AvContracts, protocol: AvRequestProtocol, origin?: RemoteRequestOrigin): AvOperationFailureResponse | undefined;
57
+ /**
58
+ * The `/_all` route under one client protocol identity: version → hash → whether
59
+ * the Contract advertises any operation, tested as `protocol.surface()` tests it.
60
+ * `undefined` when the route is there.
61
+ */
62
+ declare function allRouteFailure(contracts: AvContracts, protocol: AvRequestProtocol, origin?: RemoteRequestOrigin): AvOperationFailureResponse | undefined;
23
63
  /**
24
64
  * What a route's checks before its body resolve to: the route a request
25
65
  * reaches, or the framework response that answers it instead.
@@ -31,32 +71,45 @@ type RouteCheck<Route> = ({
31
71
  readonly ok: false;
32
72
  readonly response: AvProtocolResponse;
33
73
  };
74
+ /** A cached read's mark in the Contract a route reads: its `for` and `maxAge`. */
75
+ type ReadCacheMark = NonNullable<NonNullable<AvContractClient["resources"][string]["cache"]>["first" | "unique" | "many" | "count"]>;
34
76
  /**
35
77
  * An operation route's checks before its body (decoder steps 2–4): the path (`A2000`
36
78
  * unless `/_resources/<r>/<f>/<v>`, each segment decodable and none empty), the
37
- * identity headers' presence (`A2000`), then {@link resolveOperationRoute} — version,
38
- * hash, Resource, operation — and the method (`A2012`, `Allow: POST`). One sequence
39
- * for both route styles: `decodeOperation` reads the body only after it passes,
79
+ * identity — a `GET`'s well-formed `q`/`v` query when it has a query, otherwise
80
+ * the headers' presence (`A2000`) — then {@link resolveOperationRoute} — version, hash, Resource,
81
+ * operation — and the method (`A2012`): `POST`, or `GET` for a `find` operation of
82
+ * read the Contract marks cacheable, whose `Allow` is then `GET, POST`. One sequence for
83
+ * both route styles: `decodeOperation` reads the body only after it passes,
40
84
  * `answerAbsent` never.
41
85
  */
42
- export declare function checkOperationRoute(contracts: AvContracts, read: ReadRequest, origin?: RemoteRequestOrigin): RouteCheck<{
86
+ export declare function checkOperationRoute(contracts: AvContracts, read: ReadRequest, origin?: RemoteRequestOrigin): OperationRouteCheck;
87
+ /** What an operation route's checks resolve to. */
88
+ type OperationRouteCheck = RouteCheck<{
43
89
  readonly resource: string;
44
90
  readonly operation: AvOperationIdentity;
91
+ /** The read's cache mark, for a `find` variant the Contract marks. */
92
+ readonly cache: ReadCacheMark | undefined;
93
+ /** A `GET`'s query, read; `undefined` without one (`A2000` for a cached read). */
94
+ readonly query: ReadQuery | undefined;
45
95
  }>;
96
+ /** Each fixed `POST` route, by path, and its absence under one protocol identity. */
97
+ declare const POST_ROUTE_FAILURES: {
98
+ readonly "/_transactions": typeof transactionsRouteFailure;
99
+ readonly "/_access/can": typeof accessCanRouteFailure;
100
+ readonly "/_all": typeof allRouteFailure;
101
+ };
102
+ /** `/_transactions`, `/_access/can` or `/_all`. */
103
+ type PostRoute = keyof typeof POST_ROUTE_FAILURES;
46
104
  /**
47
- * `/_transactions`' checks before its body: the path (`A2000` unless exactly
48
- * `/_transactions`), the identity headers' presence (`A2000`), then
49
- * {@link transactionsRouteFailure} — version, hash, `"interactive"` — and the
50
- * method (`A2012`, `Allow: POST`).
51
- */
52
- export declare function checkTransactionsRoute(contracts: AvContracts, read: ReadRequest, origin?: RemoteRequestOrigin): RouteCheck<object>;
53
- /**
54
- * `/_access/can`'s checks before its body: the path (`A2000` unless exactly
55
- * `/_access/can`), the identity headers' presence (`A2000`), then
56
- * {@link accessCanRouteFailure} — version, hash, the `access` section — and the
57
- * method (`A2012`, `Allow: POST`).
105
+ * A fixed `POST` route's checks before its body: the path (`A2000` unless
106
+ * exactly `route`), the identity headers' presence (`A2000`), then the route's
107
+ * own absence — version, hash, and {@link transactionsRouteFailure}'s
108
+ * `"interactive"`, {@link accessCanRouteFailure}'s `access` section or
109
+ * {@link allRouteFailure}'s advertised operation — and the method (`A2012`,
110
+ * `Allow: POST`).
58
111
  */
59
- export declare function checkAccessCanRoute(contracts: AvContracts, read: ReadRequest, origin?: RemoteRequestOrigin): RouteCheck<object>;
112
+ export declare function checkPostRoute(route: PostRoute, contracts: AvContracts, read: ReadRequest, origin?: RemoteRequestOrigin): RouteCheck<object>;
60
113
  /**
61
114
  * `protocol.answerAbsent(request)` — the fallback a host that mounts one route per
62
115
  * `protocol.surface()` entry mounts for every path it did not. Never a catch-all into