@astrale-os/kernel-dsl 0.2.0-beta.14 → 0.2.0-beta.17

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,214 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0-beta.17](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.16...kernel-dsl-v0.2.0-beta.17) (2026-08-29)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * View declarations now contain only target and optional description. Legacy View.auth fields are rejected; callable authorization, View.resolve admission, Policies, and Shell handshakes remain independent.
9
+ * **dsl:** make edge direction explicit
10
+
11
+ ### Features
12
+
13
+ * add aliased domain dependency projection ([afb799b](https://github.com/astrale-os/kernel/commit/afb799b0d61fd6f7436fe659f558a6a62ef1e7a1))
14
+ * add aliased Domain dependency projection ([9c4c4fb](https://github.com/astrale-os/kernel/commit/9c4c4fb4f942c0c5e3961faf4428ed299d42f847))
15
+ * add compiled remote domain serving ([ac9e365](https://github.com/astrale-os/kernel/commit/ac9e36538982a91359712e4cbbc68353ea2cc1a2))
16
+ * add compiled remote Domain serving ([6149628](https://github.com/astrale-os/kernel/commit/6149628820d1294981156ff5b50ceaa522ea0403))
17
+ * **callable:** preserve native binary streams and status ([d14c6f1](https://github.com/astrale-os/kernel/commit/d14c6f13492c14a3363b2c4af59c738034752fa2))
18
+ * **dsl:** authorize Edge value reads with policies ([#502](https://github.com/astrale-os/kernel/issues/502)) ([a27e129](https://github.com/astrale-os/kernel/commit/a27e129378ff64e69031a011cbfa21299998a35e))
19
+ * **dsl:** make edge direction explicit ([3f05bf5](https://github.com/astrale-os/kernel/commit/3f05bf52ce5b20e9f549ec0fd98cb0e4e03de1ea))
20
+ * remove Property visibility and cut DSL V2 ([#518](https://github.com/astrale-os/kernel/issues/518)) ([4d99e8f](https://github.com/astrale-os/kernel/commit/4d99e8f0837136cf6be257ab3a6df666b62e06b5))
21
+ * remove View authentication declarations ([4a5bfe0](https://github.com/astrale-os/kernel/commit/4a5bfe016717267d31257748f95e7f646782f876))
22
+ * **runtime:** implement auto property projection lifecycle ([#451](https://github.com/astrale-os/kernel/issues/451)) ([e0c484a](https://github.com/astrale-os/kernel/commit/e0c484a79f2d5314b6a54597c340bd09d3e4e566))
23
+ * **schema:** split inspection and add convergence ([6afbd39](https://github.com/astrale-os/kernel/commit/6afbd39506b8a9e37225aded1c02f94ffa64e54b))
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * admit optional callable node paths ([#464](https://github.com/astrale-os/kernel/issues/464)) ([8f261d5](https://github.com/astrale-os/kernel/commit/8f261d54dfb489541d2976892c5cacadf688f1a1))
29
+ * **api:** retain visibility-free DSL as V1 ([#526](https://github.com/astrale-os/kernel/issues/526)) ([e24c1ea](https://github.com/astrale-os/kernel/commit/e24c1ea257e8567d9bd33c6ada0de63bb346a496))
30
+ * **boot:** point local host CLI at graph.query ([8341e10](https://github.com/astrale-os/kernel/commit/8341e1020cd32848ffb95de80e66936f17db3087))
31
+ * **boot:** point local host CLI at graph.query ([70c656b](https://github.com/astrale-os/kernel/commit/70c656bc7162b477a97ace4b999f8e7f6bf3a988))
32
+ * **ci:** enforce the official Kernel cohort ([#469](https://github.com/astrale-os/kernel/issues/469)) ([f6ea87a](https://github.com/astrale-os/kernel/commit/f6ea87a47f7b1f9c415e404dc1a09b480a2a3f5f))
33
+ * **core:** preserve callable identity and runtime boundaries ([#394](https://github.com/astrale-os/kernel/issues/394)) ([ad67dad](https://github.com/astrale-os/kernel/commit/ad67dad84aef3c8b79f769009595ea1f1229026b))
34
+ * **deps:** refresh the Kernel dependency cohort ([#393](https://github.com/astrale-os/kernel/issues/393)) ([883e7bb](https://github.com/astrale-os/kernel/commit/883e7bb7ce17eecb7dad1c94ad2089c576ba3746))
35
+ * **dsl:** close runtime facade contracts ([ff99450](https://github.com/astrale-os/kernel/commit/ff99450ce3889013f57c39293e7022b32e186ca6))
36
+ * **dsl:** close semantic qualification gaps ([4a48cd7](https://github.com/astrale-os/kernel/commit/4a48cd729bcaf839ceda880b26ade064d6505fe2))
37
+ * **dsl:** expose runtime-clean load paths ([7dba075](https://github.com/astrale-os/kernel/commit/7dba075887e4796e5464d5a41ddb03212eed887f))
38
+ * **dsl:** keep schema projections declaration-nameable ([#432](https://github.com/astrale-os/kernel/issues/432)) ([448d23d](https://github.com/astrale-os/kernel/commit/448d23d58fc2b564ef93be4a54dc8ebd385b5066))
39
+ * **dsl:** make schema declarations portable ([55e13c0](https://github.com/astrale-os/kernel/commit/55e13c06896eb5d6cf195607aec10f176b585504))
40
+ * **dsl:** make schema declarations portable ([90c04ac](https://github.com/astrale-os/kernel/commit/90c04acfa5af714c70a92dc90999675d53f159bc))
41
+ * **dsl:** preserve generic resolved domain type ([46f306b](https://github.com/astrale-os/kernel/commit/46f306bc3d1c73c822608c777a82f4502591d3e2))
42
+ * **dsl:** reject unknown authoring fields on edge endpoints ([0483aa9](https://github.com/astrale-os/kernel/commit/0483aa9d985459c873922262b6f60363ffb3902b))
43
+ * **dsl:** reject unknown authoring fields on edge endpoints ([cb90dae](https://github.com/astrale-os/kernel/commit/cb90dae6e165166ddcfe5e31ee2780d36b07ea53))
44
+ * **dsl:** reject unknown edge endpoint fields ([06a47ed](https://github.com/astrale-os/kernel/commit/06a47edf1bb1ba58d0ac7258e810ef2d20b30c69))
45
+ * **dsl:** reject unknown edge endpoint fields ([2d83dbf](https://github.com/astrale-os/kernel/commit/2d83dbf25a3e3818f9db2519b15741d109750727))
46
+ * **dsl:** trust exact generated build material ([#466](https://github.com/astrale-os/kernel/issues/466)) ([77f2686](https://github.com/astrale-os/kernel/commit/77f26862d8041928029c04da9f2b2521a101c17e))
47
+ * **packages:** keep workspace guard private ([e0ba76c](https://github.com/astrale-os/kernel/commit/e0ba76c5ae163245e31115e2a72e0663db0f5320))
48
+ * **packages:** keep workspace guard private ([d260a52](https://github.com/astrale-os/kernel/commit/d260a52329cde5ce4b0260c43a3bbf28cb78f408))
49
+ * **packages:** keep workspace guard private ([a3e82ec](https://github.com/astrale-os/kernel/commit/a3e82ec671f07252a5966b4de988e275e4078b8c))
50
+ * publish a TypeScript-compatible cohort ([#406](https://github.com/astrale-os/kernel/issues/406)) ([f1a0cd0](https://github.com/astrale-os/kernel/commit/f1a0cd09f2f0b4498f9fa8924b2e319cac6552b7))
51
+ * **release:** add package repository metadata ([8238077](https://github.com/astrale-os/kernel/commit/8238077d47a96c0f7b50a1bae8769fe4faab45b7))
52
+ * **release:** harden public package closure ([#397](https://github.com/astrale-os/kernel/issues/397)) ([5a5886f](https://github.com/astrale-os/kernel/commit/5a5886fe66c7b3ea0a014766a5df8c04fd93efeb))
53
+ * **schema:** harden introspection evidence and caches ([9516eb5](https://github.com/astrale-os/kernel/commit/9516eb510242427296861ef9e730b01861e45463))
54
+ * stabilize governed Kernel integration ([#347](https://github.com/astrale-os/kernel/issues/347)) ([6869e3f](https://github.com/astrale-os/kernel/commit/6869e3fc4de1e73ff701bb38383e89c934ddfdf2))
55
+ * **system:** clear Codegraph diagnostic debt ([f7a8e1f](https://github.com/astrale-os/kernel/commit/f7a8e1f5c5694d9c3c45d95fde184f0d5f2c7343))
56
+ * **system:** clear Codegraph diagnostic debt ([45f86a9](https://github.com/astrale-os/kernel/commit/45f86a9ce14a224efed0e07966a5df8d7a892078))
57
+ * **system:** preserve erased domain and runtime facade contracts ([b525d47](https://github.com/astrale-os/kernel/commit/b525d4781d2d58776ec6b4bbe1e045a3c1accebb))
58
+ * **system:** preserve public revision vocabulary ([5e990d0](https://github.com/astrale-os/kernel/commit/5e990d0b28578a040b80c508943552c46b8632ae))
59
+ * **test:** preserve authored semantic contracts ([bedb8cd](https://github.com/astrale-os/kernel/commit/bedb8cd2d36f4a95cb8d219067df0d0e39100f08))
60
+
61
+
62
+ ### Documentation
63
+
64
+ * **release:** align kernel beta changelogs ([ad59dbc](https://github.com/astrale-os/kernel/commit/ad59dbc8df458d8bd025692d594b0b4666cd2e1f))
65
+
66
+ ## [0.2.0-beta.16](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.15...kernel-dsl-v0.2.0-beta.16) (2026-08-29)
67
+
68
+
69
+ ### Features
70
+
71
+ * remove Property visibility and cut DSL V2 ([#518](https://github.com/astrale-os/kernel/issues/518)) ([4d99e8f](https://github.com/astrale-os/kernel/commit/4d99e8f0837136cf6be257ab3a6df666b62e06b5))
72
+
73
+
74
+ ### Bug Fixes
75
+
76
+ * **api:** retain visibility-free DSL as V1 ([#526](https://github.com/astrale-os/kernel/issues/526)) ([e24c1ea](https://github.com/astrale-os/kernel/commit/e24c1ea257e8567d9bd33c6ada0de63bb346a496))
77
+
78
+ ## [0.2.0-beta.15](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.14...kernel-dsl-v0.2.0-beta.15) (2026-08-27)
79
+
80
+
81
+ ### Features
82
+
83
+ * **dsl:** authorize Edge value reads with policies ([#502](https://github.com/astrale-os/kernel/issues/502)) ([a27e129](https://github.com/astrale-os/kernel/commit/a27e129378ff64e69031a011cbfa21299998a35e))
84
+
85
+ ## [0.2.0-beta.14](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.13...kernel-dsl-v0.2.0-beta.14) (2026-08-26)
86
+
87
+
88
+ ### Bug Fixes
89
+
90
+ * **ci:** enforce the official Kernel cohort ([#469](https://github.com/astrale-os/kernel/issues/469)) ([f6ea87a](https://github.com/astrale-os/kernel/commit/f6ea87a47f7b1f9c415e404dc1a09b480a2a3f5f))
91
+
92
+ ## [0.2.0-beta.13](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.12...kernel-dsl-v0.2.0-beta.13) (2026-08-26)
93
+
94
+
95
+ ### Features
96
+
97
+ * **runtime:** implement auto property projection lifecycle ([#451](https://github.com/astrale-os/kernel/issues/451)) ([e0c484a](https://github.com/astrale-os/kernel/commit/e0c484a79f2d5314b6a54597c340bd09d3e4e566))
98
+
99
+
100
+ ### Bug Fixes
101
+
102
+ * **dsl:** trust exact generated build material ([#466](https://github.com/astrale-os/kernel/issues/466)) ([77f2686](https://github.com/astrale-os/kernel/commit/77f26862d8041928029c04da9f2b2521a101c17e))
103
+
104
+ ## [0.2.0-beta.12](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.11...kernel-dsl-v0.2.0-beta.12) (2026-08-26)
105
+
106
+
107
+ ### Bug Fixes
108
+
109
+ * admit optional callable node paths ([#464](https://github.com/astrale-os/kernel/issues/464)) ([8f261d5](https://github.com/astrale-os/kernel/commit/8f261d54dfb489541d2976892c5cacadf688f1a1))
110
+ * **system:** clear Codegraph diagnostic debt ([f7a8e1f](https://github.com/astrale-os/kernel/commit/f7a8e1f5c5694d9c3c45d95fde184f0d5f2c7343))
111
+
112
+ ## [0.2.0-beta.11](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.10...kernel-dsl-v0.2.0-beta.11) (2026-08-25)
113
+
114
+
115
+ ### Features
116
+
117
+ * **callable:** preserve native binary streams and status ([d14c6f1](https://github.com/astrale-os/kernel/commit/d14c6f13492c14a3363b2c4af59c738034752fa2))
118
+ * **schema:** split inspection and add convergence ([6afbd39](https://github.com/astrale-os/kernel/commit/6afbd39506b8a9e37225aded1c02f94ffa64e54b))
119
+
120
+
121
+ ### Bug Fixes
122
+
123
+ * **schema:** harden introspection evidence and caches ([9516eb5](https://github.com/astrale-os/kernel/commit/9516eb510242427296861ef9e730b01861e45463))
124
+
125
+ ## [0.2.0-beta.10](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.9...kernel-dsl-v0.2.0-beta.10) (2026-08-25)
126
+
127
+
128
+ ### Bug Fixes
129
+
130
+ * **dsl:** keep schema projections declaration-nameable ([#432](https://github.com/astrale-os/kernel/issues/432)) ([448d23d](https://github.com/astrale-os/kernel/commit/448d23d58fc2b564ef93be4a54dc8ebd385b5066))
131
+
132
+ ## [0.2.0-beta.9](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.8...kernel-dsl-v0.2.0-beta.9) (2026-08-24)
133
+
134
+
135
+ ### Bug Fixes
136
+
137
+ * **packages:** keep workspace guard private ([e0ba76c](https://github.com/astrale-os/kernel/commit/e0ba76c5ae163245e31115e2a72e0663db0f5320))
138
+ * **packages:** keep workspace guard private ([d260a52](https://github.com/astrale-os/kernel/commit/d260a52329cde5ce4b0260c43a3bbf28cb78f408))
139
+ * **packages:** keep workspace guard private ([a3e82ec](https://github.com/astrale-os/kernel/commit/a3e82ec671f07252a5966b4de988e275e4078b8c))
140
+
141
+ ## [0.2.0-beta.8](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.7...kernel-dsl-v0.2.0-beta.8) (2026-08-24)
142
+
143
+
144
+ ### Features
145
+
146
+ * add aliased domain dependency projection ([afb799b](https://github.com/astrale-os/kernel/commit/afb799b0d61fd6f7436fe659f558a6a62ef1e7a1))
147
+ * add aliased Domain dependency projection ([9c4c4fb](https://github.com/astrale-os/kernel/commit/9c4c4fb4f942c0c5e3961faf4428ed299d42f847))
148
+
149
+ ## [0.2.0-beta.7](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.6...kernel-dsl-v0.2.0-beta.7) (2026-08-24)
150
+
151
+
152
+ ### Bug Fixes
153
+
154
+ * **dsl:** make schema declarations portable ([55e13c0](https://github.com/astrale-os/kernel/commit/55e13c06896eb5d6cf195607aec10f176b585504))
155
+ * publish a TypeScript-compatible cohort ([#406](https://github.com/astrale-os/kernel/issues/406)) ([f1a0cd0](https://github.com/astrale-os/kernel/commit/f1a0cd09f2f0b4498f9fa8924b2e319cac6552b7))
156
+
157
+ ## [0.2.0-beta.6](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.5...kernel-dsl-v0.2.0-beta.6) (2026-08-23)
158
+
159
+
160
+ ### Bug Fixes
161
+
162
+ * **core:** preserve callable identity and runtime boundaries ([#394](https://github.com/astrale-os/kernel/issues/394)) ([ad67dad](https://github.com/astrale-os/kernel/commit/ad67dad84aef3c8b79f769009595ea1f1229026b))
163
+ * **deps:** refresh the Kernel dependency cohort ([#393](https://github.com/astrale-os/kernel/issues/393)) ([883e7bb](https://github.com/astrale-os/kernel/commit/883e7bb7ce17eecb7dad1c94ad2089c576ba3746))
164
+ * **dsl:** close runtime facade contracts ([ff99450](https://github.com/astrale-os/kernel/commit/ff99450ce3889013f57c39293e7022b32e186ca6))
165
+ * **dsl:** close semantic qualification gaps ([4a48cd7](https://github.com/astrale-os/kernel/commit/4a48cd729bcaf839ceda880b26ade064d6505fe2))
166
+ * **dsl:** expose runtime-clean load paths ([7dba075](https://github.com/astrale-os/kernel/commit/7dba075887e4796e5464d5a41ddb03212eed887f))
167
+ * **dsl:** preserve generic resolved domain type ([46f306b](https://github.com/astrale-os/kernel/commit/46f306bc3d1c73c822608c777a82f4502591d3e2))
168
+ * **release:** harden public package closure ([#397](https://github.com/astrale-os/kernel/issues/397)) ([5a5886f](https://github.com/astrale-os/kernel/commit/5a5886fe66c7b3ea0a014766a5df8c04fd93efeb))
169
+ * **system:** preserve erased domain and runtime facade contracts ([b525d47](https://github.com/astrale-os/kernel/commit/b525d4781d2d58776ec6b4bbe1e045a3c1accebb))
170
+ * **system:** preserve public revision vocabulary ([5e990d0](https://github.com/astrale-os/kernel/commit/5e990d0b28578a040b80c508943552c46b8632ae))
171
+ * **test:** preserve authored semantic contracts ([bedb8cd](https://github.com/astrale-os/kernel/commit/bedb8cd2d36f4a95cb8d219067df0d0e39100f08))
172
+
173
+ ## [0.2.0-beta.5](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.4...kernel-dsl-v0.2.0-beta.5) (2026-08-21)
174
+
175
+
176
+ ### ⚠ BREAKING CHANGES
177
+
178
+ * View declarations now contain only target and optional description. Legacy View.auth fields are rejected; callable authorization, View.resolve admission, Policies, and Shell handshakes remain independent.
179
+
180
+ ### Features
181
+
182
+ * remove View authentication declarations ([4a5bfe0](https://github.com/astrale-os/kernel/commit/4a5bfe016717267d31257748f95e7f646782f876))
183
+
184
+ ## [0.2.0-beta.4](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.2.0-beta.3...kernel-dsl-v0.2.0-beta.4) (2026-08-21)
185
+
186
+
187
+ ### Bug Fixes
188
+
189
+ * **release:** add package repository metadata ([8238077](https://github.com/astrale-os/kernel/commit/8238077d47a96c0f7b50a1bae8769fe4faab45b7))
190
+
191
+ ## [0.1.5](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.1.4...kernel-dsl-v0.1.5) (2026-08-07)
192
+
193
+
194
+ ### Features
195
+
196
+ * **dsl:** add non-breaking policy IR preview ([1202d29](https://github.com/astrale-os/kernel/commit/1202d294cc7f32bc8e3e29d7537d3604403d09a5))
197
+ * **dsl:** align policy authoring with v1 ([514961f](https://github.com/astrale-os/kernel/commit/514961f9902d97e96535126b0a983764bb0f30ac))
198
+ * **dsl:** align policy authoring with v1 ([d082d5e](https://github.com/astrale-os/kernel/commit/d082d5e923458c0eec4ee28358f1b41309067843))
199
+
200
+ ## [0.1.4](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.1.3...kernel-dsl-v0.1.4) (2026-07-10)
201
+
202
+
203
+ ### Bug Fixes
204
+
205
+ * export ./package.json from all published packages ([9560a34](https://github.com/astrale-os/kernel/commit/9560a34379c68d475f09a863e9d1962b560d83a0))
206
+ * export ./package.json from all published packages ([8633acb](https://github.com/astrale-os/kernel/commit/8633acba8953644805fc43840732bd16c3e19ab1))
207
+ * export ./package.json in publishConfig.exports too — the map that ships ([85ba0a1](https://github.com/astrale-os/kernel/commit/85ba0a121466ed5ef33fced51d28c0d09a7c0ec4))
208
+
209
+ ## [0.1.3](https://github.com/astrale-os/kernel/compare/kernel-dsl-v0.1.2...kernel-dsl-v0.1.3) (2026-07-08)
210
+
211
+
212
+ ### Features
213
+
214
+ * support top-level functions of the kernel domain ([db45b06](https://github.com/astrale-os/kernel/commit/db45b061d0a7562950277344778991592f0a19eb))
@@ -53,6 +53,7 @@ export interface EdgeClassOptions {
53
53
  readonly extends?: readonly EdgeClassReferenceInput[];
54
54
  readonly properties?: PropertyRecordInput;
55
55
  readonly policies?: {
56
+ readonly read?: Lazy<Policy>;
56
57
  readonly traverse?: Lazy<Policy>;
57
58
  };
58
59
  readonly constraints?: {
@@ -114,7 +114,7 @@ function validateEdgeClassOptions(value) {
114
114
  'constraints',
115
115
  ]);
116
116
  if (value.policies !== undefined)
117
- assertKnownKeys(value.policies, ['traverse']);
117
+ assertKnownKeys(value.policies, ['read', 'traverse']);
118
118
  if (value.constraints !== undefined)
119
119
  assertKnownKeys(value.constraints, ['noSelf', 'acyclic']);
120
120
  }
@@ -128,7 +128,7 @@ function validateUndirectedEdgeClassOptions(value) {
128
128
  'constraints',
129
129
  ]);
130
130
  if (value.policies !== undefined)
131
- assertKnownKeys(value.policies, ['traverse']);
131
+ assertKnownKeys(value.policies, ['read', 'traverse']);
132
132
  if (value.constraints !== undefined)
133
133
  assertKnownKeys(value.constraints, ['noSelf']);
134
134
  }
@@ -6,7 +6,6 @@ declare const PROPERTY_INPUT: unique symbol;
6
6
  declare const AUTO_INPUT: unique symbol;
7
7
  export type ValueSchemaInput = z.ZodType | JsonSchema;
8
8
  export interface PropertyOptions {
9
- readonly visibility?: 'public' | 'private';
10
9
  readonly required?: boolean;
11
10
  readonly description?: string;
12
11
  }
@@ -10,14 +10,11 @@ export function autoPropertyAuthoringInput(value) {
10
10
  }
11
11
  export function property(schema, options) {
12
12
  const admitted = options ?? {};
13
- assertKnownKeys(admitted, ['visibility', 'required', 'description']);
13
+ assertKnownKeys(admitted, ['required', 'description']);
14
14
  return authoringValue('property', {
15
15
  [PROPERTY_INPUT]: {
16
16
  schema,
17
- options: {
18
- ...admitted,
19
- visibility: admitted.visibility ?? 'public',
20
- },
17
+ options: admitted,
21
18
  },
22
19
  });
23
20
  }
@@ -76,11 +76,16 @@ export class V1DefinitionCompiler {
76
76
  extends: this.parents(input.extends, 'edge', `${pointer}/extends`),
77
77
  properties: facet,
78
78
  ...contract,
79
- policies: input.policies?.traverse === undefined
80
- ? {}
81
- : {
82
- traverse: this.policies.ref(input.policies.traverse, `${pointer}/policies/traverse`),
83
- },
79
+ policies: {
80
+ ...(input.policies?.read === undefined
81
+ ? {}
82
+ : { read: this.policies.ref(input.policies.read, `${pointer}/policies/read`) }),
83
+ ...(input.policies?.traverse === undefined
84
+ ? {}
85
+ : {
86
+ traverse: this.policies.ref(input.policies.traverse, `${pointer}/policies/traverse`),
87
+ }),
88
+ },
84
89
  };
85
90
  }
86
91
  endpointBase(value, pointer) {
@@ -36,7 +36,6 @@ export class BuilderValueSchemas {
36
36
  compiled[name] = {
37
37
  schema: canonicalizeValueSchema(schema, 'property-facet', this.registry),
38
38
  required: authoredInput?.options.required ?? isRequired(schemaInput),
39
- visibility: authoredInput?.options.visibility ?? 'public',
40
39
  ...(autoInput === undefined ? {} : { auto: autoInput.options }),
41
40
  ...(authoredInput?.options.description === undefined
42
41
  ? {}
@@ -166,7 +166,7 @@ function compiledClass(input, values, path) {
166
166
  if (value.data !== undefined)
167
167
  dataDefinition(value.data, `${path}/data`);
168
168
  boundedString(value.icon, 1, 8000, 'Class icon', `${path}/icon`);
169
- classPolicies(value.policies, true, `${path}/policies`);
169
+ classPolicies(value.policies, `${path}/policies`);
170
170
  const methodsPath = `${path}/methods`;
171
171
  const methods = array(value.methods, 'Class methods', methodsPath);
172
172
  for (const [index, method] of methods.entries())
@@ -174,7 +174,7 @@ function compiledClass(input, values, path) {
174
174
  unique(methods.map((method, index) => string(object(method, 'Compiled Method', `${methodsPath}/${index}`).name, 'Method name', `${methodsPath}/${index}/name`)), 'Class Methods', methodsPath);
175
175
  }
176
176
  else {
177
- classPolicies(value.policies, false, `${path}/policies`);
177
+ classPolicies(value.policies, `${path}/policies`);
178
178
  edgeContract(value, path);
179
179
  }
180
180
  return value;
@@ -187,16 +187,13 @@ function compiledFunction(input, values, path) {
187
187
  }
188
188
  function compiledProperty(input, values, path) {
189
189
  const value = object(input, 'Compiled Property', path);
190
- exact(value, ['name', 'required', 'visibility', 'value'], 'Compiled Property', path, [
190
+ exact(value, ['name', 'required', 'value'], 'Compiled Property', path, [
191
191
  'auto',
192
192
  'description',
193
193
  'ordering',
194
194
  ]);
195
195
  memberName(value.name, 'Property name', `${path}/name`);
196
196
  boolean(value.required, 'Property required', `${path}/required`);
197
- if (value.visibility !== 'public' && value.visibility !== 'private') {
198
- invalid('Property visibility', undefined, `${path}/visibility`);
199
- }
200
197
  description(value.description, 'Property description', `${path}/description`);
201
198
  if (value.auto !== undefined)
202
199
  propertyAuto(value.auto, `${path}/auto`);
@@ -313,9 +310,9 @@ function propertyAuto(input, path) {
313
310
  if (value.set !== 'instant')
314
311
  invalid('Property auto setter', undefined, `${path}/set`);
315
312
  }
316
- function classPolicies(input, node, path) {
313
+ function classPolicies(input, path) {
317
314
  const value = object(input, 'Class Policies', path);
318
- exact(value, [], 'Class Policies', path, node ? ['read', 'traverse'] : ['traverse']);
315
+ exact(value, [], 'Class Policies', path, ['read', 'traverse']);
319
316
  if (value.read !== undefined)
320
317
  definitionRef(value.read, 'policy', 'Class read Policy', `${path}/read`);
321
318
  if (value.traverse !== undefined)
@@ -248,7 +248,29 @@ function edgeRefines(context, child, parent) {
248
248
  return false;
249
249
  const refine = (a, b) => endpointRefines(context, child.endpoints[a], parent.endpoints[b]) &&
250
250
  countRefines(child.endpoints[a].incident, parent.endpoints[b].incident);
251
- return (refine(0, 0) && refine(1, 1)) || (refine(0, 1) && refine(1, 0));
251
+ const direct = refine(0, 0) && refine(1, 1);
252
+ if (direct)
253
+ return true;
254
+ const reverse = refine(0, 1) && refine(1, 0);
255
+ return reverse && !hasEffectiveEdgePolicy(context, parent, new Set());
256
+ }
257
+ function hasEffectiveEdgePolicy(context, declaration, visited) {
258
+ if (declaration.policies.read !== undefined || declaration.policies.traverse !== undefined) {
259
+ return true;
260
+ }
261
+ for (const parentRef of declaration.extends) {
262
+ const key = Key.of(parentRef);
263
+ if (visited.has(key))
264
+ continue;
265
+ visited.add(key);
266
+ const parent = context.classes.get(key)?.value;
267
+ if (parent !== undefined &&
268
+ isCompiledEdge(parent) &&
269
+ hasEffectiveEdgePolicy(context, parent, visited)) {
270
+ return true;
271
+ }
272
+ }
273
+ return false;
252
274
  }
253
275
  function endpointRefines(context, child, parent) {
254
276
  return child.accepts.every((accepted) => classSatisfiesAny(context, accepted, parent.accepts));
@@ -502,16 +524,15 @@ function validatePolicyParity(context, entry, entryIndex, policies) {
502
524
  }
503
525
  }
504
526
  for (const [classIndex, definition] of entry.definitions.classes.entries()) {
505
- if (definition.kind === 'node' && definition.policies.read !== undefined) {
506
- if (!typing.policyAccepts(definition.policies.read.name, { kind: 'exact', ref: definition.ref })) {
507
- fail(`/closure/${entryIndex}/definitions/classes/${classIndex}/policies/read`, 'Read Policy is incompatible with its protected Node Class.');
508
- }
509
- }
510
- const traverse = definition.policies.traverse;
511
- if (traverse !== undefined) {
527
+ for (const operation of ['read', 'traverse']) {
528
+ const policy = definition.policies[operation];
529
+ if (policy === undefined)
530
+ continue;
531
+ const path = `/closure/${entryIndex}/definitions/classes/${classIndex}/policies/${operation}`;
532
+ const label = operation === 'read' ? 'Read' : 'Traverse';
512
533
  if (definition.kind === 'node') {
513
- if (!typing.policyAccepts(traverse.name, { kind: 'exact', ref: definition.ref })) {
514
- fail(`/closure/${entryIndex}/definitions/classes/${classIndex}/policies/traverse`, 'Traverse Policy is incompatible with its protected Node Class.');
534
+ if (!typing.policyAccepts(policy.name, { kind: 'exact', ref: definition.ref })) {
535
+ fail(path, `${label} Policy is incompatible with its protected Node Class.`);
515
536
  }
516
537
  }
517
538
  else if (isCompiledEdge(definition)) {
@@ -520,8 +541,8 @@ function validatePolicyParity(context, entry, entryIndex, policies) {
520
541
  : definition.endpoints;
521
542
  const sources = typing.concreteEndpointClasses(endpoints[0].accepts);
522
543
  const targets = typing.concreteEndpointClasses(endpoints[1].accepts);
523
- if (sources.some((source) => targets.some((target) => !typing.policyAcceptsEdge(traverse.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })))) {
524
- fail(`/closure/${entryIndex}/definitions/classes/${classIndex}/policies/traverse`, 'Traverse Policy is incompatible with an accepted Edge endpoint pair.');
544
+ if (sources.some((source) => targets.some((target) => !typing.policyAcceptsEdge(policy.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })))) {
545
+ fail(path, `${label} Policy is incompatible with an accepted Edge endpoint pair.`);
525
546
  }
526
547
  }
527
548
  }
@@ -37,7 +37,6 @@ function compileEntry(schema, lookup) {
37
37
  return {
38
38
  name,
39
39
  required: property.required,
40
- visibility: property.visibility,
41
40
  ...(property.auto === undefined ? {} : { auto: property.auto }),
42
41
  ...(property.description === undefined ? {} : { description: property.description }),
43
42
  ...(ordering === undefined ? {} : { ordering }),
@@ -25,12 +25,10 @@ export function createClasses(definitions, validation) {
25
25
  }
26
26
  const shell = {};
27
27
  const policies = Object.freeze({
28
- read: Object.freeze(definition.kind === 'node'
29
- ? uniquePolicyRefs([
30
- ...parents.flatMap((parent) => parent.kind === 'node' ? [...parent.policies.read] : []),
31
- ...(definition.policies.read === undefined ? [] : [definition.policies.read]),
32
- ])
33
- : []),
28
+ read: Object.freeze(uniquePolicyRefs([
29
+ ...parents.flatMap((parent) => [...parent.policies.read]),
30
+ ...(definition.policies.read === undefined ? [] : [definition.policies.read]),
31
+ ])),
34
32
  traverse: Object.freeze(uniquePolicyRefs([
35
33
  ...parents.flatMap((parent) => [...parent.policies.traverse]),
36
34
  ...(definition.policies.traverse === undefined ? [] : [definition.policies.traverse]),
@@ -9,6 +9,7 @@ export interface NodeClassPolicies {
9
9
  readonly traverse?: PolicyRef;
10
10
  }
11
11
  export interface EdgeClassPolicies {
12
+ readonly read?: PolicyRef;
12
13
  readonly traverse?: PolicyRef;
13
14
  }
14
15
  export interface NodeClassDefinition extends DefinitionBase<ClassRef>, PropertyFacet, DataFacet {
@@ -1,4 +1,3 @@
1
- export type PropertyVisibility = 'public' | 'private';
2
1
  export type AutoEvent = 'create' | 'update';
3
2
  export type AutoSet = 'instant';
4
3
  export interface PropertyAuto {
@@ -8,7 +7,6 @@ export interface PropertyAuto {
8
7
  export interface PropertyDefinition {
9
8
  readonly schema: import('../../value/model/schema.js').JsonSchema;
10
9
  readonly required: boolean;
11
- readonly visibility: PropertyVisibility;
12
10
  readonly auto?: PropertyAuto;
13
11
  readonly description?: string;
14
12
  }
@@ -23,8 +23,9 @@ export interface ResolvedData {
23
23
  readonly owner: ResolvedClass<'node'>;
24
24
  readonly definition: DataDefinition;
25
25
  }
26
- export interface ResolvedClassPolicies<Kind extends ClassKind = ClassKind> {
27
- readonly read: Kind extends 'node' ? readonly PolicyRef[] : readonly [];
26
+ export interface ResolvedClassPolicies {
27
+ /** Effective read Policies for this Node or Edge Class. */
28
+ readonly read: readonly PolicyRef[];
28
29
  readonly traverse: readonly PolicyRef[];
29
30
  }
30
31
  export type ResolvedPropertyCollection<ByKey extends Readonly<Record<PropertyKey, ResolvedProperty<unknown>>> = Readonly<Record<PropertyKey, ResolvedProperty<unknown>>>, ByName extends Readonly<Record<string, ResolvedProperty<unknown>>> = Readonly<Record<never, never>>> = Readonly<ByName> & Iterable<ByKey[keyof ByKey]> & {
@@ -45,7 +46,7 @@ export interface ResolvedClass<Kind extends ClassKind = ClassKind, Properties ex
45
46
  readonly definition: Definition;
46
47
  readonly extends: Parents & readonly ResolvedClass<Kind>[];
47
48
  /** Effective inherited Policy conjunction, deduplicated by exact Policy ref. */
48
- readonly policies: ResolvedClassPolicies<Kind>;
49
+ readonly policies: ResolvedClassPolicies;
49
50
  readonly data: Kind extends 'node' ? ResolvedData | undefined : undefined;
50
51
  readonly properties: Properties;
51
52
  readonly methods: Kind extends 'node' ? InstanceMethods : ResolvedMethodCollection<Record<never, never>>;
@@ -13,7 +13,6 @@ export interface EffectiveField {
13
13
  readonly name: string;
14
14
  readonly schema: JsonSchema;
15
15
  readonly required: boolean;
16
- readonly visibility: 'public' | 'private';
17
16
  readonly auto?: PropertyAuto;
18
17
  }
19
18
  export interface EffectiveMethod {
@@ -62,7 +62,6 @@ function ownFields(owner, declaration) {
62
62
  name,
63
63
  schema: property.schema,
64
64
  required: property.required,
65
- visibility: property.visibility,
66
65
  ...(property.auto === undefined ? {} : { auto: property.auto }),
67
66
  });
68
67
  }
@@ -371,7 +371,6 @@ function propertyMeaning(field) {
371
371
  name: field.name,
372
372
  schema: semanticValueSchema(field.schema),
373
373
  required: field.required,
374
- visibility: field.visibility,
375
374
  };
376
375
  }
377
376
  function methodMeaning(method) {
@@ -123,7 +123,6 @@ function canonicalizeProperty(value) {
123
123
  return {
124
124
  schema: canonicalizeValueSchema(value.schema, 'property-facet'),
125
125
  required: value.required,
126
- visibility: value.visibility,
127
126
  ...(value.auto === undefined
128
127
  ? {}
129
128
  : {
@@ -40,17 +40,15 @@ export function collectDomainDefinitionRefs(schema) {
40
40
  export function collectClassRefs(declaration, add) {
41
41
  declaration.extends.forEach(add);
42
42
  Object.values(declaration.properties).forEach((property) => collectValueDefinitionRefs(property.schema, add));
43
+ if (declaration.policies.read !== undefined)
44
+ add(declaration.policies.read);
45
+ if (declaration.policies.traverse !== undefined)
46
+ add(declaration.policies.traverse);
43
47
  if (declaration.kind === 'edge') {
44
48
  collectEndpointRefs(declaration, add);
45
- if (declaration.policies.traverse !== undefined)
46
- add(declaration.policies.traverse);
47
49
  return;
48
50
  }
49
51
  Object.values(declaration.methods).forEach((method) => collectCallableRefs(method, add));
50
- if (declaration.policies.read !== undefined)
51
- add(declaration.policies.read);
52
- if (declaration.policies.traverse !== undefined)
53
- add(declaration.policies.traverse);
54
52
  }
55
53
  function collectEndpointRefs(declaration, add) {
56
54
  const endpoints = declaration.orientation === 'directed'
@@ -130,7 +130,30 @@ function edgeContractRefines(environment, child, parent) {
130
130
  return false;
131
131
  const refines = (childIndex, parentIndex) => endpointRefines(environment, child.endpoints[childIndex], parent.endpoints[parentIndex]) &&
132
132
  countRefines(child.endpoints[childIndex].incident, parent.endpoints[parentIndex].incident);
133
- return (refines(0, 0) && refines(1, 1)) || (refines(0, 1) && refines(1, 0));
133
+ const direct = refines(0, 0) && refines(1, 1);
134
+ if (direct)
135
+ return true;
136
+ const reverse = refines(0, 1) && refines(1, 0);
137
+ return reverse && !hasEffectiveEdgePolicy(environment, parent, new Set());
138
+ }
139
+ function hasEffectiveEdgePolicy(environment, declaration, visited) {
140
+ if (declaration.policies.read !== undefined || declaration.policies.traverse !== undefined) {
141
+ return true;
142
+ }
143
+ for (const parentRef of declaration.extends) {
144
+ const key = definitionRefIndex(parentRef);
145
+ if (visited.has(key))
146
+ continue;
147
+ visited.add(key);
148
+ const parent = environment.resolveAny(parentRef);
149
+ if (parent !== undefined &&
150
+ parent.ref.kind === 'class' &&
151
+ parent.declaration.kind === 'edge' &&
152
+ hasEffectiveEdgePolicy(environment, parent.declaration, visited)) {
153
+ return true;
154
+ }
155
+ }
156
+ return false;
134
157
  }
135
158
  function endpointRefines(environment, child, parent) {
136
159
  return child.accepts.every((accepted) => classSatisfies(environment, accepted, parent.accepts));
@@ -37,7 +37,6 @@ const dataDeclarationSchema = z.strictObject({
37
37
  const propertyDefinitionSchema = z.strictObject({
38
38
  schema: jsonSchemaSchema,
39
39
  required: z.boolean(),
40
- visibility: z.enum(['public', 'private']),
41
40
  auto: z
42
41
  .strictObject({
43
42
  on: uniqueArray(z.enum(['create', 'update'])).min(1),
@@ -203,6 +202,7 @@ const nodeClassPoliciesSchema = z.strictObject({
203
202
  traverse: policyRefSchema.optional(),
204
203
  });
205
204
  const edgeClassPoliciesSchema = z.strictObject({
205
+ read: policyRefSchema.optional(),
206
206
  traverse: policyRefSchema.optional(),
207
207
  });
208
208
  const nodeClassSchema = z.strictObject({
@@ -12,29 +12,17 @@ const PROJECTION_FUNCTION = nodeClassRef('Function');
12
12
  const PROJECTION_POLICY = nodeClassRef('Policy');
13
13
  const PROJECTION_VIEW = nodeClassRef('View');
14
14
  export function validateReadUses(context, typing) {
15
- for (const [name, declaration] of Object.entries(context.environment.candidate.classes)) {
16
- if (declaration.kind !== 'node' || declaration.policies.read === undefined) {
17
- continue;
18
- }
19
- const pointer = `/classes/${escapePointer(name)}/policies/read`;
20
- const ref = declaration.policies.read;
21
- if (!context.resolvePolicy(ref, pointer))
22
- continue;
23
- const object = {
24
- kind: 'exact',
25
- ref: { origin: context.environment.candidate.origin, kind: 'class', name },
26
- };
27
- if (!typing.policyAccepts(ref.name, object)) {
28
- context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every normalized branch of protected Class ${name}.`, formatDefinitionRef(ref));
29
- }
30
- }
15
+ validateClassPolicyUses(context, typing, 'read');
31
16
  }
32
17
  export function validateTraverseUses(context, typing) {
18
+ validateClassPolicyUses(context, typing, 'traverse');
19
+ }
20
+ function validateClassPolicyUses(context, typing, operation) {
33
21
  for (const [name, declaration] of Object.entries(context.environment.candidate.classes)) {
34
- const ref = declaration.policies.traverse;
22
+ const ref = declaration.policies[operation];
35
23
  if (ref === undefined)
36
24
  continue;
37
- const pointer = `/classes/${escapePointer(name)}/policies/traverse`;
25
+ const pointer = `/classes/${escapePointer(name)}/policies/${operation}`;
38
26
  if (!context.resolvePolicy(ref, pointer))
39
27
  continue;
40
28
  if (declaration.kind === 'node') {
@@ -42,9 +30,9 @@ export function validateTraverseUses(context, typing) {
42
30
  kind: 'exact',
43
31
  ref: { origin: context.environment.candidate.origin, kind: 'class', name },
44
32
  };
45
- if (!typing.policyAccepts(ref.name, object)) {
46
- context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every normalized branch of traversed Node Class ${name}.`, formatDefinitionRef(ref));
47
- }
33
+ if (typing.policyAccepts(ref.name, object))
34
+ continue;
35
+ context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every normalized branch of ${operation} Node Class ${name}.`, formatDefinitionRef(ref));
48
36
  continue;
49
37
  }
50
38
  const endpoints = declaration.orientation === 'directed'
@@ -52,19 +40,9 @@ export function validateTraverseUses(context, typing) {
52
40
  : declaration.endpoints;
53
41
  const sources = typing.concreteEndpointClasses(endpoints[0].accepts);
54
42
  const targets = typing.concreteEndpointClasses(endpoints[1].accepts);
55
- let accepted = true;
56
- for (const source of sources) {
57
- for (const target of targets) {
58
- if (!typing.policyAcceptsEdge(ref.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })) {
59
- accepted = false;
60
- break;
61
- }
62
- }
63
- if (!accepted)
64
- break;
65
- }
43
+ const accepted = sources.every((source) => targets.every((target) => typing.policyAcceptsEdge(ref.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })));
66
44
  if (!accepted) {
67
- context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every concrete source/target pair of traversed Edge Class ${name}.`, formatDefinitionRef(ref));
45
+ context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every concrete source/target pair of ${operation} Edge Class ${name}.`, formatDefinitionRef(ref));
68
46
  }
69
47
  }
70
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-dsl",
3
- "version": "0.2.0-beta.14",
3
+ "version": "0.2.0-beta.17",
4
4
  "description": "Astrale Kernel DSL - Schema authoring, inference, and IR serialization",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {