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

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,40 @@ 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
98
  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);
99
+ addEdge(coreEdges, coreEndpoint(declaration.source, domain, persistedDomainEndpoint, coreLocations), coreEndpoint(declaration.target, domain, persistedDomainEndpoint, coreLocations), declaration.class, payload(() => declaration.properties));
75
100
  }
76
101
  return Object.freeze({
77
102
  origin: domain.origin,
78
103
  revision: domain.revision,
79
104
  managed: Object.freeze({
80
- graph: Object.freeze({
81
- nodes: Object.freeze([...managedNodes.values()]),
82
- edges: Object.freeze(managedEdges),
83
- }),
105
+ nodes: Object.freeze([...managedNodes.values()]),
106
+ edges: Object.freeze(managedEdges),
84
107
  paths: invert(managedLocations),
85
108
  }),
86
109
  core: Object.freeze({
87
- graph: Object.freeze({
88
- nodes: Object.freeze([...coreNodes.values()]),
89
- edges: Object.freeze(coreEdges),
90
- }),
110
+ nodes: Object.freeze([...coreNodes.values()]),
111
+ edges: Object.freeze(coreEdges),
91
112
  paths: invert(coreLocations),
92
113
  locators: Object.freeze(locators),
93
114
  }),
@@ -117,11 +138,11 @@ function coreEndpoint(value, domain, domainEndpoint, locations) {
117
138
  return domainEndpoint;
118
139
  return endpoint(PathValue.project({ origin: domain.origin, kind: 'core', name: value.name }).raw, locations);
119
140
  }
120
- function projectDefinitionRelations(domain, definition, definitionEndpoint, locations, edges) {
141
+ function projectDefinitionRelations(domain, definition, definitionEndpoint, locations, edges, payload) {
121
142
  if (isResolvedClass(definition)) {
122
143
  for (const parent of definition.definition.extends) {
123
144
  const path = PathValue.project(parent);
124
- addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.extends.ref, EMPTY_PROPERTIES);
145
+ addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.extends.ref, payload(() => EMPTY_PROPERTIES));
125
146
  }
126
147
  }
127
148
  if (isResolvedClass(definition)) {
@@ -144,9 +165,9 @@ function projectDefinitionRelations(domain, definition, definitionEndpoint, loca
144
165
  }
145
166
  }
146
167
  for (const { policy, operations } of policies.values()) {
147
- addEdge(edges, definitionEndpoint, endpoint(PathValue.project(policy).raw, locations), K.classes.governed_by.ref, normalizeProperties({
168
+ addEdge(edges, definitionEndpoint, endpoint(PathValue.project(policy).raw, locations), K.classes.governed_by.ref, payload(() => normalizeProperties({
148
169
  [K.classes.governed_by.self.properties.operations.key]: Object.freeze(['read', 'traverse'].filter((operation) => operations.has(operation))),
149
- }));
170
+ })));
150
171
  }
151
172
  }
152
173
  if (isResolvedView(definition)) {
@@ -164,7 +185,7 @@ function projectDefinitionRelations(domain, definition, definitionEndpoint, loca
164
185
  });
165
186
  });
166
187
  for (const path of paths) {
167
- addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.view_for.ref, EMPTY_PROPERTIES);
188
+ addEdge(edges, definitionEndpoint, endpoint(path.raw, locations), K.classes.view_for.ref, payload(() => EMPTY_PROPERTIES));
168
189
  }
169
190
  }
170
191
  }
@@ -269,7 +290,7 @@ function endpoint(path, locations) {
269
290
  const created = locations.get(path);
270
291
  return created === undefined ? Object.freeze({ path }) : Object.freeze({ created });
271
292
  }
272
- function addNode(nodes, path, classKey, props, locations) {
293
+ function addNode(nodes, path, classKey, payload, locations) {
273
294
  const existing = nodes.get(path);
274
295
  if (existing !== undefined)
275
296
  return Object.freeze({ created: existing.as });
@@ -277,14 +298,14 @@ function addNode(nodes, path, classKey, props, locations) {
277
298
  if (as === undefined) {
278
299
  throw new ProjectionError('PROJECTION_INVALID', `Projection has no binding for ${path}.`);
279
300
  }
280
- nodes.set(path, Object.freeze({ as, class: classKey, props }));
301
+ nodes.set(path, Object.freeze({ as, class: classKey, ...payload }));
281
302
  return Object.freeze({ created: as });
282
303
  }
283
- function addEdge(edges, source, target, classRef, props) {
304
+ function addEdge(edges, source, target, classRef, payload) {
284
305
  edges.push(Object.freeze({
285
306
  source,
286
307
  target,
287
308
  class: ClassKeyValue.of(classRef),
288
- props,
309
+ ...payload,
289
310
  }));
290
311
  }
@@ -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
+ }