@astrale-os/kernel-dsl 0.2.0-beta.27 → 0.2.0-beta.28

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.
@@ -91,7 +91,7 @@ export type ProjectionOfCallable<Value extends Function | Method> = Value extend
91
91
  /** Internal lowering access; Callable authoring handles expose no public configuration object. */
92
92
  export declare function callableConfiguration(value: Function | Method): CallableInput;
93
93
  export type PolicyObjectAuthoring = Class | Function | Policy | View | CoreNode;
94
- export type PolicyObjectInput = Lazy<PolicyObjectAuthoring>;
94
+ export type PolicyObjectInput = Lazy<PolicyObjectAuthoring | PolicyObjectRef>;
95
95
  export declare function func<const Config extends FunctionInput, Input = ValueInputOf<Config['input']>, Output = CallableOutputOf<Config['output']>, Auth extends FunctionAuth = Config['auth']>(config: Config): Function<CallableProjection<Input, Output, Auth, false, 'default'>>;
96
96
  export declare function method<const Config extends MethodInput, Input = ValueInputOf<Config['input']>, Output = CallableOutputOf<Config['output']>, Auth extends FunctionAuth = Config['auth'], Static extends boolean = Config extends {
97
97
  readonly static: true;
@@ -50,22 +50,22 @@ export class BuilderContext {
50
50
  this.capturePolicyObject(value, ref);
51
51
  }
52
52
  capturePolicy(value, ref, pointer) {
53
- this.ownership.capture(value, `${ref.origin}:policy.${ref.name}`, pointer);
53
+ this.ownership.captureDefinition(value, ref, pointer);
54
54
  this.policies.set(value, ref);
55
55
  this.capturePolicyObject(value, ref);
56
56
  }
57
57
  captureCoreNode(value, slug, pointer) {
58
- this.ownership.capture(value, `${this.origin}:core.${slug}`, pointer);
59
58
  const ref = { origin: this.origin, kind: 'core', name: slug };
59
+ this.ownership.captureDefinition(value, ref, pointer);
60
60
  this.coreNodes.set(value, ref);
61
61
  this.capturePolicyObject(value, ref);
62
62
  }
63
63
  captureFunction(value, ref, pointer) {
64
- this.ownership.capture(value, `${ref.origin}:function.${ref.name}`, pointer);
64
+ this.ownership.captureDefinition(value, ref, pointer);
65
65
  this.capturePolicyObject(value, ref);
66
66
  }
67
67
  captureView(value, ref, pointer) {
68
- this.ownership.capture(value, `${ref.origin}:view.${ref.name}`, pointer);
68
+ this.ownership.captureDefinition(value, ref, pointer);
69
69
  this.capturePolicyObject(value, ref);
70
70
  }
71
71
  resolveClass(input, kind, pointer) {
@@ -112,13 +112,18 @@ export class BuilderContext {
112
112
  const ref = isPolicyObjectRef(value)
113
113
  ? value
114
114
  : typeof value === 'object' && value !== null
115
- ? this.policyObjects.get(value)
115
+ ? (this.policyObjects.get(value) ?? this.ownership.definition(value))
116
116
  : undefined;
117
- if (ref === undefined ||
118
- ref.origin !== this.origin ||
119
- !this.policyObjectRefs.has(definitionRefIndex(ref))) {
120
- fail('BUILDER_POLICY_REF', pointer, 'Policy ref(...) must name one registered local Definition, Function, Policy, View, or Core Node.');
117
+ const dependency = ref === undefined ? undefined : this.#dependencies.get(ref.origin)?.schema;
118
+ const admitted = ref !== undefined &&
119
+ (ref.origin === this.origin
120
+ ? this.policyObjectRefs.has(definitionRefIndex(ref))
121
+ : dependency !== undefined && hasPolicyObject(dependency, ref));
122
+ if (!admitted || ref === undefined) {
123
+ fail('BUILDER_POLICY_REF', pointer, 'Policy ref(...) must name one registered local or direct-dependency Definition, Function, Policy, View, or Core Node.');
121
124
  }
125
+ if (ref.origin !== this.origin)
126
+ this.usedForeignOrigins.add(ref.origin);
122
127
  return { ...ref };
123
128
  }
124
129
  resolveCoreEndpoint(value, pointer) {
@@ -245,3 +250,17 @@ function definitionRefsOf(schema) {
245
250
  }
246
251
  return refs.sort(compareDefinitionRefs);
247
252
  }
253
+ function hasPolicyObject(schema, ref) {
254
+ switch (ref.kind) {
255
+ case 'class':
256
+ return Object.hasOwn(schema.classes, ref.name);
257
+ case 'function':
258
+ return Object.hasOwn(schema.functions, ref.name);
259
+ case 'policy':
260
+ return Object.hasOwn(schema.policies, ref.name);
261
+ case 'view':
262
+ return Object.hasOwn(schema.views, ref.name);
263
+ case 'core':
264
+ return Object.hasOwn(schema.core.nodes, ref.name);
265
+ }
266
+ }
@@ -1,8 +1,8 @@
1
- import type { DefinitionRef } from '../../../addressing/index.js';
1
+ import type { PolicyObjectRef } from '../../../language/policy/model/policy.js';
2
2
  export declare class OwnershipCapture {
3
3
  #private;
4
- captureDefinition(value: object, ref: DefinitionRef, pointer: string): void;
4
+ captureDefinition(value: object, ref: PolicyObjectRef, pointer: string): void;
5
5
  capture(value: object, owner: string, pointer: string): void;
6
- definition(value: object): DefinitionRef | undefined;
6
+ definition(value: object): PolicyObjectRef | undefined;
7
7
  commit(): void;
8
8
  }
@@ -438,11 +438,8 @@ function validateCallablePolicy(context, entry, expression, inputIndex, fields,
438
438
  !isSingleNodePathField(context, entry, inputIndex, object.field))
439
439
  fail(`${path}/object`, 'Callable Policy input target must be a direct required single-Node Path field.');
440
440
  }
441
- if (object.kind === 'ref') {
442
- if (object.ref.origin !== entry.origin ||
443
- context.definitions.get(Key.of(object.ref)) === undefined)
444
- fail(`${path}/object/ref`, 'Callable Policy object refs must name an exact local Definition.');
445
- }
441
+ // validateClosure already establishes that object refs name existing local
442
+ // or exact direct-dependency Definitions. Named Policy execution stays local.
446
443
  return;
447
444
  }
448
445
  const children = 'allOf' in expression ? expression.allOf : expression.anyOf;
@@ -122,7 +122,14 @@ function visitChecks(validation, typing, expression, context, pointer) {
122
122
  }
123
123
  function referenceContracts(validation, ref, pointer) {
124
124
  const candidate = validation.environment.candidate;
125
- if (ref.origin !== candidate.origin)
125
+ const local = ref.origin === candidate.origin;
126
+ const direct = Object.values(candidate.dependencies).some((entry) => entry.origin === ref.origin);
127
+ const owner = local
128
+ ? candidate
129
+ : direct
130
+ ? validation.environment.dependencies.get(ref.origin)
131
+ : undefined;
132
+ if (owner === undefined)
126
133
  return invalidPolicyObjectRef(validation, ref, pointer);
127
134
  switch (ref.kind) {
128
135
  case 'class': {
@@ -132,26 +139,26 @@ function referenceContracts(validation, ref, pointer) {
132
139
  : invalidPolicyObjectRef(validation, ref, pointer);
133
140
  }
134
141
  case 'function':
135
- return candidate.functions[ref.name] === undefined
142
+ return owner.functions[ref.name] === undefined
136
143
  ? invalidPolicyObjectRef(validation, ref, pointer)
137
144
  : [{ kind: 'exact', ref: PROJECTION_FUNCTION }];
138
145
  case 'policy':
139
- return candidate.policies[ref.name] === undefined
146
+ return owner.policies[ref.name] === undefined
140
147
  ? invalidPolicyObjectRef(validation, ref, pointer)
141
148
  : [{ kind: 'exact', ref: PROJECTION_POLICY }];
142
149
  case 'view':
143
- return candidate.views[ref.name] === undefined
150
+ return owner.views[ref.name] === undefined
144
151
  ? invalidPolicyObjectRef(validation, ref, pointer)
145
152
  : [{ kind: 'exact', ref: PROJECTION_VIEW }];
146
153
  case 'core': {
147
- const node = candidate.core.nodes[ref.name];
154
+ const node = owner.core.nodes[ref.name];
148
155
  if (node === undefined)
149
156
  return invalidPolicyObjectRef(validation, ref, pointer);
150
157
  const resolved = validation.environment.resolve(node.class);
151
158
  const analyzed = validation.analysis.definitions.get(definitionRefIndex(node.class));
152
159
  // Core validation owns invalid Core Class diagnostics. Avoid adding Policy noise for
153
160
  // a Node that cannot materialize in the first place.
154
- if (node.class.origin !== candidate.origin ||
161
+ if (node.class.origin !== owner.origin ||
155
162
  resolved?.ref.kind !== 'class' ||
156
163
  resolved.kind !== 'node' ||
157
164
  analyzed === undefined) {
@@ -163,7 +170,7 @@ function referenceContracts(validation, ref, pointer) {
163
170
  return invalidPolicyObjectRef(validation, ref, pointer);
164
171
  }
165
172
  function invalidPolicyObjectRef(validation, ref, pointer) {
166
- validation.add('PL_REF', `${pointer}/ref`, `${formatDefinitionRef(ref)} is not an exact local projected Policy object.`, formatDefinitionRef(ref));
173
+ validation.add('PL_REF', `${pointer}/ref`, `${formatDefinitionRef(ref)} is not an exact local or direct-dependency projected Policy object.`, formatDefinitionRef(ref));
167
174
  return undefined;
168
175
  }
169
176
  function selfContracts(validation, context, pointer) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/kernel-dsl",
3
- "version": "0.2.0-beta.27",
3
+ "version": "0.2.0-beta.28",
4
4
  "description": "Astrale Kernel DSL - Schema authoring, inference, and IR serialization",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {