@astrale-os/kernel-dsl 1.0.0-beta.13 → 1.0.0-beta.15

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 (103) hide show
  1. package/dist/v1/addressing/domain-dependency.d.ts +0 -6
  2. package/dist/v1/addressing/domain-dependency.js +1 -6
  3. package/dist/v1/addressing/key.js +2 -1
  4. package/dist/v1/addressing/patterns.d.ts +1 -0
  5. package/dist/v1/addressing/patterns.js +2 -1
  6. package/dist/v1/builder/class/authoring.d.ts +43 -0
  7. package/dist/v1/builder/class/property.d.ts +3 -9
  8. package/dist/v1/builder/class/property.js +1 -0
  9. package/dist/v1/builder/index.d.ts +1 -1
  10. package/dist/v1/builder/lowering/class.js +5 -1
  11. package/dist/v1/builder/lowering/policy.js +2 -0
  12. package/dist/v1/builder/lowering/schema/context.d.ts +5 -0
  13. package/dist/v1/builder/lowering/schema/context.js +22 -0
  14. package/dist/v1/builder/policy/authoring.d.ts +84 -4
  15. package/dist/v1/builder/policy/authoring.js +44 -14
  16. package/dist/v1/builder/schema/projection/class.d.ts +116 -14
  17. package/dist/v1/bundle/codec.js +9 -9
  18. package/dist/v1/bundle/diagnostic.d.ts +2 -0
  19. package/dist/v1/bundle/diagnostic.js +6 -0
  20. package/dist/v1/bundle/structure.js +2 -2
  21. package/dist/v1/compiled/admission/accept.js +3 -3
  22. package/dist/v1/compiled/admission/closure.js +2 -2
  23. package/dist/v1/compiled/admission/semantics/core.js +3 -7
  24. package/dist/v1/compiled/admission/semantics/policy/parity.js +3 -10
  25. package/dist/v1/domain/validation/create.d.ts +4 -1
  26. package/dist/v1/domain/validation/create.js +21 -34
  27. package/dist/v1/language/.spec/schemas/value-schema.schema.json +22 -0
  28. package/dist/v1/language/class/model/class.d.ts +4 -4
  29. package/dist/v1/language/class/model/edge.d.ts +2 -2
  30. package/dist/v1/language/class/model/property.d.ts +16 -7
  31. package/dist/v1/language/core/facts.d.ts +17 -4
  32. package/dist/v1/language/core/facts.js +26 -5
  33. package/dist/v1/language/definition/metadata.d.ts +5 -0
  34. package/dist/v1/language/definition/metadata.js +7 -0
  35. package/dist/v1/language/limits.d.ts +64 -0
  36. package/dist/v1/language/limits.js +60 -0
  37. package/dist/v1/language/policy/analysis/budgets.d.ts +39 -18
  38. package/dist/v1/language/policy/analysis/budgets.js +30 -20
  39. package/dist/v1/language/policy/analysis/checks.js +3 -2
  40. package/dist/v1/language/policy/analysis/typing.js +4 -3
  41. package/dist/v1/language/policy/model/policy.d.ts +5 -5
  42. package/dist/v1/language/policy/normalization/normalize.js +17 -16
  43. package/dist/v1/language/validation/diagnostic.d.ts +1 -1
  44. package/dist/v1/language/validation/rule.d.ts +29 -0
  45. package/dist/v1/language/validation/rule.js +120 -0
  46. package/dist/v1/language/value/profile/meta-schema.compiled.js +4 -1
  47. package/dist/v1/language/value/profile/rules.js +13 -37
  48. package/dist/v1/language/value/profile/vocabulary.d.ts +35 -2
  49. package/dist/v1/language/value/profile/vocabulary.js +52 -5
  50. package/dist/v1/language/value/reference/registry.index.js +2 -1
  51. package/dist/v1/language/value/regexp/ast.js +6 -7
  52. package/dist/v1/language/value/regexp/compile.d.ts +5 -11
  53. package/dist/v1/language/value/regexp/compile.js +14 -12
  54. package/dist/v1/language/value/regexp/syntax.js +3 -2
  55. package/dist/v1/language/value/syntax/keywords.d.ts +3 -3
  56. package/dist/v1/language/value/syntax/keywords.js +4 -20
  57. package/dist/v1/language/value/syntax/node-path/validate.js +2 -3
  58. package/dist/v1/schema/.spec/schemas/domain-schema.schema.json +2336 -0
  59. package/dist/v1/schema/admission/accept.js +3 -14
  60. package/dist/v1/schema/admission/callable.d.ts +21 -0
  61. package/dist/v1/schema/admission/callable.js +96 -0
  62. package/dist/v1/schema/analysis/class.js +33 -15
  63. package/dist/v1/schema/compatibility/api.d.ts +1 -1
  64. package/dist/v1/schema/compatibility/coordinate.js +3 -3
  65. package/dist/v1/schema/compatibility/model.d.ts +5 -0
  66. package/dist/v1/schema/diagnostic.d.ts +17 -3
  67. package/dist/v1/schema/diagnostic.js +11 -0
  68. package/dist/v1/schema/index.d.ts +10 -1
  69. package/dist/v1/schema/index.js +4 -0
  70. package/dist/v1/schema/model/schema.d.ts +19 -1
  71. package/dist/v1/schema/normalization/domain.d.ts +2 -0
  72. package/dist/v1/schema/normalization/domain.js +2 -1
  73. package/dist/v1/schema/resolution/closure.js +2 -1
  74. package/dist/v1/schema/resolution/context.js +10 -8
  75. package/dist/v1/schema/resolution/domain.d.ts +5 -0
  76. package/dist/v1/schema/resolution/domain.js +1 -1
  77. package/dist/v1/schema/rule.d.ts +32 -0
  78. package/dist/v1/schema/rule.js +428 -0
  79. package/dist/v1/schema/validation/callable.d.ts +35 -2
  80. package/dist/v1/schema/validation/callable.js +51 -8
  81. package/dist/v1/schema/validation/class.js +36 -44
  82. package/dist/v1/schema/validation/core.js +19 -13
  83. package/dist/v1/schema/validation/domain.js +2 -2
  84. package/dist/v1/schema/validation/domain.json-schema.d.ts +15 -0
  85. package/dist/v1/schema/validation/domain.json-schema.js +183 -0
  86. package/dist/v1/schema/validation/domain.route.d.ts +6 -1
  87. package/dist/v1/schema/validation/domain.route.js +18 -0
  88. package/dist/v1/schema/validation/domain.structure.d.ts +4020 -0
  89. package/dist/v1/schema/validation/domain.structure.js +359 -153
  90. package/dist/v1/schema/validation/json.json-schema.d.ts +24 -0
  91. package/dist/v1/schema/validation/json.json-schema.js +36 -0
  92. package/dist/v1/schema/validation/policy/budgets.d.ts +33 -2
  93. package/dist/v1/schema/validation/policy/budgets.js +89 -16
  94. package/dist/v1/schema/validation/policy/references.js +6 -21
  95. package/dist/v1/schema/validation/policy/uses.d.ts +29 -0
  96. package/dist/v1/schema/validation/policy/uses.js +28 -51
  97. package/dist/v1/schema/validation/value-api.d.ts +12 -1
  98. package/dist/v1/schema/validation/value-api.js +10 -1
  99. package/dist/v1/schema/validation/value.d.ts +3 -0
  100. package/dist/v1/schema/validation/value.js +6 -12
  101. package/dist/v1/schema/validation/value.json-schema.d.ts +51 -0
  102. package/dist/v1/schema/validation/value.json-schema.js +126 -0
  103. package/package.json +3 -1
@@ -1,13 +1,119 @@
1
1
  import type * as language from '../../../language/index.js';
2
+ import type { DomainSchema, DomainOfSchema } from '../../../schema/model/schema.js';
2
3
  import type { NodeClass, DirectedEdgeClass, UndirectedEdgeClass, Class, ProjectionOfClass } from '../../class/handle.js';
3
4
  import type { ClassReferenceProjection } from '../../class/projection.js';
4
5
  import type { DomainSchemaInput } from '../input.js';
5
6
  import type { OwnInstanceMethodProjectionsOf, OwnStaticMethodProjectionsOf } from './callable.js';
6
- import type { AbstractOf, ConstraintsOf, ResolveLazy, LocalNameOfReference, ClassesInputOf, LocalNameOf } from './identity.js';
7
+ import type { AbstractOf, ConstraintsOf, ResolveLazy, LocalNameOfReference, ClassesInputOf, LocalNameOf, RecordField } from './identity.js';
7
8
  import type { ClassProjection } from './model.js';
8
9
  import type { EffectivePropertyProjectionsOf, OwnPropertyProjectionsOf } from './property.js';
9
10
  import type { ClassProjectionOfResolved, ExactClass } from './resolved-class.js';
10
- type ProjectedClassDefinition<Origin extends string, Name extends string, Value> = Value extends NodeClass<infer Config> ? language.NodeClassDefinition & {
11
+ /**
12
+ * A Class an endpoint accepts as the Schema names it: an authored Class by the ref of every Class
13
+ * that bears its mark, else the ref it carries.
14
+ */
15
+ type AcceptedRefOf<Origin extends string, Reference, Root extends DomainSchemaInput> = Reference extends unknown ? ResolveLazy<Reference> extends infer Resolved ? Resolved extends {
16
+ readonly kind: 'node';
17
+ } ? MarkedClassRefOf<Origin, Resolved, Root> : Resolved extends {
18
+ readonly origin: infer RefOrigin extends string;
19
+ readonly kind: 'class';
20
+ readonly name: infer RefName extends string;
21
+ } ? language.ClassRef<RefName> & {
22
+ readonly origin: RefOrigin;
23
+ } : language.ClassRef : never : never;
24
+ /** The mark the class authoring module gives an accepted Node Class (`AcceptedClassMark`). */
25
+ type ClassMarkOf<Value> = Value extends NodeClass<infer Config> ? {
26
+ readonly kind: 'node';
27
+ readonly abstract: Config extends {
28
+ readonly abstract: infer Abstract;
29
+ } ? Abstract : never;
30
+ readonly depth: Config extends {
31
+ readonly depth: infer Depth;
32
+ } ? Depth : never;
33
+ readonly properties: Config extends {
34
+ readonly effectiveProperties: infer Properties;
35
+ } ? Properties extends {
36
+ readonly name: infer Name;
37
+ } ? Name : never : never;
38
+ readonly methods: Config extends {
39
+ readonly effectiveInstanceMethods: infer Instance;
40
+ readonly effectiveStaticMethods: infer Static;
41
+ } ? Instance | Static extends infer Method ? Method extends {
42
+ readonly name: infer Name;
43
+ } ? Name : never : never : never;
44
+ } : never;
45
+ type Same<Left, Right> = [Left] extends [Right] ? ([Right] extends [Left] ? true : false) : false;
46
+ /** Every local Class name whose mark is the accepted mark. */
47
+ type LocalNameOfMark<Root extends DomainSchemaInput, Mark> = {
48
+ [Name in keyof ClassesInputOf<Root>]: Same<ClassMarkOf<ClassesInputOf<Root>[Name]>, Mark> extends true ? Name : never;
49
+ }[keyof ClassesInputOf<Root>];
50
+ /**
51
+ * Every Class an authored handle bearing the mark may be: the builder resolves the handle of a
52
+ * Class of the Schema or of a direct dependency, so either may bear it. The ref stays broad when no
53
+ * Class bears it or a dependency's Classes are not named in the types.
54
+ */
55
+ type MarkedClassRefOf<Origin extends string, Mark, Root extends DomainSchemaInput> = LocalClassRefOf<Origin, LocalNameOfMark<Root, Mark>> | DependencyClassRefOfMark<Root, Mark> extends infer Refs ? [Refs] extends [never] ? language.ClassRef : Refs : never;
56
+ type LocalClassRefOf<Origin extends string, Name> = Name extends string ? language.ClassRef<Name> & {
57
+ readonly origin: Origin;
58
+ } : never;
59
+ /** The names of the members of a resolved collection. */
60
+ type MemberNamesOf<Collection> = Collection extends {
61
+ readonly byKey: infer ByKey;
62
+ } ? ByKey[keyof ByKey] extends infer Member ? Member extends {
63
+ readonly name: infer Name;
64
+ } ? Name : never : never : never;
65
+ /**
66
+ * A dependency Class may bear a mark when it agrees with it in abstractness and the names of its
67
+ * effective Properties, and its own Methods are among the mark's. Its resolved type keeps neither
68
+ * its depth nor the abstract Methods it inherits, so neither is compared.
69
+ */
70
+ type ResolvedBearsMark<Value, Mark> = Value extends {
71
+ readonly kind: 'node';
72
+ readonly definition: {
73
+ readonly abstract: infer Abstract;
74
+ };
75
+ readonly properties: infer Properties;
76
+ readonly methods: infer Methods;
77
+ readonly static: {
78
+ readonly methods: infer StaticMethods;
79
+ };
80
+ } ? Mark extends {
81
+ readonly abstract: infer MarkAbstract;
82
+ readonly properties: infer MarkProperties;
83
+ readonly methods: infer MarkMethods;
84
+ } ? Same<{
85
+ readonly abstract: Abstract;
86
+ readonly properties: MemberNamesOf<Properties>;
87
+ }, {
88
+ readonly abstract: MarkAbstract;
89
+ readonly properties: MarkProperties;
90
+ }> extends true ? [MemberNamesOf<Methods> | MemberNamesOf<StaticMethods>] extends [MarkMethods] ? true : false : false : false : false;
91
+ /** Every Node Class of a direct dependency that may bear the mark. */
92
+ type DependencyClassRefOfMark<Root extends DomainSchemaInput, Mark> = {
93
+ [Alias in keyof RecordField<Root, 'dependencies'>]: RecordField<Root, 'dependencies'>[Alias] extends infer Schema extends DomainSchema ? DomainOfSchema<Schema>['classes'] extends infer Classes ? string extends keyof Classes ? language.ClassRef : {
94
+ [Name in keyof Classes]: ResolvedBearsMark<Classes[Name], Mark> extends true ? Classes[Name] extends {
95
+ readonly ref: {
96
+ readonly origin: infer RefOrigin extends string;
97
+ readonly name: infer RefName extends string;
98
+ };
99
+ } ? language.ClassRef<RefName> & {
100
+ readonly origin: RefOrigin;
101
+ } : never : never;
102
+ }[keyof Classes] : never : never;
103
+ }[keyof RecordField<Root, 'dependencies'>];
104
+ /** Every Class an endpoint accepts, in any order: the runtime list is canonically sorted. */
105
+ type AcceptedRefsOf<Origin extends string, Accepts, Root extends DomainSchemaInput> = Accepts extends readonly (infer Reference)[] ? readonly [AcceptedRefOf<Origin, Reference, Root>, ...AcceptedRefOf<Origin, Reference, Root>[]] : readonly [language.ClassRef, ...language.ClassRef[]];
106
+ /** One endpoint as the Schema stores it: its role and its exact accepted Classes. */
107
+ type ProjectedEndpoint<Origin extends string, Endpoint, Root extends DomainSchemaInput> = Endpoint extends {
108
+ readonly as: infer Role;
109
+ readonly accepts: infer Accepts;
110
+ } ? {
111
+ readonly role: Role;
112
+ readonly accepts: AcceptedRefsOf<Origin, Accepts, Root>;
113
+ readonly onDelete?: language.EdgeLifetime;
114
+ } : never;
115
+ type EdgeDefinitionFields = 'ref' | 'kind' | 'abstract' | 'orientation' | 'endpoints' | 'constraints';
116
+ type ProjectedClassDefinition<Origin extends string, Name extends string, Value, Root extends DomainSchemaInput> = Value extends NodeClass<infer Config> ? language.NodeClassDefinition & {
11
117
  readonly ref: language.ClassRef<Name> & {
12
118
  readonly origin: Origin;
13
119
  };
@@ -22,7 +128,7 @@ type ProjectedClassDefinition<Origin extends string, Name extends string, Value>
22
128
  readonly as: string;
23
129
  readonly incoming: language.EdgeCount;
24
130
  };
25
- } ? language.EdgeClassDefinition & {
131
+ } ? Omit<language.DirectedEdgeDefinition, EdgeDefinitionFields> & {
26
132
  readonly ref: language.ClassRef<Name> & {
27
133
  readonly origin: Origin;
28
134
  };
@@ -30,12 +136,10 @@ type ProjectedClassDefinition<Origin extends string, Name extends string, Value>
30
136
  readonly abstract: AbstractOf<Input>;
31
137
  readonly orientation: 'directed';
32
138
  readonly endpoints: {
33
- readonly source: language.DirectedSourceEndpoint & {
34
- readonly role: Source['as'];
139
+ readonly source: ProjectedEndpoint<Origin, Source, Root> & {
35
140
  readonly outgoing: Source['outgoing'];
36
141
  };
37
- readonly target: language.DirectedTargetEndpoint & {
38
- readonly role: Target['as'];
142
+ readonly target: ProjectedEndpoint<Origin, Target, Root> & {
39
143
  readonly incoming: Target['incoming'];
40
144
  };
41
145
  };
@@ -51,7 +155,7 @@ type ProjectedClassDefinition<Origin extends string, Name extends string, Value>
51
155
  readonly incident: language.EdgeCount;
52
156
  }
53
157
  ];
54
- } ? language.EdgeClassDefinition & {
158
+ } ? Omit<language.UndirectedEdgeDefinition, EdgeDefinitionFields> & {
55
159
  readonly ref: language.ClassRef<Name> & {
56
160
  readonly origin: Origin;
57
161
  };
@@ -59,12 +163,10 @@ type ProjectedClassDefinition<Origin extends string, Name extends string, Value>
59
163
  readonly abstract: AbstractOf<Input>;
60
164
  readonly orientation: 'undirected';
61
165
  readonly endpoints: readonly [
62
- language.IncidentEndpoint & {
63
- readonly role: First['as'];
166
+ ProjectedEndpoint<Origin, First, Root> & {
64
167
  readonly incident: First['incident'];
65
168
  },
66
- language.IncidentEndpoint & {
67
- readonly role: Second['as'];
169
+ ProjectedEndpoint<Origin, Second, Root> & {
68
170
  readonly incident: Second['incident'];
69
171
  }
70
172
  ];
@@ -82,9 +184,9 @@ type ParentClassProjectionTuple<Origin extends string, Parents extends readonly
82
184
  type ShallowClassProjectionOfAuthoring<Origin extends string, Name extends string, Value, Root extends DomainSchemaInput> = ClassProjectionWithParents<Origin, Name, Value, Root, readonly language.AnyResolvedClass[]>;
83
185
  /** Project each authored Class independently before computing its parent tuple. */
84
186
  export type ClassProjectionOfAuthoring<Origin extends string, Name extends string, Value, Root extends DomainSchemaInput, Seen = Value> = Value extends Class ? ClassProjectionWithParents<Origin, Name, Value, Root, ParentClassProjectionTuple<Origin, ParentInputsOfConfig<ProjectionOfClass<Extract<Value, Class>>>, Root, Seen>> : never;
85
- type ClassProjectionWithParents<Origin extends string, Name extends string, Value, Root extends DomainSchemaInput, Parents extends readonly unknown[]> = Value extends NodeClass<infer _Config> ? ClassProjection<'node', Extract<ProjectedClassDefinition<Origin, Name, Value>, language.NodeClassDefinition>, language.ClassRef<Name> & {
187
+ type ClassProjectionWithParents<Origin extends string, Name extends string, Value, Root extends DomainSchemaInput, Parents extends readonly unknown[]> = Value extends NodeClass<infer _Config> ? ClassProjection<'node', Extract<ProjectedClassDefinition<Origin, Name, Value, Root>, language.NodeClassDefinition>, language.ClassRef<Name> & {
86
188
  readonly origin: Origin;
87
- }, language.DefinitionKey<Origin, 'class', Name>, Parents, EffectivePropertyProjectionsOf<Origin, Name, Value, Root>, OwnInstanceMethodProjectionsOf<Origin, Name, Value>, OwnStaticMethodProjectionsOf<Origin, Name, Value>, OwnPropertyProjectionsOf<Origin, Name, Value>, OwnInstanceMethodProjectionsOf<Origin, Name, Value>, OwnStaticMethodProjectionsOf<Origin, Name, Value>> : Value extends DirectedEdgeClass | UndirectedEdgeClass ? ClassProjection<'edge', Extract<ProjectedClassDefinition<Origin, Name, Value>, language.EdgeClassDefinition>, language.ClassRef<Name> & {
189
+ }, language.DefinitionKey<Origin, 'class', Name>, Parents, EffectivePropertyProjectionsOf<Origin, Name, Value, Root>, OwnInstanceMethodProjectionsOf<Origin, Name, Value>, OwnStaticMethodProjectionsOf<Origin, Name, Value>, OwnPropertyProjectionsOf<Origin, Name, Value>, OwnInstanceMethodProjectionsOf<Origin, Name, Value>, OwnStaticMethodProjectionsOf<Origin, Name, Value>> : Value extends DirectedEdgeClass | UndirectedEdgeClass ? ClassProjection<'edge', Extract<ProjectedClassDefinition<Origin, Name, Value, Root>, language.EdgeClassDefinition>, language.ClassRef<Name> & {
88
190
  readonly origin: Origin;
89
191
  }, language.DefinitionKey<Origin, 'class', Name>, Parents, EffectivePropertyProjectionsOf<Origin, Name, Value, Root>, never, never, OwnPropertyProjectionsOf<Origin, Name, Value>, never, never> : never;
90
192
  export {};
@@ -1,13 +1,13 @@
1
1
  import { accept as acceptJsonValue, BoundaryError as JsonBoundaryError, json, } from '@astrale-os/kernel-dsl/value';
2
- import { dependencyLimits } from '../addressing/domain-dependency.js';
3
2
  import { compareUnicode } from '../addressing/ordering.js';
3
+ import { limits } from '../language/limits.js';
4
4
  import { escapePointerToken } from '../language/value/syntax/pointer.js';
5
5
  import { acceptDomainSchema } from '../schema/admission/accept.js';
6
6
  import { canonicalDomainSchemaAfterValidation } from '../schema/canonical/revision.js';
7
7
  import { revisionOfDomainSchema } from '../schema/canonical/revision.js';
8
8
  import { MemoryDomainSchemaLookup } from '../schema/dependency/lookup.js';
9
9
  import { SchemaError } from '../schema/diagnostic.js';
10
- import { BundleError, diagnostic } from './diagnostic.js';
10
+ import { BundleError, diagnostic, schemaDiagnosticAt } from './diagnostic.js';
11
11
  import { asDomainSchemaBundle, } from './model.js';
12
12
  import { parseDomainSchemaBundleStructure } from './structure.js';
13
13
  export function acceptDomainSchemaBundle(input) {
@@ -46,12 +46,12 @@ function acceptBundleValue(input) {
46
46
  const closure = structure.closure.map((schema, index) => candidate(schema, `/closure/${index}`));
47
47
  const diagnostics = [];
48
48
  const candidates = new Map();
49
- if (closure.length + 1 > dependencyLimits.closure) {
50
- diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', '/closure', `A dependency closure may contain at most ${dependencyLimits.closure} Domains.`));
49
+ if (closure.length + 1 > limits.dependency.closure) {
50
+ diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', '/closure', `A dependency closure may contain at most ${limits.dependency.closure} Domains.`));
51
51
  }
52
52
  for (const entry of [root, ...closure]) {
53
- if (Object.keys(entry.schema.dependencies).length > dependencyLimits.direct) {
54
- diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', `${entry.pointer}/dependencies`, `A Domain may declare at most ${dependencyLimits.direct} direct dependency aliases.`));
53
+ if (Object.keys(entry.schema.dependencies).length > limits.dependency.direct) {
54
+ diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', `${entry.pointer}/dependencies`, `A Domain may declare at most ${limits.dependency.direct} direct dependency aliases.`));
55
55
  }
56
56
  }
57
57
  for (const entry of closure) {
@@ -99,7 +99,7 @@ function acceptBundleValue(input) {
99
99
  catch (error) {
100
100
  if (!(error instanceof SchemaError))
101
101
  throw error;
102
- throw new BundleError(error.diagnostics.map((item) => diagnostic(item.code, `${entry.pointer}${item.pointer}`, item.message, item.ref)));
102
+ throw new BundleError(error.diagnostics.map((item) => schemaDiagnosticAt(entry.pointer, item)));
103
103
  }
104
104
  };
105
105
  for (const entry of candidates.values()) {
@@ -128,8 +128,8 @@ function collectReachable(current, root, candidates, reachable, active, revision
128
128
  return;
129
129
  }
130
130
  active.add(current.key);
131
- if (depth > dependencyLimits.depth) {
132
- diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', current.pointer, `Dependency depth ${depth} exceeds the maximum ${dependencyLimits.depth}.`));
131
+ if (depth > limits.dependency.depth) {
132
+ diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', current.pointer, `Dependency depth ${depth} exceeds the maximum ${limits.dependency.depth}.`));
133
133
  active.delete(current.key);
134
134
  return;
135
135
  }
@@ -4,6 +4,8 @@ export type BundleDiagnostic<Code extends BundleDiagnosticCode = BundleDiagnosti
4
4
  readonly code: Code;
5
5
  };
6
6
  export declare function diagnostic<const Code extends BundleDiagnosticCode>(code: Code, pointer: string, message: string, ref?: string): BundleDiagnostic<Code>;
7
+ /** A refusal of one bundled schema, its pointer rebased under the schema's place in the bundle. */
8
+ export declare function schemaDiagnosticAt(pointer: string, refusal: SchemaDiagnostic): BundleDiagnostic;
7
9
  export declare class BundleError extends Error {
8
10
  readonly diagnostics: readonly BundleDiagnostic[];
9
11
  constructor(diagnostics: readonly BundleDiagnostic[]);
@@ -2,6 +2,12 @@ import { formatDiagnostics, orderDiagnostics } from '../language/validation/diag
2
2
  export function diagnostic(code, pointer, message, ref) {
3
3
  return Object.freeze({ code, pointer, message, ...(ref === undefined ? {} : { ref }) });
4
4
  }
5
+ /** A refusal of one bundled schema, its pointer rebased under the schema's place in the bundle. */
6
+ export function schemaDiagnosticAt(pointer, refusal) {
7
+ // Acceptance refuses a document with Schema codes only, never with comparison request codes.
8
+ const code = refusal.code;
9
+ return Object.freeze({ ...refusal, code, pointer: `${pointer}${refusal.pointer}` });
10
+ }
5
11
  export class BundleError extends Error {
6
12
  diagnostics;
7
13
  constructor(diagnostics) {
@@ -1,7 +1,7 @@
1
1
  import { escapePointerToken } from '../language/value/syntax/pointer.js';
2
2
  import { SchemaError } from '../schema/diagnostic.js';
3
3
  import { routeDomainSchema } from '../schema/validation/domain.route.js';
4
- import { BundleError, diagnostic } from './diagnostic.js';
4
+ import { BundleError, diagnostic, schemaDiagnosticAt } from './diagnostic.js';
5
5
  import { DOMAIN_BUNDLE_FORMAT, DOMAIN_BUNDLE_VERSION } from './model.js';
6
6
  export function parseDomainSchemaBundleStructure(input) {
7
7
  if (!isObject(input)) {
@@ -57,7 +57,7 @@ function routeAt(value, pointer, diagnostics) {
57
57
  catch (error) {
58
58
  if (!(error instanceof SchemaError))
59
59
  throw error;
60
- diagnostics.push(...error.diagnostics.map((entry) => diagnostic(entry.code, `${pointer}${entry.pointer}`, entry.message, entry.ref)));
60
+ diagnostics.push(...error.diagnostics.map((entry) => schemaDiagnosticAt(pointer, entry)));
61
61
  return undefined;
62
62
  }
63
63
  }
@@ -1,5 +1,5 @@
1
1
  import { accept as acceptPortable } from '@astrale-os/kernel-dsl/value';
2
- import { dependencyLimits } from '../../addressing/domain-dependency.js';
2
+ import { limits } from '../../language/limits.js';
3
3
  import {} from '../model/schema.js';
4
4
  import { validateClosure } from './closure.js';
5
5
  import { invalid, pointer } from './diagnostic.js';
@@ -20,7 +20,7 @@ export function acceptCompiledSchema(input) {
20
20
  const rootPin = dependency(root.root, 'root', '/root');
21
21
  const machines = new Map();
22
22
  const closure = array(root.closure, 'closure', '/closure').map((value, index) => entry(value, index, `/closure/${index}`, machines));
23
- if (closure.length > dependencyLimits.closure) {
23
+ if (closure.length > limits.dependency.closure) {
24
24
  invalid('dependency closure limit', 'COMPILED_DEPENDENCY_LIMITS', '/closure');
25
25
  }
26
26
  const closureOrigins = new Set();
@@ -34,7 +34,7 @@ export function acceptCompiledSchema(input) {
34
34
  if (rootEntry?.revision !== rootPin.revision)
35
35
  invalid('root pin', undefined, '/root');
36
36
  for (const [entryIndex, owner] of closure.entries()) {
37
- if (Object.keys(owner.dependencies).length > dependencyLimits.direct) {
37
+ if (Object.keys(owner.dependencies).length > limits.dependency.direct) {
38
38
  invalid('direct dependency limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${entryIndex}/dependencies`);
39
39
  }
40
40
  for (const [alias, pin] of Object.entries(owner.dependencies)) {
@@ -1,7 +1,7 @@
1
1
  import {} from '@astrale-os/kernel-dsl/value';
2
- import { dependencyLimits } from '../../addressing/domain-dependency.js';
3
2
  import { Key, isDefinitionRef } from '../../addressing/index.js';
4
3
  import {} from '../../language/class/model/edge.js';
4
+ import { limits } from '../../language/limits.js';
5
5
  import {} from '../model/schema.js';
6
6
  import { invalid, pointer } from './diagnostic.js';
7
7
  /** Require closed direct references, acyclic inheritance and concrete Core Classes. */
@@ -128,7 +128,7 @@ function validateDependencyCycles(candidate) {
128
128
  const visited = new Set();
129
129
  const frames = [];
130
130
  const push = (origin, depth) => {
131
- if (depth > dependencyLimits.depth) {
131
+ if (depth > limits.dependency.depth) {
132
132
  invalid('dependency depth limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${byOrigin.get(origin)?.index ?? 0}/dependencies`);
133
133
  }
134
134
  active.add(origin);
@@ -1,7 +1,7 @@
1
1
  import { Key } from '../../../addressing/index.js';
2
2
  import { isMethodExecutable } from '../../../language/callable/executable.js';
3
3
  import { coveringEdgeUniqueTuples, coveringNodeUniqueTuples, edgeUniqueKeys, nodeUniqueKeys, } from '../../../language/class/unique.js';
4
- import { checkCoreEdgeSet, checkHeldKeys, coreEndpointsSatisfy, } from '../../../language/core/facts.js';
4
+ import { checkCoreEdgeSet, checkHeldKeys, coreEndpointsSatisfy, DOMAIN_ENDPOINT_CLASS, } from '../../../language/core/facts.js';
5
5
  import {} from '../../../language/core/model/core.js';
6
6
  import { policyObjectOrigin, policyObjectKey, projectedMemberClass, } from '../../../language/index.js';
7
7
  import { bindValueProgram } from '../../../language/value/compile/load.js';
@@ -123,7 +123,7 @@ function validateCoreProperties(values, analysis, path) {
123
123
  }
124
124
  function resolveCoreEndpoint(context, entry, ref, nodes, path) {
125
125
  if (ref.kind === 'domain')
126
- return { key: 'domain' };
126
+ return { key: 'domain', member: { class: DOMAIN_ENDPOINT_CLASS, pointer: path } };
127
127
  const undeclared = () => fail(path, 'Core endpoint does not name a declared local Definition.');
128
128
  if (policyObjectOrigin(ref) !== entry.origin)
129
129
  return undeclared();
@@ -151,9 +151,5 @@ function declaresProjectedMember(context, entry, ref) {
151
151
  return declarations.some((declaration) => declaration.ref.name === ref.name);
152
152
  }
153
153
  function endpointSatisfies(context, endpoint, accepts) {
154
- if ('value' in endpoint)
155
- return classSatisfiesAny(context, endpoint.value.class, accepts);
156
- if ('member' in endpoint)
157
- return classSatisfiesAny(context, endpoint.member.class, accepts);
158
- return true;
154
+ return classSatisfiesAny(context, 'value' in endpoint ? endpoint.value.class : endpoint.member.class, accepts);
159
155
  }
@@ -1,6 +1,6 @@
1
1
  import {} from '../../../../addressing/index.js';
2
2
  import { branchesOf, targetMode, isConnected, } from '../../../../language/policy/analysis/branches.js';
3
- import { MAX_PATTERN_DEPTH, MAX_BRANCHES, MAX_EDGES, MAX_DOMAINS, measureChecks, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, policyMeasurer, } from '../../../../language/policy/analysis/budgets.js';
3
+ import { exceededLimits, measureChecks, policyMeasurer, } from '../../../../language/policy/analysis/budgets.js';
4
4
  import { neverAdmittedClasses, } from '../../../../language/policy/analysis/checks.js';
5
5
  import {} from '../../../../language/policy/analysis/typing.js';
6
6
  import { checksNameTheCaller, isClassRuleChecks, } from '../../../../language/policy/model/policy.js';
@@ -28,11 +28,7 @@ export function validatePolicyParity(context, entry, entryIndex, policies, origi
28
28
  }
29
29
  }
30
30
  const measure = measurePolicy(name);
31
- if (measure !== undefined &&
32
- (measure.depth > MAX_PATTERN_DEPTH ||
33
- measure.edgeCounts.length > MAX_BRANCHES ||
34
- Math.max(0, ...measure.edgeCounts) > MAX_EDGES ||
35
- measure.domains.size > MAX_DOMAINS)) {
31
+ if (measure !== undefined && exceededLimits(measure).length > 0) {
36
32
  fail(path, 'Policy expansion exceeds the V1 depth, branch, Edge, or Domain budget.');
37
33
  }
38
34
  const branches = typing.expandedBranches(name, `$${name}`);
@@ -98,10 +94,7 @@ function validatePolicyChecks(context, typing, entry, expression, input, receive
98
94
  if (!checksNameTheCaller(expression)) {
99
95
  fail(path, `${SITE[site].checks} must check a Policy on every branch: sameNode alone names no caller.`);
100
96
  }
101
- const measure = measureChecks(expression);
102
- if (measure.depth > MAX_CHECK_DEPTH ||
103
- measure.branches > MAX_BRANCHES ||
104
- measure.leaves > MAX_CHECK_LEAVES) {
97
+ if (exceededLimits(measureChecks(expression)).length > 0) {
105
98
  fail(path, `${SITE[site].checks} exceed the V1 depth, branch, or leaf budget.`);
106
99
  }
107
100
  const leaves = new Map();
@@ -14,6 +14,9 @@ export interface CallableValidation {
14
14
  validateInputField(field: string, input: unknown): readonly Diagnostic[];
15
15
  validateOutput(output: unknown): readonly Diagnostic[];
16
16
  }
17
- /** Build the one Domain-level router shared by source resolution and compiled loading. */
17
+ /**
18
+ * Build the one Domain-level router shared by source resolution and compiled loading. The Domain
19
+ * built from the same entries asks only for the Properties and Callables they declare.
20
+ */
18
21
  export declare function createDomainValidation(properties: ReadonlyMap<PropertyKey, PropertyValidation>, callables: ReadonlyMap<Key.Callable, CallableValidation>): DomainValidation;
19
22
  export declare function unknownInputField(field: string): readonly Diagnostic[];
@@ -1,34 +1,30 @@
1
- /** Build the one Domain-level router shared by source resolution and compiled loading. */
1
+ /**
2
+ * Build the one Domain-level router shared by source resolution and compiled loading. The Domain
3
+ * built from the same entries asks only for the Properties and Callables they declare.
4
+ */
2
5
  export function createDomainValidation(properties, callables) {
6
+ const propertyOf = (key) => {
7
+ const target = properties.get(key);
8
+ if (target === undefined)
9
+ throw new TypeError(`Property ${key} is absent.`);
10
+ return target;
11
+ };
12
+ const callableOf = (key) => {
13
+ const target = callables.get(key);
14
+ if (target === undefined)
15
+ throw new TypeError(`Callable ${key} is absent.`);
16
+ return target;
17
+ };
3
18
  const validation = {
4
19
  propertyExists: (key) => properties.has(key),
5
- property(key, input) {
6
- const target = properties.get(key);
7
- return target === undefined ? unknownTarget('Property', key) : target.validate(input);
8
- },
9
- propertyProgram(key) {
10
- const target = properties.get(key);
11
- if (target === undefined)
12
- throw new TypeError(`Property ${key} is absent.`);
13
- return target.program();
14
- },
20
+ property: (key, input) => propertyOf(key).validate(input),
21
+ propertyProgram: (key) => propertyOf(key).program(),
15
22
  propertyOrdering: (key) => properties.get(key)?.ordering,
16
23
  callableExists: (key) => callables.has(key),
17
- callableInput(key, input) {
18
- const target = callables.get(key);
19
- return target === undefined ? unknownTarget('Callable', key) : target.validateInput(input);
20
- },
24
+ callableInput: (key, input) => callableOf(key).validateInput(input),
21
25
  callableFields: (key) => callables.get(key)?.fields,
22
- callableInputField(key, field, input) {
23
- const target = callables.get(key);
24
- return target === undefined
25
- ? unknownTarget('Callable', key)
26
- : target.validateInputField(field, input);
27
- },
28
- callableOutput(key, output) {
29
- const target = callables.get(key);
30
- return target === undefined ? unknownTarget('Callable', key) : target.validateOutput(output);
31
- },
26
+ callableInputField: (key, field, input) => callableOf(key).validateInputField(field, input),
27
+ callableOutput: (key, output) => callableOf(key).validateOutput(output),
32
28
  };
33
29
  return Object.freeze(validation);
34
30
  }
@@ -41,12 +37,3 @@ export function unknownInputField(field) {
41
37
  }),
42
38
  ];
43
39
  }
44
- function unknownTarget(kind, key) {
45
- return [
46
- Object.freeze({
47
- code: 'DOMAIN_VALIDATION_TARGET_UNKNOWN',
48
- pointer: '',
49
- message: `${kind} ${key} is absent.`,
50
- }),
51
- ];
52
- }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.astrale.ai/dsl/v1/value-schema",
4
+ "$dynamicAnchor": "meta",
5
+ "$vocabulary": {
6
+ "https://json-schema.org/draft/2020-12/vocab/core": true,
7
+ "https://json-schema.org/draft/2020-12/vocab/applicator": true,
8
+ "https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
9
+ "https://json-schema.org/draft/2020-12/vocab/validation": true,
10
+ "https://json-schema.org/draft/2020-12/vocab/meta-data": true,
11
+ "https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
12
+ "https://json-schema.org/draft/2020-12/vocab/content": true,
13
+ "https://schemas.astrale.ai/dsl/v1/value-schema/vocabulary": true
14
+ },
15
+ "title": "Astrale V1 value schema",
16
+ "$comment": "The meta-schema of the V1 value-schema dialect: Draft 2020-12 and the required Astrale vocabulary (fullMatch, x-astrale-path, x-astrale-value-kind). Its $dynamicAnchor extends Draft 2020-12 at every subschema, not only the root. The rules of the profile beyond it are published as schema.values.RULES.",
17
+ "allOf": [{ "$ref": "https://json-schema.org/draft/2020-12/schema" }],
18
+ "properties": {
19
+ "fullMatch": { "type": "string" },
20
+ "x-astrale-path": { "type": "object" }
21
+ }
22
+ }
@@ -3,7 +3,7 @@ import type { MethodRecord } from '../../callable/model/callable.js';
3
3
  import type { ClassPolicy, NodeClassPolicy } from '../../policy/model/policy.js';
4
4
  import type { DataFacet } from './data.js';
5
5
  import type { EdgeContract } from './edge.js';
6
- import type { PropertyFacet } from './property.js';
6
+ import type { EdgePropertyDefinition, NodePropertyDefinition, PropertyFacet } from './property.js';
7
7
  export type ClassKind = 'node' | 'edge';
8
8
  /**
9
9
  * Which Classes may extend a Class: `'open'`, those of its Domain and of every Domain that depends
@@ -30,7 +30,7 @@ export type NodeUniqueTuple = readonly [PropertyKey, ...PropertyKey[]];
30
30
  * backend announces it to enforce Node keys, so a tuple is never ignored where it is not.
31
31
  */
32
32
  export type NodeUniqueForm = readonly ['property'];
33
- export interface NodeClassDefinition extends DefinitionBase<ClassRef>, PropertyFacet, DataFacet {
33
+ export interface NodeClassDefinition extends DefinitionBase<ClassRef>, PropertyFacet<NodePropertyDefinition>, DataFacet {
34
34
  readonly kind: 'node';
35
35
  readonly abstract: boolean;
36
36
  /** Absent when `'internal'`, the default, so a Class that keeps the default keeps its revision. */
@@ -44,9 +44,9 @@ export interface NodeClassDefinition extends DefinitionBase<ClassRef>, PropertyF
44
44
  * The tuples no two Nodes of this Class and of its active concrete descendants share while every
45
45
  * Property is present; absent, none. A descendant is covered without declaring them again.
46
46
  */
47
- readonly unique?: readonly NodeUniqueTuple[];
47
+ readonly unique?: readonly [NodeUniqueTuple, ...NodeUniqueTuple[]];
48
48
  }
49
- export type EdgeClassDefinition = DefinitionBase<ClassRef> & PropertyFacet & EdgeContract & {
49
+ export type EdgeClassDefinition = DefinitionBase<ClassRef> & PropertyFacet<EdgePropertyDefinition> & EdgeContract & {
50
50
  readonly kind: 'edge';
51
51
  readonly abstract: boolean;
52
52
  /** Absent when `'internal'`, the default, so a Class that keeps the default keeps its revision. */
@@ -8,7 +8,7 @@ export type EdgeOrientation = 'directed' | 'undirected';
8
8
  export type EdgeLifetime = 'restrict' | 'detach';
9
9
  export interface EdgeEndpointBase {
10
10
  readonly role: string;
11
- readonly accepts: readonly ClassRef[];
11
+ readonly accepts: readonly [ClassRef, ...ClassRef[]];
12
12
  /** Declared only when authored; otherwise derived (`edgeLifetimes`). */
13
13
  readonly onDelete?: EdgeLifetime;
14
14
  }
@@ -56,7 +56,7 @@ export interface DirectedEdgeContract {
56
56
  * The tuples no two Edges of this Class and of its active concrete descendants share. Absent
57
57
  * when the Class declares none, so a Class without one keeps its revision; never empty.
58
58
  */
59
- readonly unique?: readonly EdgeUniqueTuple[];
59
+ readonly unique?: readonly [EdgeUniqueTuple, ...EdgeUniqueTuple[]];
60
60
  }
61
61
  export interface UndirectedEdgeContract {
62
62
  readonly orientation: 'undirected';
@@ -1,20 +1,29 @@
1
+ import type { StateTopology } from '../../state/index.js';
2
+ import type { JsonSchema } from '../../value/model/schema.js';
1
3
  export type AutoEvent = 'create' | 'update';
2
4
  export type AutoSet = 'instant';
3
5
  /** `create`: written only by node or edge creation. `once`: written while absent, never unset. */
4
6
  export type PropertyImmutability = 'create' | 'once';
5
7
  export interface PropertyAuto {
6
- readonly on: readonly AutoEvent[];
8
+ readonly on: readonly [AutoEvent, ...AutoEvent[]];
7
9
  readonly set: AutoSet;
8
10
  }
9
- export interface PropertyDefinition {
10
- readonly schema: import('../../value/model/schema.js').JsonSchema;
11
+ /** A Property of a Node Class, which may be a State Property. */
12
+ export interface NodePropertyDefinition {
13
+ readonly schema: JsonSchema;
11
14
  readonly required: boolean;
12
15
  readonly auto?: PropertyAuto;
13
16
  readonly immutable?: PropertyImmutability;
14
17
  readonly description?: string;
15
- readonly state?: import('../../state/index.js').StateTopology;
18
+ readonly state?: StateTopology;
16
19
  }
17
- export type PropertyRecord = Readonly<Record<string, PropertyDefinition>>;
18
- export interface PropertyFacet {
19
- readonly properties: PropertyRecord;
20
+ /** A Property of an Edge Class: an Edge has no State Property. */
21
+ export interface EdgePropertyDefinition extends Omit<NodePropertyDefinition, 'state'> {
22
+ readonly state?: never;
23
+ }
24
+ /** A Property of a Class of either kind. */
25
+ export type PropertyDefinition = NodePropertyDefinition | EdgePropertyDefinition;
26
+ export type PropertyRecord<Definition extends PropertyDefinition = PropertyDefinition> = Readonly<Record<string, Definition>>;
27
+ export interface PropertyFacet<Definition extends PropertyDefinition = PropertyDefinition> {
28
+ readonly properties: PropertyRecord<Definition>;
20
29
  }
@@ -1,9 +1,17 @@
1
1
  import type { ClassRef } from '../../addressing/index.js';
2
2
  import type { EdgeContract, EdgeCount, EdgeEndpointBase, IncidentEndpoint } from '../class/model/edge.js';
3
+ /**
4
+ * The Class of the owning Domain's Node: every Domain principal is a Node of the final Kernel
5
+ * `Domain` Class, so a Core Edge that names the Domain must accept that Class at that endpoint.
6
+ */
7
+ export declare const DOMAIN_ENDPOINT_CLASS: ClassRef;
3
8
  /** One endpoint of a Core Edge: a Core Node, a projected member or the owning Domain. */
4
9
  export interface CoreFactEndpoint {
5
10
  readonly key: string;
6
- /** Set on a projected member: its Kernel Class, and where a breach of its degree is reported. */
11
+ /**
12
+ * Set on a projected member and on the owning Domain: the Kernel Class it is a Node of, and where
13
+ * a breach of its degree is reported.
14
+ */
7
15
  readonly member?: {
8
16
  readonly class: ClassRef;
9
17
  readonly pointer: string;
@@ -26,10 +34,12 @@ export interface CoreDegreeSubject {
26
34
  }
27
35
  export interface CoreEdgeSet<Edge> {
28
36
  readonly edges: readonly CoreFactEdge<Edge>[];
29
- /** The local exact Edge Classes, in the order their slices are checked. */
37
+ /** The local Edge Classes, in the order their slices are checked. */
30
38
  readonly classes: readonly {
31
39
  readonly key: string;
32
- readonly contract: EdgeContract;
40
+ readonly contract: EdgeContract & {
41
+ readonly abstract: boolean;
42
+ };
33
43
  }[];
34
44
  readonly nodes: readonly CoreDegreeSubject[];
35
45
  readonly satisfies: (ref: ClassRef, accepts: readonly ClassRef[]) => boolean;
@@ -68,5 +78,8 @@ export declare function coreEndpointsSatisfy<Endpoint>(contract: EdgeContract, s
68
78
  * DV-EDGE-UNIQUE); Activation checks them against stored data.
69
79
  */
70
80
  export declare function checkHeldKeys<Fact>(facts: Iterable<Fact>, keys: (fact: Fact) => readonly string[], report: (fact: Fact, previous: Fact) => void): void;
71
- /** Check normalized Edge identity, noSelf, keys, exact-Class acyclicity and Core degrees. */
81
+ /**
82
+ * Check normalized Edge identity, noSelf, keys, and the acyclicity and Core degrees of each exact
83
+ * concrete Edge Class over its own Edges.
84
+ */
72
85
  export declare function checkCoreEdgeSet<Edge>(set: CoreEdgeSet<Edge>): void;