@astrale-os/kernel-dsl 1.0.0-beta.16 → 1.0.0-beta.17

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 (74) hide show
  1. package/dist/v1/builder/class/authoring.js +3 -2
  2. package/dist/v1/builder/class/input.d.ts +45 -14
  3. package/dist/v1/builder/index.d.ts +2 -1
  4. package/dist/v1/builder/lowering/class.d.ts +8 -0
  5. package/dist/v1/builder/lowering/class.js +40 -16
  6. package/dist/v1/builder/lowering/schema/compile.js +3 -3
  7. package/dist/v1/builder/policy/authoring.js +97 -88
  8. package/dist/v1/bundle/model.js +1 -1
  9. package/dist/v1/compiled/admission/accept.js +1 -7
  10. package/dist/v1/compiled/admission/semantics/class.js +2 -3
  11. package/dist/v1/compiled/admission/semantics/policy/parity.js +25 -13
  12. package/dist/v1/compiled/admission/wire/class.js +23 -18
  13. package/dist/v1/compiled/admission/wire/policy.d.ts +4 -3
  14. package/dist/v1/compiled/admission/wire/policy.js +8 -7
  15. package/dist/v1/compiled/loader/load.js +1 -1
  16. package/dist/v1/domain/create.js +1 -1
  17. package/dist/v1/domain/model/input.d.ts +2 -1
  18. package/dist/v1/domain/projection/classes.js +1 -1
  19. package/dist/v1/domain/validation/create.d.ts +2 -1
  20. package/dist/v1/domain/validation/create.js +1 -1
  21. package/dist/v1/index.d.ts +1 -1
  22. package/dist/v1/language/callable/resolved.d.ts +11 -2
  23. package/dist/v1/language/class/model/class.d.ts +17 -5
  24. package/dist/v1/language/freeze.d.ts +5 -0
  25. package/dist/v1/{schema/canonical → language}/freeze.js +4 -0
  26. package/dist/v1/language/policy/analysis/typing.d.ts +1 -0
  27. package/dist/v1/language/policy/analysis/typing.js +74 -79
  28. package/dist/v1/language/policy/model/policy.d.ts +44 -4
  29. package/dist/v1/language/policy/model/policy.js +14 -0
  30. package/dist/v1/language/policy/normalization/normalize.d.ts +6 -6
  31. package/dist/v1/language/policy/normalization/normalize.js +5 -5
  32. package/dist/v1/language/validation/rule.d.ts +18 -8
  33. package/dist/v1/language/validation/rule.js +2 -11
  34. package/dist/v1/language/value/evaluate/program.d.ts +2 -1
  35. package/dist/v1/language/value/evaluate/program.js +2 -2
  36. package/dist/v1/language/value/evaluate/validate.d.ts +2 -2
  37. package/dist/v1/language/value/evaluate/validate.js +2 -2
  38. package/dist/v1/language/value/profile/json.validate.d.ts +3 -1
  39. package/dist/v1/language/value/profile/json.validate.js +3 -2
  40. package/dist/v1/schema/.spec/schemas/domain-schema.schema.json +180 -25
  41. package/dist/v1/schema/admission/callable.js +1 -1
  42. package/dist/v1/schema/canonical/revision.js +4 -4
  43. package/dist/v1/schema/compatibility/comparators/callables.js +1 -1
  44. package/dist/v1/schema/compatibility/comparators/classes.js +4 -4
  45. package/dist/v1/schema/compatibility/comparators/members.js +1 -1
  46. package/dist/v1/schema/compatibility/comparators/values.js +2 -2
  47. package/dist/v1/schema/compatibility/report.js +1 -1
  48. package/dist/v1/schema/compatibility/versioning/index.js +1 -1
  49. package/dist/v1/schema/model/schema.js +1 -1
  50. package/dist/v1/schema/normalization/domain.js +9 -8
  51. package/dist/v1/schema/resolution/domain.js +1 -1
  52. package/dist/v1/schema/resolution/origins.js +3 -2
  53. package/dist/v1/schema/rule.d.ts +8 -20
  54. package/dist/v1/schema/rule.js +1 -1
  55. package/dist/v1/schema/validation/class.js +2 -3
  56. package/dist/v1/schema/validation/domain.json-schema.d.ts +2 -2
  57. package/dist/v1/schema/validation/domain.json-schema.js +20 -6
  58. package/dist/v1/schema/validation/domain.structure.d.ts +4765 -1005
  59. package/dist/v1/schema/validation/domain.structure.js +21 -9
  60. package/dist/v1/schema/validation/json.json-schema.d.ts +18 -2
  61. package/dist/v1/schema/validation/json.json-schema.js +14 -4
  62. package/dist/v1/schema/validation/policy/budgets.d.ts +1 -1
  63. package/dist/v1/schema/validation/policy/budgets.js +4 -4
  64. package/dist/v1/schema/validation/policy/uses.d.ts +10 -2
  65. package/dist/v1/schema/validation/policy/uses.js +26 -13
  66. package/dist/v1/schema/validation/policy/validate.js +2 -3
  67. package/dist/v1/schema/validation/value.json-schema.d.ts +4 -6
  68. package/dist/v1/schema/validation/value.json-schema.js +18 -25
  69. package/package.json +1 -1
  70. package/dist/v1/schema/canonical/domain.d.ts +0 -3
  71. package/dist/v1/schema/canonical/domain.digest.d.ts +0 -3
  72. package/dist/v1/schema/canonical/domain.digest.js +0 -5
  73. package/dist/v1/schema/canonical/domain.js +0 -5
  74. package/dist/v1/schema/canonical/freeze.d.ts +0 -1
@@ -33,6 +33,20 @@ export function projectedMemberClass(ref) {
33
33
  function kernelClassRef(name) {
34
34
  return Object.freeze({ origin: 'kernel.astrale.ai', kind: 'class', name });
35
35
  }
36
+ /**
37
+ * Every Class slot: the observations, which admit every caller when absent, then the writes, which
38
+ * admit only the Domain that declares the Class when absent.
39
+ */
40
+ export const CLASS_OPERATIONS = Object.freeze([
41
+ 'read',
42
+ 'traverse',
43
+ 'create',
44
+ 'update',
45
+ 'delete',
46
+ ]);
47
+ export function isClassObservation(operation) {
48
+ return operation === 'read' || operation === 'traverse';
49
+ }
36
50
  export function isClassRuleChecks(value) {
37
51
  return (typeof value === 'object' &&
38
52
  ('check' in value || 'sameNode' in value || 'allOf' in value || 'anyOf' in value));
@@ -1,4 +1,4 @@
1
- import type { NodeClassPolicy, PolicyCheckExpression, PolicyExpression, PolicyPatternExpression } from '../model/policy.js';
1
+ import type { ClassSlotPolicy, PolicyCheckExpression, PolicyExpression, PolicyPatternExpression } from '../model/policy.js';
2
2
  export declare function normalizePolicyExpression(value: PolicyExpression): PolicyExpression;
3
3
  /**
4
4
  * The fixed point of the single pass: a Pattern the single pass reproduces is returned unchanged,
@@ -6,10 +6,10 @@ export declare function normalizePolicyExpression(value: PolicyExpression): Poli
6
6
  */
7
7
  export declare function normalizePolicyPattern(value: PolicyPatternExpression): PolicyPatternExpression;
8
8
  /**
9
- * The one spelling of a Node Class observation rule: normalized Policy checks without a composition
10
- * of one operand, or the Policy that a lone check of `self` names, which is how a Class has always
11
- * declared one. Callable checks keep their compositions of one operand: their revisions predate
12
- * this rule.
9
+ * The one spelling of a Class rule: normalized Policy checks without a composition of one operand,
10
+ * or the Policy that a lone check of `self` names, which is how a Class has always declared one.
11
+ * Callable checks keep their compositions of one operand: their revisions predate this rule. A
12
+ * create rule checks no `self`, so it keeps its checks.
13
13
  */
14
- export declare function normalizeClassRule(value: NodeClassPolicy): NodeClassPolicy;
14
+ export declare function normalizeClassRule<Slot extends ClassSlotPolicy>(value: Slot): Slot;
15
15
  export declare function normalizePolicyChecks(value: PolicyCheckExpression): PolicyCheckExpression;
@@ -40,16 +40,16 @@ function normalizePatternOnce(value) {
40
40
  return normalizePatternNode(rewritten);
41
41
  }
42
42
  /**
43
- * The one spelling of a Node Class observation rule: normalized Policy checks without a composition
44
- * of one operand, or the Policy that a lone check of `self` names, which is how a Class has always
45
- * declared one. Callable checks keep their compositions of one operand: their revisions predate
46
- * this rule.
43
+ * The one spelling of a Class rule: normalized Policy checks without a composition of one operand,
44
+ * or the Policy that a lone check of `self` names, which is how a Class has always declared one.
45
+ * Callable checks keep their compositions of one operand: their revisions predate this rule. A
46
+ * create rule checks no `self`, so it keeps its checks.
47
47
  */
48
48
  export function normalizeClassRule(value) {
49
49
  if (!isClassRuleChecks(value))
50
50
  return value;
51
51
  const checks = unwrapSingleOperands(normalizePolicyChecks(value));
52
- return 'check' in checks && checks.object.kind === 'self' ? checks.check : checks;
52
+ return ('check' in checks && checks.object.kind === 'self' ? checks.check : checks);
53
53
  }
54
54
  /** Replace each composition of one operand by that operand, merging what it then nests. */
55
55
  function unwrapSingleOperands(value) {
@@ -8,13 +8,15 @@ import type { DiagnosticCode } from './diagnostic.js';
8
8
  * `warning`: a value schema, which the rule reports without refusing it.
9
9
  */
10
10
  export type ValueRuleStage = 'schema' | 'context' | 'value' | 'warning';
11
- /** The rule one value diagnostic code reports. */
12
- export interface ValueRule {
13
- readonly stage: ValueRuleStage;
11
+ /**
12
+ * The rule one diagnostic code reports, whatever it checks: what `schema.RULES` and `VALUE_RULES`
13
+ * say of every code, each with the stages of its own checks.
14
+ */
15
+ export interface DiagnosticRule {
14
16
  /**
15
- * The positions the rule constrains, which its diagnostics point at, relative to the value
16
- * schema, the value or the Domain input it checks: JSON Pointer templates in which a `{name}`
17
- * token stands for one token of the kind it names and `{/path*}` for any number of tokens.
17
+ * The positions the rule constrains, which its diagnostics point at: JSON Pointer templates in
18
+ * which a `{name}` token stands for one token of the kind it names and `{/path*}` for any number
19
+ * of tokens.
18
20
  */
19
21
  readonly positions: readonly [string, ...string[]];
20
22
  /** The rule, in one plain sentence. */
@@ -23,11 +25,19 @@ export interface ValueRule {
23
25
  readonly limits?: readonly [LimitKey, ...LimitKey[]];
24
26
  /**
25
27
  * The conditions of the published JSON Schema of the document that state the rule, where some
26
- * do: the URI fragment of each `if` or `not` subschema whose failure refuses a value schema of
27
- * the document with `DV_VALUE_SCHEMA` and this rule's code as its `valueCode`.
28
+ * do: the URI fragment of each `if` or `not` subschema whose failure refuses the document with
29
+ * this rule's code.
28
30
  */
29
31
  readonly conditions?: readonly [string, ...string[]];
30
32
  }
33
+ /**
34
+ * The rule one value diagnostic code reports. Its positions are relative to the value schema, the
35
+ * value or the Domain input it checks. A condition refuses a value schema of the document with
36
+ * `DV_VALUE_SCHEMA` and this rule's code as its `valueCode`.
37
+ */
38
+ export interface ValueRule extends DiagnosticRule {
39
+ readonly stage: ValueRuleStage;
40
+ }
31
41
  /**
32
42
  * Every value diagnostic code with the rule it reports. A code added to the language does not
33
43
  * compile until it is described here.
@@ -1,8 +1,9 @@
1
+ import { deepFreeze } from '../freeze.js';
1
2
  /**
2
3
  * Every value diagnostic code with the rule it reports. A code added to the language does not
3
4
  * compile until it is described here.
4
5
  */
5
- export const VALUE_RULES = frozen({
6
+ export const VALUE_RULES = deepFreeze({
6
7
  CALLABLE_INPUT_FIELD_UNKNOWN: {
7
8
  stage: 'value',
8
9
  positions: [''],
@@ -106,13 +107,3 @@ export const VALUE_RULES = frozen({
106
107
  statement: 'A Property of value kind json is filtered by equality only, so its author is warned.',
107
108
  },
108
109
  });
109
- function frozen(rules) {
110
- for (const rule of Object.values(rules)) {
111
- Object.freeze(Object.freeze(rule).positions);
112
- if (rule.limits !== undefined)
113
- Object.freeze(rule.limits);
114
- if (rule.conditions !== undefined)
115
- Object.freeze(rule.conditions);
116
- }
117
- return Object.freeze(rules);
118
- }
@@ -1,3 +1,4 @@
1
+ import type { Options } from '@astrale-os/kernel-dsl/value';
1
2
  import type { Diagnostic } from '../../validation/diagnostic.js';
2
3
  import type { ValueProgram } from '../compile/model.js';
3
- export declare function validateValueProgram(program: ValueProgram, input: unknown, roots?: readonly number[]): readonly Diagnostic[];
4
+ export declare function validateValueProgram(program: ValueProgram, input: unknown, roots?: readonly number[], options?: Options): readonly Diagnostic[];
@@ -1,8 +1,8 @@
1
1
  import { loadValueProgram } from '../compile/load.js';
2
2
  import { validateCanonicalJsonDomain } from '../profile/json.validate.js';
3
3
  import { evaluateInstance } from './evaluator.js';
4
- export function validateValueProgram(program, input, roots = [program.root]) {
5
- const canonical = validateCanonicalJsonDomain(input, '');
4
+ export function validateValueProgram(program, input, roots = [program.root], options) {
5
+ const canonical = validateCanonicalJsonDomain(input, '', options);
6
6
  if (canonical.length > 0)
7
7
  return canonical;
8
8
  return roots.flatMap((root) => {
@@ -1,4 +1,4 @@
1
- import type { Value as JsonValue } from '@astrale-os/kernel-dsl/value';
1
+ import type { Value as JsonValue, Options } from '@astrale-os/kernel-dsl/value';
2
2
  import type { Diagnostic } from '../../validation/diagnostic.js';
3
3
  import type { JsonSchema } from '../model/schema.js';
4
4
  import type { ValueSchemaRegistry } from '../reference/registry.js';
@@ -13,4 +13,4 @@ import { type PatternPool } from './preparation.js';
13
13
  */
14
14
  export declare function validateJsonInstance(schema: JsonSchema, value: JsonValue, registry: ValueSchemaRegistry, pointer?: string, patterns?: PatternPool): Diagnostic[];
15
15
  /** Validate with the exact preparation already retained by a source-resolved Property or Callable. */
16
- export declare function validatePreparedInstance(compiled: CompiledInstanceSchema, value: unknown): Diagnostic[];
16
+ export declare function validatePreparedInstance(compiled: CompiledInstanceSchema, value: unknown, options?: Options): Diagnostic[];
@@ -24,8 +24,8 @@ export function validateJsonInstance(schema, value, registry, pointer = '', patt
24
24
  return instanceDiagnostics(prepared.value, value, pointer);
25
25
  }
26
26
  /** Validate with the exact preparation already retained by a source-resolved Property or Callable. */
27
- export function validatePreparedInstance(compiled, value) {
28
- const diagnostics = [...validateCanonicalJsonDomain(value, '')];
27
+ export function validatePreparedInstance(compiled, value, options) {
28
+ const diagnostics = [...validateCanonicalJsonDomain(value, '', options)];
29
29
  return diagnostics.length > 0
30
30
  ? diagnostics
31
31
  : instanceDiagnostics(compiled, value, '');
@@ -1,2 +1,4 @@
1
+ import { type Options } from '@astrale-os/kernel-dsl/value';
1
2
  import type { Diagnostic } from '../../validation/diagnostic.js';
2
- export declare function validateCanonicalJsonDomain(value: unknown, pointer: string): readonly Diagnostic[];
3
+ /** Whether `value` is a portable JSON Value, within the portable limits `options` overrides. */
4
+ export declare function validateCanonicalJsonDomain(value: unknown, pointer: string, options?: Options): readonly Diagnostic[];
@@ -1,8 +1,9 @@
1
1
  import { acceptForRead as acceptJsonValue, BoundaryError as JsonBoundaryError, } from '@astrale-os/kernel-dsl/value';
2
2
  import { diagnostic } from '../../validation/diagnostic.js';
3
- export function validateCanonicalJsonDomain(value, pointer) {
3
+ /** Whether `value` is a portable JSON Value, within the portable limits `options` overrides. */
4
+ export function validateCanonicalJsonDomain(value, pointer, options) {
4
5
  try {
5
- acceptJsonValue(value);
6
+ acceptJsonValue(value, options);
6
7
  return [];
7
8
  }
8
9
  catch (error) {
@@ -323,17 +323,6 @@
323
323
  }
324
324
  ]
325
325
  },
326
- "class-policy": {
327
- "anyOf": [
328
- {
329
- "type": "boolean",
330
- "const": false
331
- },
332
- {
333
- "$ref": "#/$defs/policy-ref"
334
- }
335
- ]
336
- },
337
326
  "class-ref": {
338
327
  "type": "object",
339
328
  "properties": {
@@ -587,6 +576,136 @@
587
576
  "maxLength": 100,
588
577
  "pattern": "^(?=.{1,100}$)[a-z][a-z0-9-]*(?:\\.[a-z][a-z0-9-]*)*$"
589
578
  },
579
+ "create-policy": {
580
+ "anyOf": [
581
+ {
582
+ "type": "boolean",
583
+ "const": true
584
+ },
585
+ {
586
+ "$ref": "#/$defs/create-rule-check-expr"
587
+ }
588
+ ]
589
+ },
590
+ "create-rule-check-expr": {
591
+ "anyOf": [
592
+ {
593
+ "type": "object",
594
+ "properties": {
595
+ "sameNode": {
596
+ "type": "object",
597
+ "properties": {
598
+ "left": {
599
+ "type": "object",
600
+ "properties": {
601
+ "kind": {
602
+ "type": "string",
603
+ "const": "ref"
604
+ },
605
+ "ref": {
606
+ "$ref": "#/$defs/projected-member-ref"
607
+ }
608
+ },
609
+ "required": [
610
+ "kind",
611
+ "ref"
612
+ ],
613
+ "additionalProperties": false
614
+ },
615
+ "right": {
616
+ "type": "object",
617
+ "properties": {
618
+ "kind": {
619
+ "type": "string",
620
+ "const": "ref"
621
+ },
622
+ "ref": {
623
+ "$ref": "#/$defs/projected-member-ref"
624
+ }
625
+ },
626
+ "required": [
627
+ "kind",
628
+ "ref"
629
+ ],
630
+ "additionalProperties": false
631
+ }
632
+ },
633
+ "required": [
634
+ "left",
635
+ "right"
636
+ ],
637
+ "additionalProperties": false
638
+ }
639
+ },
640
+ "required": [
641
+ "sameNode"
642
+ ],
643
+ "additionalProperties": false
644
+ },
645
+ {
646
+ "type": "object",
647
+ "properties": {
648
+ "check": {
649
+ "$ref": "#/$defs/policy-ref"
650
+ },
651
+ "object": {
652
+ "type": "object",
653
+ "properties": {
654
+ "kind": {
655
+ "type": "string",
656
+ "const": "ref"
657
+ },
658
+ "ref": {
659
+ "$ref": "#/$defs/projected-member-ref"
660
+ }
661
+ },
662
+ "required": [
663
+ "kind",
664
+ "ref"
665
+ ],
666
+ "additionalProperties": false
667
+ }
668
+ },
669
+ "required": [
670
+ "check",
671
+ "object"
672
+ ],
673
+ "additionalProperties": false
674
+ },
675
+ {
676
+ "type": "object",
677
+ "properties": {
678
+ "allOf": {
679
+ "minItems": 1,
680
+ "type": "array",
681
+ "items": {
682
+ "$ref": "#/$defs/create-rule-check-expr"
683
+ }
684
+ }
685
+ },
686
+ "required": [
687
+ "allOf"
688
+ ],
689
+ "additionalProperties": false
690
+ },
691
+ {
692
+ "type": "object",
693
+ "properties": {
694
+ "anyOf": {
695
+ "minItems": 1,
696
+ "type": "array",
697
+ "items": {
698
+ "$ref": "#/$defs/create-rule-check-expr"
699
+ }
700
+ }
701
+ },
702
+ "required": [
703
+ "anyOf"
704
+ ],
705
+ "additionalProperties": false
706
+ }
707
+ ]
708
+ },
590
709
  "dependency": {
591
710
  "type": "object",
592
711
  "properties": {
@@ -780,10 +899,19 @@
780
899
  "type": "object",
781
900
  "properties": {
782
901
  "read": {
783
- "$ref": "#/$defs/class-policy"
902
+ "$ref": "#/$defs/observation-policy"
784
903
  },
785
904
  "traverse": {
786
- "$ref": "#/$defs/class-policy"
905
+ "$ref": "#/$defs/observation-policy"
906
+ },
907
+ "create": {
908
+ "$ref": "#/$defs/write-policy"
909
+ },
910
+ "update": {
911
+ "$ref": "#/$defs/write-policy"
912
+ },
913
+ "delete": {
914
+ "$ref": "#/$defs/write-policy"
787
915
  }
788
916
  },
789
917
  "additionalProperties": false
@@ -1260,10 +1388,19 @@
1260
1388
  "type": "object",
1261
1389
  "properties": {
1262
1390
  "read": {
1263
- "$ref": "#/$defs/node-class-policy"
1391
+ "$ref": "#/$defs/observation-policy"
1264
1392
  },
1265
1393
  "traverse": {
1266
- "$ref": "#/$defs/node-class-policy"
1394
+ "$ref": "#/$defs/observation-policy"
1395
+ },
1396
+ "create": {
1397
+ "$ref": "#/$defs/create-policy"
1398
+ },
1399
+ "update": {
1400
+ "$ref": "#/$defs/write-policy"
1401
+ },
1402
+ "delete": {
1403
+ "$ref": "#/$defs/write-policy"
1267
1404
  }
1268
1405
  },
1269
1406
  "additionalProperties": false
@@ -1293,16 +1430,6 @@
1293
1430
  ],
1294
1431
  "additionalProperties": false
1295
1432
  },
1296
- "node-class-policy": {
1297
- "anyOf": [
1298
- {
1299
- "$ref": "#/$defs/class-policy"
1300
- },
1301
- {
1302
- "$ref": "#/$defs/class-rule-check-expr"
1303
- }
1304
- ]
1305
- },
1306
1433
  "node-property-definition": {
1307
1434
  "type": "object",
1308
1435
  "properties": {
@@ -1379,6 +1506,20 @@
1379
1506
  "$ref": "#/$defs/node-property-definition"
1380
1507
  }
1381
1508
  },
1509
+ "observation-policy": {
1510
+ "anyOf": [
1511
+ {
1512
+ "type": "boolean",
1513
+ "const": false
1514
+ },
1515
+ {
1516
+ "$ref": "#/$defs/policy-ref"
1517
+ },
1518
+ {
1519
+ "$ref": "#/$defs/class-rule-check-expr"
1520
+ }
1521
+ ]
1522
+ },
1382
1523
  "origin": {
1383
1524
  "type": "string",
1384
1525
  "minLength": 3,
@@ -2359,6 +2500,20 @@
2359
2500
  ],
2360
2501
  "additionalProperties": false,
2361
2502
  "description": "Every View targets its owning Domain."
2503
+ },
2504
+ "write-policy": {
2505
+ "anyOf": [
2506
+ {
2507
+ "type": "boolean",
2508
+ "const": true
2509
+ },
2510
+ {
2511
+ "$ref": "#/$defs/policy-ref"
2512
+ },
2513
+ {
2514
+ "$ref": "#/$defs/class-rule-check-expr"
2515
+ }
2516
+ ]
2362
2517
  }
2363
2518
  }
2364
2519
  }
@@ -1,12 +1,12 @@
1
1
  import { accept as acceptJsonValue, BoundaryError as JsonBoundaryError, } from '@astrale-os/kernel-dsl/value';
2
2
  import { definitionRefIndex } from '../../addressing/ordering.js';
3
3
  import { isBinaryInput } from '../../language/callable/model/callable.js';
4
+ import { deepFreeze } from '../../language/freeze.js';
4
5
  import { measureChecks } from '../../language/policy/analysis/budgets.js';
5
6
  import { PolicyTyping } from '../../language/policy/analysis/typing.js';
6
7
  import { normalizePolicyChecks } from '../../language/policy/normalization/normalize.js';
7
8
  import {} from '../../language/value/evaluate/preparation.js';
8
9
  import { analyzeDefinitions } from '../analysis/class.js';
9
- import { deepFreeze } from '../canonical/freeze.js';
10
10
  import { SchemaError, diagnostic } from '../diagnostic.js';
11
11
  import { canonicalizeCallable } from '../normalization/domain.js';
12
12
  import { lookupForDomainClosure } from '../resolution/closure.js';
@@ -1,7 +1,7 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
+ import { digestRevisionBytes } from '../../addressing/revision.js';
2
3
  import { asDomainSchema } from '../model/schema.js';
3
- import { digestDomainSchemaBytes } from './domain.digest.js';
4
- import { canonicalizeDomainSchema } from './domain.js';
4
+ import { normalizeDomainSchema } from '../normalization/domain.js';
5
5
  // Only canonical schemas created here own a retained revision, never caller-owned input.
6
6
  const revisions = new WeakMap();
7
7
  export function canonicalDomainSchema(value) {
@@ -9,9 +9,9 @@ export function canonicalDomainSchema(value) {
9
9
  }
10
10
  /** Internal acceptance seam. The caller must establish whole-Domain validity first. */
11
11
  export function canonicalDomainSchemaAfterValidation(value) {
12
- const schema = asDomainSchema(canonicalizeDomainSchema(value));
12
+ const schema = asDomainSchema(normalizeDomainSchema(value));
13
13
  const bytes = json.encode(schema);
14
- const revision = digestDomainSchemaBytes(bytes);
14
+ const revision = digestRevisionBytes(bytes);
15
15
  revisions.set(schema, revision);
16
16
  return Object.freeze({ schema, bytes, revision });
17
17
  }
@@ -1,7 +1,7 @@
1
1
  import { isMethodExecutable } from '../../../language/callable/executable.js';
2
2
  import { isBinaryInput } from '../../../language/callable/model/callable.js';
3
+ import { deepFreeze } from '../../../language/freeze.js';
3
4
  import { methodSignature as inheritedSignature } from '../../analysis/class.js';
4
- import { deepFreeze } from '../../canonical/freeze.js';
5
5
  import { keyForDefinitionRef } from '../coordinate.js';
6
6
  import { CALLABLE_FIELDS, fieldsOf } from '../fields.js';
7
7
  import { fingerprintMeaning, semanticValueSchema } from './values.js';
@@ -1,7 +1,7 @@
1
1
  import { compareUnicode } from '../../../addressing/ordering.js';
2
2
  import { compareEdgeUniqueTuples, coveringEdgeUniqueTuples, } from '../../../language/class/unique.js';
3
+ import { deepFreeze } from '../../../language/freeze.js';
3
4
  import { isClassRuleChecks } from '../../../language/policy/model/policy.js';
4
- import { deepFreeze } from '../../canonical/freeze.js';
5
5
  import { effectiveDefinition } from '../context.js';
6
6
  import { propertyCoordinate } from '../coordinate.js';
7
7
  import { keyForDefinitionRef } from '../coordinate.js';
@@ -56,12 +56,12 @@ export function classMeaning(context, coordinate, level, onto) {
56
56
  return { meaning: deepFreeze(meaning), requirement };
57
57
  }
58
58
  /**
59
- * A named Policy compares by its key; `false` or Policy checks by their value, as a callable's
59
+ * A named Policy compares by its key; a constant or Policy checks by their value, as a callable's
60
60
  * Policy does.
61
61
  */
62
62
  function classPolicyMeaning(policy) {
63
- if (policy === false)
64
- return false;
63
+ if (typeof policy === 'boolean')
64
+ return policy;
65
65
  return isClassRuleChecks(policy) ? policy : keyForDefinitionRef(policy);
66
66
  }
67
67
  /**
@@ -1,4 +1,4 @@
1
- import { deepFreeze } from '../../canonical/freeze.js';
1
+ import { deepFreeze } from '../../../language/freeze.js';
2
2
  import { CORE_FIELDS, POLICY_FIELDS, VIEW_FIELDS, fieldsOf } from '../fields.js';
3
3
  import { functionSignature } from './callables.js';
4
4
  export function memberMeaning(owner, ref) {
@@ -1,7 +1,7 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
+ import { digestRevisionBytes } from '../../../addressing/revision.js';
2
3
  import { isValueObject as isJsonObject } from '../../../language/value/model/object.js';
3
4
  import { SCHEMA_ARRAY_KEYWORDS, SCHEMA_MAP_KEYWORDS, SCHEMA_SINGLE_KEYWORDS, } from '../../../language/value/syntax/keywords.js';
4
- import { digestDomainSchemaBytes } from '../../canonical/domain.digest.js';
5
5
  import { ANNOTATION_KEYWORDS } from '../fields.js';
6
6
  /** Drop annotation keywords wherever a schema keyword nests a schema; never inside data. */
7
7
  export function semanticValueSchema(value) {
@@ -30,7 +30,7 @@ export function semanticValueSchema(value) {
30
30
  return semantic;
31
31
  }
32
32
  export function fingerprintMeaning(value) {
33
- return digestDomainSchemaBytes(json.encode(value));
33
+ return digestRevisionBytes(json.encode(value));
34
34
  }
35
35
  function isJsonSchema(value) {
36
36
  return typeof value === 'boolean' || isJsonObject(value);
@@ -1,6 +1,6 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { compareUnicode } from '../../addressing/ordering.js';
3
- import { deepFreeze } from '../canonical/freeze.js';
3
+ import { deepFreeze } from '../../language/freeze.js';
4
4
  import { fingerprintMeaning } from './comparators/values.js';
5
5
  import { differences } from './diff.js';
6
6
  import { schemaIdentity } from './references.js';
@@ -1,4 +1,4 @@
1
- import { deepFreeze } from '../../canonical/freeze.js';
1
+ import { deepFreeze } from '../../../language/freeze.js';
2
2
  import { SchemaError, diagnostic } from '../../diagnostic.js';
3
3
  import { compareFootprint } from '../meaning/footprint.js';
4
4
  import { schemaIdentity } from '../references.js';
@@ -1,4 +1,4 @@
1
- import { deepFreeze } from '../canonical/freeze.js';
1
+ import { deepFreeze } from '../../language/freeze.js';
2
2
  export function asDomainSchema(value) {
3
3
  return deepFreeze(value);
4
4
  }
@@ -2,6 +2,7 @@ import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { compareDefinitionRefs, compareUnicode } from '../../addressing/ordering.js';
3
3
  import { isBinaryInput } from '../../language/callable/model/callable.js';
4
4
  import { compareEdgeUniqueFields, compareEdgeUniqueTuples, compareNodeUniqueTuples, } from '../../language/class/unique.js';
5
+ import { CLASS_OPERATIONS } from '../../language/policy/model/policy.js';
5
6
  import { normalizeClassRule, normalizePolicyChecks, normalizePolicyExpression, } from '../../language/policy/normalization/normalize.js';
6
7
  import { admitStateTopology } from '../../language/state/topology.js';
7
8
  import { canonicalizeValueSchema } from '../../language/value/profile/canonicalize.js';
@@ -72,7 +73,7 @@ function canonicalizeClass(value) {
72
73
  methods: mapRecord(value.methods, canonicalizeMethod),
73
74
  ...(value.data === undefined ? {} : { data: { mediaType: value.data.mediaType } }),
74
75
  ...(value.icon === undefined ? {} : { icon: value.icon }),
75
- policies: canonicalizeNodePolicies(value.policies),
76
+ policies: canonicalizeClassPolicies(value.policies),
76
77
  ...(value.unique === undefined ? {} : { unique: canonicalizeNodeUnique(value.unique) }),
77
78
  };
78
79
  }
@@ -81,7 +82,7 @@ function canonicalizeClass(value) {
81
82
  ...base,
82
83
  orientation: 'directed',
83
84
  endpoints: canonicalizeDirectedEndpoints(value.endpoints),
84
- policies: value.policies,
85
+ policies: canonicalizeClassPolicies(value.policies),
85
86
  constraints: value.constraints,
86
87
  ...(value.unique === undefined ? {} : { unique: canonicalizeUnique(value.unique) }),
87
88
  }
@@ -89,7 +90,7 @@ function canonicalizeClass(value) {
89
90
  ...base,
90
91
  orientation: 'undirected',
91
92
  endpoints: canonicalizeIncidentEndpoints(value.endpoints),
92
- policies: value.policies,
93
+ policies: canonicalizeClassPolicies(value.policies),
93
94
  constraints: value.constraints,
94
95
  };
95
96
  }
@@ -106,11 +107,11 @@ function canonicalizeUnique(tuples) {
106
107
  .sort(compareEdgeUniqueTuples);
107
108
  }
108
109
  /** A rule keeps one spelling: normalized checks, or the Policy a lone `self` check names. */
109
- function canonicalizeNodePolicies(value) {
110
- return {
111
- ...(value.read === undefined ? {} : { read: normalizeClassRule(value.read) }),
112
- ...(value.traverse === undefined ? {} : { traverse: normalizeClassRule(value.traverse) }),
113
- };
110
+ function canonicalizeClassPolicies(value) {
111
+ return Object.fromEntries(CLASS_OPERATIONS.flatMap((operation) => {
112
+ const policy = value[operation];
113
+ return policy === undefined ? [] : [[operation, normalizeClassRule(policy)]];
114
+ }));
114
115
  }
115
116
  function canonicalizeFunction(value) {
116
117
  return {
@@ -97,7 +97,7 @@ export function callableValidation(input, output, registry, patterns) {
97
97
  const fields = inputFieldNodes(inputProgram);
98
98
  return Object.freeze({
99
99
  ...(fields === undefined ? {} : { fields: Object.freeze(Object.keys(fields)) }),
100
- validateInput: (value) => validatePreparedInstance(prepared.value, value),
100
+ validateInput: (value, options) => validatePreparedInstance(prepared.value, value, options),
101
101
  validateInputField(field, value) {
102
102
  const nodes = fields?.[field];
103
103
  return nodes === undefined