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

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 (228) hide show
  1. package/CHANGELOG.md +943 -16
  2. package/ERRORS.md +142 -0
  3. package/README.md +274 -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 +227 -24
  19. package/dist/compiler/managed-elsewhere.projector.d.ts +52 -0
  20. package/dist/compiler/managed-elsewhere.projector.js +179 -0
  21. package/dist/compiler/managed-elsewhere.validator.d.ts +9 -0
  22. package/dist/compiler/managed-elsewhere.validator.js +74 -0
  23. package/dist/config/computed-fields.d.ts +62 -0
  24. package/dist/config/computed-fields.js +73 -0
  25. package/dist/config/config-diagnostic.guidance.d.ts +6 -0
  26. package/dist/config/config-diagnostic.guidance.js +32 -0
  27. package/dist/config/config.resolver.d.ts +24 -0
  28. package/dist/config/config.resolver.js +65 -0
  29. package/dist/config/config.validator.js +222 -8
  30. package/dist/config/define-resource.d.ts +1 -5
  31. package/dist/config/entrypoint.normalizer.d.ts +3 -2
  32. package/dist/config/exact-framework-config.d.ts +67 -22
  33. package/dist/config/field-compute.resolver.d.ts +2 -0
  34. package/dist/config/field-compute.resolver.js +8 -0
  35. package/dist/config/framework-config.d.ts +53 -15
  36. package/dist/config/framework-resources-config.d.ts +25 -14
  37. package/dist/config/pipeline-config.d.ts +4 -4
  38. package/dist/config/pipeline-tree.resolver.d.ts +2 -2
  39. package/dist/contracts/access-route.rules.d.ts +10 -0
  40. package/dist/contracts/access-route.rules.js +45 -0
  41. package/dist/contracts/capability.d.ts +26 -1
  42. package/dist/contracts/capability.js +20 -0
  43. package/dist/contracts/client-contract-structure.validator.d.ts +301 -89
  44. package/dist/contracts/client-contract-structure.validator.js +37 -2
  45. package/dist/contracts/contract-access.d.ts +29 -0
  46. package/dist/contracts/contract-access.js +1 -0
  47. package/dist/contracts/contract-canonicalizer.d.ts +9 -1
  48. package/dist/contracts/contract-canonicalizer.js +30 -4
  49. package/dist/contracts/contract-hash.d.ts +0 -1
  50. package/dist/contracts/contract-hash.js +1 -1
  51. package/dist/contracts/contract.d.ts +27 -1
  52. package/dist/contracts/field.d.ts +58 -1
  53. package/dist/contracts/json-schema.projector.d.ts +11 -0
  54. package/dist/contracts/json-schema.projector.js +78 -0
  55. package/dist/contracts/scalar-value-type.d.ts +3 -1
  56. package/dist/framework/access-facade.d.ts +116 -0
  57. package/dist/framework/access-facade.js +120 -0
  58. package/dist/framework/contract-view.d.ts +120 -16
  59. package/dist/framework/framework-construction.error.d.ts +14 -4
  60. package/dist/framework/framework-construction.error.js +18 -2
  61. package/dist/framework/framework.d.ts +26 -5
  62. package/dist/framework/framework.factory.d.ts +1 -1
  63. package/dist/framework/framework.factory.js +115 -23
  64. package/dist/framework/operation-facade.d.ts +80 -13
  65. package/dist/framework/operation-facade.js +2 -1
  66. package/dist/index.d.ts +17 -5
  67. package/dist/index.js +1 -0
  68. package/dist/internal.d.ts +7 -2
  69. package/dist/internal.js +6 -0
  70. package/dist/operations/database-refusal.d.ts +51 -0
  71. package/dist/operations/database-refusal.js +45 -0
  72. package/dist/operations/operation-arguments.d.ts +148 -60
  73. package/dist/operations/operation-call.d.ts +9 -5
  74. package/dist/operations/operation-result.d.ts +6 -4
  75. package/dist/operations/operation-validator-core.js +159 -36
  76. package/dist/operations/operation-validator.d.ts +1 -1
  77. package/dist/operations/structural-limits.walker.d.ts +1 -1
  78. package/dist/operations/validation-code.guidance.d.ts +6 -0
  79. package/dist/operations/validation-code.guidance.js +90 -0
  80. package/dist/operations/write-scope.resolver.d.ts +4 -0
  81. package/dist/operations/write-scope.resolver.js +2 -0
  82. package/dist/policy/access-provider.interface.d.ts +91 -0
  83. package/dist/policy/access-provider.interface.js +1 -0
  84. package/dist/policy/access-provider.registry.d.ts +17 -0
  85. package/dist/policy/access-provider.registry.js +15 -0
  86. package/dist/policy/access-question.d.ts +20 -0
  87. package/dist/policy/access-question.js +1 -0
  88. package/dist/policy/access-question.registry.d.ts +5 -0
  89. package/dist/policy/access-question.registry.js +19 -0
  90. package/dist/policy/access-question.runtime.d.ts +36 -0
  91. package/dist/policy/access-question.runtime.js +297 -0
  92. package/dist/policy/access-verb.table.d.ts +56 -0
  93. package/dist/policy/access-verb.table.js +21 -0
  94. package/dist/policy/access-verbs.d.ts +46 -0
  95. package/dist/policy/access-verbs.js +1 -0
  96. package/dist/policy/policy-admission.d.ts +20 -0
  97. package/dist/policy/policy-admission.js +409 -0
  98. package/dist/policy/policy-after-update.runtime.d.ts +79 -0
  99. package/dist/policy/policy-after-update.runtime.js +208 -0
  100. package/dist/policy/policy-condition.d.ts +15 -0
  101. package/dist/policy/policy-condition.js +36 -0
  102. package/dist/policy/policy-engine.d.ts +205 -0
  103. package/dist/policy/policy-engine.js +1 -0
  104. package/dist/policy/policy-named-rows.d.ts +18 -0
  105. package/dist/policy/policy-named-rows.js +51 -0
  106. package/dist/policy/policy-nested-write.runtime.d.ts +44 -0
  107. package/dist/policy/policy-nested-write.runtime.js +545 -0
  108. package/dist/policy/policy-read.runtime.d.ts +81 -0
  109. package/dist/policy/policy-read.runtime.js +503 -0
  110. package/dist/policy/policy-reference-write.runtime.d.ts +51 -0
  111. package/dist/policy/policy-reference-write.runtime.js +345 -0
  112. package/dist/policy/policy-request.d.ts +41 -0
  113. package/dist/policy/policy-request.js +63 -0
  114. package/dist/policy/policy-session.d.ts +106 -0
  115. package/dist/policy/policy-session.js +295 -0
  116. package/dist/policy/policy-startup.validator.d.ts +10 -0
  117. package/dist/policy/policy-startup.validator.js +112 -0
  118. package/dist/policy/policy-write.runtime.d.ts +39 -0
  119. package/dist/policy/policy-write.runtime.js +532 -0
  120. package/dist/prebuilt/core-version.generated.d.ts +2 -0
  121. package/dist/prebuilt/core-version.generated.js +1 -0
  122. package/dist/prebuilt/prebuilt-changes.d.ts +29 -0
  123. package/dist/prebuilt/prebuilt-changes.js +65 -0
  124. package/dist/prebuilt/prebuilt-contracts.d.ts +40 -0
  125. package/dist/prebuilt/prebuilt-contracts.emitter.d.ts +16 -0
  126. package/dist/prebuilt/prebuilt-contracts.emitter.js +50 -0
  127. package/dist/prebuilt/prebuilt-contracts.js +1 -0
  128. package/dist/prebuilt/prebuilt-contracts.loader.d.ts +19 -0
  129. package/dist/prebuilt/prebuilt-contracts.loader.js +77 -0
  130. package/dist/prebuilt/prebuilt-inputs.fingerprint.d.ts +16 -0
  131. package/dist/prebuilt/prebuilt-inputs.fingerprint.js +229 -0
  132. package/dist/protocol/absent-route.responder.d.ts +9 -27
  133. package/dist/protocol/absent-route.responder.js +36 -3
  134. package/dist/protocol/contract-document.responder.d.ts +2 -1
  135. package/dist/protocol/http-request.decoder.d.ts +19 -3
  136. package/dist/protocol/http-request.decoder.js +24 -1
  137. package/dist/protocol/http-request.reader.d.ts +6 -3
  138. package/dist/protocol/http-request.reader.js +1 -0
  139. package/dist/protocol/http-response.encoder.js +2 -2
  140. package/dist/protocol/protocol-headers.d.ts +3 -3
  141. package/dist/protocol/protocol-surface.d.ts +6 -1
  142. package/dist/protocol/protocol-surface.js +7 -0
  143. package/dist/protocol/protocol.binder.d.ts +16 -1
  144. package/dist/protocol/protocol.binder.js +4 -1
  145. package/dist/protocol/protocol.handler.d.ts +12 -1
  146. package/dist/protocol/protocol.handler.js +86 -17
  147. package/dist/runtime/caller-data.copier.d.ts +18 -3
  148. package/dist/runtime/caller-data.copier.js +21 -8
  149. package/dist/runtime/caller-data.door.d.ts +13 -6
  150. package/dist/runtime/computed-read-runtime.d.ts +6 -1
  151. package/dist/runtime/computed-read-runtime.js +232 -45
  152. package/dist/runtime/computed-value.error.d.ts +3 -2
  153. package/dist/runtime/computed-value.error.js +3 -2
  154. package/dist/runtime/context-executor.runtime.d.ts +4 -3
  155. package/dist/runtime/context-executor.runtime.js +4 -2
  156. package/dist/runtime/core-class.brand.d.ts +10 -0
  157. package/dist/runtime/core-class.brand.js +21 -0
  158. package/dist/runtime/create-requirement.d.ts +31 -5
  159. package/dist/runtime/create-requirement.js +129 -21
  160. package/dist/runtime/decimal.d.ts +14 -0
  161. package/dist/runtime/decimal.js +21 -0
  162. package/dist/runtime/diagnostics-reporter.d.ts +44 -9
  163. package/dist/runtime/diagnostics-reporter.js +13 -1
  164. package/dist/runtime/error-boundary.d.ts +9 -2
  165. package/dist/runtime/error-boundary.js +12 -0
  166. package/dist/runtime/error-guidance.d.ts +12 -0
  167. package/dist/runtime/error-guidance.js +1 -0
  168. package/dist/runtime/error.catalog.d.ts +49 -0
  169. package/dist/runtime/error.catalog.js +49 -0
  170. package/dist/runtime/execution-options.d.ts +8 -0
  171. package/dist/runtime/field-check.evaluator.d.ts +0 -2
  172. package/dist/runtime/field-check.evaluator.js +1 -1
  173. package/dist/runtime/field-compute.d.ts +11 -10
  174. package/dist/runtime/field-stage.runtime.d.ts +3 -1
  175. package/dist/runtime/field-stage.runtime.js +8 -4
  176. package/dist/runtime/field-validator.runtime.d.ts +19 -1
  177. package/dist/runtime/field-validator.runtime.js +47 -8
  178. package/dist/runtime/framework-error.js +9 -0
  179. package/dist/runtime/framework-warning.emitter.d.ts +6 -0
  180. package/dist/runtime/framework-warning.emitter.js +8 -0
  181. package/dist/runtime/json-value.d.ts +10 -5
  182. package/dist/runtime/level-lifecycle.runtime.d.ts +4 -3
  183. package/dist/runtime/level-lifecycle.runtime.js +3 -5
  184. package/dist/runtime/mutation-planner.d.ts +1 -6
  185. package/dist/runtime/mutation-planner.js +3 -14
  186. package/dist/runtime/operation-code.guidance.d.ts +6 -0
  187. package/dist/runtime/operation-code.guidance.js +167 -0
  188. package/dist/runtime/operation-request.d.ts +16 -9
  189. package/dist/runtime/operation-runtime.d.ts +35 -17
  190. package/dist/runtime/operation-runtime.js +220 -49
  191. package/dist/runtime/outcome-mapper.d.ts +2 -1
  192. package/dist/runtime/output-validator.d.ts +1 -1
  193. package/dist/runtime/owned-execution.registry.d.ts +13 -3
  194. package/dist/runtime/pipe-output.validator.d.ts +10 -0
  195. package/dist/runtime/pipe-output.validator.js +4 -2
  196. package/dist/runtime/pipeline.d.ts +47 -22
  197. package/dist/runtime/readonly-value.d.ts +20 -5
  198. package/dist/runtime/readonly-value.js +74 -26
  199. package/dist/runtime/referential-action.d.ts +1 -1
  200. package/dist/runtime/scalar-runtime.d.ts +4 -11
  201. package/dist/runtime/scalar-runtime.js +91 -22
  202. package/dist/runtime/unsent-value.normalizer.d.ts +15 -0
  203. package/dist/runtime/unsent-value.normalizer.js +128 -0
  204. package/dist/transactions/operation-arguments-encoder.js +8 -3
  205. package/dist/transactions/operation-fingerprint.js +2 -2
  206. package/dist/transactions/sql-statement.d.ts +10 -2
  207. package/dist/transactions/sql-statement.validator.d.ts +2 -2
  208. package/dist/transactions/sql-statement.validator.js +38 -5
  209. package/dist/transactions/transaction-envelope.d.ts +5 -4
  210. package/dist/transactions/transaction-integrity-error.js +2 -0
  211. package/dist/transactions/transaction-plan-assembler.d.ts +12 -5
  212. package/dist/transactions/transaction-plan-assembler.js +48 -10
  213. package/dist/transactions/transaction-plan-validator.d.ts +23 -7
  214. package/dist/transactions/transaction-plan-validator.js +27 -1
  215. package/dist/transactions/transaction-reference-resolver.d.ts +3 -2
  216. package/dist/transactions/transaction-reference-validator.d.ts +43 -3
  217. package/dist/transactions/transaction-reference-validator.js +83 -57
  218. package/dist/transactions/transaction-reference.d.ts +1 -1
  219. package/dist/transactions/transaction-reference.js +5 -0
  220. package/dist/transactions/transaction-request.d.ts +8 -8
  221. package/dist/transactions/transaction-runtime.d.ts +5 -2
  222. package/dist/transactions/transaction-runtime.js +79 -27
  223. package/dist/transactions/transaction-settlement.runtime.d.ts +4 -3
  224. package/dist/transactions/transaction-slot-path-error.js +2 -0
  225. package/dist/transactions/transaction-stage.runtime.d.ts +5 -3
  226. package/dist/transactions/transaction-stage.runtime.js +7 -4
  227. package/package.json +6 -5
  228. package/src/runtime/field-check.evaluator.ts +1 -1
@@ -1,10 +1,15 @@
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";
2
4
  import { normalizeEntrypoint } from "./entrypoint.normalizer.js";
3
5
  import { AVZ_FORMATS } from "./framework-field-definition.js";
4
6
  const ROOT_ONLY_PROPERTIES = new Set([
5
7
  "api",
6
8
  "mcp",
7
9
  "adapter",
10
+ "prebuilt",
11
+ "policy",
12
+ "access",
8
13
  "diagnostics",
9
14
  "misuse",
10
15
  "application",
@@ -36,6 +41,7 @@ const RESOURCE_PROPERTIES = new Set([
36
41
  "operations",
37
42
  "transactions",
38
43
  "fields",
44
+ "managedElsewhere",
39
45
  ]);
40
46
  const FIELD_PROPERTIES = new Set(["definition", "pipelines"]);
41
47
  const DEFINITION_PROPERTIES = new Set([
@@ -339,7 +345,16 @@ function validateResource(value, path, resource, isRoot, diagnostics) {
339
345
  continue;
340
346
  }
341
347
  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`));
348
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", keyPath, `unknown Resource property: ${key}; a Resource takes pipelines, operations, transactions and fields (and managedElsewhere at the root)`));
349
+ continue;
350
+ }
351
+ if (key === "managedElsewhere") {
352
+ if (!isRoot) {
353
+ 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)`));
354
+ }
355
+ else if (typeof child !== "boolean") {
356
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", keyPath, `${keyPath} must be a boolean`));
357
+ }
343
358
  continue;
344
359
  }
345
360
  if (key === "pipelines") {
@@ -618,6 +633,20 @@ export function validateFrameworkConfig(value) {
618
633
  else {
619
634
  validateAdapter(value.adapter, diagnostics);
620
635
  }
636
+ if (Object.hasOwn(value, "prebuilt") &&
637
+ value.prebuilt !== undefined &&
638
+ (value.prebuilt === null || typeof value.prebuilt !== "object")) {
639
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "prebuilt", "prebuilt must be the generated prebuilt Contracts object when provided"));
640
+ }
641
+ if (Object.hasOwn(value, "policy") && value.policy !== undefined) {
642
+ validatePolicy(value.policy, diagnostics);
643
+ }
644
+ if (Object.hasOwn(value, "access") && value.access !== undefined) {
645
+ validateAccess(value.access, diagnostics);
646
+ if (Object.hasOwn(value, "policy") && value.policy !== undefined) {
647
+ 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"));
648
+ }
649
+ }
621
650
  if (Object.hasOwn(value, "diagnostics") &&
622
651
  value.diagnostics !== undefined &&
623
652
  typeof value.diagnostics !== "function") {
@@ -639,6 +668,155 @@ export function validateFrameworkConfig(value) {
639
668
  }
640
669
  return diagnostics;
641
670
  }
671
+ const POLICY_PROPERTIES = new Set(["engine", "principal"]);
672
+ function validatePolicy(value, diagnostics) {
673
+ if (!isPlainRecord(value)) {
674
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy", "policy must be { engine, principal }"));
675
+ return;
676
+ }
677
+ for (const key of Object.keys(value)) {
678
+ if (!POLICY_PROPERTIES.has(key)) {
679
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `policy.${key}`, `unknown policy property: ${key}`));
680
+ }
681
+ }
682
+ if (!Object.hasOwn(value, "principal")) {
683
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "policy.principal", "policy.principal is required"));
684
+ }
685
+ else if (typeof value.principal !== "function") {
686
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "policy.principal", "policy.principal must be a function"));
687
+ }
688
+ if (!Object.hasOwn(value, "engine")) {
689
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "policy.engine", "policy.engine is required"));
690
+ return;
691
+ }
692
+ validatePolicyEngine(value.engine, "policy.engine", diagnostics);
693
+ }
694
+ function validateAccess(value, diagnostics) {
695
+ if (value === null || typeof value !== "object") {
696
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access", "access must be an access provider, { policy, state }"));
697
+ return;
698
+ }
699
+ const provider = value;
700
+ if (typeof provider.state !== "function") {
701
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access.state", "access.state must be a function"));
702
+ }
703
+ if (provider.client !== undefined) {
704
+ validateAccessClient(provider.client, diagnostics);
705
+ }
706
+ if (provider.policy === undefined) {
707
+ diagnostics.push(diagnostic("CONFIG_REQUIRED", "access.policy", "access.policy is required"));
708
+ return;
709
+ }
710
+ validatePolicyEngine(provider.policy, "access.policy", diagnostics);
711
+ }
712
+ function validateAccessClient(value, diagnostics) {
713
+ if (value === null || typeof value !== "object") {
714
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access.client", "access.client must be an object, { url, verbs }"));
715
+ return;
716
+ }
717
+ const client = value;
718
+ if (!isAccessUrl(client.url)) {
719
+ 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")'));
720
+ }
721
+ const verbs = client.verbs;
722
+ if (verbs === null || typeof verbs !== "object") {
723
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", "access.client.verbs", `access.client.verbs must be an object of $access verbs (${ACCESS_VERB_NAMES.join(", ")})`));
724
+ return;
725
+ }
726
+ for (const name of ACCESS_VERB_NAMES) {
727
+ const verb = providerVerb(verbs, name);
728
+ if (verb !== undefined) {
729
+ validateAccessVerb(verb, `access.client.verbs.${name}`, diagnostics);
730
+ }
731
+ }
732
+ for (const name of Object.keys(verbs)) {
733
+ if (!isAccessVerbName(name)) {
734
+ diagnostics.push(diagnostic("CONFIG_UNKNOWN_PROPERTY", `access.client.verbs.${name}`, `access.client.verbs.${name} is not a $access verb`));
735
+ }
736
+ }
737
+ }
738
+ function validateAccessVerb(value, path, diagnostics) {
739
+ if (value === null || typeof value !== "object") {
740
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", path, `${path} must be an object, { method, path, args?, result, call }`));
741
+ return;
742
+ }
743
+ const verb = value;
744
+ if (verb.method !== "GET" && verb.method !== "POST") {
745
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${path}.method`, `${path}.method must be "GET" or "POST"`));
746
+ }
747
+ if (!isAccessPath(verb.path)) {
748
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${path}.path`, `${path}.path must be a path under access.client.url, starting with one "/"`));
749
+ }
750
+ for (const schema of ["args", "result"]) {
751
+ const given = verb[schema];
752
+ if ((schema === "result" || given !== undefined) && !isPlainRecord(given)) {
753
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${path}.${schema}`, `${path}.${schema} must be a JSON Schema object`));
754
+ }
755
+ }
756
+ if (typeof verb.call !== "function") {
757
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${path}.call`, `${path}.call must be a function`));
758
+ }
759
+ }
760
+ function validatePolicyEngine(engine, at, diagnostics) {
761
+ if (engine === null || typeof engine !== "object") {
762
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", at, `${at} must be an object`));
763
+ return;
764
+ }
765
+ const members = engine;
766
+ for (const question of ["can", "scopeOf", "fieldsOf"]) {
767
+ if (typeof members[question] !== "function") {
768
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${question}`, `${at}.${question} must be a function`));
769
+ }
770
+ }
771
+ for (const optional of ["grantsOf", "hosted"]) {
772
+ if (members[optional] !== undefined &&
773
+ typeof members[optional] !== "function") {
774
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${optional}`, `${at}.${optional} must be a function when present`));
775
+ }
776
+ }
777
+ validatePolicyLists(members.governed, at, "governed", { all: "string lists", one: "a list of strings" }, isStringList, diagnostics);
778
+ validatePolicyLists(members.paths, at, "paths", {
779
+ all: "path lists",
780
+ one: "a list of paths, each a list of strings",
781
+ }, (paths) => Array.isArray(paths) && paths.every(isStringList), diagnostics);
782
+ validatePolicyLists(members.afterChecks, at, "afterChecks", { all: "action lists", one: "a list of actions" }, isStringList, diagnostics);
783
+ validateAfterCheckActions(members.afterChecks, at, diagnostics);
784
+ if (members.unheld !== undefined && !isStringList(members.unheld)) {
785
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.unheld`, `${at}.unheld must be a list of Resource names when provided`));
786
+ }
787
+ }
788
+ function validateAfterCheckActions(lists, at, diagnostics) {
789
+ if (!isPlainRecord(lists)) {
790
+ return;
791
+ }
792
+ for (const [resource, actions] of Object.entries(lists)) {
793
+ if (!isStringList(actions)) {
794
+ continue;
795
+ }
796
+ for (const action of actions) {
797
+ if (action !== "update") {
798
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", `${at}.afterChecks.${resource}`, `${at}.afterChecks.${resource}: "${action}" is no action an after check runs on; only "update" is`));
799
+ }
800
+ }
801
+ }
802
+ }
803
+ function isStringList(value) {
804
+ return (Array.isArray(value) && value.every((name) => typeof name === "string"));
805
+ }
806
+ function validatePolicyLists(lists, at, list, entry, isEntry, diagnostics) {
807
+ if (lists === undefined) {
808
+ return;
809
+ }
810
+ if (!isPlainRecord(lists)) {
811
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${list}`, `${at}.${list} must be an object of ${entry.all} when provided`));
812
+ return;
813
+ }
814
+ for (const [key, value] of Object.entries(lists)) {
815
+ if (!isEntry(value)) {
816
+ diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", `${at}.${list}.${key}`, `${at}.${list}.${key} must be ${entry.one}`));
817
+ }
818
+ }
819
+ }
642
820
  function validateMcp(value, api, diagnostics) {
643
821
  if (typeof value === "string") {
644
822
  validateMcpPath(value, "mcp", api, diagnostics);
@@ -704,9 +882,10 @@ function validateMcpAuthorization(value, diagnostics) {
704
882
  }
705
883
  else {
706
884
  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`));
885
+ const serverPath = `${serversPath}[${index}]`;
886
+ const refusal = authorizationServerRefusal(server, serverPath);
887
+ if (refusal !== undefined) {
888
+ diagnostics.push(diagnostic("CONFIG_INVALID_VALUE", serverPath, refusal));
710
889
  }
711
890
  });
712
891
  }
@@ -718,14 +897,49 @@ function validateMcpAuthorization(value, diagnostics) {
718
897
  diagnostics.push(diagnostic("CONFIG_INVALID_TYPE", verifyPath, `${verifyPath} must be a function: token in, the caller or null out`));
719
898
  }
720
899
  }
721
- function isHttpsUrl(value) {
900
+ const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "[::1]"]);
901
+ const LOOPBACK_NAME = "localhost";
902
+ function authorizationServerRefusal(value, path) {
903
+ const notHttps = `${path} must be an absolute https URL`;
722
904
  if (typeof value !== "string") {
723
- return false;
905
+ return notHttps;
724
906
  }
907
+ let url;
725
908
  try {
726
- return new URL(value).protocol === "https:";
909
+ url = new URL(value);
727
910
  }
728
911
  catch {
729
- return false;
912
+ return notHttps;
913
+ }
914
+ const http = url.protocol === "http:";
915
+ if (!http && url.protocol !== "https:") {
916
+ return notHttps;
917
+ }
918
+ if (http &&
919
+ ((!LOOPBACK_HOSTNAMES.has(url.hostname) &&
920
+ url.hostname !== LOOPBACK_NAME) ||
921
+ url.username !== "" ||
922
+ url.password !== "")) {
923
+ return notHttps;
924
+ }
925
+ if (url.pathname.includes("//")) {
926
+ return `${path} has an empty path segment ("//"); a client can read what follows it as another host`;
927
+ }
928
+ if (url.port === "0") {
929
+ return `${path} names port 0, which no server listens on`;
930
+ }
931
+ if (url.href.includes("?") || url.href.includes("#")) {
932
+ return `${path} has a query or fragment; an authorization server's URL (its issuer) takes neither`;
933
+ }
934
+ if (!http) {
935
+ return undefined;
936
+ }
937
+ if (url.hostname === LOOPBACK_NAME) {
938
+ url.hostname = "127.0.0.1";
730
939
  }
940
+ const canonical = url.href;
941
+ const short = canonical === `${url.origin}/` ? url.origin : canonical;
942
+ return value === canonical || value === short
943
+ ? undefined
944
+ : `${path} is an http loopback URL; write it as ${short}, the spelling every client reads as this machine`;
731
945
  }
@@ -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 {};
@@ -103,9 +103,11 @@ type TokenOf<Member> = Member extends {
103
103
  } ? {
104
104
  [K in keyof Member]: K extends "scopes" ? never : Member[K] extends readonly (infer Token)[] ? Token : never;
105
105
  }[keyof Member] : Member extends readonly (infer Token)[] ? Token : never;
106
+ /** The capability members an exemption never names. */
107
+ type AdapterStatedMember = "nestedWriteFilter" | "filterModes" | "pathFilterModes";
106
108
  /** 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]>>>;
109
+ type CapabilityExemptionSchema<Caps> = ListOf<Exclude<keyof Caps, AdapterStatedMember>> & {
110
+ readonly [K in Exclude<keyof Caps, AdapterStatedMember>]-?: ListOf<TokenOf<NonNullable<Caps[K]>>>;
109
111
  };
110
112
  type FieldExemptionSchema<M extends AvAdapterModel, R extends AvConfigResourceKey<M>, F> = F extends AvAdapterFieldKey<M, R> ? M["resources"][R]["fields"][F] extends {
111
113
  readonly kind: "relation";
@@ -131,33 +133,58 @@ type ExemptionsSchema<M extends AvAdapterModel, Cfg> = {
131
133
  };
132
134
  };
133
135
  };
134
- /** A Pick overlay's exemptions, against the root's view. */
135
- type PickExemptionsSchema<Resources> = {
136
+ declare const refusal: unique symbol;
137
+ /** What a level refuses an unknown key for: `layer` cannot expose it, `parent` hid it, under `at`. */
138
+ type Refusal<Layer extends string, Parent extends string, At extends string> = {
139
+ readonly [refusal]: {
140
+ readonly layer: Layer;
141
+ readonly parent: Parent;
142
+ readonly at: At;
143
+ };
144
+ };
145
+ /** The sentence a refused key `K` holding `Value` is typed as; `never` for an entry written `false`. */
146
+ type RefusalOf<Info, K, Value> = [Value] extends [false] ? never : Info extends {
147
+ readonly layer: infer Layer extends string;
148
+ readonly parent: infer Parent extends string;
149
+ readonly at: infer At extends string;
150
+ } ? Value extends readonly unknown[] ? {
151
+ readonly [S in `Error: ${Layer} cannot expose '${At}${K & string}': hidden by ${Parent}`]: true;
152
+ } : readonly [
153
+ `Error: ${Layer} cannot expose '${At}${K & string}': hidden by ${Parent}`
154
+ ] : never;
155
+ /** A Pick layer's operations exemption, a family or variant its parent hid refused by name. */
156
+ type PickOperationsSchema<Ops, Layer extends string, Parent extends string, R extends string> = ListOf<keyof Ops> & {
157
+ readonly [F in keyof Ops]-?: ListOf<keyof NonNullable<Ops[F]>> & {
158
+ readonly [V in keyof NonNullable<Ops[F]>]: Leaf;
159
+ } & Refusal<Layer, Parent, `${R}.${F & string}.`>;
160
+ } & Refusal<Layer, Parent, `${R}.`>;
161
+ /** The fields of one Resource of a view. */
162
+ type ViewFields<Resource> = Resource extends {
163
+ readonly fields: infer Fields;
164
+ } ? Fields : never;
165
+ /** A Pick layer's exemptions, against its parent's view. */
166
+ type PickExemptionsSchema<Resources, Layer extends string, Parent extends string> = {
136
167
  readonly resources: {
137
168
  readonly [R in keyof Resources]: {
138
- readonly operations: OperationsExemptionSchema<Resources[R] extends {
169
+ readonly operations: PickOperationsSchema<Resources[R] extends {
139
170
  readonly operations: infer Ops;
140
- } ? Ops : never>;
171
+ } ? Ops : never, Layer, Parent, R & string>;
141
172
  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 {
173
+ readonly [F in keyof ViewFields<Resources[R]>]: CapabilityExemptionSchema<ViewFields<Resources[R]>[F] extends {
147
174
  readonly capabilities: infer Caps;
148
- } ? Caps : never>;
149
- };
175
+ } ? Caps : never> & Refusal<Layer, Parent, `${R & string}.${F & string}.`>;
176
+ } & Refusal<Layer, Parent, `${R & string}.`>;
150
177
  };
151
- };
178
+ } & Refusal<Layer, Parent, "">;
152
179
  };
153
180
  /** A layer's own configuration: `application`, `client` or `agent`. */
154
181
  type OverlayOf<Cfg, Layer extends "application" | "client" | "agent"> = (Cfg & {
155
182
  readonly [L in Layer]?: unknown;
156
183
  })[Layer];
157
184
  /** An overlay's exemptions schema, by the overlay's own `exposed`. */
158
- type OverlayExemptionsSchema<M extends AvAdapterModel, Cfg, Overlay> = Overlay extends {
185
+ type OverlayExemptionsSchema<M extends AvAdapterModel, Cfg, Overlay, Layer extends "application" | "client"> = Overlay extends {
159
186
  readonly exposed: false;
160
- } ? PickExemptionsSchema<RootViewResources<M, Cfg>> : ExemptionsSchema<M, Cfg>;
187
+ } ? PickExemptionsSchema<RootViewResources<M, Cfg>, Layer, "root"> : ExemptionsSchema<M, Cfg>;
161
188
  type LayerKeysSchema = {
162
189
  readonly exposed: Leaf;
163
190
  readonly transactionsStyle: Leaf;
@@ -167,7 +194,9 @@ type LayerKeysSchema = {
167
194
  type RootResourcesSchema<M extends AvAdapterModel> = {
168
195
  readonly [R in AvConfigResourceKey<M>]: ResourceSchema<M, R, FieldsSchema<M, R, "root", AvAdapterFieldKey<M, R>> & {
169
196
  readonly [otherKeys]: RootScalarFieldSchema;
170
- }>;
197
+ }> & {
198
+ readonly managedElsewhere: Leaf;
199
+ };
171
200
  };
172
201
  /**
173
202
  * One root `resources.<R>` block, checked key by key as
@@ -183,7 +212,7 @@ type OverlaySchema<M extends AvAdapterModel, Cfg, Layer extends "application" |
183
212
  readonly resources: {
184
213
  readonly [R in AvConfigResourceKey<M>]: ResourceSchema<M, R, FieldsSchema<M, R, "overlay", AvEffectiveFieldKey<M, Cfg, R>>>;
185
214
  };
186
- readonly exemptions: OverlayExemptionsSchema<M, Cfg, OverlayOf<Cfg, Layer>>;
215
+ readonly exemptions: OverlayExemptionsSchema<M, Cfg, OverlayOf<Cfg, Layer>, Layer>;
187
216
  };
188
217
  type McpSchema = {
189
218
  readonly path: Leaf;
@@ -197,7 +226,7 @@ type AgentParentOf<Cfg> = OverlayOf<Cfg, "agent"> extends {
197
226
  readonly extends: infer Parent;
198
227
  } ? Parent : "client";
199
228
  /** 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>>;
229
+ 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
230
  type AgentSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
202
231
  readonly extends: Leaf;
203
232
  readonly resources: {
@@ -211,6 +240,12 @@ type RootSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
211
240
  readonly api: Leaf;
212
241
  readonly mcp: McpSchema;
213
242
  readonly adapter: Leaf;
243
+ readonly prebuilt: Leaf;
244
+ readonly policy: {
245
+ readonly engine: Leaf;
246
+ readonly principal: Leaf;
247
+ };
248
+ readonly access: Leaf;
214
249
  readonly diagnostics: Leaf;
215
250
  readonly misuse: Leaf;
216
251
  readonly resources: RootResourcesSchema<M>;
@@ -219,9 +254,12 @@ type RootSchema<M extends AvAdapterModel, Cfg> = LayerKeysSchema & {
219
254
  readonly client: OverlaySchema<M, Cfg, "client">;
220
255
  readonly agent: AgentSchema<M, Cfg>;
221
256
  };
222
- /** `V` with every key schema `S` lacks mapped to `never`; every leaf `unknown`. */
257
+ /**
258
+ * `V` with every key schema `S` lacks mapped to `never`, or to the sentence a
259
+ * refusing level states; every leaf `unknown`.
260
+ */
223
261
  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;
262
+ 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
263
  } : unknown;
226
264
  /**
227
265
  * The authored configuration `Cfg`, checked key by key: a key no level of the
@@ -229,7 +267,14 @@ type Exact<S, V> = [S] extends [Leaf] ? unknown : V extends readonly unknown[] ?
229
267
  * rc.0 key, a `definition` in an overlay, a stage a relation field does not take,
230
268
  * or a name the model and the root do not have.
231
269
  */
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>;
270
+ 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 {
271
+ readonly access: object;
272
+ readonly policy: object;
273
+ } ? {
274
+ readonly policy: readonly [
275
+ "Error: `access` brings the policy engine; remove `policy`"
276
+ ];
277
+ } : unknown);
233
278
  /** A layer's own literal `transactionsStyle`, `undefined` when it states none. */
234
279
  type StyleOf<Layer> = Layer extends {
235
280
  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>;
@@ -113,3 +113,11 @@ export function chainCompute(root, overlay) {
113
113
  }
114
114
  return result;
115
115
  }
116
+ export function createComputedFields(compute, resource) {
117
+ const fields = Object.hasOwn(compute, resource)
118
+ ? compute[resource]
119
+ : undefined;
120
+ return new Set(Object.entries(fields ?? {})
121
+ .filter(([, phases]) => phases.create !== undefined)
122
+ .map(([field]) => field));
123
+ }
@@ -2,19 +2,28 @@ import type { AvAdapter } from "../adapters/adapter.interface.js";
2
2
  import type { AvAdapterModel } from "../adapters/adapter-model.js";
3
3
  import type { AvContractLimits } from "../contracts/contract-limits.js";
4
4
  import type { AvTransactionCapability } from "../contracts/transaction-capability.js";
5
+ import type { AvAccessProvider } from "../policy/access-provider.interface.js";
6
+ import type { AvPolicyEngine } from "../policy/policy-engine.js";
7
+ import type { AvPrebuiltContracts } from "../prebuilt/prebuilt-contracts.js";
5
8
  import type { AvDiagnosticsSink } from "../runtime/diagnostics-reporter.js";
6
9
  import type { AvMisuseSink } from "../runtime/misuse-reporter.js";
10
+ import type { AvState } from "../runtime/request-state.js";
7
11
  import type { AvConfigAny } from "./any-framework-config.js";
12
+ import type { AvConfigLayerName, AvRequestOrigin } from "./config-layer.js";
8
13
  import type { AvConfigExemptions } from "./framework-exemptions-config.js";
9
- import type { AvConfigLayerKind, AvConfigResources } from "./framework-resources-config.js";
14
+ import type { AvConfigLayerKind, AvConfigResources, LayerOfKind } from "./framework-resources-config.js";
10
15
  import type { AvPipeline } from "./pipeline-config.js";
11
16
  /**
12
17
  * Request limits to override; each one left out takes its default from
13
18
  * {@link DEFAULT_CONTRACT_LIMITS}.
14
19
  */
15
20
  export type AvConfigLimits = Partial<AvContractLimits>;
16
- /** rc.0's layer keys, each refused with its rc.1 location. */
17
- type MovedLayerKeys = {
21
+ /**
22
+ * The six keys every layer holds: the root, `application`, `client` and
23
+ * `agent`. Stages are added to the root's; `transactionsStyle` and `limits`
24
+ * replace it where an overlay states them; exposure only narrows.
25
+ */
26
+ export type AvConfigLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny, Kind extends AvConfigLayerKind = "root", Layer extends AvConfigLayerName = LayerOfKind<Kind>> = {
18
27
  /** Moved: `exposed` + `exemptions`. */
19
28
  readonly restrictions?: never;
20
29
  /** Moved: `resources.<R>.fields.<f>.pipelines.compute`. */
@@ -23,13 +32,6 @@ type MovedLayerKeys = {
23
32
  readonly fields?: never;
24
33
  /** Moved: `transactionsStyle`. */
25
34
  readonly transactions?: never;
26
- };
27
- /**
28
- * The six keys every layer holds: the root, `application`, `client` and
29
- * `agent`. Stages are added to the root's; `transactionsStyle` and `limits`
30
- * replace it where an overlay states them; exposure only narrows.
31
- */
32
- export type AvConfigLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny, Kind extends AvConfigLayerKind = "root"> = MovedLayerKeys & {
33
35
  /**
34
36
  * Whether the layer's `exemptions` hide (`true`, the root's default) or are
35
37
  * the only entries exposed (`false`). Each layer narrows its parent: the root
@@ -43,7 +45,7 @@ export type AvConfigLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvCon
43
45
  /** Guards, pipes, hooks, interceptors and filters run around every operation of the layer. */
44
46
  readonly pipelines?: AvPipeline<NoInfer<M>>;
45
47
  /** The per-Resource tree: stages, operations, transactions and fields. */
46
- readonly resources?: AvConfigResources<M, Cfg, Kind>;
48
+ readonly resources?: AvConfigResources<M, Cfg, Kind, Layer>;
47
49
  /**
48
50
  * The entries that are the opposite of `exposed`. An overlay that sets them
49
51
  * states its own `exposed`.
@@ -70,11 +72,45 @@ export type AvConfig<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAn
70
72
  */
71
73
  readonly mcp?: AvConfigMcp;
72
74
  readonly adapter: AvAdapter<M>;
75
+ /**
76
+ * Contracts compiled ahead of time (the generated `aventaraContracts`), for a
77
+ * fast cold start on serverless and edge platforms. Used only when they were
78
+ * compiled from this configuration and the adapter's model by this core;
79
+ * otherwise the Contracts are compiled at startup, as without it, and a
80
+ * `AVENTARA_PREBUILT_STALE` warning says why.
81
+ */
82
+ readonly prebuilt?: AvPrebuiltContracts;
83
+ /**
84
+ * The policy engine every client and agent request is checked against, and
85
+ * how a request's principal is derived from its `ctx.$state`. Application
86
+ * calls bypass it unless they name a principal (`{ as }`); calls a stage
87
+ * makes through `ctx` always do.
88
+ */
89
+ readonly policy?: {
90
+ readonly engine: AvPolicyEngine;
91
+ /**
92
+ * The request's principal, from its `ctx.$state` and its layer; `null` for
93
+ * an anonymous caller. It may answer with a promise (rc.5), which is
94
+ * awaited; a throw or a rejection answers `A3000`.
95
+ */
96
+ readonly principal: (facts: {
97
+ readonly $state: AvState;
98
+ readonly $origin: AvRequestOrigin;
99
+ }) => unknown;
100
+ };
101
+ /**
102
+ * The access provider (Aventara Access, or one written by hand): its
103
+ * `policy` engine checks every client and agent request, with
104
+ * `ctx.$state.me` as the principal, and the host seeds each request's
105
+ * `ctx.$state` with its `state`. Not together with `policy`, nor with a
106
+ * host's own `state` option.
107
+ */
108
+ readonly access?: AvAccessProvider;
73
109
  readonly diagnostics?: AvDiagnosticsSink;
74
110
  /** Told about every caller value refused as unreadable or not plain data. */
75
111
  readonly misuse?: AvMisuseSink;
76
- readonly application?: AvConfigLayer<M, Cfg, "overlay">;
77
- readonly client?: AvConfigLayer<M, Cfg, "overlay">;
112
+ readonly application?: AvConfigLayer<M, Cfg, "overlay", "application">;
113
+ readonly client?: AvConfigLayer<M, Cfg, "overlay", "client">;
78
114
  /**
79
115
  * The layer an AI agent's calls run under. It narrows the view of the layer it
80
116
  * `extends` (the client's when left out), and its stages run after that
@@ -95,7 +131,9 @@ export type AvConfigMcp = string | {
95
131
  readonly authorization?: {
96
132
  /**
97
133
  * The authorization servers (https URLs) a caller obtains its token
98
- * from, advertised in the endpoint's protected-resource metadata.
134
+ * from, advertised in the endpoint's protected-resource metadata. A
135
+ * server on this machine may be http: `http://127.0.0.1` or
136
+ * `http://[::1]`, with any port and path (not `localhost`).
99
137
  */
100
138
  readonly servers: readonly string[];
101
139
  /**
@@ -109,7 +147,7 @@ export type AvConfigMcp = string | {
109
147
  * The `agent` layer: the six layer keys, and `extends`, the layer whose final
110
148
  * view it narrows and whose stages run before its own.
111
149
  */
112
- export type AvConfigAgentLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny> = AvConfigLayer<M, Cfg, "overlay"> & {
150
+ export type AvConfigAgentLayer<M extends AvAdapterModel = AvAdapterModel, Cfg = AvConfigAny> = AvConfigLayer<M, Cfg, "overlay", "agent"> & {
113
151
  /**
114
152
  * The layer the agent starts from: `"client"` (the default), `"application"`
115
153
  * or `"root"`. The agent never widens it.