@astrale-os/kernel-dsl 0.2.0-beta.8 → 1.0.0-beta.1
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.
- package/dist/v1/addressing/class-key.js +5 -4
- package/dist/v1/addressing/method-key.js +3 -2
- package/dist/v1/addressing/patterns.d.ts +0 -5
- package/dist/v1/addressing/patterns.js +5 -5
- package/dist/v1/builder/callable/authoring.d.ts +87 -41
- package/dist/v1/builder/callable/authoring.js +29 -14
- package/dist/v1/builder/class/authoring.d.ts +311 -36
- package/dist/v1/builder/class/authoring.js +3 -4
- package/dist/v1/builder/class/property.d.ts +16 -8
- package/dist/v1/builder/class/property.js +21 -5
- package/dist/v1/builder/core/authoring.d.ts +28 -13
- package/dist/v1/builder/core/authoring.js +22 -2
- package/dist/v1/builder/index.d.ts +9 -8
- package/dist/v1/builder/index.js +2 -2
- package/dist/v1/builder/lowering/callable.d.ts +3 -1
- package/dist/v1/builder/lowering/callable.js +43 -51
- package/dist/v1/builder/lowering/class.d.ts +7 -0
- package/dist/v1/builder/lowering/class.js +79 -29
- package/dist/v1/builder/lowering/core.d.ts +3 -2
- package/dist/v1/builder/lowering/core.js +9 -6
- package/dist/v1/builder/lowering/policy.d.ts +8 -1
- package/dist/v1/builder/lowering/policy.js +35 -0
- package/dist/v1/builder/lowering/schema/capture.js +9 -4
- package/dist/v1/builder/lowering/schema/compile.d.ts +2 -2
- package/dist/v1/builder/lowering/schema/compile.js +15 -2
- package/dist/v1/builder/lowering/schema/context.d.ts +11 -8
- package/dist/v1/builder/lowering/schema/context.js +59 -29
- package/dist/v1/builder/lowering/schema/ownership.d.ts +3 -3
- package/dist/v1/builder/lowering/schema/ownership.js +2 -1
- package/dist/v1/builder/lowering/value/compile.js +14 -4
- package/dist/v1/builder/lowering/value/zod.d.ts +7 -6
- package/dist/v1/builder/lowering/value/zod.js +16 -7
- package/dist/v1/builder/lowering/view.d.ts +4 -3
- package/dist/v1/builder/lowering/view.js +2 -14
- package/dist/v1/builder/policy/authoring.d.ts +23 -6
- package/dist/v1/builder/policy/authoring.js +35 -8
- package/dist/v1/builder/schema/define.d.ts +8 -5
- package/dist/v1/builder/schema/diagnostic.d.ts +1 -1
- package/dist/v1/builder/schema/handle.d.ts +2 -1
- package/dist/v1/builder/schema/input.d.ts +9 -1
- package/dist/v1/builder/schema/projection/callable.d.ts +51 -0
- package/dist/v1/builder/schema/projection/callable.js +1 -0
- package/dist/v1/builder/schema/projection/class.d.ts +89 -0
- package/dist/v1/builder/schema/projection/class.js +1 -0
- package/dist/v1/builder/schema/projection/core-input.d.ts +32 -0
- package/dist/v1/builder/schema/projection/core-input.js +1 -0
- package/dist/v1/builder/schema/projection/domain.d.ts +59 -0
- package/dist/v1/builder/schema/projection/domain.js +1 -0
- package/dist/v1/builder/schema/projection/identity.d.ts +39 -0
- package/dist/v1/builder/schema/projection/identity.js +1 -0
- package/dist/v1/builder/schema/projection/model.d.ts +59 -0
- package/dist/v1/builder/schema/projection/model.js +1 -0
- package/dist/v1/builder/schema/projection/property.d.ts +32 -0
- package/dist/v1/builder/schema/projection/property.js +1 -0
- package/dist/v1/builder/schema/projection/resolved-class.d.ts +76 -0
- package/dist/v1/builder/schema/projection/resolved-class.js +1 -0
- package/dist/v1/builder/schema/projection.d.ts +4 -258
- package/dist/v1/builder/value/full-match.js +6 -3
- package/dist/v1/builder/value/path.d.ts +2 -2
- package/dist/v1/builder/value/path.js +2 -2
- package/dist/v1/builder/view/authoring.d.ts +6 -14
- package/dist/v1/builder/view/authoring.js +13 -5
- package/dist/v1/bundle/structure.d.ts +2 -1
- package/dist/v1/compiled/admission/accept.d.ts +1 -1
- package/dist/v1/compiled/admission/accept.js +11 -814
- package/dist/v1/compiled/admission/closure.d.ts +3 -0
- package/dist/v1/compiled/admission/closure.js +173 -0
- package/dist/v1/compiled/admission/diagnostic.d.ts +7 -0
- package/dist/v1/compiled/admission/diagnostic.js +13 -0
- package/dist/v1/compiled/admission/revision.js +9 -1
- package/dist/v1/compiled/admission/semantics/cardinality.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/cardinality.js +113 -0
- package/dist/v1/compiled/admission/semantics/class.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/class.js +125 -0
- package/dist/v1/compiled/admission/semantics/context.d.ts +60 -0
- package/dist/v1/compiled/admission/semantics/context.js +81 -0
- package/dist/v1/compiled/admission/semantics/core.d.ts +35 -0
- package/dist/v1/compiled/admission/semantics/core.js +123 -0
- package/dist/v1/compiled/admission/semantics/edge.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/edge.js +89 -0
- package/dist/v1/compiled/admission/semantics/policy/admit.d.ts +4 -0
- package/dist/v1/compiled/admission/semantics/policy/admit.js +63 -0
- package/dist/v1/compiled/admission/semantics/policy/callable.d.ts +5 -0
- package/dist/v1/compiled/admission/semantics/policy/callable.js +72 -0
- package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +24 -0
- package/dist/v1/compiled/admission/semantics/policy/contracts.js +45 -0
- package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/policy/equality.js +27 -0
- package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +9 -0
- package/dist/v1/compiled/admission/semantics/policy/measure.js +81 -0
- package/dist/v1/compiled/admission/semantics/policy/parity.d.ts +4 -0
- package/dist/v1/compiled/admission/semantics/policy/parity.js +138 -0
- package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +8 -0
- package/dist/v1/compiled/admission/semantics/policy/pattern.js +78 -0
- package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +28 -0
- package/dist/v1/compiled/admission/semantics/policy/typing.js +206 -0
- package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +10 -0
- package/dist/v1/compiled/admission/semantics/policy/variants.js +65 -0
- package/dist/v1/compiled/admission/semantics.d.ts +1 -1
- package/dist/v1/compiled/admission/semantics.js +8 -1078
- package/dist/v1/compiled/admission/wire/callable.d.ts +6 -0
- package/dist/v1/compiled/admission/wire/callable.js +90 -0
- package/dist/v1/compiled/admission/wire/class.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/class.js +133 -0
- package/dist/v1/compiled/admission/wire/core.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/core.js +32 -0
- package/dist/v1/compiled/admission/wire/dependency.d.ts +14 -0
- package/dist/v1/compiled/admission/wire/dependency.js +43 -0
- package/dist/v1/compiled/admission/wire/entry.d.ts +5 -0
- package/dist/v1/compiled/admission/wire/entry.js +100 -0
- package/dist/v1/compiled/admission/wire/pattern.d.ts +12 -0
- package/dist/v1/compiled/admission/wire/pattern.js +111 -0
- package/dist/v1/compiled/admission/wire/policy.d.ts +10 -0
- package/dist/v1/compiled/admission/wire/policy.js +189 -0
- package/dist/v1/compiled/admission/wire/program.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/program.js +52 -0
- package/dist/v1/compiled/admission/wire/property.d.ts +4 -0
- package/dist/v1/compiled/admission/wire/property.js +74 -0
- package/dist/v1/compiled/admission/wire/reference.d.ts +8 -0
- package/dist/v1/compiled/admission/wire/reference.js +33 -0
- package/dist/v1/compiled/admission/wire/value.d.ts +29 -0
- package/dist/v1/compiled/admission/wire/value.js +98 -0
- package/dist/v1/compiled/admission/wire/view.d.ts +3 -0
- package/dist/v1/compiled/admission/wire/view.js +17 -0
- package/dist/v1/compiled/compiler/compile.js +43 -11
- package/dist/v1/compiled/generated.d.ts +10 -0
- package/dist/v1/compiled/generated.js +15 -0
- package/dist/v1/compiled/loader/load.d.ts +5 -0
- package/dist/v1/compiled/loader/load.js +18 -4
- package/dist/v1/compiled/model/schema.d.ts +16 -7
- package/dist/v1/domain/create.js +18 -28
- package/dist/v1/domain/model/domain.d.ts +0 -1
- package/dist/v1/domain/model/input.d.ts +3 -0
- package/dist/v1/domain/projection/classes.js +13 -41
- package/dist/v1/domain/validation/create.d.ts +2 -0
- package/dist/v1/domain/validation/create.js +12 -0
- package/dist/v1/index.d.ts +5 -2
- package/dist/v1/index.js +3 -1
- package/dist/v1/language/callable/composition.d.ts +27 -0
- package/dist/v1/language/callable/composition.js +52 -0
- package/dist/v1/language/callable/executable.d.ts +6 -0
- package/dist/v1/language/callable/executable.js +4 -0
- package/dist/v1/language/callable/model/callable.d.ts +34 -9
- package/dist/v1/language/callable/model/callable.js +3 -1
- package/dist/v1/language/callable/resolved.d.ts +23 -8
- package/dist/v1/language/class/facets.d.ts +5 -2
- package/dist/v1/language/class/inheritance.d.ts +12 -0
- package/dist/v1/language/class/inheritance.js +25 -0
- package/dist/v1/language/class/lifetime.d.ts +17 -0
- package/dist/v1/language/class/lifetime.js +26 -0
- package/dist/v1/language/class/model/class.d.ts +8 -4
- package/dist/v1/language/class/model/property.d.ts +4 -2
- package/dist/v1/language/class/property-values.js +5 -2
- package/dist/v1/language/class/resolved.d.ts +25 -15
- package/dist/v1/language/core/model/core.d.ts +7 -1
- package/dist/v1/language/core/resolved.d.ts +6 -2
- package/dist/v1/language/definition/metadata.d.ts +8 -0
- package/dist/v1/language/definition/metadata.js +12 -0
- package/dist/v1/language/index.d.ts +9 -0
- package/dist/v1/language/index.js +6 -0
- package/dist/v1/language/policy/analysis/branches.d.ts +4 -3
- package/dist/v1/language/policy/analysis/branches.js +54 -12
- package/dist/v1/language/policy/analysis/budgets.js +1 -1
- package/dist/v1/language/policy/analysis/checks.d.ts +28 -0
- package/dist/v1/language/policy/analysis/checks.js +80 -0
- package/dist/v1/language/policy/index.d.ts +1 -0
- package/dist/v1/language/policy/index.js +1 -0
- package/dist/v1/language/policy/model/policy.d.ts +71 -5
- package/dist/v1/language/policy/model/policy.js +52 -1
- package/dist/v1/language/policy/normalization/normalize.d.ts +12 -1
- package/dist/v1/language/policy/normalization/normalize.js +178 -44
- package/dist/v1/language/state/index.d.ts +3 -0
- package/dist/v1/language/state/index.js +1 -0
- package/dist/v1/language/state/machine.d.ts +28 -0
- package/dist/v1/language/state/machine.js +40 -0
- package/dist/v1/language/state/topology.d.ts +14 -0
- package/dist/v1/language/state/topology.js +69 -0
- package/dist/v1/language/value/compile/fields.d.ts +1 -1
- package/dist/v1/language/value/compile/load.d.ts +4 -2
- package/dist/v1/language/value/compile/load.js +22 -1
- package/dist/v1/language/value/compile/model.d.ts +16 -1
- package/dist/v1/language/value/evaluate/assertions.d.ts +2 -0
- package/dist/v1/language/value/evaluate/assertions.js +13 -0
- package/dist/v1/language/value/evaluate/evaluator.js +111 -28
- package/dist/v1/language/value/evaluate/preparation.d.ts +10 -1
- package/dist/v1/language/value/evaluate/preparation.js +17 -26
- package/dist/v1/language/value/evaluate/program.js +1 -1
- package/dist/v1/language/value/evaluate/validate.d.ts +6 -2
- package/dist/v1/language/value/evaluate/validate.js +18 -11
- package/dist/v1/language/value/inclusion/includes.d.ts +9 -0
- package/dist/v1/language/value/inclusion/includes.js +777 -0
- package/dist/v1/language/value/model/blob.d.ts +31 -0
- package/dist/v1/language/value/model/blob.js +90 -0
- package/dist/v1/language/value/model/instant.d.ts +0 -2
- package/dist/v1/language/value/model/instant.js +1 -1
- package/dist/v1/language/value/model/schema.d.ts +2 -1
- package/dist/v1/language/value/model/schema.js +1 -5
- package/dist/v1/language/value/ordering.d.ts +2 -0
- package/dist/v1/language/value/ordering.js +4 -8
- package/dist/v1/language/value/profile/json.validate.js +1 -1
- package/dist/v1/language/value/profile/rules.js +48 -12
- package/dist/v1/language/value/reference/registry.d.ts +2 -1
- package/dist/v1/language/value/regexp/ast.js +3 -64
- package/dist/v1/language/value/regexp/compile.d.ts +32 -3
- package/dist/v1/language/value/regexp/compile.js +117 -21
- package/dist/v1/language/value/regexp/matcher.d.ts +6 -3
- package/dist/v1/language/value/regexp/matcher.js +185 -28
- package/dist/v1/language/value/regexp/syntax.d.ts +12 -1
- package/dist/v1/language/value/regexp/syntax.js +14 -2
- package/dist/v1/language/value/regexp/unicode.d.ts +32 -0
- package/dist/v1/language/value/regexp/unicode.js +139 -0
- package/dist/v1/language/value/syntax/full-match.js +8 -5
- package/dist/v1/language/value/syntax/node-path/validate.js +4 -6
- package/dist/v1/language/view/model/view.d.ts +2 -4
- package/dist/v1/language/view/resolved.d.ts +2 -2
- package/dist/v1/schema/analysis/class.d.ts +36 -6
- package/dist/v1/schema/analysis/class.js +31 -66
- package/dist/v1/schema/canonical/revision.d.ts +2 -1
- package/dist/v1/schema/canonical/revision.js +4 -1
- package/dist/v1/schema/compatibility/api.d.ts +3 -0
- package/dist/v1/schema/compatibility/api.js +2 -0
- package/dist/v1/schema/compatibility/comparators/callables.d.ts +39 -0
- package/dist/v1/schema/compatibility/comparators/callables.js +101 -0
- package/dist/v1/schema/compatibility/comparators/classes.d.ts +47 -0
- package/dist/v1/schema/compatibility/comparators/classes.js +160 -0
- package/dist/v1/schema/compatibility/comparators/index.d.ts +12 -0
- package/dist/v1/schema/compatibility/comparators/index.js +53 -0
- package/dist/v1/schema/compatibility/comparators/members.d.ts +4 -0
- package/dist/v1/schema/compatibility/comparators/members.js +49 -0
- package/dist/v1/schema/compatibility/comparators/values.d.ts +5 -0
- package/dist/v1/schema/compatibility/comparators/values.js +37 -0
- package/dist/v1/schema/compatibility/compare.d.ts +5 -0
- package/dist/v1/schema/compatibility/compare.js +23 -0
- package/dist/v1/schema/compatibility/context.d.ts +19 -0
- package/dist/v1/schema/compatibility/context.js +49 -0
- package/dist/v1/schema/compatibility/coordinate.d.ts +40 -0
- package/dist/v1/schema/compatibility/coordinate.js +38 -0
- package/dist/v1/schema/compatibility/diff.d.ts +12 -0
- package/dist/v1/schema/compatibility/diff.js +39 -0
- package/dist/v1/schema/compatibility/evidence.d.ts +16 -0
- package/dist/v1/schema/compatibility/evidence.js +62 -0
- package/dist/v1/schema/compatibility/fields.d.ts +194 -0
- package/dist/v1/schema/compatibility/fields.js +94 -0
- package/dist/v1/schema/compatibility/index.d.ts +6 -0
- package/dist/v1/schema/compatibility/index.js +3 -0
- package/dist/v1/schema/compatibility/meaning/footprint.d.ts +7 -0
- package/dist/v1/schema/compatibility/meaning/footprint.js +59 -0
- package/dist/v1/schema/compatibility/meaning/index.d.ts +3 -0
- package/dist/v1/schema/compatibility/meaning/index.js +16 -0
- package/dist/v1/schema/compatibility/model.d.ts +131 -0
- package/dist/v1/schema/compatibility/model.js +1 -0
- package/dist/v1/schema/compatibility/references.d.ts +38 -0
- package/dist/v1/schema/compatibility/references.js +149 -0
- package/dist/v1/schema/compatibility/report.d.ts +27 -0
- package/dist/v1/schema/compatibility/report.js +100 -0
- package/dist/v1/schema/compatibility/scope.d.ts +36 -0
- package/dist/v1/schema/compatibility/scope.js +110 -0
- package/dist/v1/schema/compatibility/structure/index.d.ts +3 -0
- package/dist/v1/schema/compatibility/structure/index.js +40 -0
- package/dist/v1/schema/compatibility/structure/inheritance.d.ts +7 -0
- package/dist/v1/schema/compatibility/structure/inheritance.js +68 -0
- package/dist/v1/schema/compatibility/structure/requirements.d.ts +7 -0
- package/dist/v1/schema/compatibility/structure/requirements.js +97 -0
- package/dist/v1/schema/compatibility/subjects.d.ts +39 -0
- package/dist/v1/schema/compatibility/subjects.js +143 -0
- package/dist/v1/schema/compatibility/versioning/index.d.ts +8 -0
- package/dist/v1/schema/compatibility/versioning/index.js +50 -0
- package/dist/v1/schema/compatibility/versioning/members.d.ts +12 -0
- package/dist/v1/schema/compatibility/versioning/members.js +47 -0
- package/dist/v1/schema/compatibility/versioning/surface.d.ts +11 -0
- package/dist/v1/schema/compatibility/versioning/surface.js +61 -0
- package/dist/v1/schema/diagnostic.d.ts +1 -1
- package/dist/v1/schema/fingerprint.d.ts +2 -0
- package/dist/v1/schema/fingerprint.js +1 -0
- package/dist/v1/schema/index.d.ts +4 -3
- package/dist/v1/schema/index.js +2 -1
- package/dist/v1/schema/model/schema.d.ts +8 -11
- package/dist/v1/schema/normalization/domain.js +57 -13
- package/dist/v1/schema/resolution/definition.index.d.ts +1 -2
- package/dist/v1/schema/resolution/definition.index.js +0 -3
- package/dist/v1/schema/resolution/domain.d.ts +4 -1
- package/dist/v1/schema/resolution/domain.js +26 -18
- package/dist/v1/schema/resolution/origins.d.ts +28 -5
- package/dist/v1/schema/resolution/origins.js +68 -31
- package/dist/v1/schema/validation/callable.d.ts +4 -0
- package/dist/v1/schema/validation/callable.js +39 -0
- package/dist/v1/schema/validation/class.d.ts +10 -0
- package/dist/v1/schema/validation/class.js +79 -60
- package/dist/v1/schema/validation/core.js +83 -55
- package/dist/v1/schema/validation/domain.d.ts +2 -1
- package/dist/v1/schema/validation/domain.js +2 -0
- package/dist/v1/schema/validation/domain.structure.d.ts +0 -2
- package/dist/v1/schema/validation/domain.structure.js +214 -171
- package/dist/v1/schema/validation/policy/budgets.js +36 -6
- package/dist/v1/schema/validation/policy/context.js +5 -16
- package/dist/v1/schema/validation/policy/objects.d.ts +4 -0
- package/dist/v1/schema/validation/policy/objects.js +71 -0
- package/dist/v1/schema/validation/policy/references.js +16 -4
- package/dist/v1/schema/validation/policy/typing.d.ts +2 -0
- package/dist/v1/schema/validation/policy/typing.js +55 -7
- package/dist/v1/schema/validation/policy/uses.js +73 -99
- package/dist/v1/schema/validation/value-api.d.ts +2 -0
- package/dist/v1/schema/validation/value-api.js +1 -0
- package/dist/v1/schema/validation/value.js +7 -1
- package/dist/v1/schema/validation/view.js +14 -9
- package/dist/value/accept.d.ts +9 -0
- package/dist/value/accept.js +106 -7
- package/dist/value/canonical.d.ts +3 -0
- package/dist/value/canonical.js +22 -6
- package/dist/value/immutable.optimization.d.ts +15 -0
- package/dist/value/immutable.optimization.js +34 -0
- package/dist/value/index.d.ts +1 -1
- package/dist/value/index.js +1 -1
- package/dist/value/json.d.ts +1 -1
- package/dist/value/json.js +1 -1
- package/dist/value/limits.d.ts +1 -1
- package/dist/value/unicode.d.ts +4 -1
- package/dist/value/unicode.js +28 -0
- package/package.json +20 -5
- package/dist/v1/schema/compatibility/meaning.d.ts +0 -29
- package/dist/v1/schema/compatibility/meaning.js +0 -605
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Key } from '../../../addressing/index.js';
|
|
2
2
|
import { definitionRefIndex } from '../../../addressing/ordering.js';
|
|
3
|
+
import { classSatisfies } from '../../../language/class/inheritance.js';
|
|
3
4
|
import { diagnostic } from '../../diagnostic.js';
|
|
4
5
|
const formatDefinitionRef = Key.of;
|
|
5
6
|
export class PolicyValidationContext {
|
|
@@ -63,22 +64,10 @@ export class PolicyValidationContext {
|
|
|
63
64
|
}
|
|
64
65
|
/** Return true when candidate is the required Class or a same-kind descendant. */
|
|
65
66
|
classExtends(candidate, required) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
const key = definitionRefIndex(ref);
|
|
71
|
-
if (key === definitionRefIndex(required))
|
|
72
|
-
return true;
|
|
73
|
-
if (visited.has(key))
|
|
74
|
-
return false;
|
|
75
|
-
visited.add(key);
|
|
76
|
-
const resolved = this.environment.resolveAny(ref);
|
|
77
|
-
if (resolved === undefined || resolved.ref.kind !== 'class')
|
|
78
|
-
return false;
|
|
79
|
-
return resolved.declaration.extends.some(visit);
|
|
80
|
-
};
|
|
81
|
-
return visit(candidate);
|
|
67
|
+
const resolve = (ref) => this.environment.resolveAny(ref)?.declaration;
|
|
68
|
+
const actual = resolve(candidate);
|
|
69
|
+
const target = resolve(required);
|
|
70
|
+
return actual !== undefined && target !== undefined && classSatisfies(actual, target, resolve);
|
|
82
71
|
}
|
|
83
72
|
add(code, pointer, message, ref) {
|
|
84
73
|
this.diagnostics.push(diagnostic(code, pointer, message, ref));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PolicyObjectRef } from '../../../language/index.js';
|
|
2
|
+
import type { PolicyValidationContext } from './context.js';
|
|
3
|
+
import type { ObjectContract } from './typing.js';
|
|
4
|
+
export declare function referenceContracts(validation: PolicyValidationContext, ref: PolicyObjectRef, pointer: string): readonly ObjectContract[] | undefined;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { definitionRefIndex } from '../../../addressing/ordering.js';
|
|
2
|
+
import { isMethodExecutable } from '../../../language/callable/executable.js';
|
|
3
|
+
import { policyObjectKey, policyObjectOrigin } from '../../../language/index.js';
|
|
4
|
+
const KERNEL_ORIGIN = 'kernel.astrale.ai';
|
|
5
|
+
const PROJECTION_CLASS = nodeClassRef('Class');
|
|
6
|
+
const PROJECTION_FUNCTION = nodeClassRef('Function');
|
|
7
|
+
const PROJECTION_POLICY = nodeClassRef('Policy');
|
|
8
|
+
const PROJECTION_VIEW = nodeClassRef('View');
|
|
9
|
+
export function referenceContracts(validation, ref, pointer) {
|
|
10
|
+
const candidate = validation.environment.candidate;
|
|
11
|
+
const local = policyObjectOrigin(ref) === candidate.origin;
|
|
12
|
+
const direct = Object.values(candidate.dependencies).some((entry) => entry.origin === policyObjectOrigin(ref));
|
|
13
|
+
const owner = local
|
|
14
|
+
? candidate
|
|
15
|
+
: direct
|
|
16
|
+
? validation.environment.dependencies.get(policyObjectOrigin(ref))
|
|
17
|
+
: undefined;
|
|
18
|
+
if (owner === undefined)
|
|
19
|
+
return invalidPolicyObjectRef(validation, ref, pointer);
|
|
20
|
+
switch (ref.kind) {
|
|
21
|
+
case 'class': {
|
|
22
|
+
const resolved = validation.environment.resolve(ref);
|
|
23
|
+
return resolved?.ref.kind === ref.kind
|
|
24
|
+
? [{ kind: 'exact', ref: PROJECTION_CLASS }]
|
|
25
|
+
: invalidPolicyObjectRef(validation, ref, pointer);
|
|
26
|
+
}
|
|
27
|
+
case 'method': {
|
|
28
|
+
const declaringClass = owner.classes[ref.owner.name];
|
|
29
|
+
const method = declaringClass?.kind === 'node' ? declaringClass.methods[ref.name] : undefined;
|
|
30
|
+
return method === undefined || !isMethodExecutable(declaringClass, method)
|
|
31
|
+
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
32
|
+
: [{ kind: 'exact', ref: PROJECTION_FUNCTION }];
|
|
33
|
+
}
|
|
34
|
+
case 'function':
|
|
35
|
+
return owner.functions[ref.name] === undefined
|
|
36
|
+
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
37
|
+
: [{ kind: 'exact', ref: PROJECTION_FUNCTION }];
|
|
38
|
+
case 'policy':
|
|
39
|
+
return owner.policies[ref.name] === undefined
|
|
40
|
+
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
41
|
+
: [{ kind: 'exact', ref: PROJECTION_POLICY }];
|
|
42
|
+
case 'view':
|
|
43
|
+
return owner.views[ref.name] === undefined
|
|
44
|
+
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
45
|
+
: [{ kind: 'exact', ref: PROJECTION_VIEW }];
|
|
46
|
+
case 'core': {
|
|
47
|
+
const node = owner.core.nodes[ref.name];
|
|
48
|
+
if (node === undefined)
|
|
49
|
+
return invalidPolicyObjectRef(validation, ref, pointer);
|
|
50
|
+
const resolved = validation.environment.resolve(node.class);
|
|
51
|
+
const analyzed = validation.analysis.definitions.get(definitionRefIndex(node.class));
|
|
52
|
+
// Core validation owns invalid Core Class diagnostics. Avoid adding Policy noise for
|
|
53
|
+
// a Node that cannot materialize in the first place.
|
|
54
|
+
if (node.class.origin !== owner.origin ||
|
|
55
|
+
resolved?.ref.kind !== 'class' ||
|
|
56
|
+
resolved.kind !== 'node' ||
|
|
57
|
+
analyzed === undefined) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return [{ kind: 'exact', ref: node.class }];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return invalidPolicyObjectRef(validation, ref, pointer);
|
|
64
|
+
}
|
|
65
|
+
function invalidPolicyObjectRef(validation, ref, pointer) {
|
|
66
|
+
validation.add('PL_REF', `${pointer}/ref`, `${policyObjectKey(ref)} is not an exact local or direct-dependency projected Policy object.`, policyObjectKey(ref));
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
function nodeClassRef(name) {
|
|
70
|
+
return { origin: KERNEL_ORIGIN, kind: 'class', name };
|
|
71
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { branchesOf, isConnected, targetMode } from '../../../language/policy/analysis/branches.js';
|
|
2
|
+
import { policyVariableClass } from '../../../language/policy/model/policy.js';
|
|
2
3
|
import { normalizePolicyExpression, normalizePolicyPattern, } from '../../../language/policy/normalization/normalize.js';
|
|
3
4
|
import { MAX_REPEAT, MAX_VARIABLES } from './budgets.js';
|
|
4
5
|
import { escapePointer } from './context.js';
|
|
6
|
+
import { referenceContracts } from './objects.js';
|
|
5
7
|
export function validatePolicyReferences(context) {
|
|
6
8
|
for (const [name, declaration] of Object.entries(context.environment.candidate.policies)) {
|
|
7
9
|
const pointer = `/policies/${escapePointer(name)}`;
|
|
@@ -34,15 +36,20 @@ function validateMatch(context, name, pattern, pointer) {
|
|
|
34
36
|
for (const [index, branch] of branches.entries()) {
|
|
35
37
|
const mode = targetMode(branch);
|
|
36
38
|
if (mode === undefined) {
|
|
37
|
-
context.add('PL_TARGET', `${pointer}/match`, `Normalized branch ${index} must use object or
|
|
39
|
+
context.add('PL_TARGET', `${pointer}/match`, `Normalized branch ${index} must use object or at least one of source and target, without mixing target modes.`);
|
|
38
40
|
continue;
|
|
39
41
|
}
|
|
40
42
|
if (!isConnected(branch)) {
|
|
41
|
-
context.add('PL_CONNECTIVITY', `${pointer}/match`, `Normalized ${mode} branch ${index} does not connect subject,
|
|
43
|
+
context.add('PL_CONNECTIVITY', `${pointer}/match`, `Normalized ${mode} branch ${index} does not connect subject, every referenced protected term, and every scoped term.`);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
function validatePatternNode(context, pattern, pointer, scope, declarations, uses) {
|
|
48
|
+
if ('sameNode' in pattern) {
|
|
49
|
+
validateTerm(context, pattern.sameNode.left, `${pointer}/sameNode/left`, scope, uses);
|
|
50
|
+
validateTerm(context, pattern.sameNode.right, `${pointer}/sameNode/right`, scope, uses);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
46
53
|
if (isEdge(pattern)) {
|
|
47
54
|
context.resolveEdge(pattern.class, `${pointer}/class`);
|
|
48
55
|
validateTerm(context, pattern.source, `${pointer}/source`, scope, uses);
|
|
@@ -71,13 +78,16 @@ function validatePatternNode(context, pattern, pointer, scope, declarations, use
|
|
|
71
78
|
context.add('PL_VARIABLE_SCOPE', `${declarationPointer}/variable/id`, `Variable ${id} is declared more than once; variable IDs are globally unique.`);
|
|
72
79
|
}
|
|
73
80
|
else {
|
|
74
|
-
declarations.set(id, {
|
|
81
|
+
declarations.set(id, { pointer: declarationPointer });
|
|
75
82
|
}
|
|
76
83
|
if (nested.has(id)) {
|
|
77
84
|
context.add('PL_VARIABLE_SCOPE', `${declarationPointer}/variable/id`, `Variable ${id} shadows an enclosing variable.`);
|
|
78
85
|
}
|
|
79
86
|
nested.add(id);
|
|
80
|
-
|
|
87
|
+
const classRef = policyVariableClass(node);
|
|
88
|
+
if (classRef !== undefined) {
|
|
89
|
+
context.resolveNodeClass(classRef, `${declarationPointer}/${'class' in node ? 'class' : 'selector/class'}`);
|
|
90
|
+
}
|
|
81
91
|
}
|
|
82
92
|
validatePatternNode(context, pattern.exists.where, `${pointer}/exists/where`, nested, declarations, uses);
|
|
83
93
|
return;
|
|
@@ -89,6 +99,8 @@ function validatePatternNode(context, pattern, pointer, scope, declarations, use
|
|
|
89
99
|
values.forEach((child, index) => validatePatternNode(context, child, `${pointer}/${key}/${index}`, scope, declarations, uses));
|
|
90
100
|
}
|
|
91
101
|
function validateTerm(context, term, pointer, scope, uses) {
|
|
102
|
+
if (term.kind === 'ref')
|
|
103
|
+
referenceContracts(context, term.ref, pointer);
|
|
92
104
|
if (term.kind === 'variable') {
|
|
93
105
|
if (!scope.has(term.id)) {
|
|
94
106
|
context.add('PL_VARIABLE_SCOPE', pointer, `Variable ${term.id} is free, escaped, or outside its defining exists scope.`);
|
|
@@ -12,6 +12,8 @@ export declare class PolicyTyping {
|
|
|
12
12
|
constructor(context: PolicyValidationContext);
|
|
13
13
|
validatePolicies(): void;
|
|
14
14
|
policyAccepts(name: string, object: ObjectContract): boolean;
|
|
15
|
+
/** Whether each normalized branch of the Policy is typed for an object of this contract. */
|
|
16
|
+
policyBranchTyping(name: string, object: ObjectContract): readonly boolean[] | undefined;
|
|
15
17
|
policyAcceptsEdge(name: string, source: ObjectContract, target: ObjectContract): boolean;
|
|
16
18
|
concreteEndpointClasses(accepts: readonly ClassRef[]): readonly ClassRef[];
|
|
17
19
|
endpointsOverlap(left: readonly ClassRef[], right: readonly ClassRef[]): boolean;
|
|
@@ -2,8 +2,16 @@ import { definitionRefIndex } from '../../../addressing/ordering.js';
|
|
|
2
2
|
import { branchesOf, branchProduct, capBranches, targetMode, termKey, } from '../../../language/policy/analysis/branches.js';
|
|
3
3
|
import { MAX_REPEAT } from './budgets.js';
|
|
4
4
|
import { escapePointer } from './context.js';
|
|
5
|
+
import { referenceContracts } from './objects.js';
|
|
5
6
|
export class PolicyTyping {
|
|
6
7
|
context;
|
|
8
|
+
// Expanded branches of each named Policy, cached by node identity. A Policy's expansion is reused
|
|
9
|
+
// across every composition path that reaches it (and across every use site and object contract,
|
|
10
|
+
// none of which the expansion depends on), so a shared-child composition DAG is expanded in work
|
|
11
|
+
// linear in the number of Policies instead of enumerating every path. The expansion result is
|
|
12
|
+
// independent of the reaching path up to the opaque term-namespace labels, which only ever
|
|
13
|
+
// disambiguate variables within one branch and leave targetMode and branch typing unchanged.
|
|
14
|
+
#expansions = new Map();
|
|
7
15
|
constructor(context) {
|
|
8
16
|
this.context = context;
|
|
9
17
|
}
|
|
@@ -16,7 +24,7 @@ export class PolicyTyping {
|
|
|
16
24
|
const mode = targetMode(branch);
|
|
17
25
|
if (mode === undefined) {
|
|
18
26
|
if (!('match' in this.context.environment.candidate.policies[name].expression)) {
|
|
19
|
-
this.context.add('PL_TARGET', `/policies/${escapePointer(name)}`, `Expanded normalized branch ${index} must use object or
|
|
27
|
+
this.context.add('PL_TARGET', `/policies/${escapePointer(name)}`, `Expanded normalized branch ${index} must use object or at least one of source and target, without mixing target modes.`);
|
|
20
28
|
}
|
|
21
29
|
continue;
|
|
22
30
|
}
|
|
@@ -34,9 +42,13 @@ export class PolicyTyping {
|
|
|
34
42
|
}
|
|
35
43
|
}
|
|
36
44
|
policyAccepts(name, object) {
|
|
45
|
+
return this.policyBranchTyping(name, object)?.every(Boolean) ?? false;
|
|
46
|
+
}
|
|
47
|
+
/** Whether each normalized branch of the Policy is typed for an object of this contract. */
|
|
48
|
+
policyBranchTyping(name, object) {
|
|
37
49
|
const branches = this.#expandedBranches(name, new Set(), `$use:${name}`);
|
|
38
50
|
const use = { kind: 'object', object };
|
|
39
|
-
return branches
|
|
51
|
+
return branches?.map((branch) => this.#branchIsTyped(branch, use));
|
|
40
52
|
}
|
|
41
53
|
policyAcceptsEdge(name, source, target) {
|
|
42
54
|
const branches = this.#expandedBranches(name, new Set(), `$edge-use:${name}`);
|
|
@@ -54,6 +66,14 @@ export class PolicyTyping {
|
|
|
54
66
|
#expandedBranches(name, visiting, namespace) {
|
|
55
67
|
if (visiting.has(name))
|
|
56
68
|
return undefined;
|
|
69
|
+
const cached = this.#expansions.get(name);
|
|
70
|
+
if (cached !== undefined || this.#expansions.has(name))
|
|
71
|
+
return cached;
|
|
72
|
+
const expanded = this.#expandDeclaration(name, visiting, namespace);
|
|
73
|
+
this.#expansions.set(name, expanded);
|
|
74
|
+
return expanded;
|
|
75
|
+
}
|
|
76
|
+
#expandDeclaration(name, visiting, namespace) {
|
|
57
77
|
const declaration = this.context.normalized.get(name);
|
|
58
78
|
if (declaration === undefined)
|
|
59
79
|
return undefined;
|
|
@@ -83,11 +103,15 @@ export class PolicyTyping {
|
|
|
83
103
|
const terms = new Set(use.kind === 'object' ? ['subject', 'object'] : ['subject', 'source', 'target']);
|
|
84
104
|
for (const key of branch.variables.keys())
|
|
85
105
|
terms.add(key);
|
|
106
|
+
for (const key of branch.terms.keys())
|
|
107
|
+
terms.add(key);
|
|
86
108
|
for (const edge of branch.edges) {
|
|
87
109
|
terms.add(termKey(edge.pattern.source, edge.namespace));
|
|
88
110
|
terms.add(termKey(edge.pattern.target, edge.namespace));
|
|
89
111
|
}
|
|
90
112
|
const union = new UnionFind(terms);
|
|
113
|
+
for (const [left, right] of branch.equalities)
|
|
114
|
+
union.join(left, right);
|
|
91
115
|
for (const variant of variants) {
|
|
92
116
|
for (const [left, right] of variant.equalities)
|
|
93
117
|
union.join(left, right);
|
|
@@ -136,11 +160,19 @@ export class PolicyTyping {
|
|
|
136
160
|
}
|
|
137
161
|
return candidates;
|
|
138
162
|
}
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
163
|
+
const referenced = branch.terms.get(term);
|
|
164
|
+
if (referenced?.kind === 'ref') {
|
|
165
|
+
const contract = referenceContracts(this.context, referenced.ref, '/policies')?.[0];
|
|
166
|
+
return contract?.kind === 'exact' ? this.#applyExact(candidates, contract.ref) : [];
|
|
167
|
+
}
|
|
168
|
+
const selector = branch.variables.get(term);
|
|
169
|
+
if (selector === undefined)
|
|
170
|
+
return [];
|
|
171
|
+
if (selector.kind === 'exact')
|
|
172
|
+
return this.#applyExact(candidates, selector.class);
|
|
173
|
+
if (selector.kind === 'any')
|
|
174
|
+
return candidates;
|
|
175
|
+
return this.#applyRequirement(candidates, selector.class);
|
|
144
176
|
}
|
|
145
177
|
#applyExact(candidates, exact) {
|
|
146
178
|
const result = [];
|
|
@@ -162,6 +194,22 @@ export class PolicyTyping {
|
|
|
162
194
|
.filter((ref) => candidate.requirements.every((required) => this.context.classExtends(ref, required)))
|
|
163
195
|
.map((ref) => ({ kind: 'exact', ref }))));
|
|
164
196
|
}
|
|
197
|
+
#applyRequirement(candidates, required) {
|
|
198
|
+
const result = [];
|
|
199
|
+
for (const candidate of candidates) {
|
|
200
|
+
if (candidate.kind === 'exact') {
|
|
201
|
+
if (this.context.classExtends(candidate.ref, required))
|
|
202
|
+
result.push(candidate);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
result.push({
|
|
206
|
+
kind: 'open',
|
|
207
|
+
requirements: uniqueClasses([...candidate.requirements, required]),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return uniqueCandidates(result);
|
|
212
|
+
}
|
|
165
213
|
#applyEndpoint(candidates, accepts) {
|
|
166
214
|
const result = [];
|
|
167
215
|
for (const candidate of candidates) {
|
|
@@ -1,40 +1,48 @@
|
|
|
1
1
|
import { Key } from '../../../addressing/index.js';
|
|
2
2
|
import { definitionRefIndex } from '../../../addressing/ordering.js';
|
|
3
|
+
import { isBinaryInput } from '../../../language/callable/model/callable.js';
|
|
4
|
+
import { admittedCheckClasses, neverAdmittedClasses, } from '../../../language/policy/analysis/checks.js';
|
|
5
|
+
import { checksNameTheCaller, isClassRuleChecks } from '../../../language/policy/model/policy.js';
|
|
3
6
|
import { normalizePolicyChecks } from '../../../language/policy/normalization/normalize.js';
|
|
4
7
|
import { GRAPH_NODE_PATH_SCHEMA_ID } from '../../../language/value/syntax/node-path/schema.js';
|
|
5
8
|
import { MAX_BRANCHES, MAX_CHECK_DEPTH, MAX_CHECK_LEAVES, measureChecks } from './budgets.js';
|
|
6
9
|
import { escapePointer } from './context.js';
|
|
10
|
+
import { referenceContracts } from './objects.js';
|
|
7
11
|
import { contractOfNodeDefinition } from './typing.js';
|
|
8
12
|
const formatDefinitionRef = Key.of;
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
/** How a refusal names the checks of each site and the contract of their objects. */
|
|
14
|
+
const SITE = {
|
|
15
|
+
callable: { checks: 'Callable checks', objects: 'the callable object contract' },
|
|
16
|
+
class: { checks: 'Class rule checks', objects: 'the Class rule object contract' },
|
|
17
|
+
};
|
|
14
18
|
export function validateReadUses(context, typing) {
|
|
15
|
-
|
|
16
|
-
if (declaration.kind !== 'node' || declaration.policies.read === undefined) {
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
const pointer = `/classes/${escapePointer(name)}/policies/read`;
|
|
20
|
-
const ref = declaration.policies.read;
|
|
21
|
-
if (!context.resolvePolicy(ref, pointer))
|
|
22
|
-
continue;
|
|
23
|
-
const object = {
|
|
24
|
-
kind: 'exact',
|
|
25
|
-
ref: { origin: context.environment.candidate.origin, kind: 'class', name },
|
|
26
|
-
};
|
|
27
|
-
if (!typing.policyAccepts(ref.name, object)) {
|
|
28
|
-
context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every normalized branch of protected Class ${name}.`, formatDefinitionRef(ref));
|
|
29
|
-
}
|
|
30
|
-
}
|
|
19
|
+
validateClassPolicyUses(context, typing, 'read');
|
|
31
20
|
}
|
|
32
21
|
export function validateTraverseUses(context, typing) {
|
|
22
|
+
validateClassPolicyUses(context, typing, 'traverse');
|
|
23
|
+
}
|
|
24
|
+
function validateClassPolicyUses(context, typing, operation) {
|
|
33
25
|
for (const [name, declaration] of Object.entries(context.environment.candidate.classes)) {
|
|
34
|
-
const ref = declaration.policies
|
|
35
|
-
if (ref
|
|
26
|
+
const ref = declaration.policies[operation];
|
|
27
|
+
if (typeof ref !== 'object')
|
|
28
|
+
continue;
|
|
29
|
+
const pointer = `/classes/${escapePointer(name)}/policies/${operation}`;
|
|
30
|
+
if (isClassRuleChecks(ref)) {
|
|
31
|
+
// A rule lifts the Class ceiling the way a named Policy does, so, as a Policy connects its
|
|
32
|
+
// subject, each way the rule holds must pass through a check of the caller.
|
|
33
|
+
if (!checksNameTheCaller(ref)) {
|
|
34
|
+
context.add('PL_CONNECTIVITY', pointer, `Every branch of the ${operation} rule of Node Class ${name} must check a Policy: sameNode alone names no caller.`);
|
|
35
|
+
}
|
|
36
|
+
// Structure admits Policy checks only on a Node Class: `self` is the observed exact Class.
|
|
37
|
+
validateChecks(context, typing, ref, {
|
|
38
|
+
site: 'class',
|
|
39
|
+
pointer,
|
|
40
|
+
input: {},
|
|
41
|
+
receiver: { origin: context.environment.candidate.origin, kind: 'class', name },
|
|
42
|
+
instanceMethod: true,
|
|
43
|
+
});
|
|
36
44
|
continue;
|
|
37
|
-
|
|
45
|
+
}
|
|
38
46
|
if (!context.resolvePolicy(ref, pointer))
|
|
39
47
|
continue;
|
|
40
48
|
if (declaration.kind === 'node') {
|
|
@@ -42,9 +50,9 @@ export function validateTraverseUses(context, typing) {
|
|
|
42
50
|
kind: 'exact',
|
|
43
51
|
ref: { origin: context.environment.candidate.origin, kind: 'class', name },
|
|
44
52
|
};
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
}
|
|
53
|
+
if (typing.policyAccepts(ref.name, object))
|
|
54
|
+
continue;
|
|
55
|
+
context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every normalized branch of ${operation} Node Class ${name}.`, formatDefinitionRef(ref));
|
|
48
56
|
continue;
|
|
49
57
|
}
|
|
50
58
|
const endpoints = declaration.orientation === 'directed'
|
|
@@ -52,29 +60,20 @@ export function validateTraverseUses(context, typing) {
|
|
|
52
60
|
: declaration.endpoints;
|
|
53
61
|
const sources = typing.concreteEndpointClasses(endpoints[0].accepts);
|
|
54
62
|
const targets = typing.concreteEndpointClasses(endpoints[1].accepts);
|
|
55
|
-
|
|
56
|
-
for (const source of sources) {
|
|
57
|
-
for (const target of targets) {
|
|
58
|
-
if (!typing.policyAcceptsEdge(ref.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })) {
|
|
59
|
-
accepted = false;
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (!accepted)
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
63
|
+
const accepted = sources.every((source) => targets.every((target) => typing.policyAcceptsEdge(ref.name, { kind: 'exact', ref: source }, { kind: 'exact', ref: target })));
|
|
66
64
|
if (!accepted) {
|
|
67
|
-
context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every concrete source/target pair of
|
|
65
|
+
context.add('PL_USE', pointer, `${formatDefinitionRef(ref)} is not valid for every concrete source/target pair of ${operation} Edge Class ${name}.`, formatDefinitionRef(ref));
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
69
|
export function validateCallableUses(context, typing) {
|
|
72
70
|
for (const [name, declaration] of Object.entries(context.environment.candidate.functions)) {
|
|
73
|
-
if (declaration.policy
|
|
71
|
+
if (typeof declaration.policy !== 'object')
|
|
74
72
|
continue;
|
|
75
73
|
validateChecks(context, typing, declaration.policy, {
|
|
74
|
+
site: 'callable',
|
|
76
75
|
pointer: `/functions/${escapePointer(name)}/policy`,
|
|
77
|
-
input: declaration.input,
|
|
76
|
+
input: isBinaryInput(declaration.input) ? declaration.input.metadata : declaration.input,
|
|
78
77
|
instanceMethod: false,
|
|
79
78
|
});
|
|
80
79
|
}
|
|
@@ -91,7 +90,7 @@ export function validateCallableUses(context, typing) {
|
|
|
91
90
|
function validateDeclaredMethods(context, typing, namespace, name, methods, receiver) {
|
|
92
91
|
const ownerAnalysis = context.analysis.definitions.get(definitionRefIndex(receiver));
|
|
93
92
|
for (const [methodName, method] of Object.entries(methods)) {
|
|
94
|
-
if (method.policy
|
|
93
|
+
if (typeof method.policy !== 'object')
|
|
95
94
|
continue;
|
|
96
95
|
// Definition analysis is the authority for the effective callable. A
|
|
97
96
|
// missing entry is already a definition diagnostic, so avoid inventing a
|
|
@@ -99,6 +98,7 @@ function validateDeclaredMethods(context, typing, namespace, name, methods, rece
|
|
|
99
98
|
if (ownerAnalysis !== undefined && !ownerAnalysis.methods.has(methodName))
|
|
100
99
|
continue;
|
|
101
100
|
validateChecks(context, typing, method.policy, {
|
|
101
|
+
site: 'callable',
|
|
102
102
|
pointer: `/${namespace}/${escapePointer(name)}/methods/${escapePointer(methodName)}/policy`,
|
|
103
103
|
input: method.input,
|
|
104
104
|
receiver,
|
|
@@ -112,11 +112,27 @@ function validateChecks(validation, typing, expression, context) {
|
|
|
112
112
|
if (measure.depth > MAX_CHECK_DEPTH ||
|
|
113
113
|
measure.branches > MAX_BRANCHES ||
|
|
114
114
|
measure.leaves > MAX_CHECK_LEAVES) {
|
|
115
|
-
validation.add('PL_BUDGET', context.pointer,
|
|
115
|
+
validation.add('PL_BUDGET', context.pointer, `${SITE[context.site].checks} require depth <= ${MAX_CHECK_DEPTH}, branches <= ${MAX_BRANCHES}, and leaves <= ${MAX_CHECK_LEAVES}; got ${measure.depth}, ${measure.branches}, ${measure.leaves}.`);
|
|
116
|
+
}
|
|
117
|
+
const leaves = new Map();
|
|
118
|
+
visitChecks(validation, typing, normalized, context, context.pointer, leaves);
|
|
119
|
+
for (const [object, className] of neverAdmittedClasses(normalized, leaves)) {
|
|
120
|
+
validation.add('PL_USE', context.pointer, `${SITE[context.site].checks} can never admit ${object} of Class ${className}.`, className);
|
|
116
121
|
}
|
|
117
|
-
visitChecks(validation, typing, normalized, context, context.pointer);
|
|
118
122
|
}
|
|
119
|
-
function visitChecks(validation, typing, expression, context, pointer) {
|
|
123
|
+
function visitChecks(validation, typing, expression, context, pointer, leaves) {
|
|
124
|
+
if ('sameNode' in expression) {
|
|
125
|
+
for (const [side, object] of Object.entries(expression.sameNode)) {
|
|
126
|
+
const objectPointer = `${pointer}/sameNode/${side}`;
|
|
127
|
+
if (object.kind === 'self')
|
|
128
|
+
selfContracts(validation, context, objectPointer);
|
|
129
|
+
else if (object.kind === 'input')
|
|
130
|
+
inputContracts(validation, context, object.field, objectPointer);
|
|
131
|
+
else
|
|
132
|
+
referenceContracts(validation, object.ref, objectPointer);
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
120
136
|
if ('check' in expression) {
|
|
121
137
|
if (!validation.resolvePolicy(expression.check, `${pointer}/check`))
|
|
122
138
|
return;
|
|
@@ -128,65 +144,26 @@ function visitChecks(validation, typing, expression, context, pointer) {
|
|
|
128
144
|
: referenceContracts(validation, expression.object.ref, objectPointer);
|
|
129
145
|
if (contracts === undefined)
|
|
130
146
|
return;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
147
|
+
const typings = new Map(contracts.map((contract) => [
|
|
148
|
+
contractName(contract),
|
|
149
|
+
typing.policyBranchTyping(expression.check.name, contract),
|
|
150
|
+
]));
|
|
151
|
+
const admitted = admittedCheckClasses(typings);
|
|
152
|
+
if (admitted === undefined) {
|
|
153
|
+
validation.add('PL_USE', pointer, `${formatDefinitionRef(expression.check)} is incompatible with ${SITE[context.site].objects}.`, formatDefinitionRef(expression.check));
|
|
154
|
+
return;
|
|
136
155
|
}
|
|
156
|
+
leaves.set(expression, { accepted: [...typings.keys()], admitted });
|
|
137
157
|
return;
|
|
138
158
|
}
|
|
139
159
|
const { key, values } = checkOperands(expression);
|
|
140
160
|
if (values.length === 0) {
|
|
141
161
|
validation.add('PL_COMPOSITION', `${pointer}/${key}`, `${key} must be non-empty.`);
|
|
142
162
|
}
|
|
143
|
-
values.forEach((child, index) => visitChecks(validation, typing, child, context, `${pointer}/${key}/${index}
|
|
163
|
+
values.forEach((child, index) => visitChecks(validation, typing, child, context, `${pointer}/${key}/${index}`, leaves));
|
|
144
164
|
}
|
|
145
|
-
function
|
|
146
|
-
|
|
147
|
-
if (ref.origin !== candidate.origin)
|
|
148
|
-
return invalidPolicyObjectRef(validation, ref, pointer);
|
|
149
|
-
switch (ref.kind) {
|
|
150
|
-
case 'class': {
|
|
151
|
-
const resolved = validation.environment.resolve(ref);
|
|
152
|
-
return resolved?.ref.kind === ref.kind
|
|
153
|
-
? [{ kind: 'exact', ref: PROJECTION_CLASS }]
|
|
154
|
-
: invalidPolicyObjectRef(validation, ref, pointer);
|
|
155
|
-
}
|
|
156
|
-
case 'function':
|
|
157
|
-
return candidate.functions[ref.name] === undefined
|
|
158
|
-
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
159
|
-
: [{ kind: 'exact', ref: PROJECTION_FUNCTION }];
|
|
160
|
-
case 'policy':
|
|
161
|
-
return candidate.policies[ref.name] === undefined
|
|
162
|
-
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
163
|
-
: [{ kind: 'exact', ref: PROJECTION_POLICY }];
|
|
164
|
-
case 'view':
|
|
165
|
-
return candidate.views[ref.name] === undefined
|
|
166
|
-
? invalidPolicyObjectRef(validation, ref, pointer)
|
|
167
|
-
: [{ kind: 'exact', ref: PROJECTION_VIEW }];
|
|
168
|
-
case 'core': {
|
|
169
|
-
const node = candidate.core.nodes[ref.name];
|
|
170
|
-
if (node === undefined)
|
|
171
|
-
return invalidPolicyObjectRef(validation, ref, pointer);
|
|
172
|
-
const resolved = validation.environment.resolve(node.class);
|
|
173
|
-
const analyzed = validation.analysis.definitions.get(definitionRefIndex(node.class));
|
|
174
|
-
// Core validation owns invalid Core Class diagnostics. Avoid adding Policy noise for
|
|
175
|
-
// a Node that cannot materialize in the first place.
|
|
176
|
-
if (node.class.origin !== candidate.origin ||
|
|
177
|
-
resolved?.ref.kind !== 'class' ||
|
|
178
|
-
resolved.kind !== 'node' ||
|
|
179
|
-
analyzed === undefined) {
|
|
180
|
-
return undefined;
|
|
181
|
-
}
|
|
182
|
-
return [contractOfNodeDefinition(node.class)];
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return invalidPolicyObjectRef(validation, ref, pointer);
|
|
186
|
-
}
|
|
187
|
-
function invalidPolicyObjectRef(validation, ref, pointer) {
|
|
188
|
-
validation.add('PL_REF', `${pointer}/ref`, `${formatDefinitionRef(ref)} is not an exact local projected Policy object.`, formatDefinitionRef(ref));
|
|
189
|
-
return undefined;
|
|
165
|
+
function contractName(contract) {
|
|
166
|
+
return contract.kind === 'exact' ? formatDefinitionRef(contract.ref) : 'default';
|
|
190
167
|
}
|
|
191
168
|
function selfContracts(validation, context, pointer) {
|
|
192
169
|
if (!context.instanceMethod || context.receiver === undefined) {
|
|
@@ -253,6 +230,3 @@ function checkOperands(value) {
|
|
|
253
230
|
? { key: 'allOf', values: value.allOf }
|
|
254
231
|
: { key: 'anyOf', values: value.anyOf };
|
|
255
232
|
}
|
|
256
|
-
function nodeClassRef(name) {
|
|
257
|
-
return { origin: KERNEL_ORIGIN, kind: 'class', name };
|
|
258
|
-
}
|
|
@@ -4,6 +4,8 @@ import type { JsonSchema } from '../../language/value/model/schema.js';
|
|
|
4
4
|
import type { OrderingKind } from '../../language/value/ordering.js';
|
|
5
5
|
import type { DomainSchema } from '../model/schema.js';
|
|
6
6
|
export { VALUE_SCHEMA_DIALECT as DIALECT, VALUE_SCHEMA_VOCABULARY as VOCABULARY, } from '../../language/value/model/schema.js';
|
|
7
|
+
export { blob, isBlobValueSchema as isBlob } from '../../language/value/model/blob.js';
|
|
8
|
+
export type { BlobOptions, BlobReceipt, BlobRef, BlobSchema, } from '../../language/value/model/blob.js';
|
|
7
9
|
export type { JsonSchema as Schema, JsonSchemaObject as SchemaObject, PathAnnotation, PropertyObjectSchema as PropertySchema, ValueSchemaContext as Context, } from '../../language/value/model/schema.js';
|
|
8
10
|
export { instant } from '../../language/value/model/instant.js';
|
|
9
11
|
export type { OrderingKind } from '../../language/value/ordering.js';
|
|
@@ -4,6 +4,7 @@ import { classifyOrdering as classifyOrderingWithRegistry } from '../../language
|
|
|
4
4
|
import { createDomainValueSchemaRegistry } from '../resolution/value.registry.js';
|
|
5
5
|
const registries = new WeakMap();
|
|
6
6
|
export { VALUE_SCHEMA_DIALECT as DIALECT, VALUE_SCHEMA_VOCABULARY as VOCABULARY, } from '../../language/value/model/schema.js';
|
|
7
|
+
export { blob, isBlobValueSchema as isBlob } from '../../language/value/model/blob.js';
|
|
7
8
|
export { instant } from '../../language/value/model/instant.js';
|
|
8
9
|
/** Validate one complete JSON value under the exact accepted schema that owns the contract. */
|
|
9
10
|
export function validate(owner, contract, input, pointer = '') {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isBinaryInput } from '../../language/callable/model/callable.js';
|
|
1
2
|
import { validateValueSchema } from '../../language/value/profile/validate.js';
|
|
2
3
|
import { diagnostic } from '../diagnostic.js';
|
|
3
4
|
export function validateEmbeddedValueSchemas(schema, registry) {
|
|
@@ -21,7 +22,12 @@ function validateDefinition(declaration, pointer, registry, diagnostics) {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
function validateCallable(declaration, pointer, registry, diagnostics) {
|
|
24
|
-
|
|
25
|
+
if (isBinaryInput(declaration.input)) {
|
|
26
|
+
validate(declaration.input.metadata, 'callable-input', `${pointer}/input/metadata`, registry, diagnostics);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
validate(declaration.input, 'callable-input', `${pointer}/input`, registry, diagnostics);
|
|
30
|
+
}
|
|
25
31
|
if (declaration.output.mode === 'value') {
|
|
26
32
|
validate(declaration.output.schema, 'callable-output', `${pointer}/output/schema`, registry, diagnostics);
|
|
27
33
|
}
|
|
@@ -9,21 +9,26 @@ export function validateViews(environment) {
|
|
|
9
9
|
if (!sameRef(view.ref, ref)) {
|
|
10
10
|
diagnostics.push(diagnostic('DV_REF_RESOLVES', `${pointer}/ref`, `View ref must be exactly ${formatDefinitionRef(ref)}.`, formatDefinitionRef(view.ref)));
|
|
11
11
|
}
|
|
12
|
-
if (view.target.kind === 'definition') {
|
|
13
|
-
view.target.definitions.forEach((ref, index) => validateDefinitionTarget(environment, ref, `${pointer}/target/definitions/${index}`, diagnostics));
|
|
14
|
-
}
|
|
15
12
|
}
|
|
13
|
+
validateEntrypoint(environment, diagnostics);
|
|
16
14
|
return Object.freeze(diagnostics);
|
|
17
15
|
}
|
|
16
|
+
/** The entrypoint names one View this Domain declares for itself. */
|
|
17
|
+
function validateEntrypoint(environment, diagnostics) {
|
|
18
|
+
const { entrypoint, origin, views } = environment.candidate;
|
|
19
|
+
if (entrypoint === undefined)
|
|
20
|
+
return;
|
|
21
|
+
// An own member only: a name such as `constructor` must not resolve on the prototype.
|
|
22
|
+
const view = entrypoint.origin === origin && Object.hasOwn(views, entrypoint.name)
|
|
23
|
+
? views[entrypoint.name]
|
|
24
|
+
: undefined;
|
|
25
|
+
if (view === undefined) {
|
|
26
|
+
diagnostics.push(diagnostic('DV_ENTRYPOINT', '/entrypoint', `Entrypoint ${formatDefinitionRef(entrypoint)} is not a Domain-targeted View of ${origin}.`, formatDefinitionRef(entrypoint)));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
18
29
|
function sameRef(left, right) {
|
|
19
30
|
return left.origin === right.origin && left.kind === right.kind && left.name === right.name;
|
|
20
31
|
}
|
|
21
|
-
function validateDefinitionTarget(environment, ref, pointer, diagnostics) {
|
|
22
|
-
const target = environment.resolve(ref);
|
|
23
|
-
if (target === undefined || target.ref.kind !== 'class' || target.kind !== 'node') {
|
|
24
|
-
diagnostics.push(diagnostic('DV_VIEW_TARGET', pointer, `Definition target ${formatDefinitionRef(ref)} does not resolve to a Node Class.`, formatDefinitionRef(ref)));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
32
|
function escapePointer(value) {
|
|
28
33
|
return value.replaceAll('~', '~0').replaceAll('/', '~1');
|
|
29
34
|
}
|
package/dist/value/accept.d.ts
CHANGED
|
@@ -6,3 +6,12 @@ import { type Options } from './limits.js';
|
|
|
6
6
|
* Every source property is obtained from one descriptor snapshot. Accessors are never invoked.
|
|
7
7
|
*/
|
|
8
8
|
export declare function accept(input: unknown, options?: Options): Value;
|
|
9
|
+
/** Admit a canonically byte-bounded immutable snapshot; owned subtrees may be shared. */
|
|
10
|
+
export declare function acceptImmutable(input: unknown, options?: Options): Value;
|
|
11
|
+
/** Admit a read-only snapshot, sharing owned immutable subtrees without freezing new wrappers. */
|
|
12
|
+
export declare function acceptForRead(input: unknown, options?: Options): Value;
|
|
13
|
+
/**
|
|
14
|
+
* Private PropertyValues owner seam. Retain immediate recursive values, not the enclosing
|
|
15
|
+
* dictionary: its canonical coordinates are re-admitted by the Property owner on every use.
|
|
16
|
+
*/
|
|
17
|
+
export declare function acceptPropertyRoot(input: unknown): Value;
|