@astrale-os/kernel-core 0.9.0-beta.65 → 0.9.0-beta.66

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 (93) hide show
  1. package/dist/auth/authority/admission/admission.d.ts +0 -1
  2. package/dist/auth/authority/admission/admission.js +8 -141
  3. package/dist/auth/authority/admission/references.d.ts +13 -0
  4. package/dist/auth/authority/admission/references.js +38 -0
  5. package/dist/auth/authority/admission/term.d.ts +6 -0
  6. package/dist/auth/authority/admission/term.js +60 -0
  7. package/dist/auth/authority/admission/wire.d.ts +8 -0
  8. package/dist/auth/authority/admission/wire.js +33 -0
  9. package/dist/graph/graph/index.d.ts +1 -1
  10. package/dist/graph/graph/index.js +1 -1
  11. package/dist/graph/graph/model/codec.js +3 -3
  12. package/dist/graph/graph/model/index.d.ts +1 -1
  13. package/dist/graph/graph/model/index.js +1 -1
  14. package/dist/graph/graph/model/model.d.ts +7 -7
  15. package/dist/graph/graph/model/model.js +6 -6
  16. package/dist/graph/graph/model/wire.d.ts +0 -20
  17. package/dist/graph/graph/model/wire.js +2 -2
  18. package/dist/graph/mutate/authoring/builder.d.ts +2 -2
  19. package/dist/graph/mutate/authoring/builder.js +2 -2
  20. package/dist/graph/mutate/index.d.ts +1 -1
  21. package/dist/graph/mutate/language/codec.js +3 -3
  22. package/dist/graph/mutate/language/model.d.ts +4 -4
  23. package/dist/graph/mutate/result/index.d.ts +3 -3
  24. package/dist/graph/mutate/result/index.js +5 -5
  25. package/dist/graph/node/identity/id.d.ts +0 -3
  26. package/dist/graph/node/identity/id.js +0 -4
  27. package/dist/graph/query/language/codec.js +3 -3
  28. package/dist/graph/query/language/model.d.ts +3 -3
  29. package/dist/graph/reconcile/condition/model.d.ts +2 -2
  30. package/dist/graph/reconcile/condition/references.d.ts +0 -1
  31. package/dist/graph/reconcile/condition/references.js +4 -4
  32. package/dist/graph/reconcile/correspondence.d.ts +9 -8
  33. package/dist/graph/reconcile/evidence.d.ts +2 -2
  34. package/dist/graph/reconcile/mutation/assess.d.ts +2 -1
  35. package/dist/graph/reconcile/observation.d.ts +4 -3
  36. package/dist/graph/reconcile/planning/context.d.ts +3 -3
  37. package/dist/graph/reconcile/planning/model.d.ts +4 -4
  38. package/dist/schema/callables/{view-for.d.ts → entrypoint.d.ts} +7 -5
  39. package/dist/schema/callables/entrypoint.js +12 -0
  40. package/dist/schema/callables/function.d.ts +0 -120
  41. package/dist/schema/callables/index.d.ts +1 -1
  42. package/dist/schema/callables/index.js +1 -1
  43. package/dist/schema/callables/view.d.ts +2 -24
  44. package/dist/schema/domain/domain.d.ts +2 -121
  45. package/dist/schema/domain/domain.js +3 -0
  46. package/dist/schema/identity/identity.d.ts +0 -8
  47. package/dist/schema/kernel/projection/core.d.ts +7 -0
  48. package/dist/schema/kernel/projection/core.js +51 -0
  49. package/dist/schema/kernel/projection/definitions.d.ts +13 -0
  50. package/dist/schema/kernel/projection/definitions.js +71 -0
  51. package/dist/schema/kernel/projection/methods.d.ts +5 -0
  52. package/dist/schema/kernel/projection/methods.js +41 -0
  53. package/dist/schema/kernel/projection/part.d.ts +34 -0
  54. package/dist/schema/kernel/projection/part.js +42 -0
  55. package/dist/schema/kernel/projection/paths.d.ts +6 -0
  56. package/dist/schema/kernel/projection/{keys.js → paths.js} +11 -12
  57. package/dist/schema/kernel/projection/project.d.ts +1 -1
  58. package/dist/schema/kernel/projection/project.js +16 -290
  59. package/dist/schema/kernel/projection/properties.d.ts +11 -0
  60. package/dist/schema/kernel/projection/properties.js +36 -0
  61. package/dist/schema/kernel/projection/relations.d.ts +7 -0
  62. package/dist/schema/kernel/projection/relations.js +49 -0
  63. package/dist/schema/kernel/projection/types.d.ts +4 -4
  64. package/dist/schema/kernel/schema.d.ts +74 -357
  65. package/dist/schema/kernel/schema.js +3 -2
  66. package/dist/schema/kernel/syscalls/contracts/blob.d.ts +12 -2
  67. package/dist/schema/kernel/syscalls/contracts/blob.js +10 -2
  68. package/dist/schema/kernel/syscalls/contracts/delegate.d.ts +0 -4
  69. package/dist/schema/kernel/syscalls/contracts/delegate.js +0 -3
  70. package/dist/schema/kernel/syscalls/contracts/index.d.ts +1 -1
  71. package/dist/schema/kernel/syscalls/contracts/index.js +1 -1
  72. package/dist/schema/kernel/syscalls/contracts/install.d.ts +3 -20
  73. package/dist/schema/kernel/syscalls/contracts/install.js +0 -2
  74. package/dist/schema/kernel/syscalls/contracts/installation.d.ts +0 -36
  75. package/dist/schema/kernel/syscalls/contracts/installation.js +3 -3
  76. package/dist/schema/kernel/syscalls/contracts/view-resolve.d.ts +3 -14
  77. package/dist/schema/kernel/syscalls/contracts/view-resolve.js +3 -18
  78. package/dist/schema/kernel/syscalls/declarations/delegate.d.ts +0 -4
  79. package/dist/schema/kernel/syscalls/declarations/download.d.ts +5 -0
  80. package/dist/schema/kernel/syscalls/declarations/index.d.ts +6 -24
  81. package/dist/schema/kernel/syscalls/declarations/install.d.ts +0 -8
  82. package/dist/schema/kernel/syscalls/declarations/view-resolve.d.ts +1 -12
  83. package/dist/schema/kernel/syscalls/descriptors/identity.d.ts +0 -4
  84. package/dist/schema/kernel/syscalls/descriptors/results/view-resolution.d.ts +2 -13
  85. package/dist/schema/kernel/syscalls/descriptors/results/view-resolution.js +4 -119
  86. package/dist/schema/kernel/syscalls/descriptors/view.d.ts +1 -12
  87. package/package.json +2 -2
  88. package/dist/schema/callables/view-for.js +0 -12
  89. package/dist/schema/kernel/projection/keys.d.ts +0 -3
  90. package/dist/schema/kernel/syscalls/contracts/legacy/delegate.d.ts +0 -5
  91. package/dist/schema/kernel/syscalls/contracts/legacy/delegate.js +0 -25
  92. package/dist/schema/kernel/syscalls/contracts/legacy/install.d.ts +0 -22
  93. package/dist/schema/kernel/syscalls/contracts/legacy/install.js +0 -31
@@ -8,7 +8,6 @@ export declare const limits: {
8
8
  readonly classesPerRelation: 1024;
9
9
  readonly repeatMaximum: 16;
10
10
  };
11
- export declare const MAX_BOOLEAN_OPERANDS: 512;
12
11
  export declare function admitAuthorityExpr(input: portable.Value): AuthorityExpr;
13
12
  /** Internal constructor admission: the outer identity binder binds subject; no local escapes into it. */
14
13
  export declare function admitBinderBody(input: portable.Value): AuthorityExpr;
@@ -1,7 +1,8 @@
1
- import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
2
1
  import { isNodeId } from '../../../graph/node/index.js';
3
- import { AuthValueError } from '../../error.js';
4
2
  import { ownsExpression } from '../ownership.optimization.js';
3
+ import { classRef } from './references.js';
4
+ import { localId, term } from './term.js';
5
+ import { array, exact, invalid, record, required } from './wire.js';
5
6
  export const limits = Object.freeze({
6
7
  expressionDepth: 64,
7
8
  operandsPerExpression: 512,
@@ -10,7 +11,7 @@ export const limits = Object.freeze({
10
11
  classesPerRelation: 1024,
11
12
  repeatMaximum: 16,
12
13
  });
13
- export const MAX_BOOLEAN_OPERANDS = limits.operandsPerExpression;
14
+ const MAX_BOOLEAN_OPERANDS = limits.operandsPerExpression;
14
15
  export function admitAuthorityExpr(input) {
15
16
  return admit(input, '/predicate', new Set(), false, 0);
16
17
  }
@@ -67,7 +68,7 @@ function admit(input, path, locals, subjectBound, depth) {
67
68
  return {
68
69
  op: 'related',
69
70
  source: term(value.source, `${path}/source`, locals, subjectBound),
70
- via: array(value.via, `${path}/via`, 1, limits.classesPerRelation).map((entry, index) => edgeClassRef(entry, `${path}/via/${index}`)),
71
+ via: array(value.via, `${path}/via`, 1, limits.classesPerRelation).map((entry, index) => classRef(entry, `${path}/via/${index}`)),
71
72
  target: term(value.target, `${path}/target`, locals, subjectBound),
72
73
  ...(hasRepeat ? { repeat: repeat(value.repeat, `${path}/repeat`) } : {}),
73
74
  };
@@ -96,11 +97,11 @@ function admit(input, path, locals, subjectBound, depth) {
96
97
  return {
97
98
  op: 'instance-of',
98
99
  node: term(value.node, `${path}/node`, locals, subjectBound),
99
- class: nodeClassRef(value.class, `${path}/class`),
100
+ class: classRef(value.class, `${path}/class`),
100
101
  };
101
102
  case 'edge-class':
102
103
  exact(value, ['class', 'op'], path);
103
- return { op: 'edge-class', class: edgeClassRef(value.class, `${path}/class`) };
104
+ return { op: 'edge-class', class: classRef(value.class, `${path}/class`) };
104
105
  case 'class-authority':
105
106
  exact(value, ['class', 'evidence', 'identity', 'op', 'operation'], path);
106
107
  return {
@@ -114,55 +115,6 @@ function admit(input, path, locals, subjectBound, depth) {
114
115
  invalid(`${path}/op`, 'Unsupported authority operation');
115
116
  }
116
117
  }
117
- function term(input, path, locals, subjectBound) {
118
- const value = record(input, path);
119
- switch (value.kind) {
120
- case 'input':
121
- exact(value, ['input', 'kind'], path);
122
- if (value.input !== 'object' && value.input !== 'source' && value.input !== 'target') {
123
- invalid(`${path}/input`, 'Expected object, source, or target');
124
- }
125
- return { kind: 'input', input: value.input };
126
- case 'node':
127
- exact(value, ['id', 'kind'], path);
128
- if (!isNodeId(value.id))
129
- invalid(`${path}/id`, 'Expected a canonical NodeId');
130
- return { kind: 'node', id: value.id };
131
- case 'class':
132
- exact(value, ['kind', 'ref'], path);
133
- return { kind: 'class', ref: classRef(value.ref, `${path}/ref`) };
134
- case 'domain':
135
- exact(value, ['kind', 'origin'], path);
136
- return { kind: 'domain', origin: domainOrigin(value.origin, `${path}/origin`) };
137
- case 'ref': {
138
- exact(value, ['kind', 'ref'], path);
139
- const ref = absoluteRef(value.ref, `${path}/ref`);
140
- if (ref.kind === 'core')
141
- return { kind: 'ref', ref: coreRef(value.ref, `${path}/ref`) };
142
- if (!['class', 'function', 'policy', 'view'].includes(ref.kind))
143
- invalid(`${path}/ref/kind`, 'Expected a projected Schema member');
144
- definitionName(ref.name, `${path}/ref/name`);
145
- return { kind: 'ref', ref: ref };
146
- }
147
- case 'core':
148
- exact(value, ['kind', 'ref'], path);
149
- return { kind: 'core', ref: coreRef(value.ref, `${path}/ref`) };
150
- case 'local': {
151
- exact(value, ['id', 'kind'], path);
152
- const id = localId(value.id, `${path}/id`);
153
- if (!locals.has(id))
154
- invalid(`${path}/id`, `Local ${id} is outside its lexical scope`);
155
- return { kind: 'local', id };
156
- }
157
- case 'subject':
158
- exact(value, ['kind'], path);
159
- if (!subjectBound)
160
- invalid(path, 'Binder subject is outside its lexical scope');
161
- return { kind: 'subject' };
162
- default:
163
- invalid(`${path}/kind`, 'Unsupported authority term');
164
- }
165
- }
166
118
  function localDeclaration(input, path) {
167
119
  const value = record(input, path);
168
120
  const id = localId(value.id, `${path}/id`);
@@ -172,7 +124,7 @@ function localDeclaration(input, path) {
172
124
  }
173
125
  if (value.kind === 'classes') {
174
126
  exact(value, ['classes', 'id', 'kind'], path);
175
- const classes = array(value.classes, `${path}/classes`, 1, limits.classesPerLocal).map((entry, index) => nodeClassRef(entry, `${path}/classes/${index}`));
127
+ const classes = array(value.classes, `${path}/classes`, 1, limits.classesPerLocal).map((entry, index) => classRef(entry, `${path}/classes/${index}`));
176
128
  return {
177
129
  id,
178
130
  kind: 'classes',
@@ -193,61 +145,6 @@ function repeat(input, path) {
193
145
  }
194
146
  return { min, max };
195
147
  }
196
- function classRef(input, path) {
197
- const value = absoluteRef(input, path);
198
- if (value.kind !== 'class')
199
- invalid(`${path}/kind`, 'Expected class');
200
- definitionName(value.name, `${path}/name`);
201
- return value;
202
- }
203
- function nodeClassRef(input, path) {
204
- const value = absoluteRef(input, path);
205
- if (value.kind !== 'class')
206
- invalid(`${path}/kind`, 'Expected class');
207
- definitionName(value.name, `${path}/name`);
208
- return value;
209
- }
210
- function edgeClassRef(input, path) {
211
- const value = absoluteRef(input, path);
212
- if (value.kind !== 'class')
213
- invalid(`${path}/kind`, 'Expected class');
214
- definitionName(value.name, `${path}/name`);
215
- return value;
216
- }
217
- function absoluteRef(input, path) {
218
- const value = record(input, path);
219
- exact(value, ['kind', 'name', 'origin'], path);
220
- const origin = domainOrigin(value.origin, `${path}/origin`);
221
- if (typeof value.kind !== 'string')
222
- invalid(`${path}/kind`, 'Expected a reference kind');
223
- if (typeof value.name !== 'string')
224
- invalid(`${path}/name`, 'Expected a reference name');
225
- return { origin, kind: value.kind, name: value.name };
226
- }
227
- function definitionName(input, path) {
228
- if (!patterns.memberName.test(input))
229
- invalid(path, 'Expected a Definition member name');
230
- }
231
- function coreRef(input, path) {
232
- const value = absoluteRef(input, path);
233
- if (value.kind !== 'core')
234
- invalid(`${path}/kind`, 'Expected core');
235
- if (!patterns.coreSlug.test(value.name))
236
- invalid(`${path}/name`, 'Expected a Core slug');
237
- return value;
238
- }
239
- function domainOrigin(input, path) {
240
- if (typeof input !== 'string' || !patterns.origin.test(input)) {
241
- invalid(path, 'Expected a canonical Domain origin');
242
- }
243
- return input;
244
- }
245
- function localId(input, path) {
246
- if (!Number.isSafeInteger(input) || input < 0) {
247
- invalid(path, 'Expected a non-negative safe integer');
248
- }
249
- return input;
250
- }
251
148
  function operation(input, path) {
252
149
  if (input !== 'create' &&
253
150
  input !== 'read' &&
@@ -263,33 +160,3 @@ function evidence(input, path) {
263
160
  invalid(path, 'Expected allowed or owner');
264
161
  return input;
265
162
  }
266
- function record(input, path) {
267
- if (input === undefined || input === null || Array.isArray(input) || typeof input !== 'object') {
268
- invalid(path, 'Expected an object');
269
- }
270
- return input;
271
- }
272
- function array(input, path, minimum, maximum) {
273
- if (!Array.isArray(input) || input.length < minimum || input.length > maximum) {
274
- invalid(path, `Expected ${minimum}-${maximum} entries`);
275
- }
276
- return input;
277
- }
278
- function required(input, path) {
279
- if (input === undefined)
280
- invalid(path, 'Expected a value');
281
- return input;
282
- }
283
- function exact(value, expected, path) {
284
- const actual = Object.keys(value).sort(compare);
285
- const wanted = [...expected].sort(compare);
286
- if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
287
- invalid(path, `Expected exactly ${expected.join(', ')}`);
288
- }
289
- }
290
- function compare(left, right) {
291
- return left < right ? -1 : left > right ? 1 : 0;
292
- }
293
- function invalid(path, message) {
294
- throw new AuthValueError('AUTHORITY_PREDICATE_INVALID', message, path);
295
- }
@@ -0,0 +1,13 @@
1
+ import type { Key } from '@astrale-os/kernel-dsl/v1';
2
+ import type { ClassRef, CoreRef } from '@astrale-os/kernel-dsl/v1/addressing';
3
+ import type * as portable from '@astrale-os/kernel-dsl/value';
4
+ /** One `{ origin, kind, name }` reference with a canonical origin and an unchecked kind and name. */
5
+ export declare function absoluteRef(input: portable.Value | undefined, path: string): {
6
+ readonly origin: Key.Origin;
7
+ readonly kind: string;
8
+ readonly name: string;
9
+ };
10
+ export declare function classRef(input: portable.Value | undefined, path: string): ClassRef;
11
+ export declare function coreRef(input: portable.Value | undefined, path: string): CoreRef;
12
+ export declare function definitionName(input: string, path: string): void;
13
+ export declare function domainOrigin(input: portable.Value | undefined, path: string): Key.Origin;
@@ -0,0 +1,38 @@
1
+ import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
2
+ import { exact, invalid, record } from './wire.js';
3
+ /** One `{ origin, kind, name }` reference with a canonical origin and an unchecked kind and name. */
4
+ export function absoluteRef(input, path) {
5
+ const value = record(input, path);
6
+ exact(value, ['kind', 'name', 'origin'], path);
7
+ const origin = domainOrigin(value.origin, `${path}/origin`);
8
+ if (typeof value.kind !== 'string')
9
+ invalid(`${path}/kind`, 'Expected a reference kind');
10
+ if (typeof value.name !== 'string')
11
+ invalid(`${path}/name`, 'Expected a reference name');
12
+ return { origin, kind: value.kind, name: value.name };
13
+ }
14
+ export function classRef(input, path) {
15
+ const value = absoluteRef(input, path);
16
+ if (value.kind !== 'class')
17
+ invalid(`${path}/kind`, 'Expected class');
18
+ definitionName(value.name, `${path}/name`);
19
+ return value;
20
+ }
21
+ export function coreRef(input, path) {
22
+ const value = absoluteRef(input, path);
23
+ if (value.kind !== 'core')
24
+ invalid(`${path}/kind`, 'Expected core');
25
+ if (!patterns.coreSlug.test(value.name))
26
+ invalid(`${path}/name`, 'Expected a Core slug');
27
+ return value;
28
+ }
29
+ export function definitionName(input, path) {
30
+ if (!patterns.memberName.test(input))
31
+ invalid(path, 'Expected a Definition member name');
32
+ }
33
+ export function domainOrigin(input, path) {
34
+ if (typeof input !== 'string' || !patterns.origin.test(input)) {
35
+ invalid(path, 'Expected a canonical Domain origin');
36
+ }
37
+ return input;
38
+ }
@@ -0,0 +1,6 @@
1
+ import type * as portable from '@astrale-os/kernel-dsl/value';
2
+ import type { Term } from '../language/index.js';
3
+ /** Admit one term; `locals` and `subjectBound` are the lexical scope it may reference. */
4
+ export declare function term(input: portable.Value | undefined, path: string, locals: ReadonlySet<number>, subjectBound: boolean): Term;
5
+ /** A local id or repeat bound: a non-negative safe integer. */
6
+ export declare function localId(input: portable.Value | undefined, path: string): number;
@@ -0,0 +1,60 @@
1
+ import { isNodeId } from '../../../graph/node/index.js';
2
+ import { absoluteRef, classRef, coreRef, definitionName, domainOrigin } from './references.js';
3
+ import { exact, invalid, record } from './wire.js';
4
+ /** Admit one term; `locals` and `subjectBound` are the lexical scope it may reference. */
5
+ export function term(input, path, locals, subjectBound) {
6
+ const value = record(input, path);
7
+ switch (value.kind) {
8
+ case 'input':
9
+ exact(value, ['input', 'kind'], path);
10
+ if (value.input !== 'object' && value.input !== 'source' && value.input !== 'target') {
11
+ invalid(`${path}/input`, 'Expected object, source, or target');
12
+ }
13
+ return { kind: 'input', input: value.input };
14
+ case 'node':
15
+ exact(value, ['id', 'kind'], path);
16
+ if (!isNodeId(value.id))
17
+ invalid(`${path}/id`, 'Expected a canonical NodeId');
18
+ return { kind: 'node', id: value.id };
19
+ case 'class':
20
+ exact(value, ['kind', 'ref'], path);
21
+ return { kind: 'class', ref: classRef(value.ref, `${path}/ref`) };
22
+ case 'domain':
23
+ exact(value, ['kind', 'origin'], path);
24
+ return { kind: 'domain', origin: domainOrigin(value.origin, `${path}/origin`) };
25
+ case 'ref': {
26
+ exact(value, ['kind', 'ref'], path);
27
+ const ref = absoluteRef(value.ref, `${path}/ref`);
28
+ if (ref.kind === 'core')
29
+ return { kind: 'ref', ref: coreRef(value.ref, `${path}/ref`) };
30
+ if (!['class', 'function', 'policy', 'view'].includes(ref.kind))
31
+ invalid(`${path}/ref/kind`, 'Expected a projected Schema member');
32
+ definitionName(ref.name, `${path}/ref/name`);
33
+ return { kind: 'ref', ref: ref };
34
+ }
35
+ case 'core':
36
+ exact(value, ['kind', 'ref'], path);
37
+ return { kind: 'core', ref: coreRef(value.ref, `${path}/ref`) };
38
+ case 'local': {
39
+ exact(value, ['id', 'kind'], path);
40
+ const id = localId(value.id, `${path}/id`);
41
+ if (!locals.has(id))
42
+ invalid(`${path}/id`, `Local ${id} is outside its lexical scope`);
43
+ return { kind: 'local', id };
44
+ }
45
+ case 'subject':
46
+ exact(value, ['kind'], path);
47
+ if (!subjectBound)
48
+ invalid(path, 'Binder subject is outside its lexical scope');
49
+ return { kind: 'subject' };
50
+ default:
51
+ invalid(`${path}/kind`, 'Unsupported authority term');
52
+ }
53
+ }
54
+ /** A local id or repeat bound: a non-negative safe integer. */
55
+ export function localId(input, path) {
56
+ if (!Number.isSafeInteger(input) || input < 0) {
57
+ invalid(path, 'Expected a non-negative safe integer');
58
+ }
59
+ return input;
60
+ }
@@ -0,0 +1,8 @@
1
+ import type * as portable from '@astrale-os/kernel-dsl/value';
2
+ /** Fail admission at one JSON-pointer path with the stable Authority predicate code. */
3
+ export declare function invalid(path: string, message: string): never;
4
+ export declare function record(input: portable.Value | undefined, path: string): portable.Object;
5
+ export declare function array(input: portable.Value | undefined, path: string, minimum: number, maximum: number): readonly portable.Value[];
6
+ export declare function required(input: portable.Value | undefined, path: string): portable.Value;
7
+ /** Reject a record whose own keys differ from `expected`, in any order. */
8
+ export declare function exact(value: portable.Object, expected: readonly string[], path: string): void;
@@ -0,0 +1,33 @@
1
+ import { AuthValueError } from '../../error.js';
2
+ /** Fail admission at one JSON-pointer path with the stable Authority predicate code. */
3
+ export function invalid(path, message) {
4
+ throw new AuthValueError('AUTHORITY_PREDICATE_INVALID', message, path);
5
+ }
6
+ export function record(input, path) {
7
+ if (input === undefined || input === null || Array.isArray(input) || typeof input !== 'object') {
8
+ invalid(path, 'Expected an object');
9
+ }
10
+ return input;
11
+ }
12
+ export function array(input, path, minimum, maximum) {
13
+ if (!Array.isArray(input) || input.length < minimum || input.length > maximum) {
14
+ invalid(path, `Expected ${minimum}-${maximum} entries`);
15
+ }
16
+ return input;
17
+ }
18
+ export function required(input, path) {
19
+ if (input === undefined)
20
+ invalid(path, 'Expected a value');
21
+ return input;
22
+ }
23
+ /** Reject a record whose own keys differ from `expected`, in any order. */
24
+ export function exact(value, expected, path) {
25
+ const actual = Object.keys(value).sort(compare);
26
+ const wanted = [...expected].sort(compare);
27
+ if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
28
+ invalid(path, `Expected exactly ${expected.join(', ')}`);
29
+ }
30
+ }
31
+ function compare(left, right) {
32
+ return left < right ? -1 : left > right ? 1 : 0;
33
+ }
@@ -4,7 +4,7 @@ export type { Delta, DeltaConflict, DeltaResult } from './delta/index.js';
4
4
  export type { MergeConflict, MergeResult } from './merge/index.js';
5
5
  export { GraphData, GraphDataDecodeError, GraphSpec, GraphSpecDecodeError } from './model/index.js';
6
6
  export type { AnonymousNodeSpec, GraphDataJson, GraphSpecEdge, GraphSpecEndpoint, GraphSpecJson, GraphSpecNode, } from './model/index.js';
7
- export { LocalBinding, isLocalBinding } from './model/index.js';
7
+ export { LocalAlias, isLocalAlias } from './model/index.js';
8
8
  export type { GraphAdmissionContext, GraphClassInfo, GraphDiagnostic } from './admission/index.js';
9
9
  export { GraphAdmissionError } from './admission/index.js';
10
10
  export type { GraphEdges, GraphNodes } from './indexes/index.js';
@@ -1,5 +1,5 @@
1
1
  /** Stable aggregate facade over Graph model, admission, indexes, delta, and merge. */
2
2
  export { Graph } from './graph.js';
3
3
  export { GraphData, GraphDataDecodeError, GraphSpec, GraphSpecDecodeError } from './model/index.js';
4
- export { LocalBinding, isLocalBinding } from './model/index.js';
4
+ export { LocalAlias, isLocalAlias } from './model/index.js';
5
5
  export { GraphAdmissionError } from './admission/index.js';
@@ -5,7 +5,7 @@ import { node as constructNode, NodeId } from '../../node/index.js';
5
5
  import { NodePath } from '../../path/index.js';
6
6
  import { normalizeProperties } from '../../properties/index.js';
7
7
  import { decodeWire } from '../../wire.js';
8
- import { isLocalBinding, LocalBinding } from './model.js';
8
+ import { isLocalAlias, LocalAlias } from './model.js';
9
9
  import { graphSpecSchema } from './wire.js';
10
10
  export class GraphDataDecodeError extends TypeError {
11
11
  path;
@@ -124,10 +124,10 @@ function decodeEndpoint(input, path) {
124
124
  return Object.freeze({ created: binding(input.created, `${path}/created`) });
125
125
  }
126
126
  function binding(input, path) {
127
- if (!isLocalBinding(input)) {
127
+ if (!isLocalAlias(input)) {
128
128
  specInvalid(path, 'Expected a local binding name of at most 64 characters');
129
129
  }
130
- return LocalBinding(input);
130
+ return LocalAlias(input);
131
131
  }
132
132
  function validateGraphSpec(nodes, edges) {
133
133
  const ids = new Set();
@@ -13,5 +13,5 @@ export declare const GraphSpec: {
13
13
  encode(spec: GraphSpecValue): GraphSpecJson;
14
14
  };
15
15
  export type { AnonymousNodeSpec, GraphSpecEdge, GraphSpecEndpoint, GraphSpecJson, GraphSpecNode, } from './model.js';
16
- export { LocalBinding, isLocalBinding } from './model.js';
16
+ export { LocalAlias, isLocalAlias } from './model.js';
17
17
  export { GraphSpecDecodeError } from './codec.js';
@@ -2,5 +2,5 @@ import { decodeGraphData, decodeGraphSpec, encodeGraphData, encodeGraphSpec } fr
2
2
  export const GraphData = Object.freeze({ decode: decodeGraphData, encode: encodeGraphData });
3
3
  export { GraphDataDecodeError } from './codec.js';
4
4
  export const GraphSpec = Object.freeze({ decode: decodeGraphSpec, encode: encodeGraphSpec });
5
- export { LocalBinding, isLocalBinding } from './model.js';
5
+ export { LocalAlias, isLocalAlias } from './model.js';
6
6
  export { GraphSpecDecodeError } from './codec.js';
@@ -2,21 +2,21 @@ import type { EdgeSpec } from '../../edge/index.js';
2
2
  import type { Node, NodeId, NodeSpec } from '../../node/index.js';
3
3
  import type { NodePath } from '../../path/index.js';
4
4
  import type { Properties } from '../../properties/index.js';
5
- declare const LOCAL_BINDING_BRAND: unique symbol;
5
+ declare const LOCAL_ALIAS_BRAND: unique symbol;
6
6
  /** A graph-local lexical name. It is never Node identity. */
7
- export type LocalBinding = string & {
8
- readonly [LOCAL_BINDING_BRAND]: true;
7
+ export type LocalAlias = string & {
8
+ readonly [LOCAL_ALIAS_BRAND]: true;
9
9
  };
10
- export declare function LocalBinding(input: string): LocalBinding;
11
- export declare function isLocalBinding(input: unknown): input is LocalBinding;
10
+ export declare function LocalAlias(input: string): LocalAlias;
11
+ export declare function isLocalAlias(input: unknown): input is LocalAlias;
12
12
  export interface AnonymousNodeSpec extends NodeSpec {
13
- readonly as: LocalBinding;
13
+ readonly as: LocalAlias;
14
14
  }
15
15
  export type GraphSpecNode = Node | AnonymousNodeSpec;
16
16
  export type GraphSpecEndpoint = NodeId | {
17
17
  readonly path: NodePath;
18
18
  } | {
19
- readonly created: LocalBinding;
19
+ readonly created: LocalAlias;
20
20
  };
21
21
  export type GraphSpecEdge = EdgeSpec<GraphSpecEndpoint>;
22
22
  /** Detached structural graph values, including graph-local anonymous Nodes. */
@@ -1,10 +1,10 @@
1
- const LOCAL_BINDING_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,63}$/u;
2
- export function LocalBinding(input) {
3
- if (!isLocalBinding(input)) {
4
- throw new TypeError(`Invalid local binding ${JSON.stringify(input)}.`);
1
+ const LOCAL_ALIAS_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,63}$/u;
2
+ export function LocalAlias(input) {
3
+ if (!isLocalAlias(input)) {
4
+ throw new TypeError(`Invalid local alias ${JSON.stringify(input)}.`);
5
5
  }
6
6
  return input;
7
7
  }
8
- export function isLocalBinding(input) {
9
- return typeof input === 'string' && LOCAL_BINDING_PATTERN.test(input);
8
+ export function isLocalAlias(input) {
9
+ return typeof input === 'string' && LOCAL_ALIAS_PATTERN.test(input);
10
10
  }
@@ -5,11 +5,6 @@ export declare const graphNodeSchema: import("zod").ZodObject<{
5
5
  class: import("zod").ZodString;
6
6
  props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
7
7
  }, import("zod/v4/core").$strict>;
8
- export declare const anonymousGraphNodeSchema: import("zod").ZodObject<{
9
- as: import("zod").ZodString;
10
- class: import("zod").ZodString;
11
- props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
12
- }, import("zod/v4/core").$strict>;
13
8
  export declare const edgeKeySchema: import("zod").ZodObject<{
14
9
  source: import("zod").ZodString;
15
10
  target: import("zod").ZodString;
@@ -22,21 +17,6 @@ export declare const graphEdgeSchema: import("zod").ZodObject<{
22
17
  slug: import("zod").ZodOptional<ZodType<EdgeSlug, unknown, import("zod/v4/core").$ZodTypeInternals<EdgeSlug, unknown>>>;
23
18
  props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
24
19
  }, import("zod/v4/core").$strict>;
25
- export declare const graphSpecEdgeSchema: import("zod").ZodObject<{
26
- source: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
27
- path: import("zod").ZodString;
28
- }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
29
- created: import("zod").ZodString;
30
- }, import("zod/v4/core").$strict>]>;
31
- target: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
32
- path: import("zod").ZodString;
33
- }, import("zod/v4/core").$strict>, import("zod").ZodObject<{
34
- created: import("zod").ZodString;
35
- }, import("zod/v4/core").$strict>]>;
36
- class: import("zod").ZodString;
37
- slug: import("zod").ZodOptional<ZodType<EdgeSlug, unknown, import("zod/v4/core").$ZodTypeInternals<EdgeSlug, unknown>>>;
38
- props: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
39
- }, import("zod/v4/core").$strict>;
40
20
  export declare const graphSpecSchema: import("zod").ZodObject<{
41
21
  nodes: import("zod").ZodArray<import("zod").ZodUnion<readonly [import("zod").ZodObject<{
42
22
  id: import("zod").ZodString;
@@ -9,7 +9,7 @@ const edgeSlug = string()
9
9
  .max(edgeSlugSchema.maxLength)
10
10
  .check(fullMatch(edgeSlugSchema.fullMatch));
11
11
  export const graphNodeSchema = strictObject({ id: text, class: text, props });
12
- export const anonymousGraphNodeSchema = strictObject({ as: binding, class: text, props });
12
+ const anonymousGraphNodeSchema = strictObject({ as: binding, class: text, props });
13
13
  export const edgeKeySchema = strictObject({ source: text, target: text, class: text });
14
14
  export const graphEdgeSchema = edgeKeySchema.extend({ slug: edgeSlug.optional(), props });
15
15
  const graphSpecEndpointSchema = union([
@@ -17,7 +17,7 @@ const graphSpecEndpointSchema = union([
17
17
  strictObject({ path: text }),
18
18
  strictObject({ created: binding }),
19
19
  ]);
20
- export const graphSpecEdgeSchema = strictObject({
20
+ const graphSpecEdgeSchema = strictObject({
21
21
  source: graphSpecEndpointSchema,
22
22
  target: graphSpecEndpointSchema,
23
23
  class: text,
@@ -6,7 +6,7 @@ import type { DeltaInput } from '../../properties/index.js';
6
6
  import type { QueryEdgeAST, QueryNodeAST } from '../../query/index.js';
7
7
  import type { MutationAST } from '../language/index.js';
8
8
  import type { MutationInputEdgeSelector, MutationInputEndpoint, MutationPropertyConditionsInput, MutationPropsInput } from './model.js';
9
- import { LocalBinding } from '../../graph/index.js';
9
+ import { LocalAlias } from '../../graph/index.js';
10
10
  export type MutationQueryPreconditionInput = {
11
11
  readonly query: QueryNodeAST;
12
12
  readonly equals: {
@@ -39,7 +39,7 @@ export interface MutationBuilder {
39
39
  readonly class: ClassKey;
40
40
  readonly props?: MutationPropsInput;
41
41
  }): {
42
- readonly created: LocalBinding;
42
+ readonly created: LocalAlias;
43
43
  };
44
44
  updateNode(input: {
45
45
  readonly node: NodeTarget;
@@ -1,4 +1,4 @@
1
- import { LocalBinding } from '../../graph/index.js';
1
+ import { LocalAlias } from '../../graph/index.js';
2
2
  import { createMutationAST } from './create.js';
3
3
  /** Run one synchronous author and admit its complete operation set. */
4
4
  export function buildMutationAST(author) {
@@ -38,7 +38,7 @@ export function buildMutationAST(author) {
38
38
  expect: expectation,
39
39
  createNode(input) {
40
40
  requireOpen();
41
- const created = LocalBinding(input.as);
41
+ const created = LocalAlias(input.as);
42
42
  operations.push({
43
43
  op: 'node.create',
44
44
  as: created,
@@ -2,7 +2,7 @@ import type { GraphSpec } from '../graph/index.js';
2
2
  import type { MutationBuilder, MutationInput } from './authoring/index.js';
3
3
  import type { MutationAST as MutationASTValue, MutationStructuralLimits } from './language/index.js';
4
4
  export type { MutationBuilder, MutationInput, MutationInputEdgeSelector, MutationInputEndpoint, MutationInputOperation, MutationInputPrecondition, MutationPropertyConditionsInput, MutationPropsInput, MutationQueryPreconditionInput, } from './authoring/index.js';
5
- export type { EdgeCreateOperation, EdgeDeleteOperation, EdgeUpdateOperation, LocalBinding, MutationEdgeSelector, MutationEndpoint, MutationOperation, MutationPrecondition, MutationPropertyConditions, MutationProps, MutationQueryPrecondition, MutationStructuralLimits, NodeCreateOperation, NodeDeleteOperation, NodeUpdateOperation, QueryExpectedSelection, } from './language/index.js';
5
+ export type { EdgeCreateOperation, EdgeDeleteOperation, EdgeUpdateOperation, LocalAlias, MutationEdgeSelector, MutationEndpoint, MutationOperation, MutationPrecondition, MutationPropertyConditions, MutationProps, MutationQueryPrecondition, MutationStructuralLimits, NodeCreateOperation, NodeDeleteOperation, NodeUpdateOperation, QueryExpectedSelection, } from './language/index.js';
6
6
  export { MutationASTDecodeError } from './language/index.js';
7
7
  export type MutationAST = MutationASTValue;
8
8
  export declare const MutationAST: {
@@ -3,7 +3,7 @@ import { ClassKey } from '@astrale-os/kernel-dsl/v1/addressing';
3
3
  import * as portable from '@astrale-os/kernel-dsl/value';
4
4
  import { EdgeSlug, encodeEdgeKey } from '../../edge/index.js';
5
5
  import { compareEdgeKeys } from '../../edge/index.js';
6
- import { isLocalBinding, LocalBinding as LocalBindingValue } from '../../graph/index.js';
6
+ import { isLocalAlias, LocalAlias as LocalAliasValue } from '../../graph/index.js';
7
7
  import { NodeId } from '../../node/index.js';
8
8
  import { compareNodeIds } from '../../node/index.js';
9
9
  import { NodePath } from '../../path/index.js';
@@ -341,9 +341,9 @@ function compare(left, right) {
341
341
  return left < right ? -1 : left > right ? 1 : 0;
342
342
  }
343
343
  function localBinding(value, path) {
344
- if (!isLocalBinding(value))
344
+ if (!isLocalAlias(value))
345
345
  invalid(path, 'Expected a local binding name of at most 64 characters');
346
- return LocalBindingValue(value);
346
+ return LocalAliasValue(value);
347
347
  }
348
348
  function propertyKey(value, path) {
349
349
  if (typeof value !== 'string' || !PropertyKey.is(value)) {
@@ -1,7 +1,7 @@
1
1
  import type { PropertyKey } from '@astrale-os/kernel-dsl/v1';
2
2
  import type { ClassKey } from '@astrale-os/kernel-dsl/v1/addressing';
3
3
  import type { EdgeSlug } from '../../edge/index.js';
4
- import type { LocalBinding } from '../../graph/index.js';
4
+ import type { LocalAlias } from '../../graph/index.js';
5
5
  import type { NodePath } from '../../path/index.js';
6
6
  import type { Delta as PropertiesDelta, Properties } from '../../properties/index.js';
7
7
  import type { QueryEdgeAST, QueryNodeAST } from '../../query/index.js';
@@ -14,10 +14,10 @@ export type MutationStructuralLimits = Readonly<{
14
14
  queryExpectedIdentities: 4096;
15
15
  }>;
16
16
  export declare const MUTATION_AST_LIMITS: MutationStructuralLimits;
17
- export type { LocalBinding } from '../../graph/index.js';
17
+ export type { LocalAlias } from '../../graph/index.js';
18
18
  export type MutationProps = Properties;
19
19
  export type MutationEndpoint = NodePath | {
20
- readonly created: LocalBinding;
20
+ readonly created: LocalAlias;
21
21
  };
22
22
  export interface MutationEdgeSelector {
23
23
  readonly source: NodePath;
@@ -55,7 +55,7 @@ export type MutationPrecondition = {
55
55
  } | MutationQueryPrecondition;
56
56
  export interface NodeCreateOperation {
57
57
  readonly op: 'node.create';
58
- readonly as: LocalBinding;
58
+ readonly as: LocalAlias;
59
59
  readonly class: ClassKey;
60
60
  readonly props: MutationProps;
61
61
  }