@astrale-os/kernel-core 0.9.0-beta.51 → 0.9.0-beta.53

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.
@@ -49,10 +49,19 @@ export declare const Identity: builder.NodeClass<{
49
49
  can: builder.Method<builder.CallableProjection<{
50
50
  policy: string;
51
51
  object: string;
52
+ } | {
53
+ checks: {
54
+ policy: string;
55
+ object: string;
56
+ }[];
52
57
  }, {
53
58
  readonly mode: 'value';
54
59
  readonly value: {
55
60
  allowed: boolean;
61
+ } | {
62
+ decisions: {
63
+ allowed: boolean;
64
+ }[];
56
65
  };
57
66
  }, "authenticated", true, false>>;
58
67
  whoami: builder.Method<builder.CallableProjection<Record<string, never>, {
@@ -188,14 +197,6 @@ export declare const Identity: builder.NodeClass<{
188
197
  readonly mode: 'value';
189
198
  readonly value: string;
190
199
  }, "authenticated", true, false>>, "delegate", "self"> | builder.AuthoredMethodProjection<builder.Method<builder.CallableProjection<{
191
- policy: string;
192
- object: string;
193
- }, {
194
- readonly mode: 'value';
195
- readonly value: {
196
- allowed: boolean;
197
- };
198
- }, "authenticated", true, false>>, "can", "self"> | builder.AuthoredMethodProjection<builder.Method<builder.CallableProjection<{
199
200
  iss: string;
200
201
  sub: string;
201
202
  }, {
@@ -218,5 +219,22 @@ export declare const Identity: builder.NodeClass<{
218
219
  op: "exists";
219
220
  })[];
220
221
  } | null;
221
- }, "authorized", true, false>>, "whois", "self">;
222
+ }, "authorized", true, false>>, "whois", "self"> | builder.AuthoredMethodProjection<builder.Method<builder.CallableProjection<{
223
+ policy: string;
224
+ object: string;
225
+ } | {
226
+ checks: {
227
+ policy: string;
228
+ object: string;
229
+ }[];
230
+ }, {
231
+ readonly mode: 'value';
232
+ readonly value: {
233
+ allowed: boolean;
234
+ } | {
235
+ decisions: {
236
+ allowed: boolean;
237
+ }[];
238
+ };
239
+ }, "authenticated", true, false>>, "can", "self">;
222
240
  }>;
@@ -1,6 +1,6 @@
1
- export { project } from './project.js';
1
+ export { project, projectTopology } from './project.js';
2
2
  export { compile } from './compile.js';
3
3
  export { projectedCallables, projectedMethodPath } from './callables.js';
4
4
  export { ProjectionError } from './diagnostics.js';
5
5
  export type { ProjectionErrorCode } from './diagnostics.js';
6
- export type { CoreProjection, Projection, ProjectionPart } from './types.js';
6
+ export type { CoreProjection, CoreProjectionTopology, Projection, ProjectionPart, ProjectionTopology, ProjectionTopologyEdge, ProjectionTopologyNode, ProjectionTopologyPart, } from './types.js';
@@ -1,4 +1,4 @@
1
- export { project } from './project.js';
1
+ export { project, projectTopology } from './project.js';
2
2
  export { compile } from './compile.js';
3
3
  export { projectedCallables, projectedMethodPath } from './callables.js';
4
4
  export { ProjectionError } from './diagnostics.js';
@@ -1,4 +1,6 @@
1
1
  import { type SourceDomain, type schema } from '@astrale-os/kernel-dsl/v1';
2
- import type { Projection } from './types.js';
2
+ import type { Projection, ProjectionTopology } from './types.js';
3
3
  /** Project a Domain into an installation-independent symbolic graph. */
4
4
  export declare function project(domain: SourceDomain<schema.DomainSchema>): Projection;
5
+ /** Project only symbolic ownership, retaining every declaration and structural check. */
6
+ export declare function projectTopology(domain: SourceDomain<schema.DomainSchema>): ProjectionTopology;
@@ -8,8 +8,31 @@ import { projectedMethodPath } from './callables.js';
8
8
  import { ProjectionError } from './diagnostics.js';
9
9
  import { coreKeys, managedKeys } from './keys.js';
10
10
  const EMPTY_PROPERTIES = normalizeProperties({});
11
+ const NO_PAYLOAD = Object.freeze({});
11
12
  /** Project a Domain into an installation-independent symbolic graph. */
12
13
  export function project(domain) {
14
+ const projected = walk(domain, (properties) => ({ props: properties() }));
15
+ return Object.freeze({
16
+ origin: projected.origin,
17
+ revision: projected.revision,
18
+ managed: Object.freeze({
19
+ graph: Object.freeze({ nodes: projected.managed.nodes, edges: projected.managed.edges }),
20
+ paths: projected.managed.paths,
21
+ }),
22
+ core: Object.freeze({
23
+ graph: Object.freeze({ nodes: projected.core.nodes, edges: projected.core.edges }),
24
+ paths: projected.core.paths,
25
+ locators: projected.core.locators,
26
+ }),
27
+ });
28
+ }
29
+ /** Project only symbolic ownership, retaining every declaration and structural check. */
30
+ export function projectTopology(domain) {
31
+ return walk(domain, () => NO_PAYLOAD);
32
+ }
33
+ function walk(domain, payload) {
34
+ // Consume payloads in argument position, before addNode's duplicate/binding checks and
35
+ // addEdge's Class conversion, preserving the full projection's original error order.
13
36
  const domainSchema = domain.source;
14
37
  const managedLocations = projectionLocations(managedKeys(domain));
15
38
  const coreLocations = projectionLocations(coreKeys(domain));
@@ -21,7 +44,7 @@ export function project(domain) {
21
44
  const domainPath = PathValue.domain(domain.origin).raw;
22
45
  const domainEndpoint = endpoint(domainPath, managedLocations);
23
46
  const persistedDomainEndpoint = Object.freeze({ path: NodePathValue(domainPath) });
24
- addNode(managedNodes, domainPath, ClassKeyValue.of(K.classes.Domain.ref), domainPropertiesFor(domain), managedLocations);
47
+ addNode(managedNodes, domainPath, ClassKeyValue.of(K.classes.Domain.ref), payload(() => domainPropertiesFor(domain)), managedLocations);
25
48
  for (const definition of domain.definitions()) {
26
49
  if (definition.ref.origin !== domain.origin)
27
50
  continue;
@@ -29,10 +52,10 @@ export function project(domain) {
29
52
  if (projectedClass === undefined)
30
53
  continue;
31
54
  const definitionPath = PathValue.project(definition.ref).raw;
32
- const definitionEndpoint = addNode(managedNodes, definitionPath, projectedClass, definitionPropertiesFor(definition), managedLocations);
33
- addEdge(managedEdges, definitionEndpoint, domainEndpoint, K.classes.of_domain.ref, normalizeProperties({
55
+ const definitionEndpoint = addNode(managedNodes, definitionPath, projectedClass, payload(() => definitionPropertiesFor(definition)), managedLocations);
56
+ addEdge(managedEdges, definitionEndpoint, domainEndpoint, K.classes.of_domain.ref, payload(() => normalizeProperties({
34
57
  [K.classes.of_domain.self.properties.member.key]: memberKey(definition),
35
- }));
58
+ })));
36
59
  }
37
60
  for (const definition of domain.definitions()) {
38
61
  if (definition.ref.origin !== domain.origin)
@@ -40,7 +63,7 @@ export function project(domain) {
40
63
  const projectedClass = projectionClassFor(definition);
41
64
  if (projectedClass === undefined)
42
65
  continue;
43
- projectDefinitionRelations(domain, definition, endpoint(PathValue.project(definition.ref).raw, managedLocations), managedLocations, managedEdges);
66
+ projectDefinitionRelations(domain, definition, endpoint(PathValue.project(definition.ref).raw, managedLocations), managedLocations, managedEdges, payload);
44
67
  }
45
68
  const methods = new Map();
46
69
  for (const definition of Object.values(domain.classes)) {
@@ -52,42 +75,41 @@ export function project(domain) {
52
75
  }
53
76
  for (const method of methods.values()) {
54
77
  const methodPath = projectedMethodPath(domain, method);
55
- const methodEndpoint = addNode(managedNodes, methodPath, ClassKeyValue.of(K.classes.Function.ref), callablePropertiesFor(method.definition), managedLocations);
78
+ const methodEndpoint = addNode(managedNodes, methodPath, ClassKeyValue.of(K.classes.Function.ref), payload(() => callablePropertiesFor(method.definition)), managedLocations);
56
79
  const ownerPath = PathValue.project(method.owner.ref);
57
- addEdge(managedEdges, methodEndpoint, endpoint(ownerPath.raw, managedLocations), K.classes.method_of.ref, normalizeProperties({
80
+ addEdge(managedEdges, methodEndpoint, endpoint(ownerPath.raw, managedLocations), K.classes.method_of.ref, payload(() => normalizeProperties({
58
81
  [K.classes.method_of.self.properties.name.key]: method.name,
59
82
  [K.classes.method_of.self.properties.static.key]: method.definition.static,
60
- }));
61
- addEdge(managedEdges, methodEndpoint, domainEndpoint, K.classes.of_domain.ref, normalizeProperties({
62
- [K.classes.of_domain.self.properties.member.key]: callableMemberKey(domain, method),
63
- }));
83
+ })));
84
+ // This structural check must also execute when no Property payload is requested.
85
+ const member = callableMemberKey(domain, method);
86
+ addEdge(managedEdges, methodEndpoint, domainEndpoint, K.classes.of_domain.ref, payload(() => normalizeProperties({
87
+ [K.classes.of_domain.self.properties.member.key]: member,
88
+ })));
64
89
  }
65
90
  for (const [slug, declaration] of Object.entries(domainSchema.core.nodes)) {
66
91
  assertIdentityAuthenticationUnowned(domain, declaration.class, declaration.properties, slug);
67
92
  const path = PathValue.project({ origin: domain.origin, kind: 'core', name: slug }).raw;
68
- const created = addNode(coreNodes, path, ClassKeyValue.of(declaration.class), declaration.properties, coreLocations);
69
- addEdge(locators, created, persistedDomainEndpoint, K.classes.of_domain.ref, normalizeProperties({
93
+ const created = addNode(coreNodes, path, ClassKeyValue.of(declaration.class), payload(() => declaration.properties), coreLocations);
94
+ addEdge(locators, created, persistedDomainEndpoint, K.classes.of_domain.ref, payload(() => normalizeProperties({
70
95
  [K.classes.of_domain.self.properties.member.key]: `core.${slug}`,
71
- }));
96
+ })));
72
97
  }
73
- for (const declaration of domainSchema.core.edges) {
74
- addEdge(coreEdges, coreEndpoint(declaration.source, domain, persistedDomainEndpoint, coreLocations), coreEndpoint(declaration.target, domain, persistedDomainEndpoint, coreLocations), declaration.class, declaration.properties);
98
+ // Resolved edges carry each endpoint's own identity; the source IR only names it.
99
+ for (const edge of domain.core.edges) {
100
+ addEdge(coreEdges, coreEndpoint(edge.source, domain, persistedDomainEndpoint, coreLocations), coreEndpoint(edge.target, domain, persistedDomainEndpoint, coreLocations), edge.class.ref, payload(() => edge.properties));
75
101
  }
76
102
  return Object.freeze({
77
103
  origin: domain.origin,
78
104
  revision: domain.revision,
79
105
  managed: Object.freeze({
80
- graph: Object.freeze({
81
- nodes: Object.freeze([...managedNodes.values()]),
82
- edges: Object.freeze(managedEdges),
83
- }),
106
+ nodes: Object.freeze([...managedNodes.values()]),
107
+ edges: Object.freeze(managedEdges),
84
108
  paths: invert(managedLocations),
85
109
  }),
86
110
  core: Object.freeze({
87
- graph: Object.freeze({
88
- nodes: Object.freeze([...coreNodes.values()]),
89
- edges: Object.freeze(coreEdges),
90
- }),
111
+ nodes: Object.freeze([...coreNodes.values()]),
112
+ edges: Object.freeze(coreEdges),
91
113
  paths: invert(coreLocations),
92
114
  locators: Object.freeze(locators),
93
115
  }),
@@ -112,16 +134,22 @@ function projectionLocations(paths) {
112
134
  function invert(locations) {
113
135
  return new Map([...locations].map(([path, binding]) => [binding, path]));
114
136
  }
137
+ /**
138
+ * A Core Node binds inside the Core part; every other local Definition is already projected as a
139
+ * managed declaration, so it is addressed by its canonical Path exactly like the owning Domain.
140
+ */
115
141
  function coreEndpoint(value, domain, domainEndpoint, locations) {
116
- if (value.kind === 'domain')
117
- return domainEndpoint;
118
- return endpoint(PathValue.project({ origin: domain.origin, kind: 'core', name: value.name }).raw, locations);
142
+ if ('ref' in value)
143
+ return endpoint(PathValue.project(value.ref).raw, locations);
144
+ if ('owner' in value)
145
+ return endpoint(projectedMethodPath(domain, value), locations);
146
+ return domainEndpoint;
119
147
  }
120
- function projectDefinitionRelations(domain, definition, definitionEndpoint, locations, edges) {
148
+ function projectDefinitionRelations(domain, definition, definitionEndpoint, locations, edges, payload) {
121
149
  if (isResolvedClass(definition)) {
122
150
  for (const parent of definition.definition.extends) {
123
151
  const path = PathValue.project(parent);
124
- addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.extends.ref, EMPTY_PROPERTIES);
152
+ addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.extends.ref, payload(() => EMPTY_PROPERTIES));
125
153
  }
126
154
  }
127
155
  if (isResolvedClass(definition)) {
@@ -144,9 +172,9 @@ function projectDefinitionRelations(domain, definition, definitionEndpoint, loca
144
172
  }
145
173
  }
146
174
  for (const { policy, operations } of policies.values()) {
147
- addEdge(edges, definitionEndpoint, endpoint(PathValue.project(policy).raw, locations), K.classes.governed_by.ref, normalizeProperties({
175
+ addEdge(edges, definitionEndpoint, endpoint(PathValue.project(policy).raw, locations), K.classes.governed_by.ref, payload(() => normalizeProperties({
148
176
  [K.classes.governed_by.self.properties.operations.key]: Object.freeze(['read', 'traverse'].filter((operation) => operations.has(operation))),
149
- }));
177
+ })));
150
178
  }
151
179
  }
152
180
  if (isResolvedView(definition)) {
@@ -164,7 +192,7 @@ function projectDefinitionRelations(domain, definition, definitionEndpoint, loca
164
192
  });
165
193
  });
166
194
  for (const path of paths) {
167
- addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.view_for.ref, EMPTY_PROPERTIES);
195
+ addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.view_for.ref, payload(() => EMPTY_PROPERTIES));
168
196
  }
169
197
  }
170
198
  }
@@ -269,7 +297,7 @@ function endpoint(path, locations) {
269
297
  const created = locations.get(path);
270
298
  return created === undefined ? Object.freeze({ path }) : Object.freeze({ created });
271
299
  }
272
- function addNode(nodes, path, classKey, props, locations) {
300
+ function addNode(nodes, path, classKey, payload, locations) {
273
301
  const existing = nodes.get(path);
274
302
  if (existing !== undefined)
275
303
  return Object.freeze({ created: existing.as });
@@ -277,14 +305,14 @@ function addNode(nodes, path, classKey, props, locations) {
277
305
  if (as === undefined) {
278
306
  throw new ProjectionError('PROJECTION_INVALID', `Projection has no binding for ${path}.`);
279
307
  }
280
- nodes.set(path, Object.freeze({ as, class: classKey, props }));
308
+ nodes.set(path, Object.freeze({ as, class: classKey, ...payload }));
281
309
  return Object.freeze({ created: as });
282
310
  }
283
- function addEdge(edges, source, target, classRef, props) {
311
+ function addEdge(edges, source, target, classRef, payload) {
284
312
  edges.push(Object.freeze({
285
313
  source,
286
314
  target,
287
315
  class: ClassKeyValue.of(classRef),
288
- props,
316
+ ...payload,
289
317
  }));
290
318
  }
@@ -1,5 +1,6 @@
1
1
  import type { Key, Revision } from '@astrale-os/kernel-dsl/v1';
2
- import type { GraphSpec, GraphSpecEdge, LocalBinding } from '#graph/graph';
2
+ import type { ClassKey } from '@astrale-os/kernel-dsl/v1/addressing';
3
+ import type { GraphSpec, GraphSpecEdge, GraphSpecEndpoint, LocalBinding } from '#graph/graph';
3
4
  import type { NodePath } from '#graph/path';
4
5
  export interface ProjectionPart {
5
6
  readonly graph: GraphSpec;
@@ -16,3 +17,28 @@ export interface Projection {
16
17
  readonly managed: ProjectionPart;
17
18
  readonly core: CoreProjection;
18
19
  }
20
+ /** Declaration identity only; this is not a Graph Node with absent or defaulted Properties. */
21
+ export interface ProjectionTopologyNode {
22
+ readonly as: LocalBinding;
23
+ readonly class: ClassKey;
24
+ }
25
+ export interface ProjectionTopologyEdge {
26
+ readonly source: GraphSpecEndpoint;
27
+ readonly target: GraphSpecEndpoint;
28
+ readonly class: ClassKey;
29
+ }
30
+ export interface ProjectionTopologyPart {
31
+ readonly paths: ReadonlyMap<LocalBinding, NodePath>;
32
+ readonly nodes: readonly ProjectionTopologyNode[];
33
+ readonly edges: readonly ProjectionTopologyEdge[];
34
+ }
35
+ export interface CoreProjectionTopology extends ProjectionTopologyPart {
36
+ readonly locators: readonly ProjectionTopologyEdge[];
37
+ }
38
+ /** Symbolic ownership coordinates without materialized schema Property payloads. */
39
+ export interface ProjectionTopology {
40
+ readonly origin: Key.Origin;
41
+ readonly revision: Revision;
42
+ readonly managed: ProjectionTopologyPart;
43
+ readonly core: CoreProjectionTopology;
44
+ }