@aventara/core 1.0.0-rc.1 → 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 (261) hide show
  1. package/CHANGELOG.md +1022 -16
  2. package/ERRORS.md +142 -0
  3. package/README.md +330 -16
  4. package/dist/adapters/adapter-discovery-diagnostic.guidance.d.ts +6 -0
  5. package/dist/adapters/adapter-discovery-diagnostic.guidance.js +7 -0
  6. package/dist/adapters/adapter-field.d.ts +22 -0
  7. package/dist/adapters/adapter-identifier.d.ts +9 -0
  8. package/dist/adapters/adapter-identifier.js +6 -1
  9. package/dist/adapters/adapter-model.d.ts +9 -0
  10. package/dist/adapters/adapter-operation.d.ts +18 -3
  11. package/dist/adapters/adapter-resource.d.ts +5 -0
  12. package/dist/adapters/adapter.interface.d.ts +10 -0
  13. package/dist/avz/avz.d.ts +1 -1
  14. package/dist/avz/json-shape.registry.d.ts +2 -1
  15. package/dist/compiler/contract-compiler-diagnostic.guidance.d.ts +6 -0
  16. package/dist/compiler/contract-compiler-diagnostic.guidance.js +97 -0
  17. package/dist/compiler/contract.compiler.d.ts +6 -0
  18. package/dist/compiler/contract.compiler.js +281 -31
  19. package/dist/compiler/create-requirements.projector.js +1 -3
  20. package/dist/compiler/field-validator.compiler.js +1 -3
  21. package/dist/compiler/managed-elsewhere.projector.d.ts +52 -0
  22. package/dist/compiler/managed-elsewhere.projector.js +179 -0
  23. package/dist/compiler/managed-elsewhere.validator.d.ts +9 -0
  24. package/dist/compiler/managed-elsewhere.validator.js +74 -0
  25. package/dist/config/cache-stage.factory.d.ts +24 -0
  26. package/dist/config/cache-stage.factory.js +3 -0
  27. package/dist/config/computed-fields.d.ts +62 -0
  28. package/dist/config/computed-fields.js +73 -0
  29. package/dist/config/config-diagnostic.guidance.d.ts +6 -0
  30. package/dist/config/config-diagnostic.guidance.js +32 -0
  31. package/dist/config/config.resolver.d.ts +24 -0
  32. package/dist/config/config.resolver.js +66 -7
  33. package/dist/config/config.validator.js +283 -21
  34. package/dist/config/define-resource.d.ts +1 -5
  35. package/dist/config/entrypoint.normalizer.d.ts +3 -2
  36. package/dist/config/exact-framework-config.d.ts +73 -22
  37. package/dist/config/field-compute.resolver.d.ts +2 -0
  38. package/dist/config/field-compute.resolver.js +9 -3
  39. package/dist/config/framework-config.d.ts +53 -15
  40. package/dist/config/framework-resources-config.d.ts +25 -14
  41. package/dist/config/pipeline-config.d.ts +20 -4
  42. package/dist/config/pipeline-tree.resolver.d.ts +2 -2
  43. package/dist/config/pipeline-tree.resolver.js +2 -3
  44. package/dist/contracts/access-route.rules.d.ts +10 -0
  45. package/dist/contracts/access-route.rules.js +45 -0
  46. package/dist/contracts/canonical-json.writer.d.ts +7 -0
  47. package/dist/contracts/canonical-json.writer.js +55 -0
  48. package/dist/contracts/capability.d.ts +26 -1
  49. package/dist/contracts/capability.js +20 -0
  50. package/dist/contracts/client-contract-structure.validator.d.ts +365 -89
  51. package/dist/contracts/client-contract-structure.validator.js +49 -2
  52. package/dist/contracts/contract-access.d.ts +29 -0
  53. package/dist/contracts/contract-access.js +1 -0
  54. package/dist/contracts/contract-canonicalizer.d.ts +9 -1
  55. package/dist/contracts/contract-canonicalizer.js +35 -4
  56. package/dist/contracts/contract-hash.d.ts +0 -1
  57. package/dist/contracts/contract-hash.js +1 -1
  58. package/dist/contracts/contract-limits.d.ts +6 -0
  59. package/dist/contracts/contract-limits.js +2 -0
  60. package/dist/contracts/contract.d.ts +42 -1
  61. package/dist/contracts/field.d.ts +58 -1
  62. package/dist/contracts/json-schema.projector.d.ts +11 -0
  63. package/dist/contracts/json-schema.projector.js +76 -0
  64. package/dist/contracts/scalar-value-type.d.ts +3 -1
  65. package/dist/framework/access-facade.d.ts +116 -0
  66. package/dist/framework/access-facade.js +118 -0
  67. package/dist/framework/contract-view.d.ts +120 -16
  68. package/dist/framework/framework-construction.error.d.ts +14 -4
  69. package/dist/framework/framework-construction.error.js +18 -2
  70. package/dist/framework/framework.d.ts +26 -5
  71. package/dist/framework/framework.factory.d.ts +1 -1
  72. package/dist/framework/framework.factory.js +145 -24
  73. package/dist/framework/operation-facade.d.ts +141 -13
  74. package/dist/framework/operation-facade.js +9 -1
  75. package/dist/framework/operation-set.runner.d.ts +47 -0
  76. package/dist/framework/operation-set.runner.js +168 -0
  77. package/dist/index.d.ts +19 -5
  78. package/dist/index.js +3 -0
  79. package/dist/internal.d.ts +9 -2
  80. package/dist/internal.js +8 -0
  81. package/dist/operations/database-refusal.d.ts +51 -0
  82. package/dist/operations/database-refusal.js +45 -0
  83. package/dist/operations/operation-arguments.d.ts +148 -60
  84. package/dist/operations/operation-call.d.ts +9 -5
  85. package/dist/operations/operation-result.d.ts +6 -4
  86. package/dist/operations/operation-validator-core.js +160 -39
  87. package/dist/operations/operation-validator.d.ts +1 -1
  88. package/dist/operations/structural-limits.walker.d.ts +1 -1
  89. package/dist/operations/structural-limits.walker.js +1 -3
  90. package/dist/operations/validation-code.guidance.d.ts +6 -0
  91. package/dist/operations/validation-code.guidance.js +90 -0
  92. package/dist/operations/write-scope.resolver.d.ts +4 -0
  93. package/dist/operations/write-scope.resolver.js +2 -0
  94. package/dist/policy/access-provider.interface.d.ts +91 -0
  95. package/dist/policy/access-provider.interface.js +1 -0
  96. package/dist/policy/access-provider.registry.d.ts +17 -0
  97. package/dist/policy/access-provider.registry.js +15 -0
  98. package/dist/policy/access-question.d.ts +20 -0
  99. package/dist/policy/access-question.js +1 -0
  100. package/dist/policy/access-question.registry.d.ts +5 -0
  101. package/dist/policy/access-question.registry.js +19 -0
  102. package/dist/policy/access-question.runtime.d.ts +36 -0
  103. package/dist/policy/access-question.runtime.js +295 -0
  104. package/dist/policy/access-verb.table.d.ts +56 -0
  105. package/dist/policy/access-verb.table.js +21 -0
  106. package/dist/policy/access-verbs.d.ts +46 -0
  107. package/dist/policy/access-verbs.js +1 -0
  108. package/dist/policy/policy-admission.d.ts +20 -0
  109. package/dist/policy/policy-admission.js +407 -0
  110. package/dist/policy/policy-after-update.runtime.d.ts +79 -0
  111. package/dist/policy/policy-after-update.runtime.js +206 -0
  112. package/dist/policy/policy-condition.d.ts +15 -0
  113. package/dist/policy/policy-condition.js +36 -0
  114. package/dist/policy/policy-engine.d.ts +205 -0
  115. package/dist/policy/policy-engine.js +1 -0
  116. package/dist/policy/policy-named-rows.d.ts +18 -0
  117. package/dist/policy/policy-named-rows.js +51 -0
  118. package/dist/policy/policy-nested-write.runtime.d.ts +44 -0
  119. package/dist/policy/policy-nested-write.runtime.js +536 -0
  120. package/dist/policy/policy-read.runtime.d.ts +81 -0
  121. package/dist/policy/policy-read.runtime.js +501 -0
  122. package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
  123. package/dist/policy/policy-reference-write.runtime.js +336 -0
  124. package/dist/policy/policy-request.d.ts +72 -0
  125. package/dist/policy/policy-request.js +115 -0
  126. package/dist/policy/policy-session.d.ts +106 -0
  127. package/dist/policy/policy-session.js +293 -0
  128. package/dist/policy/policy-startup.validator.d.ts +10 -0
  129. package/dist/policy/policy-startup.validator.js +112 -0
  130. package/dist/policy/policy-write.runtime.d.ts +39 -0
  131. package/dist/policy/policy-write.runtime.js +530 -0
  132. package/dist/prebuilt/core-version.generated.d.ts +2 -0
  133. package/dist/prebuilt/core-version.generated.js +1 -0
  134. package/dist/prebuilt/prebuilt-changes.d.ts +29 -0
  135. package/dist/prebuilt/prebuilt-changes.js +63 -0
  136. package/dist/prebuilt/prebuilt-contracts.d.ts +40 -0
  137. package/dist/prebuilt/prebuilt-contracts.emitter.d.ts +16 -0
  138. package/dist/prebuilt/prebuilt-contracts.emitter.js +50 -0
  139. package/dist/prebuilt/prebuilt-contracts.js +1 -0
  140. package/dist/prebuilt/prebuilt-contracts.loader.d.ts +19 -0
  141. package/dist/prebuilt/prebuilt-contracts.loader.js +75 -0
  142. package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
  143. package/dist/prebuilt/prebuilt-inputs.fingerprint.js +227 -0
  144. package/dist/protocol/absent-route.responder.d.ts +49 -14
  145. package/dist/protocol/absent-route.responder.js +92 -15
  146. package/dist/protocol/contract-document.responder.d.ts +9 -1
  147. package/dist/protocol/contract-document.responder.js +3 -2
  148. package/dist/protocol/http-request.decoder.d.ts +52 -3
  149. package/dist/protocol/http-request.decoder.js +45 -6
  150. package/dist/protocol/http-request.reader.d.ts +10 -3
  151. package/dist/protocol/http-request.reader.js +12 -2
  152. package/dist/protocol/http-response.encoder.d.ts +12 -0
  153. package/dist/protocol/http-response.encoder.js +17 -3
  154. package/dist/protocol/operation-response.guard.js +1 -3
  155. package/dist/protocol/operation-set.decoder.d.ts +48 -0
  156. package/dist/protocol/operation-set.decoder.js +185 -0
  157. package/dist/protocol/operation-set.handler.d.ts +27 -0
  158. package/dist/protocol/operation-set.handler.js +179 -0
  159. package/dist/protocol/protocol-headers.d.ts +12 -3
  160. package/dist/protocol/protocol-headers.js +12 -5
  161. package/dist/protocol/protocol-surface.d.ts +16 -3
  162. package/dist/protocol/protocol-surface.js +41 -1
  163. package/dist/protocol/protocol.binder.d.ts +52 -1
  164. package/dist/protocol/protocol.binder.js +6 -1
  165. package/dist/protocol/protocol.handler.d.ts +45 -1
  166. package/dist/protocol/protocol.handler.js +164 -19
  167. package/dist/protocol/read-cache.responder.d.ts +26 -0
  168. package/dist/protocol/read-cache.responder.js +47 -0
  169. package/dist/protocol/read-query.codec.d.ts +34 -0
  170. package/dist/protocol/read-query.codec.js +125 -0
  171. package/dist/runtime/caller-data.copier.d.ts +18 -3
  172. package/dist/runtime/caller-data.copier.js +21 -8
  173. package/dist/runtime/caller-data.door.d.ts +13 -6
  174. package/dist/runtime/computed-read-runtime.d.ts +6 -1
  175. package/dist/runtime/computed-read-runtime.js +229 -48
  176. package/dist/runtime/computed-value.error.d.ts +3 -2
  177. package/dist/runtime/computed-value.error.js +3 -2
  178. package/dist/runtime/context-executor.runtime.d.ts +4 -3
  179. package/dist/runtime/context-executor.runtime.js +4 -2
  180. package/dist/runtime/core-class.brand.d.ts +10 -0
  181. package/dist/runtime/core-class.brand.js +21 -0
  182. package/dist/runtime/create-requirement.d.ts +31 -5
  183. package/dist/runtime/create-requirement.js +130 -24
  184. package/dist/runtime/decimal.d.ts +14 -0
  185. package/dist/runtime/decimal.js +21 -0
  186. package/dist/runtime/diagnostics-reporter.d.ts +49 -9
  187. package/dist/runtime/diagnostics-reporter.js +16 -9
  188. package/dist/runtime/error-boundary.d.ts +9 -2
  189. package/dist/runtime/error-boundary.js +12 -0
  190. package/dist/runtime/error-guidance.d.ts +12 -0
  191. package/dist/runtime/error-guidance.js +1 -0
  192. package/dist/runtime/error.catalog.d.ts +49 -0
  193. package/dist/runtime/error.catalog.js +49 -0
  194. package/dist/runtime/execution-options.d.ts +8 -0
  195. package/dist/runtime/field-check.evaluator.d.ts +0 -2
  196. package/dist/runtime/field-check.evaluator.js +1 -1
  197. package/dist/runtime/field-compute.d.ts +11 -10
  198. package/dist/runtime/field-stage.runtime.d.ts +3 -3
  199. package/dist/runtime/field-stage.runtime.js +9 -11
  200. package/dist/runtime/field-validator.runtime.d.ts +19 -1
  201. package/dist/runtime/field-validator.runtime.js +49 -9
  202. package/dist/runtime/framework-error.js +9 -0
  203. package/dist/runtime/framework-warning.emitter.d.ts +6 -0
  204. package/dist/runtime/framework-warning.emitter.js +8 -0
  205. package/dist/runtime/json-value.d.ts +10 -5
  206. package/dist/runtime/level-lifecycle.runtime.d.ts +4 -3
  207. package/dist/runtime/level-lifecycle.runtime.js +3 -5
  208. package/dist/runtime/mutation-planner.d.ts +1 -6
  209. package/dist/runtime/mutation-planner.js +4 -17
  210. package/dist/runtime/nested-write.walker.js +2 -1
  211. package/dist/runtime/operation-code.guidance.d.ts +6 -0
  212. package/dist/runtime/operation-code.guidance.js +167 -0
  213. package/dist/runtime/operation-request.d.ts +16 -9
  214. package/dist/runtime/operation-runtime.d.ts +35 -17
  215. package/dist/runtime/operation-runtime.js +220 -49
  216. package/dist/runtime/outcome-mapper.d.ts +2 -1
  217. package/dist/runtime/output-validator.d.ts +1 -1
  218. package/dist/runtime/output-validator.js +1 -3
  219. package/dist/runtime/owned-execution.registry.d.ts +34 -4
  220. package/dist/runtime/pipe-output.validator.d.ts +10 -0
  221. package/dist/runtime/pipe-output.validator.js +4 -2
  222. package/dist/runtime/pipeline.d.ts +52 -23
  223. package/dist/runtime/readonly-value.d.ts +20 -5
  224. package/dist/runtime/readonly-value.js +74 -26
  225. package/dist/runtime/record.guard.d.ts +14 -0
  226. package/dist/runtime/record.guard.js +10 -0
  227. package/dist/runtime/referential-action.d.ts +1 -1
  228. package/dist/runtime/request-envelope.validator.js +13 -10
  229. package/dist/runtime/scalar-runtime.d.ts +4 -21
  230. package/dist/runtime/scalar-runtime.js +91 -31
  231. package/dist/runtime/thenable.guard.d.ts +7 -0
  232. package/dist/runtime/thenable.guard.js +5 -0
  233. package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
  234. package/dist/runtime/unsent-value.normalizer.js +129 -0
  235. package/dist/transactions/operation-arguments-encoder.js +9 -10
  236. package/dist/transactions/operation-fingerprint.js +2 -2
  237. package/dist/transactions/sql-statement.d.ts +10 -2
  238. package/dist/transactions/sql-statement.validator.d.ts +2 -2
  239. package/dist/transactions/sql-statement.validator.js +40 -6
  240. package/dist/transactions/transaction-envelope.d.ts +5 -4
  241. package/dist/transactions/transaction-integrity-error.js +2 -0
  242. package/dist/transactions/transaction-plan-assembler.d.ts +12 -5
  243. package/dist/transactions/transaction-plan-assembler.js +49 -17
  244. package/dist/transactions/transaction-plan-validator.d.ts +23 -7
  245. package/dist/transactions/transaction-plan-validator.js +31 -7
  246. package/dist/transactions/transaction-reference-collector.js +8 -10
  247. package/dist/transactions/transaction-reference-resolver.d.ts +3 -2
  248. package/dist/transactions/transaction-reference-resolver.js +1 -3
  249. package/dist/transactions/transaction-reference-validator.d.ts +43 -3
  250. package/dist/transactions/transaction-reference-validator.js +83 -57
  251. package/dist/transactions/transaction-reference.d.ts +1 -1
  252. package/dist/transactions/transaction-reference.js +5 -0
  253. package/dist/transactions/transaction-request.d.ts +8 -8
  254. package/dist/transactions/transaction-runtime.d.ts +5 -2
  255. package/dist/transactions/transaction-runtime.js +108 -27
  256. package/dist/transactions/transaction-settlement.runtime.d.ts +4 -3
  257. package/dist/transactions/transaction-slot-path-error.js +2 -0
  258. package/dist/transactions/transaction-stage.runtime.d.ts +5 -3
  259. package/dist/transactions/transaction-stage.runtime.js +8 -7
  260. package/package.json +6 -5
  261. package/src/runtime/field-check.evaluator.ts +1 -1
@@ -1,10 +1,16 @@
1
+ import { isAccessPath, isAccessUrl } from "../contracts/access-route.rules.js";
1
2
  import { TRANSACTION_CAPABILITIES } from "../contracts/transaction-capability.js";
3
+ import { ACCESS_VERB_NAMES, isAccessVerbName, providerVerb, } from "../policy/access-verb.table.js";
4
+ import { isPlainRecord } from "../runtime/record.guard.js";
2
5
  import { normalizeEntrypoint } from "./entrypoint.normalizer.js";
3
6
  import { AVZ_FORMATS } from "./framework-field-definition.js";
4
7
  const ROOT_ONLY_PROPERTIES = new Set([
5
8
  "api",
6
9
  "mcp",
7
10
  "adapter",
11
+ "prebuilt",
12
+ "policy",
13
+ "access",
8
14
  "diagnostics",
9
15
  "misuse",
10
16
  "application",
@@ -36,6 +42,7 @@ const RESOURCE_PROPERTIES = new Set([
36
42
  "operations",
37
43
  "transactions",
38
44
  "fields",
45
+ "managedElsewhere",
39
46
  ]);
40
47
  const FIELD_PROPERTIES = new Set(["definition", "pipelines"]);
41
48
  const DEFINITION_PROPERTIES = new Set([
@@ -71,6 +78,8 @@ const LIMIT_PROPERTIES = new Set([
71
78
  "maxTransactionOperations",
72
79
  "maxBooleanNodes",
73
80
  "maxJsonDepth",
81
+ "maxAll",
82
+ "maxAllConcurrency",
74
83
  ]);
75
84
  const PIPELINE_PROPERTIES = new Set([
76
85
  "guards",
@@ -80,13 +89,6 @@ const PIPELINE_PROPERTIES = new Set([
80
89
  "filters",
81
90
  ]);
82
91
  const PIPELINE_HOOK_PROPERTIES = new Set(["before", "after"]);
83
- function isPlainRecord(value) {
84
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
85
- return false;
86
- }
87
- const prototype = Object.getPrototypeOf(value);
88
- return prototype === Object.prototype || prototype === null;
89
- }
90
92
  function diagnostic(code, path, message) {
91
93
  return { code, path, message };
92
94
  }
@@ -113,6 +115,14 @@ function validateLimits(value, path, diagnostics) {
113
115
  diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", limitPath, `unknown limit property: ${key}`));
114
116
  continue;
115
117
  }
118
+ if (key === "maxAllConcurrency") {
119
+ if (typeof limit !== "number" ||
120
+ !Number.isSafeInteger(limit) ||
121
+ limit < 1) {
122
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", limitPath, `${limitPath} must be a whole number of at least 1`));
123
+ }
124
+ continue;
125
+ }
116
126
  if (typeof limit !== "number" ||
117
127
  !Number.isFinite(limit) ||
118
128
  !Number.isInteger(limit) ||
@@ -121,6 +131,33 @@ function validateLimits(value, path, diagnostics) {
121
131
  }
122
132
  }
123
133
  }
134
+ const CACHE_PROPERTIES = new Set(["for", "maxAge"]);
135
+ const CACHE_AUDIENCES = new Set(["user", "anonymous", "everyone"]);
136
+ function validateCache(value, path, diagnostics) {
137
+ if (!requireRecord(value, path, diagnostics)) {
138
+ return;
139
+ }
140
+ for (const key of Object.keys(value)) {
141
+ if (!CACHE_PROPERTIES.has(key)) {
142
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `${path}.${key}`, `unknown cache property: ${key}; cache takes for and maxAge`));
143
+ }
144
+ }
145
+ const maxAgePath = `${path}.maxAge`;
146
+ if (!Object.hasOwn(value, "maxAge")) {
147
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", maxAgePath, `${maxAgePath} is required`));
148
+ }
149
+ else if (typeof value.maxAge !== "number" ||
150
+ !Number.isInteger(value.maxAge) ||
151
+ value.maxAge < 0 ||
152
+ value.maxAge > MAX_CACHE_AGE) {
153
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", maxAgePath, `${maxAgePath} must be a whole number of seconds from 0 to ${MAX_CACHE_AGE}`));
154
+ }
155
+ if (Object.hasOwn(value, "for") && !CACHE_AUDIENCES.has(value.for)) {
156
+ const forPath = `${path}.for`;
157
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", forPath, `${forPath} must be "user", "anonymous" or "everyone"`));
158
+ }
159
+ }
160
+ const MAX_CACHE_AGE = 2_147_483_647;
124
161
  function validateArray(value, key, path, diagnostics) {
125
162
  if (!Object.hasOwn(value, key)) {
126
163
  return;
@@ -142,7 +179,7 @@ function validatePipelineHooks(value, path, diagnostics) {
142
179
  validateArray(value, "before", path, diagnostics);
143
180
  validateArray(value, "after", path, diagnostics);
144
181
  }
145
- function validatePipelines(value, path, diagnostics) {
182
+ function validatePipelines(value, path, diagnostics, cacheRefusal) {
146
183
  if (!requireRecord(value, path, diagnostics)) {
147
184
  return;
148
185
  }
@@ -151,6 +188,16 @@ function validatePipelines(value, path, diagnostics) {
151
188
  diagnostics.push(diagnostic("CONFIG_MOVED_PROPERTY", `${path}.${key}`, `${path}.${key} moved in rc.1: hooks are ${path}.hooks.${key}`));
152
189
  continue;
153
190
  }
191
+ if (key === "cache") {
192
+ const refusal = cacheRefusal ?? layerCacheRefusal(path);
193
+ if (refusal !== undefined) {
194
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${path}.cache`, `${path}.cache: ${refusal}`));
195
+ }
196
+ else if (value.cache !== undefined) {
197
+ validateCache(value.cache, `${path}.cache`, diagnostics);
198
+ }
199
+ continue;
200
+ }
154
201
  if (!PIPELINE_PROPERTIES.has(key)) {
155
202
  diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `${path}.${key}`, `unknown pipeline property: ${key}`));
156
203
  }
@@ -162,6 +209,13 @@ function validatePipelines(value, path, diagnostics) {
162
209
  validatePipelineHooks(value.hooks, `${path}.hooks`, diagnostics);
163
210
  }
164
211
  }
212
+ function layerCacheRefusal(path) {
213
+ const layer = path.split(".")[0];
214
+ return layer === "application" || layer === "agent"
215
+ ? `cache applies to a client's reads; the ${layer} layer is never served a GET (state it at the root or in client)`
216
+ : undefined;
217
+ }
218
+ const WRITE_CACHE_REFUSAL = "cache applies to reads (the find family) only; a write is never a GET";
165
219
  function validateForceTransaction(value, path, diagnostics) {
166
220
  if (!Object.hasOwn(value, "forceTransaction")) {
167
221
  return;
@@ -171,21 +225,21 @@ function validateForceTransaction(value, path, diagnostics) {
171
225
  diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", propertyPath, `${propertyPath} must be a boolean`));
172
226
  }
173
227
  }
174
- function validateOperationLevel(value, path, isFamily, diagnostics) {
228
+ function validateOperationLevel(value, path, isFamily, diagnostics, isRead) {
175
229
  if (!requireRecord(value, path, diagnostics)) {
176
230
  return;
177
231
  }
178
232
  for (const [key, child] of Object.entries(value)) {
179
233
  const keyPath = `${path}.${key}`;
180
234
  if (key === "pipelines") {
181
- validatePipelines(child, keyPath, diagnostics);
235
+ validatePipelines(child, keyPath, diagnostics, isRead ? undefined : WRITE_CACHE_REFUSAL);
182
236
  continue;
183
237
  }
184
238
  if (key === "forceTransaction") {
185
239
  continue;
186
240
  }
187
241
  if (isFamily && OPERATION_VARIANTS.has(key)) {
188
- validateOperationLevel(child, keyPath, false, diagnostics);
242
+ validateOperationLevel(child, keyPath, false, diagnostics, isRead);
189
243
  continue;
190
244
  }
191
245
  diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", keyPath, isFamily
@@ -204,7 +258,7 @@ function validateOperations(value, path, diagnostics) {
204
258
  diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", familyPath, `unknown operation family: ${family}`));
205
259
  continue;
206
260
  }
207
- validateOperationLevel(level, familyPath, true, diagnostics);
261
+ validateOperationLevel(level, familyPath, true, diagnostics, family === "find");
208
262
  }
209
263
  }
210
264
  function validateResourceTransactions(value, path, diagnostics) {
@@ -217,7 +271,7 @@ function validateResourceTransactions(value, path, diagnostics) {
217
271
  diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", keyPath, `unknown Resource transactions property: ${key}`));
218
272
  continue;
219
273
  }
220
- validatePipelines(child, keyPath, diagnostics);
274
+ validatePipelines(child, keyPath, diagnostics, "cache applies to reads; a transaction is never a GET");
221
275
  }
222
276
  }
223
277
  function validateDefinition(value, path, diagnostics) {
@@ -339,7 +393,16 @@ function validateResource(value, path, resource, isRoot, diagnostics) {
339
393
  continue;
340
394
  }
341
395
  if (!RESOURCE_PROPERTIES.has(key)) {
342
- diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", keyPath, `unknown Resource property: ${key}; a Resource takes pipelines, operations, transactions and fields`));
396
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", keyPath, `unknown Resource property: ${key}; a Resource takes pipelines, operations, transactions and fields (and managedElsewhere at the root)`));
397
+ continue;
398
+ }
399
+ if (key === "managedElsewhere") {
400
+ if (!isRoot) {
401
+ diagnostics.push(diagnostic("CONFIG_FORBIDDEN_IN_OVERLAY", keyPath, `${keyPath}: managedElsewhere is only allowed at root; it states who owns the table, which no layer changes (state it at resources.${resource}.managedElsewhere)`));
402
+ }
403
+ else if (typeof child !== "boolean") {
404
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", keyPath, `${keyPath} must be a boolean`));
405
+ }
343
406
  continue;
344
407
  }
345
408
  if (key === "pipelines") {
@@ -618,6 +681,20 @@ export function validateFrameworkConfig(value) {
618
681
  else {
619
682
  validateAdapter(value.adapter, diagnostics);
620
683
  }
684
+ if (Object.hasOwn(value, "prebuilt") &&
685
+ value.prebuilt !== undefined &&
686
+ (value.prebuilt === null || typeof value.prebuilt !== "object")) {
687
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "prebuilt", "prebuilt must be the generated prebuilt Contracts object when provided"));
688
+ }
689
+ if (Object.hasOwn(value, "policy") && value.policy !== undefined) {
690
+ validatePolicy(value.policy, diagnostics);
691
+ }
692
+ if (Object.hasOwn(value, "access") && value.access !== undefined) {
693
+ validateAccess(value.access, diagnostics);
694
+ if (Object.hasOwn(value, "policy") && value.policy !== undefined) {
695
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", "policy", "policy cannot be configured with access: access.policy is the policy engine, and ctx.$state.me the principal; remove policy"));
696
+ }
697
+ }
621
698
  if (Object.hasOwn(value, "diagnostics") &&
622
699
  value.diagnostics !== undefined &&
623
700
  typeof value.diagnostics !== "function") {
@@ -639,6 +716,155 @@ export function validateFrameworkConfig(value) {
639
716
  }
640
717
  return diagnostics;
641
718
  }
719
+ const POLICY_PROPERTIES = new Set(["engine", "principal"]);
720
+ function validatePolicy(value, diagnostics) {
721
+ if (!isPlainRecord(value)) {
722
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy", "policy must be { engine, principal }"));
723
+ return;
724
+ }
725
+ for (const key of Object.keys(value)) {
726
+ if (!POLICY_PROPERTIES.has(key)) {
727
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `policy.${key}`, `unknown policy property: ${key}`));
728
+ }
729
+ }
730
+ if (!Object.hasOwn(value, "principal")) {
731
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "policy.principal", "policy.principal is required"));
732
+ }
733
+ else if (typeof value.principal !== "function") {
734
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy.principal", "policy.principal must be a function"));
735
+ }
736
+ if (!Object.hasOwn(value, "engine")) {
737
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "policy.engine", "policy.engine is required"));
738
+ return;
739
+ }
740
+ validatePolicyEngine(value.engine, "policy.engine", diagnostics);
741
+ }
742
+ function validateAccess(value, diagnostics) {
743
+ if (value === null || typeof value !== "object") {
744
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access", "access must be an access provider, { policy, state }"));
745
+ return;
746
+ }
747
+ const provider = value;
748
+ if (typeof provider.state !== "function") {
749
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access.state", "access.state must be a function"));
750
+ }
751
+ if (provider.client !== undefined) {
752
+ validateAccessClient(provider.client, diagnostics);
753
+ }
754
+ if (provider.policy === undefined) {
755
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "access.policy", "access.policy is required"));
756
+ return;
757
+ }
758
+ validatePolicyEngine(provider.policy, "access.policy", diagnostics);
759
+ }
760
+ function validateAccessClient(value, diagnostics) {
761
+ if (value === null || typeof value !== "object") {
762
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access.client", "access.client must be an object, { url, verbs }"));
763
+ return;
764
+ }
765
+ const client = value;
766
+ if (!isAccessUrl(client.url)) {
767
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", "access.client.url", 'access.client.url must be an absolute http(s) URL or a root-relative path ("/api/auth")'));
768
+ }
769
+ const verbs = client.verbs;
770
+ if (verbs === null || typeof verbs !== "object") {
771
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access.client.verbs", `access.client.verbs must be an object of $access verbs (${ACCESS_VERB_NAMES.join(", ")})`));
772
+ return;
773
+ }
774
+ for (const name of ACCESS_VERB_NAMES) {
775
+ const verb = providerVerb(verbs, name);
776
+ if (verb !== undefined) {
777
+ validateAccessVerb(verb, `access.client.verbs.${name}`, diagnostics);
778
+ }
779
+ }
780
+ for (const name of Object.keys(verbs)) {
781
+ if (!isAccessVerbName(name)) {
782
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `access.client.verbs.${name}`, `access.client.verbs.${name} is not a $access verb`));
783
+ }
784
+ }
785
+ }
786
+ function validateAccessVerb(value, path, diagnostics) {
787
+ if (value === null || typeof value !== "object") {
788
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", path, `${path} must be an object, { method, path, args?, result, call }`));
789
+ return;
790
+ }
791
+ const verb = value;
792
+ if (verb.method !== "GET" && verb.method !== "POST") {
793
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${path}.method`, `${path}.method must be "GET" or "POST"`));
794
+ }
795
+ if (!isAccessPath(verb.path)) {
796
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${path}.path`, `${path}.path must be a path under access.client.url, starting with one "/"`));
797
+ }
798
+ for (const schema of ["args", "result"]) {
799
+ const given = verb[schema];
800
+ if ((schema === "result" || given !== undefined) && !isPlainRecord(given)) {
801
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${path}.${schema}`, `${path}.${schema} must be a JSON Schema object`));
802
+ }
803
+ }
804
+ if (typeof verb.call !== "function") {
805
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${path}.call`, `${path}.call must be a function`));
806
+ }
807
+ }
808
+ function validatePolicyEngine(engine, at, diagnostics) {
809
+ if (engine === null || typeof engine !== "object") {
810
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", at, `${at} must be an object`));
811
+ return;
812
+ }
813
+ const members = engine;
814
+ for (const question of ["can", "scopeOf", "fieldsOf"]) {
815
+ if (typeof members[question] !== "function") {
816
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${question}`, `${at}.${question} must be a function`));
817
+ }
818
+ }
819
+ for (const optional of ["grantsOf", "hosted"]) {
820
+ if (members[optional] !== undefined &&
821
+ typeof members[optional] !== "function") {
822
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${optional}`, `${at}.${optional} must be a function when present`));
823
+ }
824
+ }
825
+ validatePolicyLists(members.governed, at, "governed", { all: "string lists", one: "a list of strings" }, isStringList, diagnostics);
826
+ validatePolicyLists(members.paths, at, "paths", {
827
+ all: "path lists",
828
+ one: "a list of paths, each a list of strings",
829
+ }, (paths) => Array.isArray(paths) && paths.every(isStringList), diagnostics);
830
+ validatePolicyLists(members.afterChecks, at, "afterChecks", { all: "action lists", one: "a list of actions" }, isStringList, diagnostics);
831
+ validateAfterCheckActions(members.afterChecks, at, diagnostics);
832
+ if (members.unheld !== undefined && !isStringList(members.unheld)) {
833
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.unheld`, `${at}.unheld must be a list of Resource names when provided`));
834
+ }
835
+ }
836
+ function validateAfterCheckActions(lists, at, diagnostics) {
837
+ if (!isPlainRecord(lists)) {
838
+ return;
839
+ }
840
+ for (const [resource, actions] of Object.entries(lists)) {
841
+ if (!isStringList(actions)) {
842
+ continue;
843
+ }
844
+ for (const action of actions) {
845
+ if (action !== "update") {
846
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${at}.afterChecks.${resource}`, `${at}.afterChecks.${resource}: "${action}" is no action an after check runs on; only "update" is`));
847
+ }
848
+ }
849
+ }
850
+ }
851
+ function isStringList(value) {
852
+ return (Array.isArray(value) && value.every((name) => typeof name === "string"));
853
+ }
854
+ function validatePolicyLists(lists, at, list, entry, isEntry, diagnostics) {
855
+ if (lists === undefined) {
856
+ return;
857
+ }
858
+ if (!isPlainRecord(lists)) {
859
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${list}`, `${at}.${list} must be an object of ${entry.all} when provided`));
860
+ return;
861
+ }
862
+ for (const [key, value] of Object.entries(lists)) {
863
+ if (!isEntry(value)) {
864
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${list}.${key}`, `${at}.${list}.${key} must be ${entry.one}`));
865
+ }
866
+ }
867
+ }
642
868
  function validateMcp(value, api, diagnostics) {
643
869
  if (typeof value === "string") {
644
870
  validateMcpPath(value, "mcp", api, diagnostics);
@@ -704,9 +930,10 @@ function validateMcpAuthorization(value, diagnostics) {
704
930
  }
705
931
  else {
706
932
  value.servers.forEach((server, index) => {
707
- if (!isHttpsUrl(server)) {
708
- const serverPath = `${serversPath}[${index}]`;
709
- diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", serverPath, `${serverPath} must be an absolute https URL`));
933
+ const serverPath = `${serversPath}[${index}]`;
934
+ const refusal = authorizationServerRefusal(server, serverPath);
935
+ if (refusal !== undefined) {
936
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", serverPath, refusal));
710
937
  }
711
938
  });
712
939
  }
@@ -718,14 +945,49 @@ function validateMcpAuthorization(value, diagnostics) {
718
945
  diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", verifyPath, `${verifyPath} must be a function: token in, the caller or null out`));
719
946
  }
720
947
  }
721
- function isHttpsUrl(value) {
948
+ const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "[::1]"]);
949
+ const LOOPBACK_NAME = "localhost";
950
+ function authorizationServerRefusal(value, path) {
951
+ const notHttps = `${path} must be an absolute https URL`;
722
952
  if (typeof value !== "string") {
723
- return false;
953
+ return notHttps;
724
954
  }
955
+ let url;
725
956
  try {
726
- return new URL(value).protocol === "https:";
957
+ url = new URL(value);
727
958
  }
728
959
  catch {
729
- return false;
960
+ return notHttps;
961
+ }
962
+ const http = url.protocol === "http:";
963
+ if (!http && url.protocol !== "https:") {
964
+ return notHttps;
965
+ }
966
+ if (http &&
967
+ ((!LOOPBACK_HOSTNAMES.has(url.hostname) &&
968
+ url.hostname !== LOOPBACK_NAME) ||
969
+ url.username !== "" ||
970
+ url.password !== "")) {
971
+ return notHttps;
972
+ }
973
+ if (url.pathname.includes("//")) {
974
+ return `${path} has an empty path segment ("//"); a client can read what follows it as another host`;
975
+ }
976
+ if (url.port === "0") {
977
+ return `${path} names port 0, which no server listens on`;
978
+ }
979
+ if (url.href.includes("?") || url.href.includes("#")) {
980
+ return `${path} has a query or fragment; an authorization server's URL (its issuer) takes neither`;
981
+ }
982
+ if (!http) {
983
+ return undefined;
984
+ }
985
+ if (url.hostname === LOOPBACK_NAME) {
986
+ url.hostname = "127.0.0.1";
730
987
  }
988
+ const canonical = url.href;
989
+ const short = canonical === `${url.origin}/` ? url.origin : canonical;
990
+ return value === canonical || value === short
991
+ ? undefined
992
+ : `${path} is an http loopback URL; write it as ${short}, the spelling every client reads as this machine`;
731
993
  }
@@ -16,10 +16,6 @@ type OverlayLayer = "application" | "client" | "agent";
16
16
  type ResourceOverlays = {
17
17
  readonly [L in OverlayLayer]?: unknown;
18
18
  };
19
- /** The overlay blocks `Overlays`, each checked against the root `Block`. */
20
- type CheckedOverlays<M extends AvAdapterModel, R extends AvConfigResourceKey<M>, Block, Overlays> = {
21
- readonly [L in keyof Overlays]: L extends OverlayLayer ? NoInfer<AvConfigResource<M, ResourceBlockConfig<R, Block>, R, "overlay"> & ExactOverlayResource<M, ResourceBlockConfig<R, Block>, R, Overlays[L]>> : never;
22
- };
23
19
  /**
24
20
  * What {@link defineResource} returns: `root`, and `application`, `client` and
25
21
  * `agent` exactly when they were given, each `{ [R]: block }` to spread into that
@@ -53,5 +49,5 @@ export type AvDefinedResource<R extends string, Block, Overlays> = {
53
49
  * client: { resources: { ...post.client } },
54
50
  * ```
55
51
  */
56
- export declare function defineResource<M extends AvAdapterModel>(): <const R extends AvConfigResourceKey<M>, const Block = AvConfigResource<M, AvConfigAny, R, "root">, const Overlays extends ResourceOverlays = Record<never, never>>(resource: R, block: Block & NoInfer<AvConfigResource<M, ResourceBlockConfig<R, Block>, R, "root"> & ExactRootResource<M, R, Block>>, overlays?: Overlays & CheckedOverlays<M, R, Block, Overlays>) => AvDefinedResource<R, ErasedResourceBlock<Block>, ErasedOverlayBlocks<Overlays>>;
52
+ export declare function defineResource<M extends AvAdapterModel>(): <const R extends AvConfigResourceKey<M>, const Block = AvConfigResource<M, AvConfigAny, R, "root">, const Overlays extends ResourceOverlays = Record<never, never>>(resource: R, block: Block & NoInfer<AvConfigResource<M, ResourceBlockConfig<R, Block>, R, "root"> & ExactRootResource<M, R, Block>>, overlays?: Overlays & { readonly [L in keyof Overlays]: L extends OverlayLayer ? NoInfer<AvConfigResource<M, ResourceBlockConfig<R, Block>, R, "overlay", L> & ExactOverlayResource<M, ResourceBlockConfig<R, Block>, R, Overlays[L]>> : never; }) => AvDefinedResource<R, ErasedResourceBlock<Block>, ErasedOverlayBlocks<Overlays>>;
57
53
  export {};
@@ -4,7 +4,7 @@
4
4
  * Root is the empty string, not `"/"`, so a route joins onto it by concatenation with
5
5
  * no special case.
6
6
  */
7
- export type EntrypointPath = "" | `/${string}`;
7
+ type EntrypointPath = "" | `/${string}`;
8
8
  /**
9
9
  * Why a mount path is refused. Only the slash spelling is ever coerced
10
10
  * (`api`, `/api/` and `//api//` are one intent, `/api`); everything else that is
@@ -17,7 +17,7 @@ export type EntrypointRefusalReason = "whitespace" | "scheme" | "query" | "fragm
17
17
  * and the rule, and never echoes the value: an entrypoint may carry
18
18
  * credentials (the client's rule, shared by the server).
19
19
  */
20
- export type EntrypointNormalization = {
20
+ type EntrypointNormalization = {
21
21
  readonly ok: true;
22
22
  readonly path: EntrypointPath;
23
23
  } | {
@@ -30,3 +30,4 @@ export type EntrypointNormalization = {
30
30
  * or a refusal.
31
31
  */
32
32
  export declare function normalizeEntrypoint(value: string): EntrypointNormalization;
33
+ export {};
@@ -16,6 +16,10 @@ type PipelinesSchema = {
16
16
  };
17
17
  readonly interceptors: Leaf;
18
18
  readonly filters: Leaf;
19
+ readonly cache: {
20
+ readonly for: Leaf;
21
+ readonly maxAge: Leaf;
22
+ };
19
23
  };
20
24
  type LimitsSchema = {
21
25
  readonly maxRequestBytes: Leaf;
@@ -24,6 +28,8 @@ type LimitsSchema = {
24
28
  readonly maxTransactionOperations: Leaf;
25
29
  readonly maxBooleanNodes: Leaf;
26
30
  readonly maxJsonDepth: Leaf;
31
+ readonly maxAll: Leaf;
32
+ readonly maxAllConcurrency: Leaf;
27
33
  };
28
34
  type LevelSchema = {
29
35
  readonly pipelines: PipelinesSchema;
@@ -103,9 +109,11 @@ type TokenOf<Member> = Member extends {
103
109
  } ? {
104
110
  [K in keyof Member]: K extends "scopes" ? never : Member[K] extends readonly (infer Token)[] ? Token : never;
105
111
  }[keyof Member] : Member extends readonly (infer Token)[] ? Token : never;
112
+ /** The capability members an exemption never names. */
113
+ type AdapterStatedMember = "nestedWriteFilter" | "filterModes" | "pathFilterModes";
106
114
  /** A field's exemption against its capabilities: their names, and each one's tokens. */
107
- type CapabilityExemptionSchema<Caps> = ListOf<Exclude<keyof Caps, "nestedWriteFilter">> & {
108
- readonly [K in Exclude<keyof Caps, "nestedWriteFilter">]-?: ListOf<TokenOf<NonNullable<Caps[K]>>>;
115
+ type CapabilityExemptionSchema<Caps> = ListOf<Exclude<keyof Caps, AdapterStatedMember>> & {
116
+ readonly [K in Exclude<keyof Caps, AdapterStatedMember>]-?: ListOf<TokenOf<NonNullable<Caps[K]>>>;
109
117
  };
110
118
  type FieldExemptionSchema<M extends AvAdapterModel, R extends AvConfigResourceKey<M>, F> = F extends AvAdapterFieldKey<M, R> ? M["resources"][R]["fields"][F] extends {
111
119
  readonly kind: "relation";
@@ -131,33 +139,58 @@ type ExemptionsSchema<M extends AvAdapterModel, Cfg> = {
131
139
  };
132
140
  };
133
141
  };
134
- /** A Pick overlay's exemptions, against the root's view. */
135
- type PickExemptionsSchema<Resources> = {
142
+ declare const refusal: unique symbol;
143
+ /** What a level refuses an unknown key for: `layer` cannot expose it, `parent` hid it, under `at`. */
144
+ type Refusal<Layer extends string, Parent extends string, At extends string> = {
145
+ readonly [refusal]: {
146
+ readonly layer: Layer;
147
+ readonly parent: Parent;
148
+ readonly at: At;
149
+ };
150
+ };
151
+ /** The sentence a refused key `K` holding `Value` is typed as; `never` for an entry written `false`. */
152
+ type RefusalOf<Info, K, Value> = [Value] extends [false] ? never : Info extends {
153
+ readonly layer: infer Layer extends string;
154
+ readonly parent: infer Parent extends string;
155
+ readonly at: infer At extends string;
156
+ } ? Value extends readonly unknown[] ? {
157
+ readonly [S in `Error: ${Layer} cannot expose '${At}${K & string}': hidden by ${Parent}`]: true;
158
+ } : readonly [
159
+ `Error: ${Layer} cannot expose '${At}${K & string}': hidden by ${Parent}`
160
+ ] : never;
161
+ /** A Pick layer's operations exemption, a family or variant its parent hid refused by name. */
162
+ type PickOperationsSchema<Ops, Layer extends string, Parent extends string, R extends string> = ListOf<keyof Ops> & {
163
+ readonly [F in keyof Ops]-?: ListOf<keyof NonNullable<Ops[F]>> & {
164
+ readonly [V in keyof NonNullable<Ops[F]>]: Leaf;
165
+ } & Refusal<Layer, Parent, `${R}.${F & string}.`>;
166
+ } & Refusal<Layer, Parent, `${R}.`>;
167
+ /** The fields of one Resource of a view. */
168
+ type ViewFields<Resource> = Resource extends {
169
+ readonly fields: infer Fields;
170
+ } ? Fields : never;
171
+ /** A Pick layer's exemptions, against its parent's view. */
172
+ type PickExemptionsSchema<Resources, Layer extends string, Parent extends string> = {
136
173
  readonly resources: {
137
174
  readonly [R in keyof Resources]: {
138
- readonly operations: OperationsExemptionSchema<Resources[R] extends {
175
+ readonly operations: PickOperationsSchema<Resources[R] extends {
139
176
  readonly operations: infer Ops;
140
- } ? Ops : never>;
177
+ } ? Ops : never, Layer, Parent, R & string>;
141
178
  readonly fields: {
142
- readonly [F in keyof (Resources[R] extends {
143
- readonly fields: infer Fields;
144
- } ? Fields : never)]: CapabilityExemptionSchema<(Resources[R] extends {
145
- readonly fields: infer Fields;
146
- } ? Fields : never)[F] extends {
179
+ readonly [F in keyof ViewFields<Resources[R]>]: CapabilityExemptionSchema<ViewFields<Resources[R]>[F] extends {
147
180
  readonly capabilities: infer Caps;
148
- } ? Caps : never>;
149
- };
181
+ } ? Caps : never> & Refusal<Layer, Parent, `${R & string}.${F & string}.`>;
182
+ } & Refusal<Layer, Parent, `${R & string}.`>;
150
183
  };
151
- };
184
+ } & Refusal<Layer, Parent, "">;
152
185
  };
153
186
  /** A layer's own configuration: `application`, `client` or `agent`. */
154
187
  type OverlayOf<Cfg, Layer extends "application" | "client" | "agent"> = (Cfg & {
155
188
  readonly [L in Layer]?: unknown;
156
189
  })[Layer];
157
190
  /** An overlay's exemptions schema, by the overlay's own `exposed`. */
158
- type OverlayExemptionsSchema<M extends AvAdapterModel, Cfg, Overlay> = Overlay extends {
191
+ type OverlayExemptionsSchema<M extends AvAdapterModel, Cfg, Overlay, Layer extends "application" | "client"> = Overlay extends {
159
192
  readonly exposed: false;
160
- } ? PickExemptionsSchema<RootViewResources<M, Cfg>> : ExemptionsSchema<M, Cfg>;
193
+ } ? PickExemptionsSchema<RootViewResources<M, Cfg>, Layer, "root"> : ExemptionsSchema<M, Cfg>;
161
194
  type LayerKeysSchema = {
162
195
  readonly exposed: Leaf;
163
196
  readonly transactionsStyle: Leaf;
@@ -167,7 +200,9 @@ type LayerKeysSchema = {
167
200
  type RootResourcesSchema<M extends AvAdapterModel> = {
168
201
  readonly [R in AvConfigResourceKey<M>]: ResourceSchema<M, R, FieldsSchema<M, R, "root", AvAdapterFieldKey<M, R>> & {
169
202
  readonly [otherKeys]: RootScalarFieldSchema;
170
- }>;
203
+ }> & {
204
+ readonly managedElsewhere: Leaf;
205
+ };
171
206
  };
172
207
  /**
173
208
  * One root `resources.<R>` block, checked key by key as
@@ -183,7 +218,7 @@ type OverlaySchema<M extends AvAdapterModel, Cfg, Layer extends "application" |
183
218
  readonly resources: {
184
219
  readonly [R in AvConfigResourceKey<M>]: ResourceSchema<M, R, FieldsSchema<M, R, "overlay", AvEffectiveFieldKey<M, Cfg, R>>>;
185
220
  };
186
- readonly exemptions: OverlayExemptionsSchema<M, Cfg, OverlayOf<Cfg, Layer>>;
221
+ readonly exemptions: OverlayExemptionsSchema<M, Cfg, OverlayOf<Cfg, Layer>, Layer>;
187
222
  };
188
223
  type McpSchema = {
189
224
  readonly path: Leaf;
@@ -197,7 +232,7 @@ type AgentParentOf<Cfg> = OverlayOf<Cfg, "agent"> extends {
197
232
  readonly extends: infer Parent;
198
233
  } ? Parent : "client";
199
234
  /** A Pick agent's exemptions, against the view of the layer it extends. */
200
- type AgentPickExemptionsSchema<M extends AvAdapterModel, Cfg, Parent> = Parent extends "application" | "client" ? [Parent] extends ["application"] | ["client"] ? PickExemptionsSchema<OverlayViewResources<M, Cfg, Parent>> : PickExemptionsSchema<RootViewResources<M, Cfg>> : PickExemptionsSchema<RootViewResources<M, Cfg>>;
235
+ type AgentPickExemptionsSchema<M extends AvAdapterModel, Cfg, Parent> = Parent extends "application" | "client" ? [Parent] extends ["application"] | ["client"] ? PickExemptionsSchema<OverlayViewResources<M, Cfg, Parent>, "agent", Parent> : PickExemptionsSchema<RootViewResources<M, Cfg>, "agent", "root"> : PickExemptionsSchema<RootViewResources<M, Cfg>, "agent", "root">;
201
236
  type AgentSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
202
237
  readonly extends: Leaf;
203
238
  readonly resources: {
@@ -211,6 +246,12 @@ type RootSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
211
246
  readonly api: Leaf;
212
247
  readonly mcp: McpSchema;
213
248
  readonly adapter: Leaf;
249
+ readonly prebuilt: Leaf;
250
+ readonly policy: {
251
+ readonly engine: Leaf;
252
+ readonly principal: Leaf;
253
+ };
254
+ readonly access: Leaf;
214
255
  readonly diagnostics: Leaf;
215
256
  readonly misuse: Leaf;
216
257
  readonly resources: RootResourcesSchema<M>;
@@ -219,9 +260,12 @@ type RootSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
219
260
  readonly client: OverlaySchema<M, Cfg, "client">;
220
261
  readonly agent: AgentSchema<M, Cfg>;
221
262
  };
222
- /** `V` with every key schema `S` lacks mapped to `never`; every leaf `unknown`. */
263
+ /**
264
+ * `V` with every key schema `S` lacks mapped to `never`, or to the sentence a
265
+ * refusing level states; every leaf `unknown`.
266
+ */
223
267
  type Exact<S, V> = [S] extends [Leaf] ? unknown : V extends readonly unknown[] ? S extends ListOf<infer Names> ? readonly Names[] : unknown : V extends (...args: any) => any ? unknown : V extends object ? string extends keyof V ? unknown : {
224
- readonly [K in keyof V]: K extends keyof S ? Exact<S[K], V[K]> : typeof otherKeys extends keyof S ? Exact<S[typeof otherKeys], V[K]> : never;
268
+ readonly [K in keyof V]: K extends keyof S ? Exact<S[K], V[K]> : typeof otherKeys extends keyof S ? Exact<S[typeof otherKeys], V[K]> : typeof refusal extends keyof S ? RefusalOf<S[typeof refusal], K, V[K]> : never;
225
269
  } : unknown;
226
270
  /**
227
271
  * The authored configuration `Cfg`, checked key by key: a key no level of the
@@ -229,7 +273,14 @@ type Exact<S, V> = [S] extends [Leaf] ? unknown : V extends readonly unknown[] ?
229
273
  * rc.0 key, a `definition` in an overlay, a stage a relation field does not take,
230
274
  * or a name the model and the root do not have.
231
275
  */
232
- export type AvConfigExact<M extends AvAdapterModel, Cfg> = Exact<RootSchema<M, Cfg>, Cfg> & ExposedWithExemptions<Cfg, "application"> & ExposedWithExemptions<Cfg, "client"> & ExposedWithExemptions<Cfg, "agent"> & ForceNeedsTransactions<M, Cfg>;
276
+ export type AvConfigExact<M extends AvAdapterModel, Cfg> = Exact<RootSchema<M, Cfg>, Cfg> & ExposedWithExemptions<Cfg, "application"> & ExposedWithExemptions<Cfg, "client"> & ExposedWithExemptions<Cfg, "agent"> & ForceNeedsTransactions<M, Cfg> & (Cfg extends {
277
+ readonly access: object;
278
+ readonly policy: object;
279
+ } ? {
280
+ readonly policy: readonly [
281
+ "Error: `access` brings the policy engine; remove `policy`"
282
+ ];
283
+ } : unknown);
233
284
  /** A layer's own literal `transactionsStyle`, `undefined` when it states none. */
234
285
  type StyleOf<Layer> = Layer extends {
235
286
  readonly transactionsStyle: infer Style;
@@ -17,3 +17,5 @@ export declare function computeOfLayer(resources: unknown): ResolvedComputeConfi
17
17
  * chained phase by phase. Nothing is disabled from below.
18
18
  */
19
19
  export declare function chainCompute(root: ResolvedComputeConfig, overlay: ResolvedComputeConfig): ResolvedComputeConfig;
20
+ /** The fields of `resource` with a `compute.create` stage in `compute`. */
21
+ export declare function createComputedFields(compute: ResolvedComputeConfig, resource: string): ReadonlySet<string>;