@telorun/analyzer 0.45.0 → 0.47.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/alias-resolver.d.ts +45 -0
- package/dist/alias-resolver.d.ts.map +1 -1
- package/dist/alias-resolver.js +33 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +106 -5
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +3 -0
- package/dist/extends-resolution.d.ts +19 -2
- package/dist/extends-resolution.d.ts.map +1 -1
- package/dist/extends-resolution.js +25 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/kernel-globals.d.ts +9 -1
- package/dist/kernel-globals.d.ts.map +1 -1
- package/dist/kernel-globals.js +24 -1
- package/dist/resolve-ref-sentinels.d.ts +13 -1
- package/dist/resolve-ref-sentinels.d.ts.map +1 -1
- package/dist/resolve-ref-sentinels.js +56 -5
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +17 -1
- package/dist/validate-observed-state.d.ts +98 -0
- package/dist/validate-observed-state.d.ts.map +1 -0
- package/dist/validate-observed-state.js +304 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +8 -2
- package/package.json +2 -2
- package/src/alias-resolver.ts +58 -0
- package/src/analyzer.ts +126 -4
- package/src/builtins.ts +3 -0
- package/src/extends-resolution.ts +37 -3
- package/src/index.ts +13 -0
- package/src/kernel-globals.ts +20 -0
- package/src/resolve-ref-sentinels.ts +68 -4
- package/src/validate-cel-context.ts +20 -1
- package/src/validate-observed-state.ts +354 -0
- package/src/validate-references.ts +8 -2
package/dist/alias-resolver.d.ts
CHANGED
|
@@ -65,4 +65,49 @@ export declare class AliasResolver {
|
|
|
65
65
|
* the root `aliases`.
|
|
66
66
|
*/
|
|
67
67
|
export declare function scopeResolverForModule(ownModule: string | undefined, rootModules: Set<string>, aliasesByModule: Map<string, AliasResolver>): AliasResolver | undefined;
|
|
68
|
+
/** Per-declaring-module alias tables plus the set of root (consumer-owned)
|
|
69
|
+
* modules. The shape `StaticAnalyzer.analyze` already threads through its
|
|
70
|
+
* passes, and what {@link moduleScopedDefResolver} needs to re-scope. */
|
|
71
|
+
export interface ModuleScopes {
|
|
72
|
+
aliasesByModule: ReadonlyMap<string, {
|
|
73
|
+
resolveKind(kind: string): string | undefined;
|
|
74
|
+
}>;
|
|
75
|
+
rootModules: ReadonlySet<string>;
|
|
76
|
+
}
|
|
77
|
+
/** Minimal view of the definition registry a kind lookup needs. */
|
|
78
|
+
export interface DefinitionLookup {
|
|
79
|
+
resolve(kind: string): unknown;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a kind to its definition **in the scope that declared it**.
|
|
83
|
+
*
|
|
84
|
+
* An `extends` alias belongs to the file it was written in, not to whoever is
|
|
85
|
+
* reading it: a consumer that imports only a backend (the sanctioned "one import
|
|
86
|
+
* instead of two") has no alias for the abstract's library, so folding an
|
|
87
|
+
* inheritance chain with the consumer's table silently stops at the first hop
|
|
88
|
+
* and yields an un-merged schema. `from` — the definition the kind was read off —
|
|
89
|
+
* carries `metadata.module`, which is the scope to resolve in; a chain crossing
|
|
90
|
+
* several modules re-scopes at every hop.
|
|
91
|
+
*
|
|
92
|
+
* `resolveIn` takes the module explicitly, for the top-level lookup where there
|
|
93
|
+
* is no `from` yet (an exported instance's `kind: Self.X` is written in the
|
|
94
|
+
* exporting library's scope, which the consumer's table cannot resolve either).
|
|
95
|
+
*
|
|
96
|
+
* The runtime counterpart is `resource-definition-controller`, which resolves
|
|
97
|
+
* against the defining module context and stamps the result; keeping both on the
|
|
98
|
+
* same rule is what stops `telo check` and the kernel from disagreeing about
|
|
99
|
+
* which inherited fields a child kind may set.
|
|
100
|
+
*/
|
|
101
|
+
export declare function moduleScopedDefResolver<T>(defs: {
|
|
102
|
+
resolve(kind: string): T | undefined;
|
|
103
|
+
}, aliases?: {
|
|
104
|
+
resolveKind(kind: string): string | undefined;
|
|
105
|
+
}, scopes?: ModuleScopes): {
|
|
106
|
+
(kind: string, from?: {
|
|
107
|
+
metadata?: {
|
|
108
|
+
module?: string;
|
|
109
|
+
};
|
|
110
|
+
}): T | undefined;
|
|
111
|
+
in(kind: string, module?: string): T | undefined;
|
|
112
|
+
};
|
|
68
113
|
//# sourceMappingURL=alias-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-resolver.d.ts","sourceRoot":"","sources":["../src/alias-resolver.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE;;4FAEwF;IACxF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAE7D;;;;;0EAKsE;IACtE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAO5F;+FAC2F;IAC3F,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAI/D;sFACkF;IAClF,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAIhF;;;;qDAIiD;IACjD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjD;;;;;;;;iFAQ6E;IAC7E,iBAAiB,CACf,IAAI,EAAE,MAAM,GAEV;QAAE,MAAM,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,GACvD;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE;IAoBzB;8EAC0E;IAC1E,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC,YAAY,IAAI,MAAM,EAAE;IAIxB;;qEAEiE;IACjE,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE;CAO3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC1C,aAAa,GAAG,SAAS,CAI3B"}
|
|
1
|
+
{"version":3,"file":"alias-resolver.d.ts","sourceRoot":"","sources":["../src/alias-resolver.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE;;4FAEwF;IACxF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAE7D;;;;;0EAKsE;IACtE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAO5F;+FAC2F;IAC3F,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAI/D;sFACkF;IAClF,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAIhF;;;;qDAIiD;IACjD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjD;;;;;;;;iFAQ6E;IAC7E,iBAAiB,CACf,IAAI,EAAE,MAAM,GAEV;QAAE,MAAM,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,GACvD;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE;IAoBzB;8EAC0E;IAC1E,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC,YAAY,IAAI,MAAM,EAAE;IAIxB;;qEAEiE;IACjE,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE;CAO3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC1C,aAAa,GAAG,SAAS,CAI3B;AAED;;0EAE0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE;QAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC;IACxF,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EACvC,IAAI,EAAE;IAAE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAA;CAAE,EAC9C,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAAE,EAC3D,MAAM,CAAC,EAAE,YAAY,GACpB;IACD,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IACzE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAClD,CAgBA"}
|
package/dist/alias-resolver.js
CHANGED
|
@@ -107,3 +107,36 @@ export function scopeResolverForModule(ownModule, rootModules, aliasesByModule)
|
|
|
107
107
|
? aliasesByModule.get(ownModule)
|
|
108
108
|
: undefined;
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Resolve a kind to its definition **in the scope that declared it**.
|
|
112
|
+
*
|
|
113
|
+
* An `extends` alias belongs to the file it was written in, not to whoever is
|
|
114
|
+
* reading it: a consumer that imports only a backend (the sanctioned "one import
|
|
115
|
+
* instead of two") has no alias for the abstract's library, so folding an
|
|
116
|
+
* inheritance chain with the consumer's table silently stops at the first hop
|
|
117
|
+
* and yields an un-merged schema. `from` — the definition the kind was read off —
|
|
118
|
+
* carries `metadata.module`, which is the scope to resolve in; a chain crossing
|
|
119
|
+
* several modules re-scopes at every hop.
|
|
120
|
+
*
|
|
121
|
+
* `resolveIn` takes the module explicitly, for the top-level lookup where there
|
|
122
|
+
* is no `from` yet (an exported instance's `kind: Self.X` is written in the
|
|
123
|
+
* exporting library's scope, which the consumer's table cannot resolve either).
|
|
124
|
+
*
|
|
125
|
+
* The runtime counterpart is `resource-definition-controller`, which resolves
|
|
126
|
+
* against the defining module context and stamps the result; keeping both on the
|
|
127
|
+
* same rule is what stops `telo check` and the kernel from disagreeing about
|
|
128
|
+
* which inherited fields a child kind may set.
|
|
129
|
+
*/
|
|
130
|
+
export function moduleScopedDefResolver(defs, aliases, scopes) {
|
|
131
|
+
const resolveIn = (kind, module) => {
|
|
132
|
+
const scoped = module && scopes && !scopes.rootModules.has(module)
|
|
133
|
+
? scopes.aliasesByModule.get(module)
|
|
134
|
+
: undefined;
|
|
135
|
+
return ((scoped ? defs.resolve(scoped.resolveKind(kind) ?? kind) : undefined) ??
|
|
136
|
+
defs.resolve(aliases?.resolveKind(kind) ?? kind) ??
|
|
137
|
+
defs.resolve(kind));
|
|
138
|
+
};
|
|
139
|
+
const resolver = ((kind, from) => resolveIn(kind, from?.metadata?.module));
|
|
140
|
+
resolver.in = resolveIn;
|
|
141
|
+
return resolver;
|
|
142
|
+
}
|
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;AAKzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AA6B9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAyyB/F,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,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,GAC1B,kBAAkB,EAAE;IA4hCvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,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,4 +1,4 @@
|
|
|
1
|
-
import { canonicalTypeSchemaId } from "@telorun/sdk";
|
|
1
|
+
import { canonicalTypeSchemaId, OBSERVED_STATE_KEY } from "@telorun/sdk";
|
|
2
2
|
import { defaultRegistry, isRefSentinel, isTaggedSentinel } from "@telorun/templating";
|
|
3
3
|
import { AliasResolver, scopeResolverForModule } from "./alias-resolver.js";
|
|
4
4
|
import { buildCelEnvironment, buildImportInputCelEnvironment, buildTypedCelEnvironment, } from "./cel-environment.js";
|
|
@@ -6,6 +6,7 @@ import { DefinitionRegistry } from "./definition-registry.js";
|
|
|
6
6
|
import { effectiveAuthorSchema } from "./extends-resolution.js";
|
|
7
7
|
import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
|
|
8
8
|
import { buildKernelGlobalsSchema, mergeKernelGlobalsIntoContext } from "./kernel-globals.js";
|
|
9
|
+
import { buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, } from "./validate-observed-state.js";
|
|
9
10
|
import { computeSuggestKind } from "./kind-suggest.js";
|
|
10
11
|
import { visitManifest } from "./manifest-visitor.js";
|
|
11
12
|
import { isModuleKind } from "./module-kinds.js";
|
|
@@ -19,7 +20,7 @@ import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
|
|
|
19
20
|
import { celTypeSatisfiesJsonSchema, substituteCelFields, validateAgainstSchema, } from "./schema-compat.js";
|
|
20
21
|
import { collectValueSchemaIssues } from "./validate-value-schema.js";
|
|
21
22
|
import { DiagnosticSeverity } from "./types.js";
|
|
22
|
-
import { extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
|
|
23
|
+
import { extractAccessChains, extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
|
|
23
24
|
import { buildEvalPaths, evalPathsCover } from "./eval-paths.js";
|
|
24
25
|
import { validateExtends } from "./validate-extends.js";
|
|
25
26
|
import { validateLogging } from "./validate-logging.js";
|
|
@@ -601,6 +602,16 @@ function errorContextForPath(path, scopes) {
|
|
|
601
602
|
}
|
|
602
603
|
return best?.schema;
|
|
603
604
|
}
|
|
605
|
+
/** Member-access chains in a CEL expression, or none when it doesn't parse.
|
|
606
|
+
* Best-effort: a syntax error is reported by the engine pass, not here. */
|
|
607
|
+
function celAccessChains(env, expr) {
|
|
608
|
+
try {
|
|
609
|
+
return extractAccessChains(env.parse(expr).ast);
|
|
610
|
+
}
|
|
611
|
+
catch {
|
|
612
|
+
return [];
|
|
613
|
+
}
|
|
614
|
+
}
|
|
604
615
|
const CEL_PURE_RE = /^\s*\$\{\{[^}]*\}\}\s*$/;
|
|
605
616
|
const CEL_EXPR_RE = /\$\{\{\s*([^}]+?)\s*\}\}/;
|
|
606
617
|
/** Recursively walk `data`+`schema` together, type-checking every pure CEL template
|
|
@@ -962,7 +973,7 @@ export class StaticAnalyzer {
|
|
|
962
973
|
// {kind, name} objects so downstream phases (validation, dependency graph,
|
|
963
974
|
// kernel controllers) see a uniform shape. Runs after normalize so both
|
|
964
975
|
// original and inline-extracted manifests have their sentinels resolved.
|
|
965
|
-
resolveRefSentinels(allManifests, aliases, aliasesByModule);
|
|
976
|
+
resolveRefSentinels(allManifests, aliases, aliasesByModule, [], defs);
|
|
966
977
|
// Phase 2.6: register each named `Telo.Type` resource's schema under its
|
|
967
978
|
// canonical module-scoped id (`telo://<module>/<name>`), validate
|
|
968
979
|
// `telo://Self|Alias/Type` schema refs resolve to one, then rewrite those
|
|
@@ -1100,9 +1111,34 @@ export class StaticAnalyzer {
|
|
|
1100
1111
|
}
|
|
1101
1112
|
}
|
|
1102
1113
|
}
|
|
1114
|
+
// What each resource reports while running (`status:`), and which resources
|
|
1115
|
+
// some slot can actually start. Both feed the observed-state checks below.
|
|
1116
|
+
// A RESOURCE's kind is written in the module that declares it and is never
|
|
1117
|
+
// canonicalized (unlike a definition's `extends`, normalized at registration
|
|
1118
|
+
// above), so an exported instance's `kind: Self.X` only resolves in its own
|
|
1119
|
+
// library's scope.
|
|
1120
|
+
const moduleScopes = { aliasesByModule, rootModules };
|
|
1121
|
+
const observedState = buildObservedStateIndex(allManifests, defs, aliases, moduleScopes);
|
|
1122
|
+
const reportsObservedState = [...observedState.values()].some((r) => r.status);
|
|
1123
|
+
const runReachable = reportsObservedState
|
|
1124
|
+
? collectRunReachableNames(allManifests, defs, aliases)
|
|
1125
|
+
: new Set();
|
|
1103
1126
|
// Build typed kernel globals schema so x-telo-context chain validation
|
|
1104
1127
|
// recognises variables, secrets, resources, env automatically
|
|
1105
|
-
const kernelGlobals = buildKernelGlobalsSchema(allManifests);
|
|
1128
|
+
const kernelGlobals = buildKernelGlobalsSchema(allManifests, observedState);
|
|
1129
|
+
// Fallback context for CEL in a slot with no `x-telo-context` annotation:
|
|
1130
|
+
// everything stays open except the typed `.status` nodes, so unknown-field
|
|
1131
|
+
// checking reaches observed state everywhere without newly rejecting any
|
|
1132
|
+
// read that passes today.
|
|
1133
|
+
const observedStateContext = reportsObservedState
|
|
1134
|
+
? {
|
|
1135
|
+
type: "object",
|
|
1136
|
+
additionalProperties: true,
|
|
1137
|
+
properties: {
|
|
1138
|
+
resources: buildObservedStateResourcesSchema(observedState, true),
|
|
1139
|
+
},
|
|
1140
|
+
}
|
|
1141
|
+
: null;
|
|
1106
1142
|
// The module doc (Application/Library) carries the Application-only `ports`
|
|
1107
1143
|
// namespace; threaded into per-resource CEL typing so `${{ ports.X }}`
|
|
1108
1144
|
// resolves its nominal brand cross-doc.
|
|
@@ -1358,6 +1394,9 @@ export class StaticAnalyzer {
|
|
|
1358
1394
|
// `x-telo-step-context` / `x-telo-error-context` scopes. A `!cel` outside
|
|
1359
1395
|
// every region is read as a literal — the runtime never evaluates it.
|
|
1360
1396
|
let celEvalPaths = [];
|
|
1397
|
+
// The compile half alone: a field that resolves at startup, where observed
|
|
1398
|
+
// state cannot exist yet.
|
|
1399
|
+
let celCompilePaths = [];
|
|
1361
1400
|
let celRegionScopes = [];
|
|
1362
1401
|
let celRuleApplies = false;
|
|
1363
1402
|
visitManifest(allManifests, defs, {
|
|
@@ -1382,10 +1421,15 @@ export class StaticAnalyzer {
|
|
|
1382
1421
|
? buildEvalPaths(capabilityDef.schema)
|
|
1383
1422
|
: { compile: [], runtime: [] };
|
|
1384
1423
|
celEvalPaths = [...own.compile, ...own.runtime, ...parent.compile, ...parent.runtime];
|
|
1424
|
+
// A `Telo.Provider`'s fields are implicitly compile-eval — the
|
|
1425
|
+
// capability abstract carries the root annotation — so its reads are
|
|
1426
|
+
// covered here without the provider restating anything.
|
|
1427
|
+
celCompilePaths = [...own.compile, ...parent.compile];
|
|
1385
1428
|
celRegionScopes = extractCelRegionScopes(ownSchema);
|
|
1386
1429
|
}
|
|
1387
1430
|
else {
|
|
1388
1431
|
celEvalPaths = [];
|
|
1432
|
+
celCompilePaths = [];
|
|
1389
1433
|
celRegionScopes = [];
|
|
1390
1434
|
}
|
|
1391
1435
|
},
|
|
@@ -1414,6 +1458,40 @@ export class StaticAnalyzer {
|
|
|
1414
1458
|
});
|
|
1415
1459
|
return;
|
|
1416
1460
|
}
|
|
1461
|
+
// Observed state exists only while the application runs, so a path
|
|
1462
|
+
// through `.status` is illegal in a field that resolves at startup —
|
|
1463
|
+
// and a resource nothing can start reports nothing, ever. Both are
|
|
1464
|
+
// decided from the expression and the manifest alone.
|
|
1465
|
+
if (reportsObservedState && engineName === "cel" && expr.includes(OBSERVED_STATE_KEY)) {
|
|
1466
|
+
for (const chain of celAccessChains(this.celEnv, expr)) {
|
|
1467
|
+
const read = observedStateRead(chain);
|
|
1468
|
+
if (!read)
|
|
1469
|
+
continue;
|
|
1470
|
+
// An import's exported instance is indexed under `<Alias>.<name>`,
|
|
1471
|
+
// the two-level shape it publishes under, so a cross-module read
|
|
1472
|
+
// is checked exactly like a local one.
|
|
1473
|
+
const reported = observedState.get(read.alias ? `${read.alias}.${read.name}` : read.name);
|
|
1474
|
+
if (celRuleApplies && evalPathsCover(celCompilePaths, path)) {
|
|
1475
|
+
diagnostics.push({
|
|
1476
|
+
severity: DiagnosticSeverity.Error,
|
|
1477
|
+
code: "OBSERVED_STATE_IN_STARTUP_FIELD",
|
|
1478
|
+
source: SOURCE,
|
|
1479
|
+
message: `${m.kind}/${resource.name}: '${path}' is resolved once at startup, so '${chain.join(".")}' does not exist yet — '${read.name}' reports it only while the application is running. Read reported values where the call happens: a step's inputs:, a request's url, a route handler, or a returns: expression.`,
|
|
1480
|
+
data: { resource, filePath, path },
|
|
1481
|
+
});
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
if (reported && !runReachable.has(read.name)) {
|
|
1485
|
+
diagnostics.push({
|
|
1486
|
+
severity: DiagnosticSeverity.Error,
|
|
1487
|
+
code: "OBSERVED_STATE_NEVER_RUN",
|
|
1488
|
+
source: SOURCE,
|
|
1489
|
+
message: `${m.kind}/${resource.name}: '${read.name}' reports '${read.field ?? OBSERVED_STATE_KEY}' only while it is running, and nothing starts it. Add '!ref ${read.name}' to a targets: list, or invoke it from a step.`,
|
|
1490
|
+
data: { resource, filePath, path },
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1417
1495
|
let matchedContext = e.contextSchema ?? celInvocationContext;
|
|
1418
1496
|
if (celStepContextSchema) {
|
|
1419
1497
|
const base = matchedContext ?? { type: "object", properties: {}, additionalProperties: true };
|
|
@@ -1452,6 +1530,13 @@ export class StaticAnalyzer {
|
|
|
1452
1530
|
});
|
|
1453
1531
|
effectiveContext = mergeKernelGlobalsIntoContext(resolvedContext, kernelGlobals);
|
|
1454
1532
|
}
|
|
1533
|
+
else if (observedStateContext) {
|
|
1534
|
+
// No `x-telo-context` matched, so nothing was chain-validated here
|
|
1535
|
+
// before. Validate the observed-state segment alone rather than
|
|
1536
|
+
// merging the kernel globals, whose closed `variables` / `ports`
|
|
1537
|
+
// nodes would newly reject reads that pass today.
|
|
1538
|
+
effectiveContext = observedStateContext;
|
|
1539
|
+
}
|
|
1455
1540
|
const engine = defaultRegistry().get(engineName);
|
|
1456
1541
|
if (!engine) {
|
|
1457
1542
|
// No registered engine owns this tag — the expression would go
|
|
@@ -1515,6 +1600,22 @@ export class StaticAnalyzer {
|
|
|
1515
1600
|
// deliberately skips (behind the step `$ref`), so a missing instance or a
|
|
1516
1601
|
// kind-instead-of-instance ref there is caught statically, not at runtime.
|
|
1517
1602
|
diagnostics.push(...validateStepInvokeReferences(allManifests, defs, aliases));
|
|
1603
|
+
// `required:` inside a `status:` block — reported here rather than by the
|
|
1604
|
+
// AJV shape, which could only say "must NOT be valid" without naming the
|
|
1605
|
+
// rule or the fix.
|
|
1606
|
+
for (const issue of validateObservedStateDeclarations(allManifests)) {
|
|
1607
|
+
diagnostics.push({
|
|
1608
|
+
severity: DiagnosticSeverity.Error,
|
|
1609
|
+
code: "OBSERVED_STATE_REQUIRED_FORBIDDEN",
|
|
1610
|
+
source: SOURCE,
|
|
1611
|
+
message: issue.message,
|
|
1612
|
+
data: {
|
|
1613
|
+
resource: { kind: issue.kind, name: issue.name },
|
|
1614
|
+
filePath: issue.filePath,
|
|
1615
|
+
path: "status.required",
|
|
1616
|
+
},
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1518
1619
|
// Validate `extends` fields and flag legacy `capability: <UserAbstract>` overload.
|
|
1519
1620
|
diagnostics.push(...validateExtends(allManifests, defs, aliases));
|
|
1520
1621
|
diagnostics.push(...validateBaseMapping(allManifests, defs, aliases));
|
|
@@ -1541,7 +1642,7 @@ export class StaticAnalyzer {
|
|
|
1541
1642
|
// Resolve !ref sentinels after normalize so both the original and
|
|
1542
1643
|
// inline-extracted manifests get their refs canonicalized to
|
|
1543
1644
|
// {kind, name} for the kernel that consumes this output.
|
|
1544
|
-
resolveRefSentinels(normalized, ctx.aliases, ctx.aliasesByModule, crossModuleTargets ?? []);
|
|
1645
|
+
resolveRefSentinels(normalized, ctx.aliases, ctx.aliasesByModule, crossModuleTargets ?? [], ctx.definitions);
|
|
1545
1646
|
// Canonicalize import-scoped schema `$ref`s (`telo://Self|Alias/Type`) so the
|
|
1546
1647
|
// kernel that executes this output compiles inputs/outputs against the same
|
|
1547
1648
|
// ids the type controllers register their schemas under.
|
package/dist/builtins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA4GvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EA+nB/C,CAAC"}
|
package/dist/builtins.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OBSERVED_STATE_SCHEMA } from "./validate-observed-state.js";
|
|
1
2
|
/** Descriptive provenance a module declares about itself, shared by
|
|
2
3
|
* `Telo.Application` and `Telo.Library`.
|
|
3
4
|
*
|
|
@@ -177,6 +178,7 @@ export const KERNEL_BUILTINS = [
|
|
|
177
178
|
},
|
|
178
179
|
capability: { type: "string" },
|
|
179
180
|
schema: { type: "object", additionalProperties: true },
|
|
181
|
+
status: OBSERVED_STATE_SCHEMA,
|
|
180
182
|
},
|
|
181
183
|
required: ["metadata"],
|
|
182
184
|
// Telo.Abstract is an extension point by design — it must accept forward-compatible
|
|
@@ -205,6 +207,7 @@ export const KERNEL_BUILTINS = [
|
|
|
205
207
|
type: "object",
|
|
206
208
|
additionalProperties: true,
|
|
207
209
|
properties: {
|
|
210
|
+
status: OBSERVED_STATE_SCHEMA,
|
|
208
211
|
resources: {
|
|
209
212
|
type: "array",
|
|
210
213
|
items: {
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { ResourceDefinition } from "@telorun/sdk";
|
|
2
2
|
/** Resolves a kind string (canonical or alias form, depending on the caller's
|
|
3
|
-
* registry) to its `Telo.Definition` / `Telo.Abstract`, or undefined.
|
|
4
|
-
|
|
3
|
+
* registry) to its `Telo.Definition` / `Telo.Abstract`, or undefined.
|
|
4
|
+
*
|
|
5
|
+
* `from` is the definition the kind was read off. An `extends` alias belongs to
|
|
6
|
+
* the file that DECLARES the definition, not to whoever is reading it, so a
|
|
7
|
+
* resolver that walks an inheritance chain across module boundaries must
|
|
8
|
+
* re-scope at each hop — `from.metadata.module` is what it scopes to. Resolvers
|
|
9
|
+
* that operate in a single scope ignore the parameter. */
|
|
10
|
+
export type DefResolver = (kind: string, from?: ResourceDefinition) => ResourceDefinition | undefined;
|
|
5
11
|
/** The definition a given definition directly `extends`, or undefined when it
|
|
6
12
|
* extends nothing / the target can't be resolved. */
|
|
7
13
|
export declare function resolveParent(def: ResourceDefinition | undefined, resolve: DefResolver): ResourceDefinition | undefined;
|
|
@@ -30,4 +36,15 @@ export declare function inheritedCapability(def: ResourceDefinition | undefined,
|
|
|
30
36
|
* `mergeTypeSchemas` that `Type.JsonSchema.extends` uses.
|
|
31
37
|
* - no `extends` → the own schema unchanged. */
|
|
32
38
|
export declare function effectiveAuthorSchema(def: ResourceDefinition | undefined, resolve: DefResolver): Record<string, any>;
|
|
39
|
+
/** The observed state a kind reports (`status:`), folded through `extends`:
|
|
40
|
+
* - with `base:` present → the **parent's** effective status unchanged; the
|
|
41
|
+
* child delegates to the parent's controller and *is* a parent instance, so
|
|
42
|
+
* it publishes exactly what the parent publishes.
|
|
43
|
+
* - without `base:` but with `extends` → `merge(parent-effective, own)`, so a
|
|
44
|
+
* contract can mandate what its implementations report and an implementation
|
|
45
|
+
* can add to it.
|
|
46
|
+
* - no `extends` → the own block unchanged.
|
|
47
|
+
* Undefined when nothing in the chain declares one — the signal that the kind
|
|
48
|
+
* has not opted into typed `.status` reads. */
|
|
49
|
+
export declare function effectiveStatusSchema(def: ResourceDefinition | undefined, resolve: DefResolver): Record<string, any> | undefined;
|
|
33
50
|
//# sourceMappingURL=extends-resolution.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extends-resolution.d.ts","sourceRoot":"","sources":["../src/extends-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD;
|
|
1
|
+
{"version":3,"file":"extends-resolution.d.ts","sourceRoot":"","sources":["../src/extends-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD;;;;;;;2DAO2D;AAC3D,MAAM,MAAM,WAAW,GAAG,CACxB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,kBAAkB,KACtB,kBAAkB,GAAG,SAAS,CAAC;AAsBpC;sDACsD;AACtD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,kBAAkB,GAAG,SAAS,CAIhC;AAED;6EAC6E;AAC7E,wBAAgB,aAAa,CAC3B,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,kBAAkB,EAAE,CAUtB;AAED;iFACiF;AACjF,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAUvF;AAED;;mFAEmF;AACnF,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,kBAAkB,GAAG,SAAS,CAMhC;AAED;;sCAEsC;AACtC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,OAAO,CAGT;AAED;2EAC2E;AAC3E,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,MAAM,GAAG,SAAS,CAMpB;AAED;;;;;;iDAMiD;AACjD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAOrB;AAED;;;;;;;;;gDASgD;AAChD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CASjC"}
|
|
@@ -6,7 +6,7 @@ export function resolveParent(def, resolve) {
|
|
|
6
6
|
const ext = body(def).extends;
|
|
7
7
|
if (typeof ext !== "string" || ext.length === 0)
|
|
8
8
|
return undefined;
|
|
9
|
-
return resolve(ext);
|
|
9
|
+
return resolve(ext, def);
|
|
10
10
|
}
|
|
11
11
|
/** The `extends` ancestor chain, nearest-first, excluding `def` itself.
|
|
12
12
|
* Cycle-guarded so a malformed self/mutual `extends` can't loop forever. */
|
|
@@ -80,3 +80,27 @@ export function effectiveAuthorSchema(def, resolve) {
|
|
|
80
80
|
const parentSchema = effectiveAuthorSchema(parent, resolve);
|
|
81
81
|
return mergeTypeSchemas([parentSchema, own]);
|
|
82
82
|
}
|
|
83
|
+
/** The observed state a kind reports (`status:`), folded through `extends`:
|
|
84
|
+
* - with `base:` present → the **parent's** effective status unchanged; the
|
|
85
|
+
* child delegates to the parent's controller and *is* a parent instance, so
|
|
86
|
+
* it publishes exactly what the parent publishes.
|
|
87
|
+
* - without `base:` but with `extends` → `merge(parent-effective, own)`, so a
|
|
88
|
+
* contract can mandate what its implementations report and an implementation
|
|
89
|
+
* can add to it.
|
|
90
|
+
* - no `extends` → the own block unchanged.
|
|
91
|
+
* Undefined when nothing in the chain declares one — the signal that the kind
|
|
92
|
+
* has not opted into typed `.status` reads. */
|
|
93
|
+
export function effectiveStatusSchema(def, resolve) {
|
|
94
|
+
const own = body(def).status;
|
|
95
|
+
const parent = resolveParent(def, resolve);
|
|
96
|
+
if (!parent)
|
|
97
|
+
return own;
|
|
98
|
+
const parentStatus = effectiveStatusSchema(parent, resolve);
|
|
99
|
+
if (body(def).base)
|
|
100
|
+
return parentStatus;
|
|
101
|
+
if (!parentStatus)
|
|
102
|
+
return own;
|
|
103
|
+
if (!own)
|
|
104
|
+
return parentStatus;
|
|
105
|
+
return mergeTypeSchemas([parentStatus, own]);
|
|
106
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,11 @@ export { importResolutionDiagnostics } from "./import-resolution-diagnostics.js"
|
|
|
5
5
|
export type { GraphLoadError, ImportEdge, LoadedFile, LoadedGraph, LoadedModule, ParseError, } from "./loaded-types.js";
|
|
6
6
|
export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampExportedKinds, stampReExportedKinds, type ParsedExportEntry, type ReExportSpec, } from "./flatten-for-analyzer.js";
|
|
7
7
|
export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
|
|
8
|
-
export {
|
|
8
|
+
export { applyObservedStateNode, buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, OBSERVED_STATE_SCHEMA, } from "./validate-observed-state.js";
|
|
9
|
+
export type { AnalyzedResource, ObservedStateRead } from "./validate-observed-state.js";
|
|
10
|
+
export { moduleScopedDefResolver, scopeResolverForModule } from "./alias-resolver.js";
|
|
11
|
+
export type { ModuleScopes } from "./alias-resolver.js";
|
|
12
|
+
export { ancestorChain, controllerBearingAncestor, effectiveAuthorSchema, effectiveStatusSchema, hasOwnControllerOrTemplate, inheritedCapability, isInheritedDelegation, resolveParent, } from "./extends-resolution.js";
|
|
9
13
|
export type { DefResolver } from "./extends-resolution.js";
|
|
10
14
|
export { hasIntermediateWildcard, parseRedactionPath, RedactionPathError, } from "./redaction-path.js";
|
|
11
15
|
export type { RedactionSegment } from "./redaction-path.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,9 @@ export { StaticAnalyzer } from "./analyzer.js";
|
|
|
3
3
|
export { importResolutionDiagnostics } from "./import-resolution-diagnostics.js";
|
|
4
4
|
export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampExportedKinds, stampReExportedKinds, } from "./flatten-for-analyzer.js";
|
|
5
5
|
export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
|
|
6
|
-
export {
|
|
6
|
+
export { applyObservedStateNode, buildObservedStateIndex, buildObservedStateResourcesSchema, collectRunReachableNames, observedStateRead, validateObservedStateDeclarations, OBSERVED_STATE_SCHEMA, } from "./validate-observed-state.js";
|
|
7
|
+
export { moduleScopedDefResolver, scopeResolverForModule } from "./alias-resolver.js";
|
|
8
|
+
export { ancestorChain, controllerBearingAncestor, effectiveAuthorSchema, effectiveStatusSchema, hasOwnControllerOrTemplate, inheritedCapability, isInheritedDelegation, resolveParent, } from "./extends-resolution.js";
|
|
7
9
|
export { hasIntermediateWildcard, parseRedactionPath, RedactionPathError, } from "./redaction-path.js";
|
|
8
10
|
export { buildReferenceFieldMap, isRefEntry, isScopeEntry } from "./reference-field-map.js";
|
|
9
11
|
export { visitManifest } from "./manifest-visitor.js";
|
package/dist/kernel-globals.d.ts
CHANGED
|
@@ -24,7 +24,15 @@ export declare const KERNEL_GLOBAL_NAMES: readonly ["variables", "secrets", "res
|
|
|
24
24
|
* the manifest list to a single library's file.
|
|
25
25
|
* - `resources`: enumerates all non-system resource names
|
|
26
26
|
*/
|
|
27
|
-
export declare function buildKernelGlobalsSchema(manifests: ResourceManifest[]
|
|
27
|
+
export declare function buildKernelGlobalsSchema(manifests: ResourceManifest[],
|
|
28
|
+
/** Every resource a CEL read can name, including scope-declared ones (see
|
|
29
|
+
* `buildObservedStateIndex`). Kinds that declare a `status:` get a typed,
|
|
30
|
+
* closed `status` node; every other resource node stays open, so no flat read
|
|
31
|
+
* that passes today can start failing. */
|
|
32
|
+
resources?: ReadonlyMap<string, {
|
|
33
|
+
kind: string;
|
|
34
|
+
status?: Record<string, any>;
|
|
35
|
+
}>): Record<string, any>;
|
|
28
36
|
/**
|
|
29
37
|
* Merge kernel globals into an `x-telo-context` schema so chain-access
|
|
30
38
|
* validation recognises `variables`, `secrets`, `resources`, `ports`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kernel-globals.d.ts","sourceRoot":"","sources":["../src/kernel-globals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"kernel-globals.d.ts","sourceRoot":"","sources":["../src/kernel-globals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIrD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,yDAA0D,CAAC;AAS3F;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,gBAAgB,EAAE;AAC7B;;;2CAG2C;AAC3C,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC,GAC9E,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA+CrB;AA4CD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACjC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CASrB"}
|
package/dist/kernel-globals.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { residualEntrySchemaMap } from "./residual-schema.js";
|
|
2
|
+
import { applyObservedStateNode } from "./validate-observed-state.js";
|
|
2
3
|
/**
|
|
3
4
|
* Kernel global names available in every CEL evaluation context at runtime.
|
|
4
5
|
* Both `buildKernelGlobalsSchema` (chain-access validation) and
|
|
@@ -30,7 +31,12 @@ const SYSTEM_KINDS = new Set([
|
|
|
30
31
|
* the manifest list to a single library's file.
|
|
31
32
|
* - `resources`: enumerates all non-system resource names
|
|
32
33
|
*/
|
|
33
|
-
export function buildKernelGlobalsSchema(manifests
|
|
34
|
+
export function buildKernelGlobalsSchema(manifests,
|
|
35
|
+
/** Every resource a CEL read can name, including scope-declared ones (see
|
|
36
|
+
* `buildObservedStateIndex`). Kinds that declare a `status:` get a typed,
|
|
37
|
+
* closed `status` node; every other resource node stays open, so no flat read
|
|
38
|
+
* that passes today can start failing. */
|
|
39
|
+
resources) {
|
|
34
40
|
const moduleManifest = manifests.find((m) => m.kind === "Telo.Application") ??
|
|
35
41
|
manifests.find((m) => m.kind === "Telo.Library");
|
|
36
42
|
const resourceProps = {};
|
|
@@ -44,6 +50,23 @@ export function buildKernelGlobalsSchema(manifests) {
|
|
|
44
50
|
resourceProps[name] = { type: "object", additionalProperties: true };
|
|
45
51
|
}
|
|
46
52
|
}
|
|
53
|
+
// Scope-declared resources (a `Run.Sequence`'s `with:`) publish like any other
|
|
54
|
+
// now, so their names resolve too — inside the scope's regions, which is where
|
|
55
|
+
// the only expressions that can name them live.
|
|
56
|
+
for (const [key, entry] of resources ?? []) {
|
|
57
|
+
if (key.includes("."))
|
|
58
|
+
continue;
|
|
59
|
+
resourceProps[key] ??= { type: "object", additionalProperties: true };
|
|
60
|
+
if (entry.status)
|
|
61
|
+
applyObservedStateNode(resourceProps, key, entry.status);
|
|
62
|
+
}
|
|
63
|
+
// Imports' exported instances publish two levels deep (`resources.<Alias>.<name>`);
|
|
64
|
+
// the alias node stays open so its other keys keep resolving.
|
|
65
|
+
for (const [key, entry] of resources ?? []) {
|
|
66
|
+
if (!key.includes(".") || !entry.status)
|
|
67
|
+
continue;
|
|
68
|
+
applyObservedStateNode(resourceProps, key, entry.status);
|
|
69
|
+
}
|
|
47
70
|
return {
|
|
48
71
|
type: "object",
|
|
49
72
|
properties: {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { ResourceManifest } from "@telorun/sdk";
|
|
2
2
|
import type { AliasResolver } from "./alias-resolver.js";
|
|
3
|
+
import { type ReferenceFieldMap } from "./reference-field-map.js";
|
|
4
|
+
/** The slice of the definition registry this pass needs: a kind's field map, from
|
|
5
|
+
* which the `x-telo-scope` slots are read. */
|
|
6
|
+
export interface ScopeFieldMapSource {
|
|
7
|
+
getFieldMapForKind(kind: string, aliases?: {
|
|
8
|
+
resolveKind(k: string): string | undefined;
|
|
9
|
+
}): ReferenceFieldMap | undefined;
|
|
10
|
+
}
|
|
3
11
|
/**
|
|
4
12
|
* Rewrites every `!ref <name>` sentinel in each non-system resource's value tree
|
|
5
13
|
* to `{kind, name}` (local) or `{kind, name, alias}` (cross-module), in place.
|
|
@@ -36,5 +44,9 @@ import type { AliasResolver } from "./alias-resolver.js";
|
|
|
36
44
|
* `metadata.module` that isn't a root module) are resolution TARGETS only — they are not
|
|
37
45
|
* re-walked as sources here, since their own ref slots belong to their own module scope.
|
|
38
46
|
*/
|
|
39
|
-
export declare function resolveRefSentinels(resources: ResourceManifest[], aliases?: AliasResolver, aliasesByModule?: Map<string, AliasResolver>, crossModuleTargets?: ResourceManifest[]
|
|
47
|
+
export declare function resolveRefSentinels(resources: ResourceManifest[], aliases?: AliasResolver, aliasesByModule?: Map<string, AliasResolver>, crossModuleTargets?: ResourceManifest[],
|
|
48
|
+
/** Supplies each kind's `x-telo-scope` slots. Without it a scoped name cannot be
|
|
49
|
+
* told from a module-level one, and a shadowed `!ref` resolves to the resource
|
|
50
|
+
* it shadows — so both call sites pass it. */
|
|
51
|
+
defs?: ScopeFieldMapSource): void;
|
|
40
52
|
//# sourceMappingURL=resolve-ref-sentinels.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-ref-sentinels.d.ts","sourceRoot":"","sources":["../src/resolve-ref-sentinels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-ref-sentinels.d.ts","sourceRoot":"","sources":["../src/resolve-ref-sentinels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAGlC;+CAC+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,GACvD,iBAAiB,GAAG,SAAS,CAAC;CAClC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAK5C,kBAAkB,GAAE,gBAAgB,EAAO;AAC3C;;+CAE+C;AAC/C,IAAI,CAAC,EAAE,mBAAmB,GACzB,IAAI,CA8HN"}
|