@telorun/analyzer 0.67.0 → 0.69.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/analysis-registry.d.ts +12 -0
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +26 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +23 -0
- package/dist/call-graph.d.ts +80 -1
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +145 -12
- package/dist/extends-resolution.d.ts +20 -0
- package/dist/extends-resolution.d.ts.map +1 -1
- package/dist/extends-resolution.js +29 -0
- package/dist/import-resolution-diagnostics.d.ts.map +1 -1
- package/dist/import-resolution-diagnostics.js +22 -8
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/invocation-contract.d.ts +20 -0
- package/dist/invocation-contract.d.ts.map +1 -1
- package/dist/invocation-contract.js +74 -0
- package/dist/loaded-types.d.ts +4 -4
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-analysis.d.ts +19 -0
- package/dist/manifest-analysis.d.ts.map +1 -1
- package/dist/manifest-analysis.js +27 -0
- package/dist/manifest-loader.d.ts +3 -4
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +4 -5
- package/dist/manifest-schemas.d.ts +2 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +4 -0
- package/dist/module-graph.d.ts +500 -0
- package/dist/module-graph.d.ts.map +1 -0
- package/dist/module-graph.js +1411 -0
- package/dist/reconcile-module-versions.d.ts.map +1 -1
- package/dist/reconcile-module-versions.js +10 -11
- package/dist/release/release-plan.d.ts +1 -1
- package/dist/resolve-zone-containment.d.ts +9 -1
- package/dist/resolve-zone-containment.d.ts.map +1 -1
- package/dist/resolve-zone-containment.js +34 -6
- package/dist/resolve-zone-requirements.d.ts.map +1 -1
- package/dist/resolve-zone-requirements.js +4 -2
- package/dist/schema-keywords.d.ts +16 -1
- package/dist/schema-keywords.d.ts.map +1 -1
- package/dist/schema-keywords.js +20 -0
- package/dist/sources/default-sources.d.ts +6 -6
- package/dist/sources/default-sources.d.ts.map +1 -1
- package/dist/sources/default-sources.js +7 -8
- package/dist/sources/integrity.d.ts +3 -2
- package/dist/sources/integrity.d.ts.map +1 -1
- package/dist/sources/integrity.js +26 -3
- package/dist/sources/versioned-ref.d.ts +17 -12
- package/dist/sources/versioned-ref.d.ts.map +1 -1
- package/dist/sources/versioned-ref.js +22 -24
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/validate-extends.d.ts.map +1 -1
- package/dist/validate-extends.js +42 -1
- package/dist/validate-sensitive-slots.d.ts +28 -0
- package/dist/validate-sensitive-slots.d.ts.map +1 -0
- package/dist/validate-sensitive-slots.js +75 -0
- package/dist/value-type-keyword.d.ts +1 -1
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +1 -0
- package/package.json +1 -1
- package/src/analysis-registry.ts +37 -0
- package/src/analyzer.ts +26 -0
- package/src/call-graph.ts +207 -14
- package/src/extends-resolution.ts +33 -0
- package/src/import-resolution-diagnostics.ts +24 -7
- package/src/index.ts +42 -5
- package/src/invocation-contract.ts +71 -0
- package/src/loaded-types.ts +4 -4
- package/src/manifest-analysis.ts +39 -0
- package/src/manifest-loader.ts +4 -5
- package/src/manifest-schemas.ts +4 -0
- package/src/module-graph.ts +2005 -0
- package/src/reconcile-module-versions.ts +10 -11
- package/src/release/release-plan.ts +1 -1
- package/src/resolve-zone-containment.ts +49 -9
- package/src/resolve-zone-requirements.ts +7 -2
- package/src/schema-keywords.ts +33 -1
- package/src/sources/default-sources.ts +7 -8
- package/src/sources/integrity.ts +28 -3
- package/src/sources/versioned-ref.ts +26 -28
- package/src/telo-version.ts +1 -1
- package/src/validate-extends.ts +51 -1
- package/src/validate-sensitive-slots.ts +109 -0
- package/src/value-type-keyword.ts +1 -0
- package/dist/sources/module-ref.d.ts +0 -21
- package/dist/sources/module-ref.d.ts.map +0 -1
- package/dist/sources/module-ref.js +0 -36
- package/dist/sources/registry-source.d.ts +0 -14
- package/dist/sources/registry-source.d.ts.map +0 -1
- package/dist/sources/registry-source.js +0 -45
- package/src/sources/module-ref.ts +0 -49
- package/src/sources/registry-source.ts +0 -52
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-module-versions.d.ts","sourceRoot":"","sources":["../src/reconcile-module-versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOlE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;0CAI0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;2EACuE;IACvE,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"reconcile-module-versions.d.ts","sourceRoot":"","sources":["../src/reconcile-module-versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOlE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;0CAI0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;2EACuE;IACvE,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AA+ID;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAClC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAChD,qBAAqB,CAsEvB"}
|
|
@@ -19,15 +19,14 @@ const SOURCE = "telo-analyzer";
|
|
|
19
19
|
* **What this key cannot relate.** It compares ref *spellings*, so it groups by
|
|
20
20
|
* origin exactly and nothing else. Two consequences, both accepted:
|
|
21
21
|
*
|
|
22
|
-
* - A module imported once by
|
|
23
|
-
* groups, so a version skew between them is not hoisted. Keying on what
|
|
24
|
-
* module declares about itself would catch that case, but only by
|
|
25
|
-
* self-declared identity — which is what this change removes, and
|
|
26
|
-
* cannot tell two same-named modules from different origins apart.
|
|
27
|
-
* -
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* function does not have. */
|
|
22
|
+
* - A module imported once by an `oci://` ref and once by a relative path is
|
|
23
|
+
* two groups, so a version skew between them is not hoisted. Keying on what
|
|
24
|
+
* the module declares about itself would catch that case, but only by
|
|
25
|
+
* trusting a self-declared identity — which is what this change removes, and
|
|
26
|
+
* which cannot tell two same-named modules from different origins apart.
|
|
27
|
+
* - An `oci://` ref and a direct `https://…/telo.yaml` URL serving the same
|
|
28
|
+
* module are two groups. Relating them needs knowledge of the origin's
|
|
29
|
+
* layout, which this pure, browser-safe function does not have. */
|
|
31
30
|
function refIdentity(ref) {
|
|
32
31
|
const base = ref.split("#")[0];
|
|
33
32
|
if (!base || base.startsWith(".") || base.startsWith("/") || base.startsWith("file:")) {
|
|
@@ -137,8 +136,8 @@ export function reconcileModuleVersions(modules, importEdges) {
|
|
|
137
136
|
// source normally maps to exactly one identity; the entry module has no
|
|
138
137
|
// inbound edge and needs none (it is never reconciled against itself).
|
|
139
138
|
//
|
|
140
|
-
// One source CAN be reached by two spellings of the same location (a
|
|
141
|
-
//
|
|
139
|
+
// One source CAN be reached by two spellings of the same location (a ref and
|
|
140
|
+
// the direct URL it resolves to). Both name the same module
|
|
142
141
|
// at the same version, so either identity groups it correctly — but the choice
|
|
143
142
|
// must not depend on edge iteration order, or the same graph could reconcile
|
|
144
143
|
// differently across runs. First edge wins.
|
|
@@ -51,7 +51,7 @@ export interface ModuleEvidence {
|
|
|
51
51
|
readonly inlines: ReadonlyMap<ModuleKey, readonly string[]>;
|
|
52
52
|
/**
|
|
53
53
|
* Modules reached by an in-repo **relative** `imports:` source. A pinned
|
|
54
|
-
*
|
|
54
|
+
* remote ref is deliberately not an edge: pinning is the statement "I am not
|
|
55
55
|
* affected until I choose to be", and moving it is `telo upgrade`'s job.
|
|
56
56
|
*/
|
|
57
57
|
readonly imports: readonly ModuleKey[];
|
|
@@ -81,8 +81,15 @@ export interface ZoneRegion {
|
|
|
81
81
|
* DECLARED it — the same resolver the projection takes, passed in rather than
|
|
82
82
|
* rebuilt so both walks agree about what a kind means. */
|
|
83
83
|
export type DefinitionLookup = (kind: string, module?: string) => ResourceDefinition | undefined;
|
|
84
|
+
/** A region as the WALK finds it, before any attribute is asked for: the slot
|
|
85
|
+
* that opens it and everything it reaches. Every attribute query is a filter
|
|
86
|
+
* over these, so a consumer wanting regions regardless of what they declare —
|
|
87
|
+
* an editor drawing the enclosure, where a zone declaring no attribute is
|
|
88
|
+
* still a zone — reads them directly instead of enumerating the vocabulary and
|
|
89
|
+
* silently missing whatever is not in it. */
|
|
90
|
+
export type ZoneProvider = Omit<ZoneRegion, "attribute" | "reason">;
|
|
84
91
|
/**
|
|
85
|
-
* Every region in the graph
|
|
92
|
+
* Every region in the graph, keyed by the slot that opens it.
|
|
86
93
|
*
|
|
87
94
|
* The provider itself is NOT in `contents` — a zone constrains what runs inside
|
|
88
95
|
* its body, not the resource that establishes it. A transaction's own
|
|
@@ -90,6 +97,7 @@ export type DefinitionLookup = (kind: string, module?: string) => ResourceDefini
|
|
|
90
97
|
* treated the provider as contained would report the provider against its own
|
|
91
98
|
* constraint.
|
|
92
99
|
*/
|
|
100
|
+
export declare function findZoneProviders(graph: CallGraph, resolveDef: DefinitionLookup): ZoneProvider[];
|
|
93
101
|
export declare function findZoneRegions(graph: CallGraph, resolveDef: DefinitionLookup, attribute: string): ZoneRegion[];
|
|
94
102
|
/** Convenience for a consumer that only wants membership: every node id inside
|
|
95
103
|
* any region opened by `attribute`, mapped to the region that contains it. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-zone-containment.d.ts","sourceRoot":"","sources":["../src/resolve-zone-containment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAKlG,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB;wDACoD;IACpD,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED;;;;;gFAKgF;AAChF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,mDAAmD;IACnD,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB;uEACmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb;4EACwE;IACxE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;8EAC0E;IAC1E,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,0EAA0E;IAC1E,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;CACvC;AAED;;2DAE2D;AAC3D,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;AA4GjG;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,MAAM,GAChB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"resolve-zone-containment.d.ts","sourceRoot":"","sources":["../src/resolve-zone-containment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAKlG,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB;wDACoD;IACpD,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED;;;;;gFAKgF;AAChF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,mDAAmD;IACnD,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB;uEACmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb;4EACwE;IACxE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;8EAC0E;IAC1E,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,0EAA0E;IAC1E,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;CACvC;AAED;;2DAE2D;AAC3D,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;AA4GjG;;;;;8CAK8C;AAC9C,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,GAC3B,YAAY,EAAE,CA0DhB;AAmBD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,MAAM,GAChB,UAAU,EAAE,CAad;AAoCD;+EAC+E;AAC/E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,UAAU,EAAE,GAC7B,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAQjC;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAMtE"}
|
|
@@ -91,7 +91,7 @@ function collect(graph, entries, contents, boundaries) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
|
-
* Every region in the graph
|
|
94
|
+
* Every region in the graph, keyed by the slot that opens it.
|
|
95
95
|
*
|
|
96
96
|
* The provider itself is NOT in `contents` — a zone constrains what runs inside
|
|
97
97
|
* its body, not the resource that establishes it. A transaction's own
|
|
@@ -99,7 +99,7 @@ function collect(graph, entries, contents, boundaries) {
|
|
|
99
99
|
* treated the provider as contained would report the provider against its own
|
|
100
100
|
* constraint.
|
|
101
101
|
*/
|
|
102
|
-
export function
|
|
102
|
+
export function findZoneProviders(graph, resolveDef) {
|
|
103
103
|
const regions = [];
|
|
104
104
|
for (const node of graph.nodes.values()) {
|
|
105
105
|
if (node.type !== "resource")
|
|
@@ -112,8 +112,7 @@ export function findZoneRegions(graph, resolveDef, attribute) {
|
|
|
112
112
|
// properties rather than by knowing any kind's field names.
|
|
113
113
|
for (const [slot, slotSchema] of providingSlots(rootSchema)) {
|
|
114
114
|
const provides = readProvidesZone(slotSchema);
|
|
115
|
-
|
|
116
|
-
if (!provides || typeof reason !== "string")
|
|
115
|
+
if (!provides)
|
|
117
116
|
continue;
|
|
118
117
|
const contents = new Map();
|
|
119
118
|
const boundaries = [];
|
|
@@ -147,8 +146,6 @@ export function findZoneRegions(graph, resolveDef, attribute) {
|
|
|
147
146
|
collect(graph, entries, contents, boundaries);
|
|
148
147
|
}
|
|
149
148
|
regions.push({
|
|
150
|
-
attribute,
|
|
151
|
-
reason,
|
|
152
149
|
provider: node,
|
|
153
150
|
slot,
|
|
154
151
|
attributes: provides.attributes,
|
|
@@ -159,6 +156,37 @@ export function findZoneRegions(graph, resolveDef, attribute) {
|
|
|
159
156
|
}
|
|
160
157
|
return regions;
|
|
161
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Every region opened by a slot declaring `attribute`.
|
|
161
|
+
*
|
|
162
|
+
* A filter over {@link findZoneProviders}, so the walk is stated once: what an
|
|
163
|
+
* attribute query adds is which regions are in scope and the author's `reason`,
|
|
164
|
+
* which is the attribute's own value.
|
|
165
|
+
*
|
|
166
|
+
* **The provider list is memoized per graph**, because the filter made the walk
|
|
167
|
+
* unconditional: it used to skip the containment BFS for any provider not
|
|
168
|
+
* declaring the queried attribute, and six queries per analysis (four zone
|
|
169
|
+
* attributes plus two durable ones) became six full walks over every provider
|
|
170
|
+
* in the module. The cache is keyed on the CallGraph object, which is itself
|
|
171
|
+
* built once per analysis — so it lives exactly as long as the answer stays
|
|
172
|
+
* true, and a rebuilt graph gets a fresh one.
|
|
173
|
+
*/
|
|
174
|
+
const providersByGraph = new WeakMap();
|
|
175
|
+
export function findZoneRegions(graph, resolveDef, attribute) {
|
|
176
|
+
let providers = providersByGraph.get(graph);
|
|
177
|
+
if (!providers) {
|
|
178
|
+
providers = findZoneProviders(graph, resolveDef);
|
|
179
|
+
providersByGraph.set(graph, providers);
|
|
180
|
+
}
|
|
181
|
+
const out = [];
|
|
182
|
+
for (const region of providers) {
|
|
183
|
+
const reason = region.attributes[attribute];
|
|
184
|
+
if (typeof reason !== "string")
|
|
185
|
+
continue;
|
|
186
|
+
out.push({ ...region, attribute, reason });
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
162
190
|
/** Field-map paths of every slot in a kind's schema carrying a provides-zone
|
|
163
191
|
* annotation, with the schema node at each. Walks properties, array items and
|
|
164
192
|
* `additionalProperties`, resolving local `$ref`s — the paths the call graph's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-zone-requirements.d.ts","sourceRoot":"","sources":["../src/resolve-zone-requirements.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAMnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;uCAEuC;AACvC,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb;;wBAEoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;sDACkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;gCAG4B;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,6EAA6E;AAC7E,MAAM,MAAM,sBAAsB,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAkBhE,UAAU,cAAc;IACtB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C;qEACiE;IACjE,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC;0EACsE;IACtE,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC3C;2CACuC;IACvC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,MAAM,GAAG,SAAS,CAAC;CAC5D;AAED,UAAU,gBAAgB;IACxB,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC,WAAW,EAAE,sBAAsB,CAAC;CACrC;AAwKD,yCAAyC;AACzC,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"resolve-zone-requirements.d.ts","sourceRoot":"","sources":["../src/resolve-zone-requirements.ts"],"names":[],"mappings":"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"}
|
|
@@ -175,7 +175,9 @@ export function projectZoneRequirements(args) {
|
|
|
175
175
|
if (local)
|
|
176
176
|
return local;
|
|
177
177
|
}
|
|
178
|
-
|
|
178
|
+
// In the scope that WROTE the name: a bare reference means the reader's own
|
|
179
|
+
// module, and two libraries may each declare one.
|
|
180
|
+
return graph.resourceByName(name, from.manifest.metadata?.module);
|
|
179
181
|
};
|
|
180
182
|
const acceptedFor = (zone) => {
|
|
181
183
|
const out = new Set([zone]);
|
|
@@ -550,7 +552,7 @@ export function runZoneAnalysis(args) {
|
|
|
550
552
|
for (const [exportName, specs] of openExports) {
|
|
551
553
|
if (!lib.exportedNames.has(exportName))
|
|
552
554
|
continue;
|
|
553
|
-
const node = graph.resourceByName(exportName);
|
|
555
|
+
const node = graph.resourceByName(exportName, lib.module);
|
|
554
556
|
if (!node || node.manifest.metadata?.module !== lib.module) {
|
|
555
557
|
continue;
|
|
556
558
|
}
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
* Browser-safe: no Node built-ins.
|
|
27
27
|
*/
|
|
28
28
|
import { X_TELO_TYPE } from "@telorun/sdk";
|
|
29
|
+
/** The one annotation read from a DATA schema rather than a kind schema. */
|
|
30
|
+
declare const X_TELO_SENSITIVE: "x-telo-sensitive";
|
|
29
31
|
import { ANNOTATION_KEYWORDS } from "./value-type-keyword.js";
|
|
30
32
|
/** A keyword entry: the JSON Schema its VALUE must satisfy, carrying the title
|
|
31
33
|
* and description completion and hover show. */
|
|
@@ -64,5 +66,18 @@ export declare function jsonSchemaKeywords(self: string): SchemaKeywords;
|
|
|
64
66
|
* neither validation nor completion. Closing it needs the walkers to distinguish
|
|
65
67
|
* a schema describing an annotation from an annotation, which nothing does yet.
|
|
66
68
|
*/
|
|
67
|
-
export declare const TELO_SCHEMA_ANNOTATIONS: Record<(typeof ANNOTATION_KEYWORDS)[number] | typeof X_TELO_TYPE, Record<string, unknown>>;
|
|
69
|
+
export declare const TELO_SCHEMA_ANNOTATIONS: Record<Exclude<(typeof ANNOTATION_KEYWORDS)[number], typeof X_TELO_SENSITIVE> | typeof X_TELO_TYPE, Record<string, unknown>>;
|
|
70
|
+
/**
|
|
71
|
+
* Annotations that belong on a DATA schema — an `inputType` / `outputType`
|
|
72
|
+
* contract — rather than on a kind's own `schema:`.
|
|
73
|
+
*
|
|
74
|
+
* Split out because {@link TELO_SCHEMA_ANNOTATIONS} is offered only where the
|
|
75
|
+
* fragment is `KindSchema`, which is a kind's CONFIGURATION. `x-telo-sensitive`
|
|
76
|
+
* is read from the opposite place: the kernel resolves it off a bound contract,
|
|
77
|
+
* which stamps `JsonSchema7`. Offering it from the kind vocabulary alone put it
|
|
78
|
+
* on the one schema where nothing reads it and withheld it from the two where it
|
|
79
|
+
* is the whole mechanism.
|
|
80
|
+
*/
|
|
81
|
+
export declare const TELO_DATA_SCHEMA_ANNOTATIONS: Record<typeof X_TELO_SENSITIVE, Record<string, unknown>>;
|
|
82
|
+
export {};
|
|
68
83
|
//# sourceMappingURL=schema-keywords.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-keywords.d.ts","sourceRoot":"","sources":["../src/schema-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"schema-keywords.d.ts","sourceRoot":"","sources":["../src/schema-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,4EAA4E;AAC5E,QAAA,MAAM,gBAAgB,EAAG,kBAA2B,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;iDACiD;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AASrE;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuJ/D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAMxC,OAAO,CAAC,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,gBAAgB,CAAC,GACtE,OAAO,WAAW,EACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwJxB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAC/C,OAAO,gBAAgB,EACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQxB,CAAC"}
|
package/dist/schema-keywords.js
CHANGED
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Browser-safe: no Node built-ins.
|
|
27
27
|
*/
|
|
28
|
+
/** The one annotation read from a DATA schema rather than a kind schema. */
|
|
29
|
+
const X_TELO_SENSITIVE = "x-telo-sensitive";
|
|
28
30
|
/** A JSON type name, as `type:` accepts it — one, or a list (`[string, "null"]`,
|
|
29
31
|
* the spelling `CEL_NULLABLE_ACCESS` guards). */
|
|
30
32
|
const TYPE_NAME = {
|
|
@@ -342,3 +344,21 @@ export const TELO_SCHEMA_ANNOTATIONS = {
|
|
|
342
344
|
type: "string",
|
|
343
345
|
},
|
|
344
346
|
};
|
|
347
|
+
/**
|
|
348
|
+
* Annotations that belong on a DATA schema — an `inputType` / `outputType`
|
|
349
|
+
* contract — rather than on a kind's own `schema:`.
|
|
350
|
+
*
|
|
351
|
+
* Split out because {@link TELO_SCHEMA_ANNOTATIONS} is offered only where the
|
|
352
|
+
* fragment is `KindSchema`, which is a kind's CONFIGURATION. `x-telo-sensitive`
|
|
353
|
+
* is read from the opposite place: the kernel resolves it off a bound contract,
|
|
354
|
+
* which stamps `JsonSchema7`. Offering it from the kind vocabulary alone put it
|
|
355
|
+
* on the one schema where nothing reads it and withheld it from the two where it
|
|
356
|
+
* is the whole mechanism.
|
|
357
|
+
*/
|
|
358
|
+
export const TELO_DATA_SCHEMA_ANNOTATIONS = {
|
|
359
|
+
[X_TELO_SENSITIVE]: {
|
|
360
|
+
title: "Sensitive",
|
|
361
|
+
description: "This value is auth material or equivalent: carry it as `[redacted]` in trace payloads and on the debug wire rather than verbatim. Read only from a resource's declared `inputType` / `outputType`.",
|
|
362
|
+
type: "boolean",
|
|
363
|
+
},
|
|
364
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ManifestSource } from "../types.js";
|
|
2
|
-
/** The browser-safe built-in sources
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
export declare function defaultSources(
|
|
2
|
+
/** The browser-safe built-in sources. Node-specific sources (local filesystem)
|
|
3
|
+
* are supplied by the consuming package and passed alongside these into the
|
|
4
|
+
* `Loader` constructor. Callers that only want a subset (e.g. the editor, which
|
|
5
|
+
* brings its own manifest-cache adapter) construct the individual sources
|
|
6
|
+
* directly. */
|
|
7
|
+
export declare function defaultSources(): ManifestSource[];
|
|
8
8
|
//# sourceMappingURL=default-sources.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-sources.d.ts","sourceRoot":"","sources":["../../src/sources/default-sources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"default-sources.d.ts","sourceRoot":"","sources":["../../src/sources/default-sources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;gBAIgB;AAChB,wBAAgB,cAAc,IAAI,cAAc,EAAE,CAEjD"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { HttpSource } from "./http-source.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return [new HttpSource(), new RegistrySource(registryUrl)];
|
|
2
|
+
/** The browser-safe built-in sources. Node-specific sources (local filesystem)
|
|
3
|
+
* are supplied by the consuming package and passed alongside these into the
|
|
4
|
+
* `Loader` constructor. Callers that only want a subset (e.g. the editor, which
|
|
5
|
+
* brings its own manifest-cache adapter) construct the individual sources
|
|
6
|
+
* directly. */
|
|
7
|
+
export function defaultSources() {
|
|
8
|
+
return [new HttpSource()];
|
|
10
9
|
}
|
|
@@ -43,8 +43,9 @@ export declare function verifyIntegrity(bytes: Uint8Array, integrity: string, de
|
|
|
43
43
|
/** The single verified network read for remote manifests: fetch `fetchUrl`,
|
|
44
44
|
* verify the raw bytes against `integrity` (when pinned), and return both the
|
|
45
45
|
* bytes and the decoded text. The one choke point every network `ManifestSource`
|
|
46
|
-
* routes through, so verification cannot drift between them
|
|
47
|
-
* the
|
|
46
|
+
* routes through, so verification cannot drift between them — which is also why
|
|
47
|
+
* the object-storage non-manifest check lives here rather than in each source.
|
|
48
|
+
* `describe` names the artifact in error messages. */
|
|
48
49
|
export declare function verifiedFetch(fetchUrl: string, integrity: string | undefined, describe: string): Promise<{
|
|
49
50
|
bytes: Uint8Array;
|
|
50
51
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/sources/integrity.ts"],"names":[],"mappings":"AAAA;;;;;;6EAM6E;AAc7E;;;qDAGqD;AACrD,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAIhF;AAED;;;kFAGkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED;;;;;;;;8DAQ8D;AAC9D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEpE;AAcD,iFAAiF;AACjF,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxE;AAED;;gFAEgF;AAChF,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf;
|
|
1
|
+
{"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/sources/integrity.ts"],"names":[],"mappings":"AAAA;;;;;;6EAM6E;AAc7E;;;qDAGqD;AACrD,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAIhF;AAED;;;kFAGkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED;;;;;;;;8DAQ8D;AAC9D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEpE;AAcD,iFAAiF;AACjF,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxE;AAED;;gFAEgF;AAChF,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf;AAgBD;;;;;uDAKuD;AACvD,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAoB9C"}
|
|
@@ -93,18 +93,41 @@ export async function verifyIntegrity(bytes, integrity, describe) {
|
|
|
93
93
|
`the module may have been tampered with or republished.`);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
+
/** Object-storage backends (Cloudflare R2, S3) surface auth and permission
|
|
97
|
+
* failures as a **200 with an XML error body**. Caught here rather than left to
|
|
98
|
+
* the loader, which would parse the XML as YAML and report a downstream
|
|
99
|
+
* `UNDEFINED_KIND` — naming the manifest's contents as the problem instead of
|
|
100
|
+
* the origin that refused to serve it. Returns the failure detail, or `null`
|
|
101
|
+
* when the body is not an XML error document. */
|
|
102
|
+
function objectStorageError(text) {
|
|
103
|
+
const head = text.trimStart();
|
|
104
|
+
if (!head.startsWith("<?xml") && !head.startsWith("<Error"))
|
|
105
|
+
return null;
|
|
106
|
+
const code = text.match(/<Code>([^<]+)<\/Code>/);
|
|
107
|
+
const message = text.match(/<Message>([^<]+)<\/Message>/);
|
|
108
|
+
return code && message ? `${code[1]}: ${message[1]}` : text.slice(0, 200);
|
|
109
|
+
}
|
|
96
110
|
/** The single verified network read for remote manifests: fetch `fetchUrl`,
|
|
97
111
|
* verify the raw bytes against `integrity` (when pinned), and return both the
|
|
98
112
|
* bytes and the decoded text. The one choke point every network `ManifestSource`
|
|
99
|
-
* routes through, so verification cannot drift between them
|
|
100
|
-
* the
|
|
113
|
+
* routes through, so verification cannot drift between them — which is also why
|
|
114
|
+
* the object-storage non-manifest check lives here rather than in each source.
|
|
115
|
+
* `describe` names the artifact in error messages. */
|
|
101
116
|
export async function verifiedFetch(fetchUrl, integrity, describe) {
|
|
102
117
|
const response = await fetch(fetchUrl);
|
|
103
118
|
if (!response.ok) {
|
|
104
119
|
throw new Error(`Failed to fetch manifest ${describe}: ${response.status} ${response.statusText} (${fetchUrl})`);
|
|
105
120
|
}
|
|
106
121
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
122
|
+
const text = new TextDecoder().decode(bytes);
|
|
123
|
+
// Before the integrity check: a bucket's error page hashes to something, and
|
|
124
|
+
// reporting a pin mismatch would name the wrong cause just as the loader does.
|
|
125
|
+
const storageError = objectStorageError(text);
|
|
126
|
+
if (storageError) {
|
|
127
|
+
throw new Error(`The origin returned a non-manifest response for ${describe} ` +
|
|
128
|
+
`(URL: ${fetchUrl}): ${storageError}`);
|
|
129
|
+
}
|
|
107
130
|
if (integrity)
|
|
108
131
|
await verifyIntegrity(bytes, integrity, describe);
|
|
109
|
-
return { bytes, text
|
|
132
|
+
return { bytes, text };
|
|
110
133
|
}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* ref, the version segment it currently names, and any inline pin. */
|
|
3
3
|
export interface ParsedVersionedRef {
|
|
4
4
|
/** The ref with its `@version` segment and integrity fragment removed —
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
5
|
+
* `oci://ghcr.io/telorun/timer`. This is the identity a version list is keyed
|
|
6
|
+
* by (the hub registers modules under exactly this form). */
|
|
7
7
|
baseRef: string;
|
|
8
|
-
/** The version segment, raw —
|
|
9
|
-
*
|
|
8
|
+
/** The version segment, raw — an OCI tag or an OCI digest reference
|
|
9
|
+
* (`sha256:…`). The caller applies its own SemVer check. */
|
|
10
10
|
version: string;
|
|
11
11
|
/** Telo's inline `sha256-<base64url>` pin, when the ref carried one. */
|
|
12
12
|
integrity?: string;
|
|
@@ -15,12 +15,17 @@ export interface ParsedVersionedRef {
|
|
|
15
15
|
* upgradeable version — a local path, a bare `https://` URL, or an OCI ref
|
|
16
16
|
* with no explicit reference (an implicit `latest` is not a pin).
|
|
17
17
|
*
|
|
18
|
-
* Browser-safe
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Browser-safe: this is the *grammar* half of an upgrade, shared by the kernel
|
|
19
|
+
* transports (whose `refVersion` / `withVersion` delegate here) and the editor,
|
|
20
|
+
* which cannot use a transport at all — the *network* half (enumerating
|
|
21
|
+
* versions) is scheme-specific and stays behind `Transport.listVersions` on
|
|
22
|
+
* Node and the hub's `/module/versions` in the browser.
|
|
23
|
+
*
|
|
24
|
+
* It is NOT transport-neutral: `oci://` is the only versionable grammar, named
|
|
25
|
+
* literally below. That was equally true when the registry ref was the second
|
|
26
|
+
* branch, and a third scheme still means editing this file — the versionable
|
|
27
|
+
* set would have to become data the transports contribute before that claim
|
|
28
|
+
* could be made honestly. */
|
|
24
29
|
export declare function parseVersionedRef(ref: string): ParsedVersionedRef | null;
|
|
25
30
|
/** `ref` rewritten to name `version`, dropping any integrity fragment (the
|
|
26
31
|
* caller re-pins the result). Appends the version when the ref carries none —
|
|
@@ -28,7 +33,7 @@ export declare function parseVersionedRef(ref: string): ParsedVersionedRef | nul
|
|
|
28
33
|
*
|
|
29
34
|
* Throws when the ref's grammar has no version segment at all — a relative
|
|
30
35
|
* path, a bare `https://` URL. Producing `../lib@0.4.0` for those would write
|
|
31
|
-
* a ref nothing can resolve, so this fails where the transport-specific
|
|
32
|
-
*
|
|
36
|
+
* a ref nothing can resolve, so this fails where the transport-specific parser
|
|
37
|
+
* it replaced (`parseOciRef`) also failed. */
|
|
33
38
|
export declare function withRefVersion(ref: string, version: string): string;
|
|
34
39
|
//# sourceMappingURL=versioned-ref.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versioned-ref.d.ts","sourceRoot":"","sources":["../../src/sources/versioned-ref.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"versioned-ref.d.ts","sourceRoot":"","sources":["../../src/sources/versioned-ref.ts"],"names":[],"mappings":"AAGA;uEACuE;AACvE,MAAM,WAAW,kBAAkB;IACjC;;kEAE8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB;iEAC6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;8BAc8B;AAC9B,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAOxE;AAED;;;;;;;+CAO+C;AAC/C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CASnE"}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { splitIntegrity } from "./integrity.js";
|
|
2
|
-
import { isRegistryRef } from "./module-ref.js";
|
|
3
2
|
import { OCI_SCHEME } from "./oci-ref.js";
|
|
4
3
|
/** Split a versioned module ref. Returns `null` when the ref names no
|
|
5
4
|
* upgradeable version — a local path, a bare `https://` URL, or an OCI ref
|
|
6
5
|
* with no explicit reference (an implicit `latest` is not a pin).
|
|
7
6
|
*
|
|
8
|
-
* Browser-safe
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* Browser-safe: this is the *grammar* half of an upgrade, shared by the kernel
|
|
8
|
+
* transports (whose `refVersion` / `withVersion` delegate here) and the editor,
|
|
9
|
+
* which cannot use a transport at all — the *network* half (enumerating
|
|
10
|
+
* versions) is scheme-specific and stays behind `Transport.listVersions` on
|
|
11
|
+
* Node and the hub's `/module/versions` in the browser.
|
|
12
|
+
*
|
|
13
|
+
* It is NOT transport-neutral: `oci://` is the only versionable grammar, named
|
|
14
|
+
* literally below. That was equally true when the registry ref was the second
|
|
15
|
+
* branch, and a third scheme still means editing this file — the versionable
|
|
16
|
+
* set would have to become data the transports contribute before that claim
|
|
17
|
+
* could be made honestly. */
|
|
14
18
|
export function parseVersionedRef(ref) {
|
|
15
19
|
const { base, integrity } = splitIntegrity(ref);
|
|
16
20
|
const at = versionSeparator(base);
|
|
@@ -27,34 +31,28 @@ export function parseVersionedRef(ref) {
|
|
|
27
31
|
*
|
|
28
32
|
* Throws when the ref's grammar has no version segment at all — a relative
|
|
29
33
|
* path, a bare `https://` URL. Producing `../lib@0.4.0` for those would write
|
|
30
|
-
* a ref nothing can resolve, so this fails where the transport-specific
|
|
31
|
-
*
|
|
34
|
+
* a ref nothing can resolve, so this fails where the transport-specific parser
|
|
35
|
+
* it replaced (`parseOciRef`) also failed. */
|
|
32
36
|
export function withRefVersion(ref, version) {
|
|
33
37
|
const { base } = splitIntegrity(ref);
|
|
34
|
-
if (
|
|
35
|
-
throw new Error(`Cannot set a version on '${ref}' — only
|
|
36
|
-
`and oci:// refs carry a version segment.`);
|
|
38
|
+
if (!isVersionableRef(base)) {
|
|
39
|
+
throw new Error(`Cannot set a version on '${ref}' — only oci:// refs carry a version segment.`);
|
|
37
40
|
}
|
|
38
41
|
const at = versionSeparator(base);
|
|
39
42
|
return `${at === null ? base : base.slice(0, at)}@${version}`;
|
|
40
43
|
}
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return base.indexOf("/", OCI_SCHEME.length) > OCI_SCHEME.length ? "oci" : null;
|
|
47
|
-
}
|
|
48
|
-
// `isRegistryRef` requires the `@`, so a version-less `std/console` is not a
|
|
49
|
-
// registry ref by this test — matching `parseModuleRef`, which throws on it.
|
|
50
|
-
return isRegistryRef(base) ? "registry" : null;
|
|
44
|
+
/** True when `base` is written in a grammar that carries a version segment — a
|
|
45
|
+
* relative/absolute path and a `file:`/`https://` URL are not. */
|
|
46
|
+
function isVersionableRef(base) {
|
|
47
|
+
// A host alone is not addressable; the repo path is what carries a version.
|
|
48
|
+
return base.startsWith(OCI_SCHEME) && base.indexOf("/", OCI_SCHEME.length) > OCI_SCHEME.length;
|
|
51
49
|
}
|
|
52
50
|
/** Index of the `@` that separates the version, or `null` when the ref names
|
|
53
51
|
* none. Split on the LAST `@` so a digest reference (`repo@sha256:…`) keeps
|
|
54
52
|
* everything before it as the ref. */
|
|
55
53
|
function versionSeparator(base) {
|
|
56
|
-
if (
|
|
54
|
+
if (!isVersionableRef(base))
|
|
57
55
|
return null;
|
|
58
56
|
const at = base.lastIndexOf("@");
|
|
59
|
-
return at >
|
|
57
|
+
return at > OCI_SCHEME.length ? at : null;
|
|
60
58
|
}
|
package/dist/telo-version.d.ts
CHANGED
package/dist/telo-version.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
// its release identity, this is the scale a module's `requires.telo` range is
|
|
6
6
|
// written against, and every kernel in every language reports the same scale.
|
|
7
7
|
/** The surface generation this analyzer implements. */
|
|
8
|
-
export const TELO_SURFACE_VERSION = "0.
|
|
8
|
+
export const TELO_SURFACE_VERSION = "0.85.0";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-extends.d.ts","sourceRoot":"","sources":["../src/validate-extends.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"validate-extends.d.ts","sourceRoot":"","sources":["../src/validate-extends.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAQnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAiCzE,wBAAgB,eAAe,CAC7B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GACrB,kBAAkB,EAAE,CAqMtB"}
|
package/dist/validate-extends.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { inheritedCapability } from "./extends-resolution.js";
|
|
1
|
+
import { controllerBearingAncestor, effectiveAuthorSchema, inheritedCapability, isInheritedDelegation, } from "./extends-resolution.js";
|
|
2
2
|
import { DiagnosticSeverity } from "./types.js";
|
|
3
3
|
const SOURCE = "telo-analyzer";
|
|
4
4
|
/** Alias-form pattern for `extends`: "<Alias>.<AbstractName>", two PascalCase segments. */
|
|
@@ -19,6 +19,9 @@ const EXTENDS_ALIAS_RE = /^[A-Z][A-Za-z0-9_]*\.[A-Z][A-Za-z0-9_]*$/;
|
|
|
19
19
|
* - EXTENDS_UNKNOWN_TARGET: alias resolves to a module, but that module has no
|
|
20
20
|
* registered definition with the target name.
|
|
21
21
|
* - EXTENDS_NON_ABSTRACT: target resolves to a Telo.Definition, not a Telo.Abstract.
|
|
22
|
+
* - EXTENDS_CLOSED_PARENT_ADDS_FIELD: a child with no `base:` declares a property its
|
|
23
|
+
* controller-bearing ancestor's closed schema rejects — the runtime counterpart is a
|
|
24
|
+
* create-time failure phrased against the ancestor kind.
|
|
22
25
|
* - CAPABILITY_SHADOWS_EXTENDS (warning): `capability` names a user-declared abstract
|
|
23
26
|
* (metadata.module !== "Telo"). Builtin lifecycle capabilities (Telo.Invocable, etc.)
|
|
24
27
|
* never trigger this — they're lifecycle roles by design.
|
|
@@ -140,6 +143,44 @@ export function validateExtends(manifests, registry, aliases) {
|
|
|
140
143
|
data: { resource, filePath, path: "capability" },
|
|
141
144
|
});
|
|
142
145
|
}
|
|
146
|
+
// A merge-form child (no `base:`) forwards its WHOLE config to the
|
|
147
|
+
// inherited controller as the parent's config, so a field the
|
|
148
|
+
// parent's schema closes out is rejected at the parent's own
|
|
149
|
+
// create-time validation — phrased against the parent kind, at the
|
|
150
|
+
// instance's line, about a resource the author never wrote.
|
|
151
|
+
// Reported here instead, at the property that has to change.
|
|
152
|
+
if (m.base == null &&
|
|
153
|
+
isInheritedDelegation(m, resolveDef)) {
|
|
154
|
+
const ancestor = controllerBearingAncestor(m, resolveDef);
|
|
155
|
+
const ancestorSchema = ancestor
|
|
156
|
+
? effectiveAuthorSchema(ancestor, resolveDef)
|
|
157
|
+
: undefined;
|
|
158
|
+
if (ancestorSchema?.additionalProperties === false) {
|
|
159
|
+
const inherited = new Set(Object.keys(ancestorSchema.properties ?? {}));
|
|
160
|
+
const ownProps = (m
|
|
161
|
+
.schema?.properties ?? {});
|
|
162
|
+
const ancestorKind = `${ancestor?.metadata.module}.${ancestor?.metadata.name}`;
|
|
163
|
+
for (const prop of Object.keys(ownProps)) {
|
|
164
|
+
if (inherited.has(prop))
|
|
165
|
+
continue;
|
|
166
|
+
diagnostics.push({
|
|
167
|
+
severity: DiagnosticSeverity.Error,
|
|
168
|
+
code: "EXTENDS_CLOSED_PARENT_ADDS_FIELD",
|
|
169
|
+
source: SOURCE,
|
|
170
|
+
message: `${label}: declares '${prop}', but '${ancestorKind}' closes its schema ` +
|
|
171
|
+
`(additionalProperties: false) and a child without 'base:' forwards its whole ` +
|
|
172
|
+
`config as that kind's config — so '${prop}' is rejected when the resource is ` +
|
|
173
|
+
`created. Add a 'base:' mapping, which makes this kind's fields construction ` +
|
|
174
|
+
`inputs and builds the parent's config explicitly.`,
|
|
175
|
+
data: {
|
|
176
|
+
resource,
|
|
177
|
+
filePath,
|
|
178
|
+
path: `schema.properties.${prop}`,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
143
184
|
}
|
|
144
185
|
}
|
|
145
186
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ResourceManifest } from "@telorun/sdk";
|
|
2
|
+
/**
|
|
3
|
+
* `x-telo-sensitive` where nothing reads it.
|
|
4
|
+
*
|
|
5
|
+
* The annotation has exactly one consumer: the kernel resolves it from a
|
|
6
|
+
* resource's bound CONTRACT — `inputType` / `outputType` — and carries the
|
|
7
|
+
* marked value as `[redacted]` in trace payloads. Written anywhere else it is an
|
|
8
|
+
* unknown keyword in an open schema, which is to say it validates, ships, and
|
|
9
|
+
* does nothing.
|
|
10
|
+
*
|
|
11
|
+
* For a security control that is the worst available failure: an author marks a
|
|
12
|
+
* token, sees no error, and puts it on the debug wire anyway. So a misplacement
|
|
13
|
+
* is reported rather than ignored — the same posture `X_TELO_REF_UNRESOLVED`
|
|
14
|
+
* takes toward a reference constraint that resolves to nothing, and for the same
|
|
15
|
+
* reason: silence reads as protection.
|
|
16
|
+
*
|
|
17
|
+
* Scoped by the caller to the entry's own modules, since a dependency's schema
|
|
18
|
+
* is not the consumer's to fix.
|
|
19
|
+
*/
|
|
20
|
+
export interface SensitiveSlotIssue {
|
|
21
|
+
code: "SENSITIVE_ANNOTATION_MISPLACED" | "SENSITIVE_ANNOTATION_INVALID";
|
|
22
|
+
manifest: ResourceManifest;
|
|
23
|
+
/** Dotted path to the annotated schema node. */
|
|
24
|
+
path: string;
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function validateSensitiveSlots(manifest: ResourceManifest): SensitiveSlotIssue[];
|
|
28
|
+
//# sourceMappingURL=validate-sensitive-slots.d.ts.map
|