@telorun/analyzer 0.65.0 → 0.66.0
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/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +157 -63
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +7 -1
- package/dist/cel-environment.d.ts +12 -0
- package/dist/cel-environment.d.ts.map +1 -1
- package/dist/cel-environment.js +35 -19
- package/dist/cel-scope.d.ts.map +1 -1
- package/dist/cel-scope.js +24 -4
- package/dist/definition-registry.d.ts +24 -0
- package/dist/definition-registry.d.ts.map +1 -1
- package/dist/definition-registry.js +41 -0
- package/dist/eval-paths.d.ts +68 -0
- package/dist/eval-paths.d.ts.map +1 -1
- package/dist/eval-paths.js +138 -0
- package/dist/flatten-for-analyzer.d.ts +1 -1
- package/dist/flatten-for-analyzer.js +1 -1
- package/dist/import-resolution-diagnostics.d.ts +1 -1
- package/dist/import-resolution-diagnostics.js +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -5
- package/dist/manifest-visitor.d.ts.map +1 -1
- package/dist/manifest-visitor.js +8 -1
- package/dist/migrations/entries/index.d.ts.map +1 -1
- package/dist/migrations/entries/index.js +2 -0
- package/dist/migrations/entries/schema-prepare-bucket.json +27 -0
- package/dist/peer-binding.d.ts +232 -0
- package/dist/peer-binding.d.ts.map +1 -0
- package/dist/peer-binding.js +418 -0
- package/dist/ref-slot.d.ts +13 -0
- package/dist/ref-slot.d.ts.map +1 -1
- package/dist/ref-slot.js +26 -0
- package/dist/reference-field-map.d.ts +28 -0
- package/dist/reference-field-map.d.ts.map +1 -1
- package/dist/reference-field-map.js +25 -0
- package/dist/referrer-rule.d.ts +17 -0
- package/dist/referrer-rule.d.ts.map +1 -1
- package/dist/referrer-rule.js +4 -1
- package/dist/release/index.d.ts +1 -1
- package/dist/release/index.js +1 -1
- package/dist/resource-rule.d.ts +40 -27
- package/dist/resource-rule.d.ts.map +1 -1
- package/dist/resource-rule.js +61 -7
- package/dist/rule-condition.d.ts +11 -0
- package/dist/rule-condition.d.ts.map +1 -1
- package/dist/rule-condition.js +13 -0
- package/dist/schema-projection.d.ts +106 -4
- package/dist/schema-projection.d.ts.map +1 -1
- package/dist/schema-projection.js +206 -18
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/validate-cel-context.d.ts +1 -17
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +5 -70
- package/dist/validate-reference-forms.d.ts +10 -0
- package/dist/validate-reference-forms.d.ts.map +1 -1
- package/dist/validate-reference-forms.js +23 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +9 -2
- package/dist/validate-referrer-rules.d.ts +38 -4
- package/dist/validate-referrer-rules.d.ts.map +1 -1
- package/dist/validate-referrer-rules.js +139 -31
- package/dist/validate-resource-rules.d.ts +11 -2
- package/dist/validate-resource-rules.d.ts.map +1 -1
- package/dist/validate-resource-rules.js +18 -12
- package/dist/validate-schema-projection.d.ts.map +1 -1
- package/dist/validate-schema-projection.js +33 -2
- package/dist/with-synthetic-positions.d.ts +1 -1
- package/dist/with-synthetic-positions.js +1 -1
- package/package.json +3 -3
- package/src/analyzer.ts +191 -68
- package/src/call-graph.ts +7 -1
- package/src/cel-environment.ts +48 -19
- package/src/cel-scope.ts +24 -6
- package/src/definition-registry.ts +42 -0
- package/src/eval-paths.ts +152 -0
- package/src/flatten-for-analyzer.ts +1 -1
- package/src/import-resolution-diagnostics.ts +1 -1
- package/src/index.ts +45 -4
- package/src/manifest-visitor.ts +8 -1
- package/src/migrations/entries/index.ts +2 -0
- package/src/migrations/entries/schema-prepare-bucket.json +27 -0
- package/src/peer-binding.ts +641 -0
- package/src/ref-slot.ts +36 -0
- package/src/reference-field-map.ts +42 -0
- package/src/referrer-rule.ts +20 -1
- package/src/release/index.ts +1 -1
- package/src/resource-rule.ts +69 -7
- package/src/rule-condition.ts +15 -0
- package/src/schema-projection.ts +283 -20
- package/src/telo-version.ts +1 -1
- package/src/validate-cel-context.ts +6 -71
- package/src/validate-reference-forms.ts +22 -0
- package/src/validate-references.ts +15 -2
- package/src/validate-referrer-rules.ts +215 -28
- package/src/validate-resource-rules.ts +26 -12
- package/src/validate-schema-projection.ts +50 -1
- package/src/with-synthetic-positions.ts +1 -1
package/dist/analyzer.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare class StaticAnalyzer {
|
|
|
33
33
|
* `DUPLICATE_RESOURCE_NAME` reads those fields to tell a pipeline echo
|
|
34
34
|
* apart from a genuine collision, and downstream diagnostic positioning
|
|
35
35
|
* depends on them too. Real callers stamp positions already (the `Loader`,
|
|
36
|
-
* `flattenForAnalyzer`,
|
|
36
|
+
* `flattenForAnalyzer`, telo studio's `emitDocsFor`, the VSCode
|
|
37
37
|
* extension). Programmatic callers — tests, ad-hoc scripts — should pass
|
|
38
38
|
* their inputs through `withSyntheticPositions(...)` before calling
|
|
39
39
|
* `analyze()`. A missing position throws a clear error rather than
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAiBzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAiBzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AA8B9B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAWvF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAwDjE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AA+F/F;0CAC0C;AAC1C,eAAO,MAAM,eAAe,GAAI,OAAO;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAG,OACT,CAAC;AAErD;8EAC8E;AAC9E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAqUD,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACtC;AA6DD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAkFD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAu4DvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAyBrB,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
|
package/dist/analyzer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { canonicalTypeSchemaId, OBSERVED_STATE_KEY } from "@telorun/sdk";
|
|
2
2
|
import { defaultRegistry, isRefSentinel, isTaggedSentinel, plainChainOf, } from "@telorun/templating";
|
|
3
3
|
import { AliasResolver, scopeResolverForModule, } from "./alias-resolver.js";
|
|
4
|
-
import { buildCelEnvironment, } from "./cel-environment.js";
|
|
4
|
+
import { buildCelEnvironment, isKindDocument, } from "./cel-environment.js";
|
|
5
5
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
6
6
|
import { effectiveAuthorSchema } from "./extends-resolution.js";
|
|
7
7
|
import { analyzerContractScope, resolveContract, } from "./invocation-contract.js";
|
|
@@ -30,10 +30,11 @@ export { analyzerContractScope } from "./invocation-contract.js";
|
|
|
30
30
|
import { validateZoneSlotDeclarations } from "./validate-zone-slots.js";
|
|
31
31
|
import { validateSchemaProjection, } from "./validate-schema-projection.js";
|
|
32
32
|
import { evaluateResourceRules, reportResourceRules, reportUnexercisedRule, ruleExercised, validateResourceRuleDeclarations, } from "./validate-resource-rules.js";
|
|
33
|
-
import { readResourceRules } from "./resource-rule.js";
|
|
33
|
+
import { pointerToPath, readResourceRules } from "./resource-rule.js";
|
|
34
34
|
import { readReferrerRules } from "./referrer-rule.js";
|
|
35
35
|
import { evaluateReferrerRules, referrerRuleExercised, reportReferrerRules, reportUnexercisedReferrerRule, validateReferrerRuleDeclarations, } from "./validate-referrer-rules.js";
|
|
36
|
-
import {
|
|
36
|
+
import { analyzerPeerBinder, analyzerPeersTarget } from "./peer-binding.js";
|
|
37
|
+
import { describeProjectionFailure, manifestListScope, resolveSchemaProjections, } from "./schema-projection.js";
|
|
37
38
|
import { validateDynamicSelectors, validateRefSlotDeclarations, } from "./validate-ref-slots.js";
|
|
38
39
|
import { validateValueTypeSlots, } from "./validate-value-type-slots.js";
|
|
39
40
|
import { resolveSchemaTypeRefs } from "./resolve-schema-type-refs.js";
|
|
@@ -42,8 +43,8 @@ import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
|
|
|
42
43
|
import { celTypeSatisfiesJsonSchema, checkSchemaCompatibility, navigateSchemaToExprPath, substituteCelFields, validateAgainstSchema, } from "./schema-compat.js";
|
|
43
44
|
import { collectValueSchemaIssues } from "./validate-value-schema.js";
|
|
44
45
|
import { DiagnosticSeverity } from "./types.js";
|
|
45
|
-
import { extractAccessChains,
|
|
46
|
-
import {
|
|
46
|
+
import { extractAccessChains, } from "./validate-cel-context.js";
|
|
47
|
+
import { celEvalModeAt, celEvalSites, mergeCelEvalSites, NO_CEL_EVAL_SITES, } from "./eval-paths.js";
|
|
47
48
|
import { BINDINGS_ANNOTATION, findBindingSites, resolveBindingOrder, } from "./cel-bindings.js";
|
|
48
49
|
import { CEL_RESERVED_WORDS, checkName } from "./identifier-name.js";
|
|
49
50
|
import { validateIdentifierNames } from "./validate-identifier-names.js";
|
|
@@ -554,7 +555,7 @@ export class StaticAnalyzer {
|
|
|
554
555
|
* `DUPLICATE_RESOURCE_NAME` reads those fields to tell a pipeline echo
|
|
555
556
|
* apart from a genuine collision, and downstream diagnostic positioning
|
|
556
557
|
* depends on them too. Real callers stamp positions already (the `Loader`,
|
|
557
|
-
* `flattenForAnalyzer`,
|
|
558
|
+
* `flattenForAnalyzer`, telo studio's `emitDocsFor`, the VSCode
|
|
558
559
|
* extension). Programmatic callers — tests, ad-hoc scripts — should pass
|
|
559
560
|
* their inputs through `withSyntheticPositions(...)` before calling
|
|
560
561
|
* `analyze()`. A missing position throws a clear error rather than
|
|
@@ -776,6 +777,11 @@ export class StaticAnalyzer {
|
|
|
776
777
|
const projectionIssues = [];
|
|
777
778
|
const resourceRuleIssues = [];
|
|
778
779
|
const referrerRuleIssues = [];
|
|
780
|
+
/** Definition docs of the entry's own modules that may declare rules. Their
|
|
781
|
+
* referrer-rule declarations are checked after every kind is registered,
|
|
782
|
+
* because a `peers:` pointer is checked against the REFERRER kind's schema
|
|
783
|
+
* and that kind may be declared later in the same file. */
|
|
784
|
+
const ownRuleDeclarers = [];
|
|
779
785
|
// A rule that never had anything to iterate is never proven — the second way
|
|
780
786
|
// coverage varies invisibly, beside the dynamic-leaf skip. Tracked across the
|
|
781
787
|
// whole run and reported once, since "empty on every resource" is not a fact
|
|
@@ -822,7 +828,10 @@ export class StaticAnalyzer {
|
|
|
822
828
|
// inherited field resolves — which is what lets a rule shared by every
|
|
823
829
|
// backend be declared once on the abstract they extend.
|
|
824
830
|
resourceRuleIssues.push(...validateResourceRuleDeclarations(m, effectiveAuthorSchema(m, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k))));
|
|
825
|
-
|
|
831
|
+
// Deferred to after the registration loop: the `peers:` half is checked
|
|
832
|
+
// against the REFERRER kind's schema, and a rule may name a kind
|
|
833
|
+
// declared later in the same file.
|
|
834
|
+
ownRuleDeclarers.push(m);
|
|
826
835
|
for (const rule of readReferrerRules(m.schema)) {
|
|
827
836
|
referrerRuleExercise.set(`${m.metadata?.module}.${m.metadata?.name}#${rule.code}`, {
|
|
828
837
|
manifest: m,
|
|
@@ -873,6 +882,23 @@ export class StaticAnalyzer {
|
|
|
873
882
|
: def;
|
|
874
883
|
defs.register(normalized);
|
|
875
884
|
}
|
|
885
|
+
/**
|
|
886
|
+
* What a peer rule's `peers:` pointer names in the kind its `referrer:`
|
|
887
|
+
* filters to.
|
|
888
|
+
*
|
|
889
|
+
* Liskov in BOTH directions, which is what the check has to be: the filter
|
|
890
|
+
* is usually an abstract (`Sql.Schema`, so one rule serves every backend)
|
|
891
|
+
* while the collection is declared by the backends that implement it, so a
|
|
892
|
+
* pointer resolving on any candidate resolves the rule. Reported only when
|
|
893
|
+
* NO candidate declares it, or when every candidate that does holds plain
|
|
894
|
+
* data — the two shapes where the rule would see no declaration at all.
|
|
895
|
+
*/
|
|
896
|
+
const peersTarget = analyzerPeersTarget(defs);
|
|
897
|
+
if (!options?.skipValidation) {
|
|
898
|
+
for (const declarer of ownRuleDeclarers) {
|
|
899
|
+
referrerRuleIssues.push(...validateReferrerRuleDeclarations(declarer, { peersTarget }));
|
|
900
|
+
}
|
|
901
|
+
}
|
|
876
902
|
// Reference-form validation — enforce `!ref` as the only reference shape.
|
|
877
903
|
// Runs on the RAW manifests, BEFORE inline extraction and sentinel
|
|
878
904
|
// resolution, while an author-written `{kind, name}` is still
|
|
@@ -1277,13 +1303,12 @@ export class StaticAnalyzer {
|
|
|
1277
1303
|
if (options?.skipValidation) {
|
|
1278
1304
|
return suppressUnreadableModuleDiagnostics(diagnostics, unreadableFiles);
|
|
1279
1305
|
}
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
}
|
|
1306
|
+
// ONE binder for the whole run, built beside the binding it serves: it caches
|
|
1307
|
+
// each referrer's resolved collection, which is what keeps a rule over an
|
|
1308
|
+
// n-entry collection from re-resolving that collection once per entry.
|
|
1309
|
+
const referrerRuleContext = {
|
|
1310
|
+
peerBinder: analyzerPeerBinder(defs, aliases, allManifests),
|
|
1311
|
+
};
|
|
1287
1312
|
// Fail loud on definition schemas AJV cannot compile. `validateAgainstSchema`
|
|
1288
1313
|
// and `validateWithRefs` swallow compile failures (returning no issues),
|
|
1289
1314
|
// which would silently skip schema validation for every resource of that
|
|
@@ -1420,6 +1445,44 @@ export class StaticAnalyzer {
|
|
|
1420
1445
|
moduleManifest,
|
|
1421
1446
|
observedStateContext,
|
|
1422
1447
|
});
|
|
1448
|
+
/**
|
|
1449
|
+
* The schema a resource of this kind is validated against, per DEFINITION.
|
|
1450
|
+
*
|
|
1451
|
+
* Both halves derive a fresh object — `effectiveAuthorSchema` merges along
|
|
1452
|
+
* `extends`, and the closed-schema branch spreads `kind` / `metadata` in —
|
|
1453
|
+
* so asking per resource handed `validateResourceConfig` a schema object it
|
|
1454
|
+
* had never seen. That registry memoizes its compiled AJV validator by
|
|
1455
|
+
* object IDENTITY, precisely because every resource of a kind is checked
|
|
1456
|
+
* against the same one at keystroke time, so a fresh object per resource
|
|
1457
|
+
* recompiled the whole kind schema per resource. Keyed on the definition,
|
|
1458
|
+
* which is stable for the run.
|
|
1459
|
+
*/
|
|
1460
|
+
const authorSchemaCache = new WeakMap();
|
|
1461
|
+
const validationSchemaFor = (def) => {
|
|
1462
|
+
const cached = authorSchemaCache.get(def);
|
|
1463
|
+
if (cached)
|
|
1464
|
+
return cached;
|
|
1465
|
+
const authorSchema = effectiveAuthorSchema(def, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k));
|
|
1466
|
+
// `kind` and `metadata` are implicit on every resource — inject them so
|
|
1467
|
+
// module authors don't have to repeat them under `additionalProperties:
|
|
1468
|
+
// false`.
|
|
1469
|
+
const schema = authorSchema.additionalProperties === false
|
|
1470
|
+
? {
|
|
1471
|
+
...authorSchema,
|
|
1472
|
+
properties: {
|
|
1473
|
+
kind: { type: "string" },
|
|
1474
|
+
metadata: { type: "object" },
|
|
1475
|
+
...authorSchema.properties,
|
|
1476
|
+
},
|
|
1477
|
+
}
|
|
1478
|
+
: authorSchema;
|
|
1479
|
+
authorSchemaCache.set(def, schema);
|
|
1480
|
+
return schema;
|
|
1481
|
+
};
|
|
1482
|
+
// One scope for the whole run: it closes over the manifest list and the
|
|
1483
|
+
// registry, neither of which changes per resource, and it is asked once per
|
|
1484
|
+
// schema-valued slot that carries a projection.
|
|
1485
|
+
const resourceProjectionScope = manifestListScope(allManifests, (kind) => (defs.resolve(kind) ?? defs.resolve(aliases.resolveKind(kind) ?? kind)));
|
|
1423
1486
|
// Validate each non-definition, non-system resource
|
|
1424
1487
|
for (const m of allManifests) {
|
|
1425
1488
|
const filePath = m.metadata?.source;
|
|
@@ -1510,34 +1573,47 @@ export class StaticAnalyzer {
|
|
|
1510
1573
|
continue;
|
|
1511
1574
|
}
|
|
1512
1575
|
// Validate resource config against the definition's AUTHOR-FACING schema —
|
|
1513
|
-
// inheritance-resolved
|
|
1514
|
-
//
|
|
1515
|
-
//
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
// authors don't have to repeat them when using additionalProperties: false.
|
|
1519
|
-
const authorSchema = effectiveAuthorSchema(definition, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k));
|
|
1520
|
-
if (authorSchema && Object.keys(authorSchema).length > 0) {
|
|
1521
|
-
const schema = authorSchema.additionalProperties === false
|
|
1522
|
-
? {
|
|
1523
|
-
...authorSchema,
|
|
1524
|
-
properties: {
|
|
1525
|
-
kind: { type: "string" },
|
|
1526
|
-
metadata: { type: "object" },
|
|
1527
|
-
...authorSchema.properties,
|
|
1528
|
-
},
|
|
1529
|
-
}
|
|
1530
|
-
: authorSchema;
|
|
1576
|
+
// inheritance-resolved, with `kind` / `metadata` injected. See
|
|
1577
|
+
// `validationSchemaFor`, which is where both derivations and the reason
|
|
1578
|
+
// they are memoized per definition live.
|
|
1579
|
+
const schema = validationSchemaFor(definition);
|
|
1580
|
+
if (Object.keys(schema).length > 0) {
|
|
1531
1581
|
// Phase 1: collect the pure-CEL leaves and the schema of the slot each
|
|
1532
1582
|
// flows into. The expression's own type is resolved later, by the
|
|
1533
1583
|
// engine walk that owns type-checking; this half only knows the target.
|
|
1534
1584
|
for (const slot of collectCelValueSlots(m, schema, "")) {
|
|
1535
1585
|
celReturnSlots.push({ manifest: m, resource, filePath, ...slot });
|
|
1536
1586
|
}
|
|
1587
|
+
// A kind's own schema may point a slot at a PROJECTION — of a resource it
|
|
1588
|
+
// references, or (the empty pointer) of this very declaration, which is
|
|
1589
|
+
// what types a table's seed rows against its own `columns:`. Resolved
|
|
1590
|
+
// PER RESOURCE, because a projection is declaration-derived: the same
|
|
1591
|
+
// kind schema yields a different row shape for every table.
|
|
1592
|
+
//
|
|
1593
|
+
// A failure here is REPORTED, never dropped. An entry that could not be
|
|
1594
|
+
// read vanishes from the projected shape, so the slot typed from it then
|
|
1595
|
+
// rejects a field the author did declare ("'status' is not allowed") with
|
|
1596
|
+
// nothing saying why — the projection's own failure mode, blaming the
|
|
1597
|
+
// wrong line. Entry-module-scoped, like every other schema issue.
|
|
1598
|
+
const projectionFailures = [];
|
|
1599
|
+
const projected = resolveSchemaProjections(schema, m, resourceProjectionScope, projectionFailures);
|
|
1600
|
+
if (!ownModule || rootModules.has(ownModule)) {
|
|
1601
|
+
for (const failure of projectionFailures) {
|
|
1602
|
+
diagnostics.push({
|
|
1603
|
+
severity: DiagnosticSeverity.Error,
|
|
1604
|
+
code: "SCHEMA_PROJECTION_FROM_UNRESOLVED",
|
|
1605
|
+
source: SOURCE,
|
|
1606
|
+
message: `${m.kind}/${resource.name}: ${describeProjectionFailure(failure)}`,
|
|
1607
|
+
data: { resource, filePath, path: pointerToPath(failure.pointer) },
|
|
1608
|
+
});
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1537
1611
|
// Phase 2+3: AJV on substituted data — CEL fields replaced with typed
|
|
1538
1612
|
// placeholders. Through the REGISTRY, so a kind whose schema references
|
|
1539
1613
|
// a shape declared elsewhere is checked on the instance that holds it.
|
|
1540
|
-
const ajvIssues = defs.validateResourceConfig(substituteCelFields(m,
|
|
1614
|
+
const ajvIssues = defs.validateResourceConfig(substituteCelFields(m, projected, undefined, {
|
|
1615
|
+
external: (ref) => defs.schemaForId(ref),
|
|
1616
|
+
}), projected);
|
|
1541
1617
|
// Phase 4: value slots that must satisfy a type declared elsewhere on
|
|
1542
1618
|
// the resource (`x-telo-value-schema-from`) — e.g. every row of a
|
|
1543
1619
|
// decision table against its declared `outputType`, so a mistyped branch
|
|
@@ -1563,10 +1639,10 @@ export class StaticAnalyzer {
|
|
|
1563
1639
|
// `validate-resource-rules.ts`, the shape every neighbouring pass uses:
|
|
1564
1640
|
// issues out, one emit here.
|
|
1565
1641
|
const ruleDeclarer = definition.metadata?.module;
|
|
1566
|
-
for (const report of reportResourceRules(m, definition, evaluateResourceRules(m,
|
|
1642
|
+
for (const report of reportResourceRules(m, definition, evaluateResourceRules(m, schema), !ruleDeclarer || rootModules.has(ruleDeclarer))) {
|
|
1567
1643
|
diagnostics.push(resourceRuleDiagnostic(report));
|
|
1568
1644
|
}
|
|
1569
|
-
for (const rule of readResourceRules(
|
|
1645
|
+
for (const rule of readResourceRules(schema)) {
|
|
1570
1646
|
const key = `${definition.metadata?.module}.${definition.metadata?.name}#${rule.code}`;
|
|
1571
1647
|
const tracked = ruleExercise.get(key);
|
|
1572
1648
|
if (!tracked)
|
|
@@ -1581,10 +1657,10 @@ export class StaticAnalyzer {
|
|
|
1581
1657
|
// literal appears on the referring side, where the spelling would be the
|
|
1582
1658
|
// consumer's import alias rather than anything the rule's author controls.
|
|
1583
1659
|
// A consumer of the shared call graph, never a second traversal.
|
|
1584
|
-
const referrerRules = readReferrerRules(
|
|
1660
|
+
const referrerRules = readReferrerRules(schema);
|
|
1585
1661
|
if (referrerRules.length > 0) {
|
|
1586
1662
|
const referrers = referrersOf(m, getCallGraph());
|
|
1587
|
-
for (const report of reportReferrerRules(m, definition, evaluateReferrerRules(m,
|
|
1663
|
+
for (const report of reportReferrerRules(m, definition, evaluateReferrerRules(m, schema, referrers, kindMatches, referrerRuleContext), !ruleDeclarer || rootModules.has(ruleDeclarer))) {
|
|
1588
1664
|
// A VIOLATION is the referrer's data, so it is reported only when that
|
|
1589
1665
|
// manifest is the entry's own — the same direction a resource-rule
|
|
1590
1666
|
// violation takes, one hop further out.
|
|
@@ -1593,6 +1669,15 @@ export class StaticAnalyzer {
|
|
|
1593
1669
|
continue;
|
|
1594
1670
|
}
|
|
1595
1671
|
diagnostics.push(referrerRuleDiagnostic(report));
|
|
1672
|
+
// A rule that VIOLATED plainly ran, whatever its peer set held. The
|
|
1673
|
+
// unexercised report exists to catch silence — a `peers:` naming
|
|
1674
|
+
// nothing makes every `!peers.exists(…)` pass vacuously — so a finding
|
|
1675
|
+
// is exactly the evidence it asks for.
|
|
1676
|
+
if (report.code === "REFERRER_RULE_VIOLATED") {
|
|
1677
|
+
const violated = referrerRuleExercise.get(`${definition.metadata?.module}.${definition.metadata?.name}#${report.rule}`);
|
|
1678
|
+
if (violated)
|
|
1679
|
+
violated.exercised = true;
|
|
1680
|
+
}
|
|
1596
1681
|
}
|
|
1597
1682
|
for (const rule of referrerRules) {
|
|
1598
1683
|
const key = `${definition.metadata?.module}.${definition.metadata?.name}#${rule.code}`;
|
|
@@ -1600,8 +1685,9 @@ export class StaticAnalyzer {
|
|
|
1600
1685
|
if (!tracked)
|
|
1601
1686
|
continue;
|
|
1602
1687
|
tracked.seen = true;
|
|
1603
|
-
if (referrerRuleExercised(rule, referrers, kindMatches))
|
|
1688
|
+
if (referrerRuleExercised(rule, referrers, kindMatches, referrerRuleContext)) {
|
|
1604
1689
|
tracked.exercised = true;
|
|
1690
|
+
}
|
|
1605
1691
|
}
|
|
1606
1692
|
}
|
|
1607
1693
|
// Validate inline resources nested inside this resource's body (e.g. a
|
|
@@ -1769,18 +1855,15 @@ export class StaticAnalyzer {
|
|
|
1769
1855
|
// same schema an expression is typed against.
|
|
1770
1856
|
let celStepContextSchema;
|
|
1771
1857
|
let celErrorScopes = new Map();
|
|
1772
|
-
//
|
|
1773
|
-
//
|
|
1774
|
-
//
|
|
1775
|
-
//
|
|
1776
|
-
|
|
1858
|
+
// Where this kind says its values are evaluated — `x-telo-eval` paths (own +
|
|
1859
|
+
// capability) and the regions covering their contents. A `!cel` outside every
|
|
1860
|
+
// one of them is read as a literal, and one under a compile path resolves at
|
|
1861
|
+
// startup, where observed state cannot exist yet. Both questions are
|
|
1862
|
+
// `celEvalModeAt`, which the editor asks of the same sites.
|
|
1863
|
+
let celSites = NO_CEL_EVAL_SITES;
|
|
1777
1864
|
// The bindings field this kind declares (if any), read by the CEL sites that
|
|
1778
1865
|
// see the names it introduces.
|
|
1779
1866
|
let celBindingSites;
|
|
1780
|
-
// The compile half alone: a field that resolves at startup, where observed
|
|
1781
|
-
// state cannot exist yet.
|
|
1782
|
-
let celCompilePaths = [];
|
|
1783
|
-
let celRegionScopes = [];
|
|
1784
1867
|
let celRuleApplies = false;
|
|
1785
1868
|
visitManifest(allManifests, defs, {
|
|
1786
1869
|
onResourceEnter: (e) => {
|
|
@@ -1912,23 +1995,23 @@ export class StaticAnalyzer {
|
|
|
1912
1995
|
celRuleApplies =
|
|
1913
1996
|
!!e.definition?.schema && capability !== undefined && capability !== "Telo.Template";
|
|
1914
1997
|
if (celRuleApplies) {
|
|
1915
|
-
|
|
1916
|
-
|
|
1998
|
+
// The INHERITANCE-RESOLVED schema, not the kind's own: without
|
|
1999
|
+
// `base:`, an `extends` child is authored against merge(parent, own),
|
|
2000
|
+
// so a CEL-bearing field the parent declares is a legal field on the
|
|
2001
|
+
// child and the kernel expands it — it stamps the merged schema at
|
|
2002
|
+
// definition registration and builds eval paths from that. Reading
|
|
2003
|
+
// the own schema here reported `CEL_IN_NON_EVAL_FIELD` for an
|
|
2004
|
+
// expression the runtime evaluates correctly, which is the two halves
|
|
2005
|
+
// disagreeing about what the manifest means.
|
|
2006
|
+
const ownSchema = effectiveAuthorSchema(e.definition, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k));
|
|
1917
2007
|
const capabilityDef = capability ? defs.resolve(capability) : undefined;
|
|
1918
|
-
const parent = capabilityDef?.schema
|
|
1919
|
-
? buildEvalPaths(capabilityDef.schema)
|
|
1920
|
-
: { compile: [], runtime: [] };
|
|
1921
|
-
celEvalPaths = [...own.compile, ...own.runtime, ...parent.compile, ...parent.runtime];
|
|
1922
2008
|
// A `Telo.Provider`'s fields are implicitly compile-eval — the
|
|
1923
2009
|
// capability abstract carries the root annotation — so its reads are
|
|
1924
2010
|
// covered here without the provider restating anything.
|
|
1925
|
-
|
|
1926
|
-
celRegionScopes = extractCelRegionScopes(ownSchema);
|
|
2011
|
+
celSites = mergeCelEvalSites(celEvalSites(ownSchema), celEvalSites(capabilityDef?.schema));
|
|
1927
2012
|
}
|
|
1928
2013
|
else {
|
|
1929
|
-
|
|
1930
|
-
celCompilePaths = [];
|
|
1931
|
-
celRegionScopes = [];
|
|
2014
|
+
celSites = NO_CEL_EVAL_SITES;
|
|
1932
2015
|
}
|
|
1933
2016
|
},
|
|
1934
2017
|
onCel: (e) => {
|
|
@@ -1944,8 +2027,7 @@ export class StaticAnalyzer {
|
|
|
1944
2027
|
if (celRuleApplies &&
|
|
1945
2028
|
engineName === "cel" &&
|
|
1946
2029
|
celScope.invocationContextSchema === undefined &&
|
|
1947
|
-
|
|
1948
|
-
!celRegionScopes.some((scope) => pathMatchesScope(path, scope)) &&
|
|
2030
|
+
celEvalModeAt(celSites, path) === null &&
|
|
1949
2031
|
!pathCrossesNestedResource(m, path)) {
|
|
1950
2032
|
diagnostics.push({
|
|
1951
2033
|
severity: DiagnosticSeverity.Error,
|
|
@@ -1969,7 +2051,7 @@ export class StaticAnalyzer {
|
|
|
1969
2051
|
// the two-level shape it publishes under, so a cross-module read
|
|
1970
2052
|
// is checked exactly like a local one.
|
|
1971
2053
|
const reported = observedState.get(read.alias ? `${read.alias}.${read.name}` : read.name);
|
|
1972
|
-
if (celRuleApplies &&
|
|
2054
|
+
if (celRuleApplies && celEvalModeAt(celSites, path) === "compile") {
|
|
1973
2055
|
diagnostics.push({
|
|
1974
2056
|
severity: DiagnosticSeverity.Error,
|
|
1975
2057
|
code: "OBSERVED_STATE_IN_STARTUP_FIELD",
|
|
@@ -2013,7 +2095,19 @@ export class StaticAnalyzer {
|
|
|
2013
2095
|
contextSchema: e.contextSchema,
|
|
2014
2096
|
matchedScope,
|
|
2015
2097
|
});
|
|
2016
|
-
const result = engine.analyze(expr, {
|
|
2098
|
+
const result = engine.analyze(expr, {
|
|
2099
|
+
celEnv: typedEnv,
|
|
2100
|
+
contextSchema: effectiveContext,
|
|
2101
|
+
// `scopeFor` registers every kernel global and every name the site's
|
|
2102
|
+
// context declares, so a root this environment does not know is one
|
|
2103
|
+
// nothing puts in scope. Two places where the CEL belongs to another
|
|
2104
|
+
// scope, both already recognised by the non-eval-field check: a kind
|
|
2105
|
+
// document, whose CEL is written for whoever instantiates the kind,
|
|
2106
|
+
// and anything below a nested inline `{ kind }`, whose CEL the
|
|
2107
|
+
// nested kind evaluates — and which is analyzed again, in its own
|
|
2108
|
+
// scope, as the resource it was extracted into.
|
|
2109
|
+
rootsDeclared: !isKindDocument(m) && !pathCrossesNestedResource(m, path),
|
|
2110
|
+
});
|
|
2017
2111
|
if (result.type !== undefined) {
|
|
2018
2112
|
let byPath = celTypeByPath.get(m);
|
|
2019
2113
|
if (!byPath)
|
|
@@ -2049,7 +2143,7 @@ export class StaticAnalyzer {
|
|
|
2049
2143
|
// intent (a boot timestamp, a run id), so it warns rather than
|
|
2050
2144
|
// blocking. The engine reports which calls re-evaluate; the eval mode
|
|
2051
2145
|
// is manifest policy and stays here.
|
|
2052
|
-
if (celRuleApplies &&
|
|
2146
|
+
if (celRuleApplies && celEvalModeAt(celSites, path) === "compile") {
|
|
2053
2147
|
const volatile = [
|
|
2054
2148
|
...new Set(result.calls.filter((c) => c.deterministic === false).map((c) => c.name)),
|
|
2055
2149
|
].sort();
|
package/dist/call-graph.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call-graph.d.ts","sourceRoot":"","sources":["../src/call-graph.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"call-graph.d.ts","sourceRoot":"","sources":["../src/call-graph.ts"],"names":[],"mappings":"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"}
|
package/dist/call-graph.js
CHANGED
|
@@ -119,7 +119,13 @@ function resolveUseAtSite(entry, root, concretePath, schemaDefault) {
|
|
|
119
119
|
if (resolved)
|
|
120
120
|
return { use: resolved };
|
|
121
121
|
}
|
|
122
|
-
const slot = {
|
|
122
|
+
const slot = {
|
|
123
|
+
kinds: entry.refs,
|
|
124
|
+
uses: entry.uses,
|
|
125
|
+
useCases: entry.useCases,
|
|
126
|
+
inline: false,
|
|
127
|
+
valueBranches: [],
|
|
128
|
+
};
|
|
123
129
|
const unresolvedReason = isTaggedSentinel(selector)
|
|
124
130
|
? "dynamic"
|
|
125
131
|
: selector === undefined
|
|
@@ -13,6 +13,18 @@ export type { CelHandlers } from "@telorun/templating";
|
|
|
13
13
|
* NOTE: The set of kernel globals registered here must match `KERNEL_GLOBAL_NAMES`
|
|
14
14
|
* in kernel-globals.ts, which is used for chain-access validation. */
|
|
15
15
|
export declare function buildTypedCelEnvironment(baseEnv: Environment, manifest: ResourceManifest, extraContextSchema?: Record<string, any> | null, rootModuleManifest?: ResourceManifest): Environment;
|
|
16
|
+
/**
|
|
17
|
+
* A kind document — whose CEL is written for whoever instantiates the kind, not
|
|
18
|
+
* evaluated in the declaring module's own scope.
|
|
19
|
+
*
|
|
20
|
+
* Its `examples:` show a consumer's route reading `request` and `result`, its
|
|
21
|
+
* `description`s show `${{ secrets.API_KEY }}`, and a rule condition reads the
|
|
22
|
+
* `self` / `referrer` its own evaluator binds. None of those names are in scope
|
|
23
|
+
* where they are WRITTEN, and all of them are correct where they are READ — so
|
|
24
|
+
* every check that asks "is this name in scope here" has to stand down on these
|
|
25
|
+
* documents, or it reports errors nobody can fix without deleting the example.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isKindDocument(manifest: ResourceManifest): boolean;
|
|
16
28
|
/** CEL environment for the `variables:`/`secrets:` expressions on a `Telo.Import`.
|
|
17
29
|
*
|
|
18
30
|
* Import inputs are a config-only contract: their expressions are evaluated
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cel-environment.d.ts","sourceRoot":"","sources":["../src/cel-environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAcrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;uEASuE;AACvE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,gBAAgB,EAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,EAI/C,kBAAkB,CAAC,EAAE,gBAAgB,GACpC,WAAW,
|
|
1
|
+
{"version":3,"file":"cel-environment.d.ts","sourceRoot":"","sources":["../src/cel-environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAcrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;uEASuE;AACvE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,gBAAgB,EAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,EAI/C,kBAAkB,CAAC,EAAE,gBAAgB,GACpC,WAAW,CA8Gb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAElE;AAuBD;;;;;;8DAM8D;AAC9D,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,WAAW,EACpB,cAAc,EAAE,gBAAgB,GAAG,SAAS,GAC3C,WAAW,CAkCb"}
|
package/dist/cel-environment.js
CHANGED
|
@@ -35,24 +35,26 @@ rootModuleManifest) {
|
|
|
35
35
|
for (const brand of Object.keys(VALUE_BRAND_BASE)) {
|
|
36
36
|
env.registerType(brand, { fields: {} });
|
|
37
37
|
}
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
// `variables` / `secrets`: the DECLARING module's blocks, which is the
|
|
39
|
+
// contract the resource's CEL is evaluated against at runtime. Read the
|
|
40
|
+
// same three ways `ports` and `module` are, and for the same reason — a
|
|
41
|
+
// resource doc does not carry them, so typing from `manifest` alone left
|
|
42
|
+
// every ordinary resource with an open `variables` and no check at all,
|
|
43
|
+
// while `ports.<typo>` one line away was an error.
|
|
44
|
+
//
|
|
45
|
+
// Order matters: a module-identity doc analyzing itself carries its own
|
|
46
|
+
// block; a resource forwarded from an imported library carries its
|
|
47
|
+
// library's as `metadata.moduleGlobals`, which must win over the consuming
|
|
48
|
+
// application's; everything else is the entry module's own doc.
|
|
49
|
+
const moduleGlobals = manifest.metadata?.moduleGlobals;
|
|
50
|
+
// A KIND document is the exception, and it is not a detail: the CEL inside
|
|
51
|
+
// a `Telo.Definition`'s `schema:` — an `examples:` entry, a `description`
|
|
52
|
+
// showing `${{ secrets.API_KEY }}` — illustrates what a CONSUMER writes, in
|
|
53
|
+
// the consumer's scope. Closing those over the declaring module's blocks
|
|
54
|
+
// reported an error against a name the module never meant to declare, and
|
|
55
|
+
// one nobody could fix without deleting the example.
|
|
56
|
+
const root = (isKindDocument(manifest) ? undefined : rootModuleManifest);
|
|
57
|
+
registerConfigNamespace(env, manifest.variables ?? moduleGlobals?.variables ?? root?.variables, "variables");
|
|
56
58
|
// `ports` namespace: each entry types as the brand its `protocol` selects
|
|
57
59
|
// (tcp → TcpPort, udp → UdpPort), so `${{ ports.http }}` carries a nominal
|
|
58
60
|
// type that consuming fields can check against.
|
|
@@ -73,7 +75,7 @@ rootModuleManifest) {
|
|
|
73
75
|
else {
|
|
74
76
|
env.registerVariable("ports", "map");
|
|
75
77
|
}
|
|
76
|
-
env.
|
|
78
|
+
registerConfigNamespace(env, manifest.secrets ?? moduleGlobals?.secrets ?? root?.secrets, "secrets");
|
|
77
79
|
env.registerVariable("resources", "map");
|
|
78
80
|
// `module` — the declaring module's own `metadata`, so a manifest reads its
|
|
79
81
|
// version instead of restating it. A resource forwarded from an imported
|
|
@@ -110,6 +112,20 @@ rootModuleManifest) {
|
|
|
110
112
|
return baseEnv.clone();
|
|
111
113
|
}
|
|
112
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* A kind document — whose CEL is written for whoever instantiates the kind, not
|
|
117
|
+
* evaluated in the declaring module's own scope.
|
|
118
|
+
*
|
|
119
|
+
* Its `examples:` show a consumer's route reading `request` and `result`, its
|
|
120
|
+
* `description`s show `${{ secrets.API_KEY }}`, and a rule condition reads the
|
|
121
|
+
* `self` / `referrer` its own evaluator binds. None of those names are in scope
|
|
122
|
+
* where they are WRITTEN, and all of them are correct where they are READ — so
|
|
123
|
+
* every check that asks "is this name in scope here" has to stand down on these
|
|
124
|
+
* documents, or it reports errors nobody can fix without deleting the example.
|
|
125
|
+
*/
|
|
126
|
+
export function isKindDocument(manifest) {
|
|
127
|
+
return manifest.kind === "Telo.Definition" || manifest.kind === "Telo.Abstract";
|
|
128
|
+
}
|
|
113
129
|
/** Register a `variables`/`secrets` namespace typed from a module doc's schema map
|
|
114
130
|
* (`{ name: <schema>, … }`), falling back to dyn `map` when absent or untyped. */
|
|
115
131
|
function registerConfigNamespace(env, block, name) {
|
package/dist/cel-scope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cel-scope.d.ts","sourceRoot":"","sources":["../src/cel-scope.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cel-scope.d.ts","sourceRoot":"","sources":["../src/cel-scope.ts"],"names":[],"mappings":"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"}
|
package/dist/cel-scope.js
CHANGED
|
@@ -293,10 +293,16 @@ export class CelScopeResolver {
|
|
|
293
293
|
enterResource(m, definition) {
|
|
294
294
|
const { allManifests, defs, aliases, scopes } = this.inputs;
|
|
295
295
|
this.invocationContext = m.metadata?.xTeloInvocationContext;
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
// The INHERITANCE-RESOLVED schema at both sites, for the reason the CEL
|
|
297
|
+
// context regions use it: an `extends` child is authored against
|
|
298
|
+
// merge(parent, own), so a step body or a `catch:` region the parent
|
|
299
|
+
// declares is in force on the child. All three consumers share one memo so
|
|
300
|
+
// they cannot come to disagree about which schema a kind means.
|
|
301
|
+
const authorSchema = defs.effectiveSchemaOf(definition);
|
|
302
|
+
this.stepContext = authorSchema
|
|
303
|
+
? buildStepContextSchema(m, authorSchema, allManifests, defs, aliases, scopes)
|
|
298
304
|
: undefined;
|
|
299
|
-
this.errorScopes = collectErrorContextScopes(
|
|
305
|
+
this.errorScopes = collectErrorContextScopes(authorSchema);
|
|
300
306
|
}
|
|
301
307
|
/**
|
|
302
308
|
* What the expression at `site` is typed against.
|
|
@@ -337,7 +343,21 @@ export class CelScopeResolver {
|
|
|
337
343
|
const base = matched ?? { type: "object", properties: {}, additionalProperties: true };
|
|
338
344
|
matched = {
|
|
339
345
|
...base,
|
|
340
|
-
properties: {
|
|
346
|
+
properties: {
|
|
347
|
+
// `inputs` is in scope beside `steps` wherever a step body runs — the
|
|
348
|
+
// step engine evaluates a step against the enclosing kind's own
|
|
349
|
+
// arguments, which is what `steps[0].inputs.x` reads. Modelled here
|
|
350
|
+
// because it was modelled NOWHERE: the step context is open, so a
|
|
351
|
+
// chain through it was never checked and the name's absence went
|
|
352
|
+
// unnoticed until something asked whether the root existed.
|
|
353
|
+
//
|
|
354
|
+
// OPEN, not typed from the kind's `inputType`: closing it would newly
|
|
355
|
+
// reject every read of an argument the contract does not spell out,
|
|
356
|
+
// which is a separate decision from knowing the name is legal.
|
|
357
|
+
inputs: { type: "object", additionalProperties: true },
|
|
358
|
+
...(base.properties ?? {}),
|
|
359
|
+
steps: this.stepContext,
|
|
360
|
+
},
|
|
341
361
|
};
|
|
342
362
|
}
|
|
343
363
|
// `error` is only in scope inside an error-bearing branch (e.g. a
|