@astrale-os/kernel-dsl 1.0.0-beta.2 → 1.0.0-beta.20

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 (307) hide show
  1. package/dist/v1/addressing/class-key.js +3 -3
  2. package/dist/v1/addressing/definition-ref.js +21 -37
  3. package/dist/v1/addressing/domain-dependency.d.ts +0 -6
  4. package/dist/v1/addressing/domain-dependency.js +1 -6
  5. package/dist/v1/addressing/key.d.ts +4 -1
  6. package/dist/v1/addressing/key.js +23 -3
  7. package/dist/v1/addressing/ordering.d.ts +2 -0
  8. package/dist/v1/addressing/ordering.js +4 -0
  9. package/dist/v1/addressing/patterns.d.ts +1 -1
  10. package/dist/v1/addressing/patterns.js +2 -6
  11. package/dist/v1/builder/callable/authoring.d.ts +11 -5
  12. package/dist/v1/builder/callable/authoring.js +2 -0
  13. package/dist/v1/builder/class/authoring.d.ts +94 -224
  14. package/dist/v1/builder/class/authoring.js +31 -33
  15. package/dist/v1/builder/class/handle.d.ts +27 -0
  16. package/dist/v1/builder/class/handle.js +1 -0
  17. package/dist/v1/builder/class/input.d.ts +159 -0
  18. package/dist/v1/builder/class/projection.d.ts +129 -0
  19. package/dist/v1/builder/class/projection.js +1 -0
  20. package/dist/v1/builder/class/property.d.ts +3 -9
  21. package/dist/v1/builder/class/property.js +1 -0
  22. package/dist/v1/builder/core/authoring.d.ts +1 -1
  23. package/dist/v1/builder/index.d.ts +5 -2
  24. package/dist/v1/builder/lowering/callable.js +1 -0
  25. package/dist/v1/builder/lowering/class.d.ts +9 -1
  26. package/dist/v1/builder/lowering/class.js +62 -17
  27. package/dist/v1/builder/lowering/policy.js +2 -0
  28. package/dist/v1/builder/lowering/property-keys.d.ts +27 -0
  29. package/dist/v1/builder/lowering/property-keys.js +108 -0
  30. package/dist/v1/builder/lowering/schema/compile.js +11 -6
  31. package/dist/v1/builder/lowering/schema/context.d.ts +9 -1
  32. package/dist/v1/builder/lowering/schema/context.js +36 -4
  33. package/dist/v1/builder/lowering/schema/lifetime.d.ts +11 -0
  34. package/dist/v1/builder/lowering/schema/lifetime.js +55 -0
  35. package/dist/v1/builder/lowering/value/path.d.ts +1 -1
  36. package/dist/v1/builder/lowering/value/path.js +2 -4
  37. package/dist/v1/builder/lowering/value/zod.js +1 -3
  38. package/dist/v1/builder/policy/authoring.d.ts +85 -5
  39. package/dist/v1/builder/policy/authoring.js +107 -68
  40. package/dist/v1/builder/schema/define.d.ts +0 -1
  41. package/dist/v1/builder/schema/diagnostic.d.ts +3 -2
  42. package/dist/v1/builder/schema/diagnostic.js +5 -10
  43. package/dist/v1/builder/schema/input.d.ts +1 -1
  44. package/dist/v1/builder/schema/projection/callable.d.ts +7 -5
  45. package/dist/v1/builder/schema/projection/class.d.ts +118 -15
  46. package/dist/v1/builder/schema/projection/core-input.d.ts +2 -1
  47. package/dist/v1/builder/schema/projection/identity.d.ts +2 -1
  48. package/dist/v1/builder/schema/projection/model.d.ts +4 -2
  49. package/dist/v1/builder/schema/projection/property.d.ts +1 -1
  50. package/dist/v1/builder/schema/projection/resolved-class.d.ts +2 -1
  51. package/dist/v1/builder/schema/projection.d.ts +1 -1
  52. package/dist/v1/builder/value/full-match.d.ts +0 -1
  53. package/dist/v1/builder/value/full-match.js +0 -1
  54. package/dist/v1/builder/value/path-metadata.d.ts +1 -1
  55. package/dist/v1/builder/value/path.d.ts +1 -1
  56. package/dist/v1/bundle/codec.js +11 -13
  57. package/dist/v1/bundle/diagnostic.d.ts +2 -0
  58. package/dist/v1/bundle/diagnostic.js +9 -7
  59. package/dist/v1/bundle/model.js +1 -1
  60. package/dist/v1/bundle/structure.js +4 -6
  61. package/dist/v1/compiled/admission/accept.js +4 -10
  62. package/dist/v1/compiled/admission/closure.js +2 -2
  63. package/dist/v1/compiled/admission/diagnostic.d.ts +1 -1
  64. package/dist/v1/compiled/admission/diagnostic.js +1 -3
  65. package/dist/v1/compiled/admission/revision.d.ts +9 -1
  66. package/dist/v1/compiled/admission/revision.js +6 -3
  67. package/dist/v1/compiled/admission/semantics/class.d.ts +4 -1
  68. package/dist/v1/compiled/admission/semantics/class.js +37 -12
  69. package/dist/v1/compiled/admission/semantics/core.d.ts +1 -24
  70. package/dist/v1/compiled/admission/semantics/core.js +56 -24
  71. package/dist/v1/compiled/admission/semantics/edge.d.ts +2 -4
  72. package/dist/v1/compiled/admission/semantics/edge.js +6 -65
  73. package/dist/v1/compiled/admission/semantics/policy/callable.js +0 -2
  74. package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +5 -20
  75. package/dist/v1/compiled/admission/semantics/policy/contracts.js +8 -21
  76. package/dist/v1/compiled/admission/semantics/policy/parity.js +40 -43
  77. package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +4 -1
  78. package/dist/v1/compiled/admission/semantics/policy/pattern.js +4 -16
  79. package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +2 -24
  80. package/dist/v1/compiled/admission/semantics/policy/typing.js +19 -201
  81. package/dist/v1/compiled/admission/wire/callable.js +11 -1
  82. package/dist/v1/compiled/admission/wire/class.js +73 -21
  83. package/dist/v1/compiled/admission/wire/policy.d.ts +4 -3
  84. package/dist/v1/compiled/admission/wire/policy.js +8 -7
  85. package/dist/v1/compiled/compiler/compile.js +8 -8
  86. package/dist/v1/compiled/diagnostic.js +2 -3
  87. package/dist/v1/compiled/loader/load.d.ts +3 -2
  88. package/dist/v1/compiled/loader/load.js +11 -45
  89. package/dist/v1/domain/create.js +5 -6
  90. package/dist/v1/domain/model/domain.d.ts +2 -7
  91. package/dist/v1/domain/model/input.d.ts +2 -1
  92. package/dist/v1/domain/namespace/member-collection.js +4 -6
  93. package/dist/v1/domain/projection/classes.js +4 -1
  94. package/dist/v1/domain/validation/create.d.ts +6 -3
  95. package/dist/v1/domain/validation/create.js +21 -69
  96. package/dist/v1/index.d.ts +2 -1
  97. package/dist/v1/language/.spec/schemas/draft-2020-12.schema.json +462 -0
  98. package/dist/v1/language/.spec/schemas/value-schema.schema.json +22 -0
  99. package/dist/v1/language/callable/admission.d.ts +15 -0
  100. package/dist/v1/language/callable/admission.js +43 -0
  101. package/dist/v1/language/callable/model/callable.d.ts +10 -0
  102. package/dist/v1/language/callable/resolved.d.ts +16 -3
  103. package/dist/v1/language/class/inheritance.d.ts +36 -5
  104. package/dist/v1/language/class/inheritance.js +87 -1
  105. package/dist/v1/language/class/lifetime.d.ts +50 -11
  106. package/dist/v1/language/class/lifetime.js +89 -20
  107. package/dist/v1/language/class/model/class.d.ts +45 -9
  108. package/dist/v1/language/class/model/edge.d.ts +31 -2
  109. package/dist/v1/language/class/model/property.d.ts +16 -7
  110. package/dist/v1/language/class/property-values.js +2 -4
  111. package/dist/v1/language/class/unique.d.ts +143 -0
  112. package/dist/v1/language/class/unique.js +264 -0
  113. package/dist/v1/language/core/facts.d.ts +85 -0
  114. package/dist/v1/language/core/facts.js +116 -0
  115. package/dist/v1/language/definition/metadata.d.ts +5 -0
  116. package/dist/v1/language/definition/metadata.js +7 -0
  117. package/dist/v1/language/freeze.d.ts +5 -0
  118. package/dist/v1/{schema/canonical → language}/freeze.js +4 -0
  119. package/dist/v1/language/index.d.ts +7 -2
  120. package/dist/v1/language/index.js +5 -1
  121. package/dist/v1/language/limits.d.ts +64 -0
  122. package/dist/v1/language/limits.js +60 -0
  123. package/dist/v1/language/policy/analysis/branches.d.ts +8 -0
  124. package/dist/v1/language/policy/analysis/branches.js +2 -1
  125. package/dist/v1/language/policy/analysis/budgets.d.ts +45 -12
  126. package/dist/v1/language/policy/analysis/budgets.js +133 -19
  127. package/dist/v1/language/policy/analysis/checks.js +3 -2
  128. package/dist/v1/language/policy/analysis/typing.d.ts +51 -0
  129. package/dist/v1/language/policy/analysis/typing.js +455 -0
  130. package/dist/v1/language/policy/model/policy.d.ts +49 -9
  131. package/dist/v1/language/policy/model/policy.js +14 -0
  132. package/dist/v1/language/policy/normalization/normalize.d.ts +6 -6
  133. package/dist/v1/language/policy/normalization/normalize.js +22 -21
  134. package/dist/v1/language/validation/diagnostic.d.ts +15 -1
  135. package/dist/v1/language/validation/diagnostic.js +21 -0
  136. package/dist/v1/language/validation/rule.d.ts +45 -0
  137. package/dist/v1/language/validation/rule.js +109 -0
  138. package/dist/v1/language/value/compile/fields.js +4 -8
  139. package/dist/v1/language/value/evaluate/program.d.ts +2 -1
  140. package/dist/v1/language/value/evaluate/program.js +2 -2
  141. package/dist/v1/language/value/evaluate/validate.d.ts +2 -2
  142. package/dist/v1/language/value/evaluate/validate.js +6 -2
  143. package/dist/v1/language/value/evaluate/validity.optimization.d.ts +14 -0
  144. package/dist/v1/language/value/evaluate/validity.optimization.js +342 -0
  145. package/dist/v1/language/value/inclusion/arrays.d.ts +3 -0
  146. package/dist/v1/language/value/inclusion/arrays.js +85 -0
  147. package/dist/v1/language/value/inclusion/assertions.d.ts +18 -0
  148. package/dist/v1/language/value/inclusion/assertions.js +29 -0
  149. package/dist/v1/language/value/inclusion/combinators.d.ts +3 -0
  150. package/dist/v1/language/value/inclusion/combinators.js +67 -0
  151. package/dist/v1/language/value/inclusion/equivalence.d.ts +4 -0
  152. package/dist/v1/language/value/inclusion/equivalence.js +74 -0
  153. package/dist/v1/language/value/inclusion/evidence.d.ts +34 -0
  154. package/dist/v1/language/value/inclusion/evidence.js +138 -0
  155. package/dist/v1/language/value/inclusion/includes.d.ts +17 -0
  156. package/dist/v1/language/value/inclusion/includes.js +25 -719
  157. package/dist/v1/language/value/inclusion/keywords.d.ts +5 -0
  158. package/dist/v1/language/value/inclusion/keywords.js +31 -0
  159. package/dist/v1/language/value/inclusion/kinds.d.ts +17 -0
  160. package/dist/v1/language/value/inclusion/kinds.js +57 -0
  161. package/dist/v1/language/value/inclusion/location.d.ts +24 -0
  162. package/dist/v1/language/value/inclusion/location.js +63 -0
  163. package/dist/v1/language/value/inclusion/numbers.d.ts +3 -0
  164. package/dist/v1/language/value/inclusion/numbers.js +41 -0
  165. package/dist/v1/language/value/inclusion/objects.d.ts +3 -0
  166. package/dist/v1/language/value/inclusion/objects.js +190 -0
  167. package/dist/v1/language/value/inclusion/strings.d.ts +3 -0
  168. package/dist/v1/language/value/inclusion/strings.js +29 -0
  169. package/dist/v1/language/value/inclusion/types.d.ts +3 -0
  170. package/dist/v1/language/value/inclusion/types.js +11 -0
  171. package/dist/v1/language/value/ordering.d.ts +14 -0
  172. package/dist/v1/language/value/ordering.js +86 -9
  173. package/dist/v1/language/value/profile/canonicalize.js +6 -5
  174. package/dist/v1/language/value/profile/json.validate.d.ts +3 -1
  175. package/dist/v1/language/value/profile/json.validate.js +3 -2
  176. package/dist/v1/language/value/profile/meta-schema.compiled.js +4 -1
  177. package/dist/v1/language/value/profile/rules.js +17 -43
  178. package/dist/v1/language/value/profile/validate.js +1 -10
  179. package/dist/v1/language/value/profile/vocabulary.d.ts +35 -2
  180. package/dist/v1/language/value/profile/vocabulary.js +52 -5
  181. package/dist/v1/language/value/reference/closure.js +3 -4
  182. package/dist/v1/language/value/reference/recursion.js +2 -22
  183. package/dist/v1/language/value/reference/registry.index.d.ts +2 -0
  184. package/dist/v1/language/value/reference/registry.index.js +33 -16
  185. package/dist/v1/language/value/regexp/ast.js +6 -7
  186. package/dist/v1/language/value/regexp/compile.d.ts +5 -11
  187. package/dist/v1/language/value/regexp/compile.js +14 -12
  188. package/dist/v1/language/value/regexp/syntax.js +3 -2
  189. package/dist/v1/language/value/syntax/keywords.d.ts +3 -3
  190. package/dist/v1/language/value/syntax/keywords.js +4 -20
  191. package/dist/v1/language/value/syntax/node-path/validate.js +2 -3
  192. package/dist/v1/language/value/syntax/pointer.d.ts +2 -0
  193. package/dist/v1/language/value/syntax/pointer.js +5 -2
  194. package/dist/v1/language/value/syntax/walk.d.ts +2 -0
  195. package/dist/v1/language/value/syntax/walk.js +19 -20
  196. package/dist/v1/schema/.spec/schemas/domain-schema.schema.json +2519 -0
  197. package/dist/v1/schema/admission/accept.js +3 -14
  198. package/dist/v1/schema/admission/callable.d.ts +21 -0
  199. package/dist/v1/schema/admission/callable.js +96 -0
  200. package/dist/v1/schema/analysis/class.js +33 -15
  201. package/dist/v1/schema/canonical/revision.js +4 -4
  202. package/dist/v1/schema/compatibility/api.d.ts +2 -1
  203. package/dist/v1/schema/compatibility/api.js +1 -0
  204. package/dist/v1/schema/compatibility/comparators/callables.js +1 -1
  205. package/dist/v1/schema/compatibility/comparators/classes.d.ts +9 -4
  206. package/dist/v1/schema/compatibility/comparators/classes.js +29 -8
  207. package/dist/v1/schema/compatibility/comparators/index.d.ts +1 -1
  208. package/dist/v1/schema/compatibility/comparators/members.js +1 -1
  209. package/dist/v1/schema/compatibility/comparators/values.js +2 -2
  210. package/dist/v1/schema/compatibility/coordinate.js +3 -3
  211. package/dist/v1/schema/compatibility/diff.js +2 -4
  212. package/dist/v1/schema/compatibility/extension.d.ts +11 -0
  213. package/dist/v1/schema/compatibility/extension.js +22 -0
  214. package/dist/v1/schema/compatibility/fields.d.ts +20 -4
  215. package/dist/v1/schema/compatibility/fields.js +13 -3
  216. package/dist/v1/schema/compatibility/meaning/footprint.js +16 -50
  217. package/dist/v1/schema/compatibility/model.d.ts +17 -5
  218. package/dist/v1/schema/compatibility/report.js +1 -1
  219. package/dist/v1/schema/compatibility/scope.d.ts +2 -0
  220. package/dist/v1/schema/compatibility/scope.js +4 -1
  221. package/dist/v1/schema/compatibility/structure/index.js +6 -4
  222. package/dist/v1/schema/compatibility/structure/requirements.js +57 -58
  223. package/dist/v1/schema/compatibility/versioning/index.js +1 -1
  224. package/dist/v1/schema/compatibility/versioning/surface.d.ts +1 -1
  225. package/dist/v1/schema/compatibility/versioning/surface.js +30 -2
  226. package/dist/v1/schema/compatibility/walk.d.ts +17 -0
  227. package/dist/v1/schema/compatibility/walk.js +41 -0
  228. package/dist/v1/schema/diagnostic.d.ts +17 -3
  229. package/dist/v1/schema/diagnostic.js +14 -11
  230. package/dist/v1/schema/index.d.ts +10 -1
  231. package/dist/v1/schema/index.js +4 -0
  232. package/dist/v1/schema/model/schema.d.ts +20 -1
  233. package/dist/v1/schema/model/schema.js +1 -1
  234. package/dist/v1/schema/normalization/domain.d.ts +2 -0
  235. package/dist/v1/schema/normalization/domain.js +29 -9
  236. package/dist/v1/schema/resolution/closure.js +2 -1
  237. package/dist/v1/schema/resolution/context.js +13 -13
  238. package/dist/v1/schema/resolution/domain.d.ts +5 -0
  239. package/dist/v1/schema/resolution/domain.js +2 -2
  240. package/dist/v1/schema/resolution/origins.js +3 -2
  241. package/dist/v1/schema/rule.d.ts +26 -0
  242. package/dist/v1/schema/rule.js +440 -0
  243. package/dist/v1/schema/validation/callable.d.ts +35 -2
  244. package/dist/v1/schema/validation/callable.js +65 -9
  245. package/dist/v1/schema/validation/class.d.ts +6 -2
  246. package/dist/v1/schema/validation/class.js +127 -104
  247. package/dist/v1/schema/validation/core.js +90 -168
  248. package/dist/v1/schema/validation/domain.js +4 -13
  249. package/dist/v1/schema/validation/domain.json-schema.d.ts +15 -0
  250. package/dist/v1/schema/validation/domain.json-schema.js +197 -0
  251. package/dist/v1/schema/validation/domain.route.d.ts +6 -1
  252. package/dist/v1/schema/validation/domain.route.js +18 -0
  253. package/dist/v1/schema/validation/domain.structure.d.ts +7780 -0
  254. package/dist/v1/schema/validation/domain.structure.js +398 -147
  255. package/dist/v1/schema/validation/json.json-schema.d.ts +40 -0
  256. package/dist/v1/schema/validation/json.json-schema.js +46 -0
  257. package/dist/v1/schema/validation/policy/budgets.d.ts +33 -2
  258. package/dist/v1/schema/validation/policy/budgets.js +87 -121
  259. package/dist/v1/schema/validation/policy/context.d.ts +6 -5
  260. package/dist/v1/schema/validation/policy/context.js +7 -10
  261. package/dist/v1/schema/validation/policy/objects.d.ts +1 -1
  262. package/dist/v1/schema/validation/policy/objects.js +6 -14
  263. package/dist/v1/schema/validation/policy/references.js +11 -27
  264. package/dist/v1/schema/validation/policy/typing.d.ts +3 -18
  265. package/dist/v1/schema/validation/policy/typing.js +22 -356
  266. package/dist/v1/schema/validation/policy/uses.d.ts +40 -3
  267. package/dist/v1/schema/validation/policy/uses.js +66 -89
  268. package/dist/v1/schema/validation/policy/validate.js +5 -5
  269. package/dist/v1/schema/validation/value-api.d.ts +22 -0
  270. package/dist/v1/schema/validation/value-api.js +34 -1
  271. package/dist/v1/schema/validation/value.d.ts +3 -0
  272. package/dist/v1/schema/validation/value.js +9 -17
  273. package/dist/v1/schema/validation/value.json-schema.d.ts +49 -0
  274. package/dist/v1/schema/validation/value.json-schema.js +137 -0
  275. package/dist/v1/schema/validation/view.js +4 -8
  276. package/dist/value/canonical.d.ts +6 -0
  277. package/dist/value/canonical.js +36 -0
  278. package/dist/value/decode.d.ts +7 -0
  279. package/dist/value/decode.js +159 -9
  280. package/dist/value/index.d.ts +1 -1
  281. package/dist/value/json.d.ts +2 -2
  282. package/dist/value/json.js +2 -2
  283. package/dist/value/types.d.ts +6 -0
  284. package/dist/value/unicode.d.ts +2 -1
  285. package/dist/value/unicode.js +2 -0
  286. package/package.json +8 -1
  287. package/dist/v1/builder/lowering/core-properties.d.ts +0 -10
  288. package/dist/v1/builder/lowering/core-properties.js +0 -76
  289. package/dist/v1/compiled/admission/semantics/cardinality.d.ts +0 -5
  290. package/dist/v1/compiled/admission/semantics/cardinality.js +0 -113
  291. package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +0 -8
  292. package/dist/v1/compiled/admission/semantics/policy/equality.js +0 -27
  293. package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +0 -9
  294. package/dist/v1/compiled/admission/semantics/policy/measure.js +0 -81
  295. package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +0 -10
  296. package/dist/v1/compiled/admission/semantics/policy/variants.js +0 -65
  297. package/dist/v1/language/class/index.d.ts +0 -8
  298. package/dist/v1/language/class/index.js +0 -1
  299. package/dist/v1/language/core/index.d.ts +0 -2
  300. package/dist/v1/language/value/index.d.ts +0 -11
  301. package/dist/v1/language/value/index.js +0 -8
  302. package/dist/v1/schema/canonical/domain.d.ts +0 -3
  303. package/dist/v1/schema/canonical/domain.digest.d.ts +0 -3
  304. package/dist/v1/schema/canonical/domain.digest.js +0 -5
  305. package/dist/v1/schema/canonical/domain.js +0 -5
  306. package/dist/v1/schema/canonical/freeze.d.ts +0 -1
  307. /package/dist/v1/{language/core/index.js → builder/class/input.js} +0 -0
@@ -1,61 +1,156 @@
1
- import { array, boolean, custom, discriminatedUnion, enum as enumeration, lazy, literal, null as nullSchema, number, record, strictObject, string, tuple, union, } from 'zod';
1
+ import { array, boolean, custom, discriminatedUnion, enum as enumeration, lazy, literal, null as nullSchema, number, record, registry, strictObject, string, tuple, union, } from 'zod';
2
2
  import { PropertyKey as SemanticPropertyKey } from '../../addressing/index.js';
3
- import { CORE_SLUG_PATTERN, DEPENDENCY_ALIAS_PATTERN, DOMAIN_ORIGIN_PATTERN, DOMAIN_REVISION_PATTERN, MEMBER_NAME_PATTERN, } from '../../addressing/patterns.js';
3
+ import { CORE_SLUG_PATTERN, DEPENDENCY_ALIAS_PATTERN, DOMAIN_ORIGIN_PATTERN, DOMAIN_REVISION_PATTERN, MEMBER_NAME_PATTERN, PROPERTY_KEY_PATTERN, } from '../../addressing/patterns.js';
4
4
  import { MEDIA_TYPE_PATTERN } from '../../language/class/model/data.js';
5
5
  import * as metadata from '../../language/definition/metadata.js';
6
- import { SchemaError, diagnostic } from '../diagnostic.js';
6
+ import { limits } from '../../language/limits.js';
7
+ import { BLOB_VALUE_KIND, isBlobValueSchema } from '../../language/value/model/blob.js';
8
+ import { escapePointerToken } from '../../language/value/syntax/pointer.js';
9
+ import { SchemaError, diagnostic, } from '../diagnostic.js';
7
10
  import { DOMAIN_FORMAT, DOMAIN_VERSION } from '../model/format.js';
8
- const originSchema = string().min(3).max(253).regex(DOMAIN_ORIGIN_PATTERN);
9
- const memberNameSchema = string().regex(MEMBER_NAME_PATTERN);
11
+ export const documentJsonSchema = registry();
12
+ /**
13
+ * The checks of the structure JSON Schema cannot state. The published document names each with the
14
+ * positions it constrains, so that a validator of the document knows what it leaves to the Kernel.
15
+ */
16
+ export const structureRules = {
17
+ 'unique-tuple-set': {
18
+ code: 'STRUCTURE_DUPLICATE_ITEM',
19
+ statement: 'A unique tuple is a set of fields: two tuples naming the same fields in another order are one tuple, repeated.',
20
+ },
21
+ 'length-in-utf16-code-units': {
22
+ code: 'STRUCTURE_MAXIMUM',
23
+ statement: 'A maxLength counts UTF-16 code units, where JSON Schema counts code points: a string within the bound in code points and beyond it in code units is refused.',
24
+ },
25
+ };
26
+ // The pattern refuses `__proto__`, which zod skips before any key check (`lostProtoKeys`).
27
+ const RESERVED_DEPENDENCY_ALIASES = ['prototype', 'constructor'];
28
+ const originSchema = string()
29
+ .min(3)
30
+ .max(253)
31
+ .regex(DOMAIN_ORIGIN_PATTERN)
32
+ .register(documentJsonSchema, { id: 'origin' });
33
+ const memberNameSchema = string()
34
+ .regex(MEMBER_NAME_PATTERN)
35
+ .register(documentJsonSchema, { id: 'name' });
10
36
  const dependencyAliasSchema = string()
11
37
  .regex(DEPENDENCY_ALIAS_PATTERN)
12
- .refine((value) => value !== '__proto__' && value !== 'prototype' && value !== 'constructor', 'Expected a non-reserved dependency alias.');
13
- const propertyKeySchema = string().refine(SemanticPropertyKey.is, 'Expected a canonical PropertyKey.');
14
- const coreSlugSchema = string().min(1).max(100).regex(CORE_SLUG_PATTERN);
15
- const revisionSchema = string().regex(DOMAIN_REVISION_PATTERN);
38
+ .refine((value) => !RESERVED_DEPENDENCY_ALIASES.includes(value), {
39
+ message: 'Expected a non-reserved dependency alias.',
40
+ params: { structureCode: 'STRUCTURE_DEPENDENCY_ALIAS' },
41
+ })
42
+ .register(documentJsonSchema, {
43
+ id: 'dependency-alias',
44
+ not: { enum: [...RESERVED_DEPENDENCY_ALIASES] },
45
+ });
46
+ const propertyKeySchema = string()
47
+ .refine(SemanticPropertyKey.is, {
48
+ message: 'Expected a canonical PropertyKey.',
49
+ params: { structureCode: 'STRUCTURE_PROPERTY_KEY' },
50
+ })
51
+ .register(documentJsonSchema, { id: 'property-key', pattern: PROPERTY_KEY_PATTERN.source });
52
+ const coreSlugSchema = string()
53
+ .min(1)
54
+ .max(100)
55
+ .regex(CORE_SLUG_PATTERN)
56
+ .register(documentJsonSchema, { id: 'core-slug' });
57
+ const revisionSchema = string()
58
+ .regex(DOMAIN_REVISION_PATTERN)
59
+ .register(documentJsonSchema, { id: 'revision' });
16
60
  const descriptionSchema = string()
17
61
  .min(metadata.description.minLength)
18
- .max(metadata.description.maxLength);
19
- const iconSchema = string().min(metadata.icon.minLength).max(metadata.icon.maxLength);
62
+ .max(metadata.description.maxLength)
63
+ .register(documentJsonSchema, { id: 'description' });
64
+ const iconSchema = string()
65
+ .min(metadata.icon.minLength)
66
+ .max(metadata.icon.maxLength)
67
+ .register(documentJsonSchema, { id: 'icon' });
20
68
  const domainNameSchema = string()
21
69
  .min(metadata.name.minLength)
22
70
  .max(metadata.name.maxLength)
23
- .refine(metadata.isDomainNameText, 'Expected one trimmed line of text.');
71
+ .refine(metadata.isDomainNameText, {
72
+ message: 'Expected one trimmed line of text.',
73
+ params: { structureCode: 'STRUCTURE_DOMAIN_NAME' },
74
+ })
75
+ .register(documentJsonSchema, {
76
+ id: 'domain-name',
77
+ description: 'The display name of the Domain: one trimmed line of text.',
78
+ pattern: metadata.DOMAIN_NAME_TEXT_PATTERN.source,
79
+ });
80
+ // Zod skips a `__proto__` member, which the structure therefore refuses (`lostProtoKeys`). The JSON
81
+ // Schema refuses it by the fields of a closed object and the pattern of a record's names; a record
82
+ // of any string states it here, by its property names.
83
+ const PROTO_KEY = '__proto__';
84
+ const anyKeyRecord = { propertyNames: { not: { const: PROTO_KEY } } };
24
85
  const jsonValueSchema = lazy(() => union([
25
86
  nullSchema(),
26
87
  boolean(),
27
88
  number(),
28
89
  string(),
29
90
  array(jsonValueSchema),
30
- record(string(), jsonValueSchema),
31
- ]));
32
- const jsonObjectSchema = record(string(), jsonValueSchema);
33
- const jsonSchemaSchema = union([boolean(), jsonObjectSchema]);
91
+ record(string(), jsonValueSchema).register(documentJsonSchema, anyKeyRecord),
92
+ ])).register(documentJsonSchema, { id: 'json-value' });
93
+ const jsonObjectSchema = record(string(), jsonValueSchema).register(documentJsonSchema, anyKeyRecord);
94
+ const jsonSchemaSchema = union([boolean(), jsonObjectSchema]).register(documentJsonSchema, {
95
+ id: 'value-schema',
96
+ description: 'A value schema of the dialect https://schemas.astrale.ai/dsl/v1/value-schema. The structure admits any boolean or object; the language admits its keywords.',
97
+ });
34
98
  const dataDeclarationSchema = strictObject({
35
- mediaType: string().regex(MEDIA_TYPE_PATTERN),
99
+ mediaType: string().regex(MEDIA_TYPE_PATTERN).register(documentJsonSchema, { id: 'media-type' }),
36
100
  });
37
101
  const stateNameSchema = string().min(1);
38
- const stateTransitionsSchema = custom(isStateTransitions);
102
+ // A custom check reads the relation in place: a record would copy it and drop a `__proto__` state.
103
+ const stateTransitionsSchema = custom(isStateTransitions, {
104
+ message: 'Expected each non-empty state to map non-empty events to non-empty states.',
105
+ params: { structureCode: 'STRUCTURE_STATE_TRANSITIONS' },
106
+ }).register(documentJsonSchema, {
107
+ type: 'object',
108
+ propertyNames: { type: 'string', minLength: 1 },
109
+ additionalProperties: {
110
+ type: 'object',
111
+ propertyNames: { type: 'string', minLength: 1 },
112
+ additionalProperties: { type: 'string', minLength: 1 },
113
+ },
114
+ });
39
115
  const stateTopologySchema = strictObject({
40
116
  initial: stateNameSchema,
41
117
  transitions: stateTransitionsSchema,
42
- });
43
- const propertyDefinitionSchema = strictObject({
118
+ }).register(documentJsonSchema, { id: 'state-topology' });
119
+ const propertyShape = {
44
120
  schema: jsonSchemaSchema,
45
121
  required: boolean(),
46
122
  auto: strictObject({
47
- on: uniqueArray(enumeration(['create', 'update'])).min(1),
123
+ on: nonEmpty(uniqueArray(enumeration(['create', 'update']))),
48
124
  set: literal('instant'),
49
- }).optional(),
125
+ })
126
+ .register(documentJsonSchema, { id: 'auto' })
127
+ .optional(),
50
128
  immutable: enumeration(['create', 'once']).optional(),
51
129
  description: descriptionSchema.optional(),
52
- state: stateTopologySchema.optional(),
130
+ };
131
+ const nodePropertyRecordSchema = record(memberNameSchema, strictObject({ ...propertyShape, state: stateTopologySchema.optional() }).register(documentJsonSchema, { id: 'node-property-definition' })).register(documentJsonSchema, { id: 'node-property-record' });
132
+ // An Edge has no State Property, and only a Node holds Blob contents.
133
+ const BLOB_KIND_KEYWORD = 'x-astrale-value-kind';
134
+ const edgePropertySchema = jsonSchemaSchema
135
+ .refine((value) => !isBlobValueSchema(value), {
136
+ message: 'Blob values are held only by Node Properties.',
137
+ path: [BLOB_KIND_KEYWORD],
138
+ params: { structureCode: 'STRUCTURE_EDGE_BLOB' },
139
+ })
140
+ .register(documentJsonSchema, {
141
+ not: {
142
+ type: 'object',
143
+ required: [BLOB_KIND_KEYWORD],
144
+ properties: { [BLOB_KIND_KEYWORD]: { const: BLOB_VALUE_KIND } },
145
+ },
53
146
  });
54
- const propertyRecordSchema = record(memberNameSchema, propertyDefinitionSchema);
147
+ const edgePropertyRecordSchema = record(memberNameSchema, strictObject({ ...propertyShape, schema: edgePropertySchema }).register(documentJsonSchema, {
148
+ id: 'edge-property-definition',
149
+ })).register(documentJsonSchema, { id: 'edge-property-record' });
55
150
  const domainDependencySchema = strictObject({
56
151
  origin: originSchema,
57
152
  revision: revisionSchema,
58
- });
153
+ }).register(documentJsonSchema, { id: 'dependency' });
59
154
  const classRefSchema = absoluteRefSchema('class');
60
155
  const functionRefSchema = absoluteRefSchema('function');
61
156
  const policyRefSchema = absoluteRefSchema('policy');
@@ -64,40 +159,67 @@ const coreRefSchema = strictObject({
64
159
  origin: originSchema,
65
160
  kind: literal('core'),
66
161
  name: coreSlugSchema,
162
+ }).register(documentJsonSchema, { id: 'core-ref' });
163
+ const domainRefSchema = strictObject({ kind: literal('domain') }).register(documentJsonSchema, {
164
+ id: 'domain-endpoint',
67
165
  });
68
- const domainRefSchema = strictObject({ kind: literal('domain') });
69
166
  /** Every Definition whose installed projection resolves through one exact member Path. */
70
167
  const projectedMemberRefOptions = [
71
- strictObject({ kind: literal('method'), owner: classRefSchema, name: memberNameSchema }),
168
+ strictObject({
169
+ kind: literal('method'),
170
+ owner: classRefSchema,
171
+ name: memberNameSchema,
172
+ }).register(documentJsonSchema, { id: 'method-address' }),
72
173
  classRefSchema,
73
174
  functionRefSchema,
74
175
  policyRefSchema,
75
176
  viewRefSchema,
76
177
  coreRefSchema,
77
178
  ];
78
- const policyObjectRefSchema = discriminatedUnion('kind', projectedMemberRefOptions);
179
+ const policyObjectRefSchema = discriminatedUnion('kind', projectedMemberRefOptions).register(documentJsonSchema, { id: 'projected-member-ref' });
79
180
  const coreEndpointRefSchema = discriminatedUnion('kind', [
80
181
  ...projectedMemberRefOptions,
81
182
  domainRefSchema,
82
- ]);
183
+ ]).register(documentJsonSchema, { id: 'core-endpoint' });
83
184
  const edgeEndpointBaseShape = {
84
185
  role: memberNameSchema,
85
- accepts: uniqueArray(classRefSchema).min(1),
186
+ accepts: nonEmpty(uniqueArray(classRefSchema)),
187
+ onDelete: enumeration(['restrict', 'detach'])
188
+ .register(documentJsonSchema, { id: 'edge-lifetime' })
189
+ .optional(),
86
190
  };
87
- const edgeCountSchema = enumeration(['0..*', '1..*', '0..1', '1']);
88
- const directedEdgeEndpointsSchema = strictObject({
89
- source: strictObject({ ...edgeEndpointBaseShape, outgoing: edgeCountSchema }),
90
- target: strictObject({ ...edgeEndpointBaseShape, incoming: edgeCountSchema }),
191
+ const edgeCountSchema = enumeration(['0..*', '1..*', '0..1', '1']).register(documentJsonSchema, {
192
+ id: 'edge-count',
91
193
  });
194
+ const directedEdgeEndpointsSchema = strictObject({
195
+ source: strictObject({ ...edgeEndpointBaseShape, outgoing: edgeCountSchema }).register(documentJsonSchema, { id: 'directed-source-endpoint' }),
196
+ target: strictObject({ ...edgeEndpointBaseShape, incoming: edgeCountSchema }).register(documentJsonSchema, { id: 'directed-target-endpoint' }),
197
+ }).register(documentJsonSchema, { id: 'directed-endpoints' });
92
198
  const incidentEndpointSchema = strictObject({
93
199
  ...edgeEndpointBaseShape,
94
200
  incident: edgeCountSchema,
95
- });
96
- const undirectedEdgeEndpointsSchema = tuple([incidentEndpointSchema, incidentEndpointSchema]);
201
+ }).register(documentJsonSchema, { id: 'incident-endpoint' });
202
+ const undirectedEdgeEndpointsSchema = tuple([
203
+ incidentEndpointSchema,
204
+ incidentEndpointSchema,
205
+ ]).register(documentJsonSchema, { id: 'undirected-endpoints' });
97
206
  const edgeConstraintsSchema = strictObject({
98
207
  noSelf: literal(true).optional(),
99
208
  acyclic: literal(true).optional(),
100
- });
209
+ }).register(documentJsonSchema, { id: 'edge-constraints' });
210
+ // A tuple names distinct fields: endpoints, the slug and Properties by key. Normalization puts
211
+ // them, and the tuples, in canonical order (`compareEdgeUniqueFields`). No tuple is spelled by the
212
+ // absence of the field, never by an empty list: one spelling per meaning, one revision.
213
+ const edgeUniqueFieldSchema = union([
214
+ literal('source'),
215
+ literal('target'),
216
+ literal('slug'),
217
+ strictObject({ property: propertyKeySchema }),
218
+ ]).register(documentJsonSchema, { id: 'edge-unique-field' });
219
+ const edgeUniqueSchema = nonEmpty(uniqueTupleSet(nonEmpty(uniqueArray(edgeUniqueFieldSchema))));
220
+ // A Node tuple names distinct Properties by key, which normalization puts in code-point order, as
221
+ // it does the tuples (`compareNodeUniqueTuples`). Two orders of one set of keys are one tuple.
222
+ const nodeUniqueSchema = nonEmpty(uniqueTupleSet(nonEmpty(uniqueArray(propertyKeySchema))));
101
223
  const policyPatternSubjectSchema = strictObject({ kind: literal('subject') });
102
224
  const policyPatternObjectSchema = strictObject({ kind: literal('object') });
103
225
  const policyPatternSourceSchema = strictObject({ kind: literal('source') });
@@ -105,7 +227,7 @@ const policyPatternTargetSchema = strictObject({ kind: literal('target') });
105
227
  const policyPatternVariableSchema = strictObject({
106
228
  kind: literal('variable'),
107
229
  id: number().int().min(0),
108
- });
230
+ }).register(documentJsonSchema, { id: 'policy-pattern-variable' });
109
231
  const policyPatternNodeSchema = discriminatedUnion('kind', [
110
232
  policyPatternSubjectSchema,
111
233
  policyPatternObjectSchema,
@@ -113,19 +235,19 @@ const policyPatternNodeSchema = discriminatedUnion('kind', [
113
235
  policyPatternTargetSchema,
114
236
  policyPatternVariableSchema,
115
237
  strictObject({ kind: literal('ref'), ref: policyObjectRefSchema }),
116
- ]);
238
+ ]).register(documentJsonSchema, { id: 'policy-pattern-node' });
117
239
  const policyVariableSelectorSchema = discriminatedUnion('kind', [
118
240
  strictObject({ kind: literal('any') }),
119
241
  strictObject({ kind: literal('satisfies'), class: classRefSchema }),
120
- ]);
242
+ ]).register(documentJsonSchema, { id: 'policy-variable-selector' });
121
243
  const policyVariableSchema = union([
122
244
  strictObject({ variable: policyPatternVariableSchema, class: classRefSchema }),
123
245
  strictObject({ variable: policyPatternVariableSchema, selector: policyVariableSelectorSchema }),
124
- ]);
246
+ ]).register(documentJsonSchema, { id: 'policy-variable' });
125
247
  const policyRepeatSchema = strictObject({
126
- min: number().int().min(0).max(3),
127
- max: number().int().min(0).max(3),
128
- });
248
+ min: number().int().min(0).max(limits.policy.repetition),
249
+ max: number().int().min(0).max(limits.policy.repetition),
250
+ }).register(documentJsonSchema, { id: 'policy-repeat' });
129
251
  const policyPatternExpressionSchema = lazy(() => union([
130
252
  strictObject({
131
253
  sameNode: strictObject({ left: policyPatternNodeSchema, right: policyPatternNodeSchema }),
@@ -138,17 +260,13 @@ const policyPatternExpressionSchema = lazy(() => union([
138
260
  }),
139
261
  strictObject({
140
262
  exists: strictObject({
141
- nodes: array(policyVariableSchema).min(1).max(4),
263
+ nodes: nonEmpty(array(policyVariableSchema).max(limits.policy.variablesPerExists)),
142
264
  where: policyPatternExpressionSchema,
143
265
  }),
144
266
  }),
145
- strictObject({
146
- allOf: array(policyPatternExpressionSchema).min(1),
147
- }),
148
- strictObject({
149
- anyOf: array(policyPatternExpressionSchema).min(1),
150
- }),
151
- ]));
267
+ strictObject({ allOf: nonEmpty(array(policyPatternExpressionSchema)) }),
268
+ strictObject({ anyOf: nonEmpty(array(policyPatternExpressionSchema)) }),
269
+ ])).register(documentJsonSchema, { id: 'policy-pattern-expr' });
152
270
  const selfObjectSchema = strictObject({ kind: literal('self') });
153
271
  const refObjectSchema = strictObject({ kind: literal('ref'), ref: policyObjectRefSchema });
154
272
  const policyCheckObjectSchema = discriminatedUnion('kind', [
@@ -158,21 +276,26 @@ const policyCheckObjectSchema = discriminatedUnion('kind', [
158
276
  field: memberNameSchema,
159
277
  }),
160
278
  refObjectSchema,
161
- ]);
162
- /** A Node Class rule checks the observed Node or one exact member: it has no input. */
163
- const classRuleObjectSchema = discriminatedUnion('kind', [selfObjectSchema, refObjectSchema]);
279
+ ]).register(documentJsonSchema, { id: 'policy-check-object' });
280
+ /** A Class rule checks the observed or written instance or one exact member: it has no input. */
281
+ const classRuleObjectSchema = discriminatedUnion('kind', [
282
+ selfObjectSchema,
283
+ refObjectSchema,
284
+ ]).register(documentJsonSchema, { id: 'class-rule-object' });
164
285
  /** The recursive Policy check grammar, over the objects one use site admits. */
165
- function policyChecksSchema(objectSchema) {
286
+ function policyChecksSchema(objectSchema, id) {
166
287
  const checks = lazy(() => union([
167
288
  strictObject({ sameNode: strictObject({ left: objectSchema, right: objectSchema }) }),
168
289
  strictObject({ check: policyRefSchema, object: objectSchema }),
169
- strictObject({ allOf: array(checks).min(1) }),
170
- strictObject({ anyOf: array(checks).min(1) }),
171
- ]));
290
+ strictObject({ allOf: nonEmpty(array(checks)) }),
291
+ strictObject({ anyOf: nonEmpty(array(checks)) }),
292
+ ])).register(documentJsonSchema, { id });
172
293
  return checks;
173
294
  }
174
- const policyCheckExpressionSchema = policyChecksSchema(policyCheckObjectSchema);
175
- const classRuleChecksSchema = policyChecksSchema(classRuleObjectSchema);
295
+ const policyCheckExpressionSchema = policyChecksSchema(policyCheckObjectSchema, 'policy-check-expr');
296
+ const classRuleChecksSchema = policyChecksSchema(classRuleObjectSchema, 'class-rule-check-expr');
297
+ /** A Node create rule has no Node to check yet: its objects are exact members only. */
298
+ const createRuleChecksSchema = policyChecksSchema(refObjectSchema, 'create-rule-check-expr');
176
299
  const callableOutputSchema = discriminatedUnion('mode', [
177
300
  strictObject({
178
301
  mode: literal('value'),
@@ -185,139 +308,191 @@ const callableOutputSchema = discriminatedUnion('mode', [
185
308
  strictObject({
186
309
  mode: literal('binary'),
187
310
  }),
188
- ]);
311
+ ]).register(documentJsonSchema, { id: 'callable-output' });
189
312
  const binaryInputSchema = strictObject({
190
313
  mode: literal('binary'),
191
314
  metadata: jsonSchemaSchema,
192
315
  maximumBytes: number().int().min(1).max(Number.MAX_SAFE_INTEGER),
316
+ }).register(documentJsonSchema, { id: 'binary-input' });
317
+ const valueFunctionInputSchema = jsonSchemaSchema
318
+ .refine((value) => typeof value !== 'object' || value === null || value.mode !== 'binary', {
319
+ message: 'Binary input must declare metadata and maximumBytes.',
320
+ params: { structureCode: 'STRUCTURE_BINARY_INPUT' },
321
+ })
322
+ .register(documentJsonSchema, {
323
+ not: { type: 'object', required: ['mode'], properties: { mode: { const: 'binary' } } },
193
324
  });
194
- const valueFunctionInputSchema = jsonSchemaSchema.refine((value) => typeof value !== 'object' || value === null || value.mode !== 'binary', 'Binary input must declare metadata and maximumBytes.');
195
325
  const callableExecutionSchema = strictObject({
196
326
  durable: boolean(),
197
- });
327
+ }).register(documentJsonSchema, { id: 'callable-execution' });
328
+ // Its range is language meaning, refused by callable validation with DV_CALLABLE_ADMISSION.
329
+ const callableAdmissionSchema = strictObject({
330
+ maxAge: number(),
331
+ }).register(documentJsonSchema, { id: 'callable-admission' });
198
332
  const callableShape = {
199
333
  description: descriptionSchema.optional(),
200
334
  input: jsonSchemaSchema,
201
335
  output: callableOutputSchema,
202
336
  execution: callableExecutionSchema.optional(),
337
+ admission: callableAdmissionSchema.optional(),
203
338
  auth: enumeration(['anonymous', 'authenticated', 'authorized']),
204
- policy: union([literal(true), policyCheckExpressionSchema]).optional(),
339
+ policy: union([literal(true), policyCheckExpressionSchema])
340
+ .register(documentJsonSchema, { id: 'callable-policy' })
341
+ .optional(),
342
+ };
343
+ const authorizedPolicy = {
344
+ if: { properties: { auth: { enum: ['anonymous', 'authenticated'] } }, required: ['auth'] },
345
+ // oxlint-disable-next-line unicorn/no-thenable -- the JSON Schema keyword
346
+ then: { properties: { policy: false } },
205
347
  };
206
348
  const methodDeclarationSchema = strictObject({
207
349
  ...callableShape,
208
350
  static: boolean(),
209
351
  abstract: boolean(),
210
- }).superRefine((method, context) => {
211
- if (method.auth !== 'authorized' && method.policy !== undefined) {
212
- context.addIssue({
213
- code: 'custom',
214
- path: ['policy'],
215
- message: 'Only an authorized method may declare a policy.',
216
- params: { structureCode: 'STRUCTURE_CALLABLE_POLICY_AUTH' },
217
- });
218
- }
352
+ })
353
+ .refine((method) => method.auth === 'authorized' || method.policy === undefined, callablePolicyIssue('method'))
354
+ .register(documentJsonSchema, { id: 'method-definition', ...authorizedPolicy });
355
+ const methodRecordSchema = record(memberNameSchema, methodDeclarationSchema).register(documentJsonSchema, {
356
+ id: 'method-record',
219
357
  });
220
- const methodRecordSchema = record(memberNameSchema, methodDeclarationSchema);
221
- const classPolicySchema = union([literal(false), policyRefSchema]);
222
- const nodeClassPolicySchema = union([classPolicySchema, classRuleChecksSchema]);
358
+ // Each slot spells one constant: the other one is what its absence already means.
359
+ const observationPolicySchema = union([
360
+ literal(false),
361
+ policyRefSchema,
362
+ classRuleChecksSchema,
363
+ ]).register(documentJsonSchema, { id: 'observation-policy' });
364
+ const writePolicySchema = union([literal(true), policyRefSchema, classRuleChecksSchema]).register(documentJsonSchema, { id: 'write-policy' });
365
+ const createPolicySchema = union([literal(true), createRuleChecksSchema]).register(documentJsonSchema, { id: 'create-policy' });
223
366
  const nodeClassPoliciesSchema = strictObject({
224
- read: nodeClassPolicySchema.optional(),
225
- traverse: nodeClassPolicySchema.optional(),
367
+ read: observationPolicySchema.optional(),
368
+ traverse: observationPolicySchema.optional(),
369
+ create: createPolicySchema.optional(),
370
+ update: writePolicySchema.optional(),
371
+ delete: writePolicySchema.optional(),
226
372
  });
227
373
  const edgeClassPoliciesSchema = strictObject({
228
- read: classPolicySchema.optional(),
229
- traverse: classPolicySchema.optional(),
374
+ read: observationPolicySchema.optional(),
375
+ traverse: observationPolicySchema.optional(),
376
+ create: writePolicySchema.optional(),
377
+ update: writePolicySchema.optional(),
378
+ delete: writePolicySchema.optional(),
230
379
  });
380
+ // The default `'internal'` is the absence of the field: one spelling per meaning, one revision.
381
+ const inheritanceSchema = enumeration(['open', 'final']);
231
382
  const nodeClassSchema = strictObject({
232
383
  ref: classRefSchema,
233
384
  kind: literal('node'),
234
385
  abstract: boolean(),
386
+ inheritance: inheritanceSchema.optional(),
235
387
  description: descriptionSchema.optional(),
236
388
  extends: uniqueArray(classRefSchema),
237
- properties: propertyRecordSchema,
389
+ properties: nodePropertyRecordSchema,
238
390
  methods: methodRecordSchema,
239
391
  data: dataDeclarationSchema.optional(),
240
392
  icon: iconSchema.optional(),
241
393
  policies: nodeClassPoliciesSchema,
242
- });
243
- const edgeClassShape = {
394
+ unique: nodeUniqueSchema.optional(),
395
+ }).register(documentJsonSchema, { id: 'node-class' });
396
+ const orientationIssue = { params: { structureCode: 'STRUCTURE_EDGE_ORIENTATION' } };
397
+ const edgeClassSchema = strictObject({
244
398
  ref: classRefSchema,
245
399
  kind: literal('edge'),
246
400
  abstract: boolean(),
401
+ inheritance: inheritanceSchema.optional(),
247
402
  description: descriptionSchema.optional(),
248
403
  extends: uniqueArray(classRefSchema),
249
- properties: propertyRecordSchema,
404
+ properties: edgePropertyRecordSchema,
250
405
  constraints: edgeConstraintsSchema,
251
- };
252
- const edgeClassSchema = strictObject({
253
- ...edgeClassShape,
406
+ unique: edgeUniqueSchema.optional(),
254
407
  orientation: enumeration(['directed', 'undirected']),
255
408
  endpoints: union([directedEdgeEndpointsSchema, undirectedEdgeEndpointsSchema]),
256
409
  policies: edgeClassPoliciesSchema,
257
- }).superRefine(validateEdgeOrientationShape);
258
- const classDeclarationSchema = discriminatedUnion('kind', [nodeClassSchema, edgeClassSchema]);
259
- function validateEdgeOrientationShape(value, context) {
260
- if ((value.orientation === 'undirected') === Array.isArray(value.endpoints))
261
- return;
262
- context.addIssue({
263
- code: 'custom',
264
- path: ['endpoints'],
265
- message: `${value.orientation} Edge endpoints have the wrong structural shape.`,
266
- params: { structureCode: 'STRUCTURE_EDGE_ORIENTATION' },
267
- });
268
- }
269
- const functionDefinitionSchema = strictObject({
270
- ref: functionRefSchema,
410
+ })
411
+ .refine((edge) => (edge.orientation === 'undirected') === Array.isArray(edge.endpoints), {
412
+ ...orientationIssue,
413
+ path: ['endpoints'],
414
+ error: 'Edge endpoints do not have the structural shape of its orientation.',
415
+ })
416
+ .refine((edge) => edge.orientation === 'directed' || edge.unique === undefined, {
417
+ ...orientationIssue,
418
+ path: ['unique'],
419
+ error: 'Only a directed Edge Class declares unique tuples.',
420
+ })
421
+ .refine((edge) => edge.orientation === 'directed' || edge.constraints.acyclic === undefined, {
422
+ ...orientationIssue,
423
+ path: ['constraints', 'acyclic'],
424
+ error: 'Only a directed Edge Class is acyclic.',
425
+ })
426
+ .register(documentJsonSchema, {
427
+ id: 'edge-class',
428
+ if: { properties: { orientation: { const: 'undirected' } }, required: ['orientation'] },
429
+ // oxlint-disable-next-line unicorn/no-thenable -- the JSON Schema keyword
430
+ then: {
431
+ properties: {
432
+ endpoints: { type: 'array' },
433
+ unique: false,
434
+ constraints: { type: 'object', properties: { acyclic: false } },
435
+ },
436
+ },
437
+ else: { properties: { endpoints: { type: 'object' } } },
438
+ });
439
+ const classDeclarationSchema = discriminatedUnion('kind', [
440
+ nodeClassSchema,
441
+ edgeClassSchema,
442
+ ]).register(documentJsonSchema, { id: 'class-definition' });
443
+ const functionContractShape = {
271
444
  ...callableShape,
272
445
  input: union([binaryInputSchema, valueFunctionInputSchema]),
273
- }).superRefine((callable, context) => {
274
- if (callable.auth !== 'authorized' && callable.policy !== undefined) {
275
- context.addIssue({
276
- code: 'custom',
277
- path: ['policy'],
278
- message: 'Only an authorized function may declare a policy.',
279
- params: { structureCode: 'STRUCTURE_CALLABLE_POLICY_AUTH' },
280
- });
281
- }
282
- });
446
+ };
447
+ const functionDefinitionSchema = strictObject({
448
+ ref: functionRefSchema,
449
+ ...functionContractShape,
450
+ })
451
+ .refine((callable) => callable.auth === 'authorized' || callable.policy === undefined, callablePolicyIssue('function'))
452
+ .register(documentJsonSchema, { id: 'function-definition', ...authorizedPolicy });
453
+ // A callable contract has the structure of a Function declaration without its ref, wherever it is.
454
+ const callableContractSchema = strictObject(functionContractShape).refine((callable) => callable.auth === 'authorized' || callable.policy === undefined, callablePolicyIssue('function'));
283
455
  const policyExpressionSchema = union([
284
456
  strictObject({
285
457
  match: policyPatternExpressionSchema,
286
458
  }),
287
- strictObject({
288
- allOf: array(policyRefSchema).min(1),
289
- }),
290
- strictObject({
291
- anyOf: array(policyRefSchema).min(1),
292
- }),
459
+ strictObject({ allOf: nonEmpty(array(policyRefSchema)) }),
460
+ strictObject({ anyOf: nonEmpty(array(policyRefSchema)) }),
293
461
  ]);
294
462
  const policyDefinitionSchema = strictObject({
295
463
  ref: policyRefSchema,
296
464
  expression: policyExpressionSchema,
297
465
  description: descriptionSchema.optional(),
466
+ }).register(documentJsonSchema, { id: 'policy-definition' });
467
+ const viewTargetSchema = strictObject({ kind: literal('domain') }).register(documentJsonSchema, {
468
+ id: 'view-target',
469
+ description: 'Every View targets its owning Domain.',
298
470
  });
299
- const viewTargetSchema = strictObject({ kind: literal('domain') });
300
471
  const viewDefinitionSchema = strictObject({
301
472
  ref: viewRefSchema,
302
473
  description: descriptionSchema.optional(),
303
474
  target: viewTargetSchema,
475
+ }).register(documentJsonSchema, { id: 'view-definition' });
476
+ const propertyValuesSchema = record(propertyKeySchema, jsonValueSchema).register(documentJsonSchema, {
477
+ id: 'property-values',
304
478
  });
305
479
  const coreNodeSchema = strictObject({
306
480
  ref: coreRefSchema,
307
481
  class: classRefSchema,
308
- properties: record(propertyKeySchema, jsonValueSchema),
309
- });
482
+ properties: propertyValuesSchema,
483
+ }).register(documentJsonSchema, { id: 'core-definition' });
310
484
  const coreEdgeSchema = strictObject({
311
485
  class: classRefSchema,
312
486
  source: coreEndpointRefSchema,
313
487
  target: coreEndpointRefSchema,
314
- properties: record(propertyKeySchema, jsonValueSchema),
315
- });
488
+ properties: propertyValuesSchema,
489
+ }).register(documentJsonSchema, { id: 'core-edge' });
316
490
  const coreSchema = strictObject({
317
491
  nodes: record(coreSlugSchema, coreNodeSchema),
318
492
  edges: array(coreEdgeSchema),
319
- });
320
- const structuralSchema = strictObject({
493
+ }).register(documentJsonSchema, { id: 'core' });
494
+ /** The structure of an authored Domain schema document, the single source of its JSON Schema. */
495
+ export const domainSchemaStructure = strictObject({
321
496
  format: literal(DOMAIN_FORMAT),
322
497
  version: literal(DOMAIN_VERSION),
323
498
  origin: originSchema,
@@ -330,19 +505,65 @@ const structuralSchema = strictObject({
330
505
  views: record(memberNameSchema, viewDefinitionSchema),
331
506
  core: coreSchema,
332
507
  });
333
- const domainSchemaStructuralSchema = structuralSchema;
334
508
  export function parseDomainSchemaStructure(input) {
335
- const result = domainSchemaStructuralSchema.safeParse(input);
336
- if (result.success)
337
- return result.data;
338
- throw new SchemaError(result.error.issues.flatMap((issue) => diagnosticsForIssue(issue, input)));
509
+ const result = domainSchemaStructure.safeParse(input);
510
+ if (!result.success) {
511
+ throw new SchemaError(result.error.issues.flatMap((issue) => diagnosticsForIssue(issue, input)));
512
+ }
513
+ const lost = lostProtoKeys(input, result.data, []);
514
+ if (lost.length > 0)
515
+ throw new SchemaError(lost);
516
+ return modelOf(result.data);
517
+ }
518
+ /**
519
+ * Each `__proto__` member of the input that the parsed document lost. Zod skips that member in an
520
+ * object or a record, so the structure would accept the document without it; it refuses the
521
+ * document instead. A State's transitions are read in place and keep the member.
522
+ */
523
+ function lostProtoKeys(input, parsed, path) {
524
+ if (!isObject(input) || !isObject(parsed))
525
+ return [];
526
+ const lost = Object.hasOwn(input, PROTO_KEY) && !Object.hasOwn(parsed, PROTO_KEY)
527
+ ? [
528
+ diagnostic('STRUCTURE_PROTO_KEY', pointer([...path, PROTO_KEY]), 'A member named __proto__ is refused: the parsed document cannot keep it.'),
529
+ ]
530
+ : [];
531
+ return [
532
+ ...lost,
533
+ ...Object.keys(parsed).flatMap((key) => lostProtoKeys(Reflect.get(input, key), Reflect.get(parsed, key), [...path, key])),
534
+ ];
535
+ }
536
+ /** Parse the structure of one callable contract: a Function declaration without its ref. */
537
+ export function parseCallableContract(input) {
538
+ const result = callableContractSchema.safeParse(input);
539
+ if (!result.success) {
540
+ throw new SchemaError(result.error.issues.flatMap((issue) => diagnosticsForIssue(issue, input)));
541
+ }
542
+ const lost = lostProtoKeys(input, result.data, []);
543
+ if (lost.length > 0)
544
+ throw new SchemaError(lost);
545
+ return result.data;
546
+ }
547
+ /**
548
+ * The structure admits the document the model types: this parameter checks one direction, and
549
+ * `domain.structure.typecheck.ts` both. The brands are the model's own proofs from here on.
550
+ */
551
+ function modelOf(document) {
552
+ return document;
339
553
  }
340
554
  function absoluteRefSchema(kind) {
341
555
  return strictObject({
342
556
  origin: originSchema,
343
557
  kind: literal(kind),
344
558
  name: memberNameSchema,
345
- });
559
+ }).register(documentJsonSchema, { id: `${kind}-ref` });
560
+ }
561
+ function callablePolicyIssue(owner) {
562
+ return {
563
+ path: ['policy'],
564
+ params: { structureCode: 'STRUCTURE_CALLABLE_POLICY_AUTH' },
565
+ error: `Only an authorized ${owner} may declare a policy.`,
566
+ };
346
567
  }
347
568
  function isStateTransitions(input) {
348
569
  if (!isRecord(input))
@@ -366,13 +587,31 @@ function isStateTransitions(input) {
366
587
  return true;
367
588
  }
368
589
  function isRecord(input) {
369
- return input !== null && typeof input === 'object' && !Array.isArray(input);
590
+ return isObject(input) && !Array.isArray(input);
591
+ }
592
+ function isObject(input) {
593
+ return input !== null && typeof input === 'object';
594
+ }
595
+ /** At least one item, which `min(1)` proves: the output is typed as the non-empty tuple it is. */
596
+ function nonEmpty(list) {
597
+ return list.min(1);
370
598
  }
599
+ /** Items distinct by JSON equality, which JSON Schema states as `uniqueItems`. */
371
600
  function uniqueArray(element) {
601
+ return distinctArray(element, canonicalJson).register(documentJsonSchema, { uniqueItems: true });
602
+ }
603
+ /**
604
+ * Tuples distinct as sets of fields. JSON Schema states their JSON equality, `uniqueItems`; the
605
+ * rule `unique-tuple-set` names the rest.
606
+ */
607
+ function uniqueTupleSet(tuple) {
608
+ return distinctArray(tuple, (fields) => JSON.stringify(fields.map(canonicalJson).sort())).register(documentJsonSchema, { uniqueItems: true, 'x-astrale-rule': 'unique-tuple-set' });
609
+ }
610
+ function distinctArray(element, keyOf) {
372
611
  return array(element).superRefine((values, context) => {
373
612
  const firstIndexByValue = new Map();
374
613
  values.forEach((value, index) => {
375
- const key = canonicalJson(value);
614
+ const key = keyOf(value);
376
615
  const firstIndex = firstIndexByValue.get(key);
377
616
  if (firstIndex === undefined) {
378
617
  firstIndexByValue.set(key, index);
@@ -401,24 +640,40 @@ function diagnosticsForIssue(issue, input) {
401
640
  if (issue.code === 'unrecognized_keys') {
402
641
  return issue.keys.map((key) => diagnostic('STRUCTURE_UNKNOWN_FIELD', pointer([...issue.path, key]), `Unknown field ${JSON.stringify(key)}.`));
403
642
  }
404
- const customCode = issue.code === 'custom' ? customStructureCode(issue.params?.structureCode) : undefined;
643
+ // A record key refused by a refinement reports that refinement, at the key.
644
+ const refinement = issue.code === 'invalid_key' ? issue.issues.find(isRefinement) : undefined;
645
+ if (refinement !== undefined) {
646
+ return [diagnostic(refinementCode(refinement), pointer(issue.path), refinement.message)];
647
+ }
405
648
  return [
406
- diagnostic(customCode ?? structureCode(issue, input), pointer(issue.path), structureMessage(issue, input)),
649
+ diagnostic(structureCode(issue, input), pointer(issue.path), structureMessage(issue, input)),
407
650
  ];
408
651
  }
409
- function customStructureCode(input) {
410
- switch (input) {
411
- case 'STRUCTURE_ABSTRACT_POLICY':
652
+ function isRefinement(issue) {
653
+ return issue.code === 'custom';
654
+ }
655
+ /** Every refinement of the structure names its own code. */
656
+ function refinementCode(issue) {
657
+ const code = issue.params?.structureCode;
658
+ switch (code) {
659
+ case 'STRUCTURE_BINARY_INPUT':
412
660
  case 'STRUCTURE_CALLABLE_POLICY_AUTH':
661
+ case 'STRUCTURE_DEPENDENCY_ALIAS':
662
+ case 'STRUCTURE_DOMAIN_NAME':
413
663
  case 'STRUCTURE_DUPLICATE_ITEM':
664
+ case 'STRUCTURE_EDGE_BLOB':
414
665
  case 'STRUCTURE_EDGE_ORIENTATION':
415
- return input;
666
+ case 'STRUCTURE_PROPERTY_KEY':
667
+ case 'STRUCTURE_STATE_TRANSITIONS':
668
+ return code;
416
669
  default:
417
- return undefined;
670
+ throw new TypeError(`A structure refinement names no Schema code: ${String(code)}.`);
418
671
  }
419
672
  }
420
673
  function structureCode(issue, input) {
421
674
  switch (issue.code) {
675
+ case 'custom':
676
+ return refinementCode(issue);
422
677
  case 'invalid_type':
423
678
  return valueAtPath(input, issue.path) === undefined ? 'STRUCTURE_REQUIRED' : 'STRUCTURE_TYPE';
424
679
  case 'invalid_value':
@@ -433,10 +688,9 @@ function structureCode(issue, input) {
433
688
  return 'STRUCTURE_MINIMUM';
434
689
  case 'too_big':
435
690
  return 'STRUCTURE_MAXIMUM';
436
- case 'not_multiple_of':
437
- return 'STRUCTURE_MULTIPLE';
438
691
  default:
439
- return 'STRUCTURE_INVALID';
692
+ // The structure declares no multipleOf, Map or Set.
693
+ throw new TypeError(`The structure raised a ${issue.code} issue it declares no check for.`);
440
694
  }
441
695
  }
442
696
  function structureMessage(issue, input) {
@@ -463,8 +717,5 @@ function valueAtPath(input, path) {
463
717
  function pointer(path) {
464
718
  if (path.length === 0)
465
719
  return '';
466
- return `/${path.map((segment) => escapePointerSegment(String(segment))).join('/')}`;
467
- }
468
- function escapePointerSegment(segment) {
469
- return segment.replaceAll('~', '~0').replaceAll('/', '~1');
720
+ return `/${path.map((segment) => escapePointerToken(String(segment))).join('/')}`;
470
721
  }