@telorun/cli 0.61.0 → 0.63.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.
Files changed (35) hide show
  1. package/README.md +19 -4
  2. package/dist/bundle/partition-layers.d.ts +4 -2
  3. package/dist/bundle/partition-layers.d.ts.map +1 -1
  4. package/dist/bundle/partition-layers.js +13 -14
  5. package/dist/bundle/partition-layers.js.map +1 -1
  6. package/dist/bundle/payload-drift.d.ts +46 -0
  7. package/dist/bundle/payload-drift.d.ts.map +1 -0
  8. package/dist/bundle/payload-drift.js +109 -0
  9. package/dist/bundle/payload-drift.js.map +1 -0
  10. package/dist/bundle/select-files.d.ts +13 -0
  11. package/dist/bundle/select-files.d.ts.map +1 -1
  12. package/dist/bundle/select-files.js +27 -4
  13. package/dist/bundle/select-files.js.map +1 -1
  14. package/dist/commands/check.d.ts +1 -0
  15. package/dist/commands/check.d.ts.map +1 -1
  16. package/dist/commands/check.js +136 -10
  17. package/dist/commands/check.js.map +1 -1
  18. package/dist/commands/manifest-imports.d.ts.map +1 -1
  19. package/dist/commands/manifest-imports.js +2 -2
  20. package/dist/commands/manifest-imports.js.map +1 -1
  21. package/dist/commands/publish.d.ts.map +1 -1
  22. package/dist/commands/publish.js +51 -7
  23. package/dist/commands/publish.js.map +1 -1
  24. package/dist/commands/run.d.ts.map +1 -1
  25. package/dist/commands/run.js +149 -30
  26. package/dist/commands/run.js.map +1 -1
  27. package/dist/logger.d.ts +5 -1
  28. package/dist/logger.d.ts.map +1 -1
  29. package/dist/logger.js +55 -26
  30. package/dist/logger.js.map +1 -1
  31. package/dist/manifest-freshness.d.ts +120 -0
  32. package/dist/manifest-freshness.d.ts.map +1 -0
  33. package/dist/manifest-freshness.js +261 -0
  34. package/dist/manifest-freshness.js.map +1 -0
  35. package/package.json +6 -6
package/README.md CHANGED
@@ -122,6 +122,15 @@ telo check https://example.com/manifest.yaml
122
122
 
123
123
  Accepts local paths, directories containing a `telo.yaml`, or HTTP(S) URLs.
124
124
 
125
+ Imports resolve through the same `.telo/manifests/` cache `telo run` reads, and `check` writes through to it after a successful load (disable with `--no-cache-write`). Freshness depends on how the import addresses its target:
126
+
127
+ - **Pinned** (`…@1.2.3#sha256-…`, or an `@sha256:` reference) — verified against the hash on read, so a repeat check of a fully pinned manifest needs no network at all.
128
+ - **Mutable OCI tag** — revalidated with one `HEAD` per reference against the digest recorded in `.telo/manifests/.origins.json`. If the tag has moved, that entry is dropped and refetched.
129
+ - **Registry ref** (`<namespace>/<name>@<version>`) — served from cache without revalidation; a published version is immutable by convention.
130
+ - **HTTP(S) URL** — never read from the cache by `check`, since its key carries no version segment and a hit would be served indefinitely. Always re-fetched (one request, the same cost revalidating would have).
131
+
132
+ One loader serves every path in a single invocation, so `telo check a b c` resolves a module shared between them once.
133
+
125
134
  **Example output:**
126
135
 
127
136
  ```
@@ -161,12 +170,14 @@ telo install ./apps/a/telo.yaml ./apps/b/telo.yaml
161
170
 
162
171
  The cache lives next to the manifest at `<entry-manifest-dir>/.telo/`:
163
172
 
164
- - `.telo/npm/` — controller node_modules tree (one realm per manifest).
173
+ - `.telo/npm/` — controller node_modules tree (one realm per manifest), for the modules that still deliver their controller from npm.
174
+ - `.telo/controller-src/` — bundles built from a **local** module's controller sources. Only ever written for a module that is a working copy on disk: a published module ships a prebuilt bundle in its artifact and never reaches this path. Each entry is named by a digest of every input the build read, so an edit anywhere in the source graph yields a new entry rather than invalidating one.
165
175
  - `.telo/manifests/registry/<host>/<path…>/<version>/telo.yaml` — registry-served manifests.
166
176
  - `.telo/manifests/oci/<host>/<repo…>/<tag>/telo.yaml` — manifests imported from an OCI registry.
167
177
  - `.telo/manifests/url/<host>/<pathname>` — manifests imported via raw HTTP URLs.
178
+ - `.telo/manifests/.origins.json` — for each cached import named by a **mutable tag**, the OCI manifest digest that produced the copy. `telo check` revalidates against it with one `HEAD` per reference; a pinned import needs no entry, since its bytes are verified against the ref's own hash.
168
179
 
169
- Every entry is keyed `<transport>/<host>/<path…>/<version>/<file>`, the same grammar the
180
+ Every manifest entry is keyed `<transport>/<host>/<path…>/<version>/<file>`, the same grammar the
170
181
  discovery hub uses for its cached manifests.
171
182
 
172
183
  Per-manifest scope means the whole `.telo/` tree is naturally portable: `COPY` the manifest dir into your image and both caches travel with it; no environment variable is required.
@@ -175,13 +186,17 @@ Per-manifest scope means the whole `.telo/` tree is naturally portable: `COPY` t
175
186
 
176
187
  ```
177
188
  Installing 20 controllers for apps/my-app/telo.yaml
178
- ✓ pkg:npm/@telorun/http-server@<version>?local_path=./nodejs#http-server
179
- ✓ pkg:npm/@telorun/http-client@<version>?local_path=./nodejs#http-client
189
+ ✓ pkg:telo/local/js?path=./nodejs/server.mjs
190
+ ✓ pkg:telo/local/js?path=./nodejs/request.mjs
180
191
  ...
181
192
 
182
193
  ✓ 20 installed in 3.2s
183
194
  ```
184
195
 
196
+ A bundled controller (`pkg:telo/local/js`) ships inside its module's own artifact, so
197
+ "installing" it is materializing that artifact's controller layer — nothing is fetched
198
+ from npm. A `pkg:npm` candidate still resolves through the npm cache above.
199
+
185
200
  **Typical Dockerfile usage:**
186
201
 
187
202
  ```dockerfile
@@ -54,8 +54,10 @@ export declare function readControllerClaims(manifestText: string): ControllerCl
54
54
  * are optional and only ever buy laziness.
55
55
  *
56
56
  * `files` are the manifest-relative paths `selectFiles` produced; `assetPatterns`
57
- * is the author's `assets:` list. Layers with no files are dropped, so a
58
- * controller-only module publishes exactly one payload layer.
57
+ * is the author's `assets:` list. Every bundled controller's `path=` entry joins
58
+ * the payload whether or not `files:` selected it — the manifest already names
59
+ * it, so restating it would be pure duplication. Layers with no files are
60
+ * dropped, so a controller-only module publishes exactly one payload layer.
59
61
  */
60
62
  export declare function partitionLayers(manifestText: string, files: string[], assetPatterns: string[]): Partition;
61
63
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"partition-layers.d.ts","sourceRoot":"","sources":["../../src/bundle/partition-layers.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD;;uDAEuD;AACvD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;uEAEuE;AACvE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB;yDACqD;IACrD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;oBACgB;IAChB,iBAAiB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D;AAgBD,UAAU,eAAe;IACvB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAQD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE,CAmC5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,MAAM,EAAE,GACtB,SAAS,CAqEX;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,EAAE,CAYhE"}
1
+ {"version":3,"file":"partition-layers.d.ts","sourceRoot":"","sources":["../../src/bundle/partition-layers.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAKpD;;uDAEuD;AACvD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;uEAEuE;AACvE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB;yDACqD;IACrD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;oBACgB;IAChB,iBAAiB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D;AAgBD,UAAU,eAAe;IACvB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAQD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,EAAE,CAmC5E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,MAAM,EAAE,GACtB,SAAS,CAgEX;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,EAAE,CAYhE"}
@@ -77,24 +77,23 @@ export function readControllerClaims(manifestText) {
77
77
  * are optional and only ever buy laziness.
78
78
  *
79
79
  * `files` are the manifest-relative paths `selectFiles` produced; `assetPatterns`
80
- * is the author's `assets:` list. Layers with no files are dropped, so a
81
- * controller-only module publishes exactly one payload layer.
80
+ * is the author's `assets:` list. Every bundled controller's `path=` entry joins
81
+ * the payload whether or not `files:` selected it — the manifest already names
82
+ * it, so restating it would be pure duplication. Layers with no files are
83
+ * dropped, so a controller-only module publishes exactly one payload layer.
82
84
  */
83
85
  export function partitionLayers(manifestText, files, assetPatterns) {
84
86
  const claims = readControllerClaims(manifestText);
85
- const selected = new Set(files);
87
+ // A controller entry point is part of the payload because `controllers:` names
88
+ // it, not because `files:` restates it. `files:` keeps its role for everything
89
+ // the manifest cannot otherwise see — assets, static files, sidecars — and a
90
+ // module whose only payload is its controller declares no `files:` at all.
91
+ //
92
+ // Sibling patterns are still matched against `files:` alone: a sibling is a
93
+ // glob over the payload, so a pattern that selects nothing there means the
94
+ // author forgot to include the file, which `unmatchedSiblings` reports.
95
+ const selected = new Set([...files, ...claims.map((claim) => claim.entry)]);
86
96
  const unclaimed = new Set(files);
87
- // A controller entry point the `files:` list does not select is a broken
88
- // artifact, and it is decidable right here: its layer would ship without it (or
89
- // be dropped entirely as empty), and the consumer would only find out at load
90
- // time as "ships no layer for <selector>". Fail at publish, naming both the PURL
91
- // and the path that has to be added.
92
- const missing = claims.filter((c) => !selected.has(c.entry));
93
- if (missing.length > 0) {
94
- throw new Error(`controller entry point${missing.length === 1 ? "" : "s"} not selected by 'files:':\n` +
95
- missing.map((c) => ` ${c.entry} (from ${c.purl})`).join("\n") +
96
- `\nAdd the path to 'files:' — a bundled controller must ship in the module's artifact.`);
97
- }
98
97
  // Controller layers first: a file an entry point or sibling claims belongs to
99
98
  // that selector, never to assets or common, so the layer a kernel skips is
100
99
  // genuinely skippable. A file several candidates claim is copied into each of
@@ -1 +1 @@
1
- {"version":3,"file":"partition-layers.js","sourceRoot":"","sources":["../../src/bundle/partition-layers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,WAAW,GAEZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAwBzC;;4BAE4B;AAC5B,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAElC;;;;;4EAK4E;AAC5E,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAYtC;mEACmE;AACnE,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAoB;IACvD,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,iBAAiB,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,CAAC,EAAE,CAAC;QACvF,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,EAAsC,CAAC;QAC9D,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,OAAO,SAAS,KAAK,QAAQ;gBAAE,SAAS;YAC5C,IAAI,MAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;gBACpE,yEAAyE;gBACzE,SAAS;YACX,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,SAAS,KAAK,iBAAiB;gBAAE,SAAS;YACrF,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;YACtC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;gBAAE,SAAS;YACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;iBACnE,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,sBAAsB,CAC9B,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,UAAU,EACjB,eAAe,SAAS,GAAG,CAC5B;gBACD,KAAK,EAAE,iBAAiB,CAAC,KAAK,CAAC;gBAC/B,QAAQ;gBACR,IAAI,EAAE,SAAS;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAC7B,YAAoB,EACpB,KAAe,EACf,aAAuB;IAEvB,MAAM,MAAM,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAEjC,yEAAyE;IACzE,gFAAgF;IAChF,8EAA8E;IAC9E,iFAAiF;IACjF,qCAAqC;IACrC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,yBAAyB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,8BAA8B;YACpF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC/D,uFAAuF,CAC1F,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,2EAA2E;IAC3E,8EAA8E;IAC9E,2EAA2E;IAC3E,+EAA+E;IAC/E,qEAAqE;IACrE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAqB,CAAC;IAChD,MAAM,iBAAiB,GAA6C,EAAE,CAAC;IACvE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YACnE,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE;YAC/D,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QACH,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,IAAI,gBAAgB,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3F,iBAAiB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;YAC9C,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,gBAAgB,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,aAAa,EAAE;QACjE,kBAAkB,EAAE,KAAK;KAC1B,CAAC,CAAC;IACH,KAAK,MAAM,IAAI,IAAI,UAAU;QAAE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAC1C,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACxB,gBAAgB,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CACzF,CAAC;IAEF,MAAM,MAAM,GAAgB;QAC1B,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClF,EAAE,IAAI,EAAE,QAAiB,EAAE,KAAK,EAAE,UAAU,EAAE;QAC9C,EAAE,IAAI,EAAE,QAAiB,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;KAC1D,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAChD,eAAe;QACf,iBAAiB;KAClB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;QAChG,OAAO,GAAG,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC;IACnD,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,eAAe,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,mBAAmB,OAAO,mBAAmB,CAAC,CAAC;IAC5D,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,SAAS,CAAC,iBAAiB,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,qBAAqB,OAAO,2BAA2B,IAAI,GAAG,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"partition-layers.js","sourceRoot":"","sources":["../../src/bundle/partition-layers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { type ArtifactSelector } from "@telorun/analyzer";
2
+ import { type PayloadFile } from "@telorun/kernel";
3
+ /**
4
+ * Does the payload we are about to publish differ from what is already published
5
+ * at this `metadata.version`?
6
+ *
7
+ * Bundling moves a module's dependency coupling from load time to build time. It
8
+ * does not remove it: once `codec` — or `fastify`, or a transitive dependency the
9
+ * lockfile alone moved — is copied into a module's bundle, that module's bytes
10
+ * have changed while nothing under its own directory has. No path-scoped rule and
11
+ * no version ledger can see that, so a fix silently ships to nobody.
12
+ *
13
+ * The artifact already carries the exact answer. Each layer's `integrity` is a
14
+ * framing-independent digest of its contents, so comparing the layer we just
15
+ * built against the one published under the same version decides the question
16
+ * from the bytes themselves — it fires for a shared-library fix, a lockfile bump
17
+ * and a sibling source edit alike, and it cannot fire spuriously, because
18
+ * identical bytes hash identically.
19
+ */
20
+ export interface LayerDrift {
21
+ role: string;
22
+ selector?: string;
23
+ /** `integrity` recorded in the published `layers:` index, or `undefined` when
24
+ * the published artifact ships no layer for this role/selector at all. */
25
+ published?: string;
26
+ /** `integrity` of the layer built from the working copy, or `undefined` when
27
+ * the build no longer produces this layer. */
28
+ built?: string;
29
+ }
30
+ export interface BuiltLayer {
31
+ role: string;
32
+ selector?: ArtifactSelector;
33
+ files: PayloadFile[];
34
+ }
35
+ /**
36
+ * Compare the built payload against the published one at the same version.
37
+ *
38
+ * Returns `null` when nothing is published at that ref — a new version, so there
39
+ * is nothing to disagree with. Returns an empty array when the payloads match.
40
+ */
41
+ export declare function findPayloadDrift(destination: string, version: string, built: BuiltLayer[], registry: string): Promise<LayerDrift[] | null>;
42
+ /** The message shown when the gate fires. It names the version to bump, because
43
+ * that — not a re-push — is the fix: overwriting a published tag would change
44
+ * what an existing pinned import resolves to. */
45
+ export declare function describeDrift(moduleRef: string, version: string, drift: LayerDrift[]): string;
46
+ //# sourceMappingURL=payload-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-drift.d.ts","sourceRoot":"","sources":["../../src/bundle/payload-drift.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGpG;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;+EAC2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;mDAC+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AA2DD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,EAAE,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CA6B9B;AAED;;kDAEkD;AAClD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAc7F"}
@@ -0,0 +1,109 @@
1
+ import { describeSelector, parseLayerIndex, selectorKey, } from "@telorun/analyzer";
2
+ import { computeFilesIntegrity, defaultTransportRegistry } from "@telorun/kernel";
3
+ import { parseAllDocuments } from "yaml";
4
+ /** Identity of a layer within an artifact: its role, plus its selector for the
5
+ * controller layers, of which there is one per selector. */
6
+ function layerKey(role, selector) {
7
+ return selector ? `${role}\0${selectorKey(selector)}` : role;
8
+ }
9
+ function describeKey(role, selector) {
10
+ return selector ? `${role} (${describeSelector(selector)})` : role;
11
+ }
12
+ /** A published version genuinely absent from the registry — the normal case on
13
+ * every release, and the ONLY reason this gate is allowed to pass without
14
+ * comparing anything. */
15
+ const NOT_FOUND = /\b404\b|not found|MANIFEST_UNKNOWN|NAME_UNKNOWN/i;
16
+ /**
17
+ * Read the `layers:` index off an already-published manifest, or `null` when
18
+ * nothing is published at that ref.
19
+ *
20
+ * A ref that does not resolve is not an error: a new version has no predecessor.
21
+ * **Anything else is.** A 401, a 5xx or a DNS failure says nothing about whether
22
+ * the payload changed, and answering "no drift" to a question the registry
23
+ * refused to answer would turn a byte-equality gate into a no-op during exactly
24
+ * the kind of incident where a release is most likely to ship something wrong.
25
+ * Those propagate and fail the publish.
26
+ */
27
+ async function readPublishedLayers(ref, registry) {
28
+ const transport = defaultTransportRegistry(registry).forRef(ref);
29
+ if (!transport) {
30
+ throw new Error(`Cannot verify the published payload of '${ref}': no transport owns that ref.`);
31
+ }
32
+ let text;
33
+ try {
34
+ ({ text } = await transport.source.read(ref));
35
+ }
36
+ catch (err) {
37
+ const message = err instanceof Error ? err.message : String(err);
38
+ if (NOT_FOUND.test(message))
39
+ return null;
40
+ throw new Error(`Cannot verify whether '${ref}' is already published with a different payload: ${message}. ` +
41
+ `Publishing without that answer could ship changed bytes at an unchanged version — ` +
42
+ `resolve the registry error and retry.`);
43
+ }
44
+ for (const doc of parseAllDocuments(text)) {
45
+ const json = doc.toJSON();
46
+ if (json?.kind !== "Telo.Application" && json?.kind !== "Telo.Library")
47
+ continue;
48
+ if (json.layers === undefined)
49
+ return [];
50
+ return parseLayerIndex(json.layers, `${ref} layers`);
51
+ }
52
+ return [];
53
+ }
54
+ /**
55
+ * Compare the built payload against the published one at the same version.
56
+ *
57
+ * Returns `null` when nothing is published at that ref — a new version, so there
58
+ * is nothing to disagree with. Returns an empty array when the payloads match.
59
+ */
60
+ export async function findPayloadDrift(destination, version, built, registry) {
61
+ const published = await readPublishedLayers(`${destination}@${version}`, registry);
62
+ if (published === null)
63
+ return null;
64
+ const publishedByKey = new Map();
65
+ for (const layer of published)
66
+ publishedByKey.set(layerKey(layer.role, layer.selector), layer);
67
+ const drift = [];
68
+ const seen = new Set();
69
+ for (const layer of built) {
70
+ const key = layerKey(layer.role, layer.selector);
71
+ seen.add(key);
72
+ const integrity = await computeFilesIntegrity(layer.files);
73
+ const before = publishedByKey.get(key);
74
+ if (before?.integrity !== integrity) {
75
+ drift.push({
76
+ role: describeKey(layer.role, layer.selector),
77
+ published: before?.integrity,
78
+ built: integrity,
79
+ });
80
+ }
81
+ }
82
+ // A layer that was published and is no longer built is drift too — the payload
83
+ // shrank, which changes what a consumer receives just as much as a byte edit.
84
+ for (const [key, layer] of publishedByKey) {
85
+ if (seen.has(key))
86
+ continue;
87
+ drift.push({ role: describeKey(layer.role, layer.selector), published: layer.integrity });
88
+ }
89
+ return drift;
90
+ }
91
+ /** The message shown when the gate fires. It names the version to bump, because
92
+ * that — not a re-push — is the fix: overwriting a published tag would change
93
+ * what an existing pinned import resolves to. */
94
+ export function describeDrift(moduleRef, version, drift) {
95
+ const lines = drift.map((entry) => {
96
+ if (!entry.built)
97
+ return ` ${entry.role}: published, no longer built`;
98
+ if (!entry.published)
99
+ return ` ${entry.role}: newly built, not in the published artifact`;
100
+ return ` ${entry.role}: ${entry.published} → ${entry.built}`;
101
+ });
102
+ return (`${moduleRef} is already published at ${version}, but its payload has changed:\n` +
103
+ lines.join("\n") +
104
+ `\nA bundle inlines its dependencies, so a change in a shared library or the ` +
105
+ `lockfile alters these bytes without touching this module's own files. ` +
106
+ `Add a changie fragment for this module so metadata.version moves — republishing ` +
107
+ `over the existing tag would change what an already-pinned import resolves to.`);
108
+ }
109
+ //# sourceMappingURL=payload-drift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-drift.js","sourceRoot":"","sources":["../../src/bundle/payload-drift.ts"],"names":[],"mappings":"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"}
@@ -14,4 +14,17 @@
14
14
  export declare function selectFiles(manifestDir: string, patterns: string[], opts?: {
15
15
  applyDefaultIgnore?: boolean;
16
16
  }): string[];
17
+ /**
18
+ * Reject any path that resolves — via a symlink — outside `manifestDir`.
19
+ *
20
+ * Separate from {@link selectFiles} because a `files:` pattern is no longer the
21
+ * only route into the payload: a bundled controller's `path=` entry joins it
22
+ * from `controllers:`, and the guard has to cover what actually ships rather
23
+ * than what a pattern happened to match. Applied to the whole partition, so
24
+ * every file in every layer passes it.
25
+ *
26
+ * A missing file is reported here too — publish is about to read it, and
27
+ * "declared but absent" is the same class of mistake as "declared but outside".
28
+ */
29
+ export declare function assertWithinModule(manifestDir: string, rels: Iterable<string>): void;
17
30
  //# sourceMappingURL=select-files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"select-files.d.ts","sourceRoot":"","sources":["../../src/bundle/select-files.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,MAAM,EAAE,CA8BV"}
1
+ {"version":3,"file":"select-files.d.ts","sourceRoot":"","sources":["../../src/bundle/select-files.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,MAAM,EAAE,CAoBV;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAoBpF"}
@@ -31,14 +31,37 @@ export function selectFiles(manifestDir, patterns, opts = {}) {
31
31
  const selected = selectByPatterns(rels, patterns, {
32
32
  applyDefaultIgnore: opts.applyDefaultIgnore,
33
33
  });
34
+ assertWithinModule(manifestDir, selected);
35
+ return selected;
36
+ }
37
+ /**
38
+ * Reject any path that resolves — via a symlink — outside `manifestDir`.
39
+ *
40
+ * Separate from {@link selectFiles} because a `files:` pattern is no longer the
41
+ * only route into the payload: a bundled controller's `path=` entry joins it
42
+ * from `controllers:`, and the guard has to cover what actually ships rather
43
+ * than what a pattern happened to match. Applied to the whole partition, so
44
+ * every file in every layer passes it.
45
+ *
46
+ * A missing file is reported here too — publish is about to read it, and
47
+ * "declared but absent" is the same class of mistake as "declared but outside".
48
+ */
49
+ export function assertWithinModule(manifestDir, rels) {
34
50
  const realManifestDir = fs.realpathSync(manifestDir) + path.sep;
35
- for (const rel of selected) {
36
- const real = fs.realpathSync(path.resolve(manifestDir, rel));
51
+ for (const rel of rels) {
52
+ let real;
53
+ try {
54
+ real = fs.realpathSync(path.resolve(manifestDir, rel));
55
+ }
56
+ catch {
57
+ throw new Error(`'${rel}' is declared as part of this module's payload but does not exist. ` +
58
+ `A bundled controller's entry point is built from its source — run the module's ` +
59
+ `build before publishing.`);
60
+ }
37
61
  if (!real.startsWith(realManifestDir)) {
38
- throw new Error(`files pattern selected '${rel}', which resolves outside the module directory. ` +
62
+ throw new Error(`'${rel}' resolves outside the module directory. ` +
39
63
  `Bundling files from outside the module root is not allowed.`);
40
64
  }
41
65
  }
42
- return selected;
43
66
  }
44
67
  //# sourceMappingURL=select-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select-files.js","sourceRoot":"","sources":["../../src/bundle/select-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CACzB,WAAmB,EACnB,QAAkB,EAClB,OAAyC,EAAE;IAE3C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,8EAA8E;IAC9E,2EAA2E;IAC3E,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACtF,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,yEAAyE;QACzE,mDAAmD;QACnD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,SAAS;QAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE;QAChD,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;KAC5C,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IAChE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CACb,2BAA2B,GAAG,kDAAkD;gBAC9E,6DAA6D,CAChE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"select-files.js","sourceRoot":"","sources":["../../src/bundle/select-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CACzB,WAAmB,EACnB,QAAkB,EAClB,OAAyC,EAAE;IAE3C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,8EAA8E;IAC9E,2EAA2E;IAC3E,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACtF,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,yEAAyE;QACzE,mDAAmD;QACnD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,SAAS;QAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE;QAChD,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;KAC5C,CAAC,CAAC;IAEH,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,IAAsB;IAC5E,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IAChE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,IAAI,GAAG,qEAAqE;gBAC1E,iFAAiF;gBACjF,0BAA0B,CAC7B,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CACb,IAAI,GAAG,2CAA2C;gBAChD,6DAA6D,CAChE,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -2,6 +2,7 @@ import type { Argv } from "yargs";
2
2
  export declare function check(argv: {
3
3
  paths: string[];
4
4
  registryUrl?: string;
5
+ cacheWrite?: boolean;
5
6
  }): Promise<void>;
6
7
  export declare function checkCommand(yargs: Argv): Argv;
7
8
  //# sourceMappingURL=check.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAoDlC,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B1F;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAoB9C"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAkOlC,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DhB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAoB9C"}
@@ -1,13 +1,42 @@
1
1
  import { Loader, StaticAnalyzer, flattenForAnalyzer } from "@telorun/analyzer";
2
2
  import { assembleGraphDiagnostics } from "@telorun/ide-support";
3
+ import { LocalManifestCacheSource, resolveCacheRoot, resolveEntryDir, writeManifestCache, } from "@telorun/kernel";
3
4
  import { LocalFileSource } from "@telorun/kernel/manifest-sources/local-file-source";
4
5
  import { defaultTransportRegistry } from "@telorun/kernel/transports";
6
+ import * as fs from "fs/promises";
5
7
  import * as path from "path";
8
+ import { pathToFileURL } from "url";
6
9
  import { createLogger, formatAnalysisDiagnostics, formatDiagnostics } from "../logger.js";
10
+ import { RecordingCacheSource, readOriginDigests, revalidateMutableOciRefs, writeOriginDigests, } from "../manifest-freshness.js";
7
11
  const DEFAULT_REGISTRY_URL = "https://registry.telo.run";
8
- async function checkOne(inputPath, registryUrl, log) {
12
+ function cacheTargetFor(entryPath) {
13
+ const cacheRoot = resolveCacheRoot(entryPath);
14
+ const entryDir = resolveEntryDir(entryPath);
15
+ if (!cacheRoot || entryDir === null)
16
+ return null;
17
+ return { entryDir, manifestsDir: path.join(cacheRoot, "manifests") };
18
+ }
19
+ function resolveEntryPath(inputPath) {
9
20
  const isUrl = inputPath.startsWith("http://") || inputPath.startsWith("https://");
10
- const entryPath = isUrl ? inputPath : path.resolve(process.cwd(), inputPath);
21
+ return isUrl ? inputPath : path.resolve(process.cwd(), inputPath);
22
+ }
23
+ /**
24
+ * One loader for the whole invocation, ahead of the transports:
25
+ *
26
+ * - `LocalManifestCacheSource` makes a repeat check hermetic. Without it every
27
+ * `oci://` / registry import was re-pulled on every run even when fully
28
+ * pinned, which is the bulk of `check`'s wall time.
29
+ * - The loader is shared across *all* input paths, so `telo check a b c` reads
30
+ * a module common to several of them once. Its `urlToSource` / `fileCache`
31
+ * dedupe by canonical URL, so this is purely a cache-hit question — the
32
+ * resolution result for a given URL does not depend on which entry asked.
33
+ *
34
+ * A cache source is registered for every input path's cache root: the entries
35
+ * are content-addressed, so a hit under any root is as good as a hit under the
36
+ * one this path would write to, and a miss falls through unchanged.
37
+ */
38
+ function openSession(cacheTargets, registryUrl) {
39
+ const recorders = cacheTargets.map((t) => new RecordingCacheSource(new LocalManifestCacheSource(t.entryDir, registryUrl, t.manifestsDir), registryUrl));
11
40
  // The kernel's transport sources — the same set `install` / `run` use — so
12
41
  // `check` resolves every scheme they do, `oci://` included, direct-to-origin.
13
42
  // The browser-only `manifests.telo.sh` cache path stays the editor's; a CLI
@@ -15,14 +44,78 @@ async function checkOne(inputPath, registryUrl, log) {
15
44
  // plan: resolution never routes through the hub).
16
45
  const loader = new Loader([
17
46
  new LocalFileSource(),
47
+ ...recorders,
18
48
  ...defaultTransportRegistry(registryUrl).sources(),
19
49
  ]);
50
+ return {
51
+ loader,
52
+ recorders,
53
+ manifestsDirs: cacheTargets.map((t) => t.manifestsDir),
54
+ verified: new Map(),
55
+ };
56
+ }
57
+ /**
58
+ * Drop a stale cache entry: the file, the loader's memo of it, and the record
59
+ * that it was ever served. The next load re-resolves that one manifest through
60
+ * the transports and leaves every other file's memo intact.
61
+ *
62
+ * Removal failures are warned, not thrown. This is cache maintenance, and the
63
+ * rest of the command already treats caching as an optimization — a read-only
64
+ * or root-owned `.telo` must not change the exit code of a static check. An
65
+ * entry that could not be removed is still forgotten by the loader, so the
66
+ * reload re-fetches it rather than trusting bytes it just judged stale.
67
+ */
68
+ async function dropStaleEntry(file, session, log) {
69
+ try {
70
+ await fs.rm(file, { force: true });
71
+ }
72
+ catch (err) {
73
+ process.stderr.write(`${log.warn(`[manifest-cache] could not remove stale entry ${file}: ${err instanceof Error ? err.message : String(err)}`)}\n`);
74
+ }
75
+ session.loader.forget(pathToFileURL(file).href);
76
+ for (const recorder of session.recorders) {
77
+ for (const [url, served] of recorder.served) {
78
+ if (served === file)
79
+ recorder.served.delete(url);
80
+ }
81
+ }
82
+ }
83
+ async function checkOne(inputPath, registryUrl, session, cacheTarget, cacheWrite,
84
+ /** Digests already verified by a prior pass. Present only on the retry after
85
+ * a stale entry was dropped: revalidating again would re-`HEAD` the same
86
+ * tags, and the freshly fetched bytes are current by construction. */
87
+ knownDigests, log) {
88
+ const entryPath = resolveEntryPath(inputPath);
89
+ const isUrl = entryPath.startsWith("http://") || entryPath.startsWith("https://");
20
90
  try {
21
91
  // `desugarImports` so inline `imports:` maps expand into synthetic
22
92
  // Telo.Import manifests before analysis — `telo check` is a static
23
93
  // resolution consumer and must see inline imports exactly as the kernel does.
24
- const graph = await loader.loadGraph(entryPath, { desugarImports: true });
25
- const manifests = flattenForAnalyzer(graph);
94
+ const graph = await session.loader.loadGraph(entryPath, { desugarImports: true });
95
+ // Freshness before analysis: a verdict computed from a moved tag would be
96
+ // reported as authoritative. Pinned imports make this a no-op.
97
+ let digests = knownDigests ?? new Map();
98
+ if (!knownDigests && session.recorders.length > 0) {
99
+ const served = new Map();
100
+ for (const recorder of session.recorders) {
101
+ for (const [url, file] of recorder.served)
102
+ served.set(url, file);
103
+ }
104
+ const originsByRoot = new Map();
105
+ for (const dir of session.manifestsDirs) {
106
+ originsByRoot.set(dir, await readOriginDigests(dir));
107
+ }
108
+ const freshness = await revalidateMutableOciRefs(graph, served, originsByRoot, registryUrl, session.verified);
109
+ if (freshness.staleFiles.length > 0) {
110
+ return {
111
+ errorCount: 0,
112
+ warnCount: 0,
113
+ staleFiles: freshness.staleFiles,
114
+ digests: freshness.digests,
115
+ };
116
+ }
117
+ digests = freshness.digests;
118
+ }
26
119
  // `assembleGraphDiagnostics` is the shared assembler every host uses: it
27
120
  // folds parse, version-reconciliation, import-resolution, and static
28
121
  // analysis diagnostics into one list, holding back the cascade for files
@@ -30,28 +123,61 @@ async function checkOne(inputPath, registryUrl, log) {
30
123
  // `imports:` source thus surfaces here as a coded diagnostic — identical to
31
124
  // the editor — instead of a bare re-thrown load error. The CLI drops the
32
125
  // suppressed cascade; the editor / VS Code keep it available to render.
33
- const analysis = new StaticAnalyzer().analyze(manifests);
126
+ const analysis = new StaticAnalyzer().analyze(flattenForAnalyzer(graph));
34
127
  const { diagnostics } = assembleGraphDiagnostics(graph, analysis);
35
- return formatAnalysisDiagnostics(diagnostics, graph, log, entryPath);
128
+ const counts = formatAnalysisDiagnostics(diagnostics, graph, log, entryPath);
129
+ if (cacheWrite && cacheTarget) {
130
+ // Write-through so the next check — and the next `telo run` from this
131
+ // directory, which reads the same cache — is hermetic. Caching is an
132
+ // optimization: a read-only filesystem warns rather than fails the check.
133
+ try {
134
+ await writeManifestCache(graph, cacheTarget.entryDir, registryUrl, cacheTarget.manifestsDir);
135
+ await writeOriginDigests(cacheTarget.manifestsDir, digests);
136
+ }
137
+ catch (err) {
138
+ process.stderr.write(`${log.warn(`[manifest-cache] write failed: ${err instanceof Error ? err.message : String(err)}`)}\n`);
139
+ }
140
+ }
141
+ return { ...counts, staleFiles: [], digests };
36
142
  }
37
143
  catch (err) {
38
144
  const sourceLine = err.sourceLine;
39
145
  const displayPath = isUrl ? entryPath : path.relative(process.cwd(), entryPath);
40
146
  const loc = sourceLine !== undefined ? `:${sourceLine + 1}` : "";
41
147
  formatDiagnostics([{ message: err instanceof Error ? err.message : String(err) }], log, `${displayPath}${loc}`);
42
- return { errorCount: 1, warnCount: 0 };
148
+ return { errorCount: 1, warnCount: 0, staleFiles: [], digests: new Map() };
43
149
  }
44
150
  }
45
151
  export async function check(argv) {
46
152
  const log = createLogger(false);
47
153
  // Same fallback chain as `run` / `install`.
48
154
  const registryUrl = argv.registryUrl ?? process.env.TELO_REGISTRY_URL ?? DEFAULT_REGISTRY_URL;
155
+ const cacheWrite = argv.cacheWrite !== false;
156
+ const cacheTargets = new Map();
157
+ for (const p of argv.paths) {
158
+ const target = cacheTargetFor(resolveEntryPath(p));
159
+ if (target)
160
+ cacheTargets.set(target.manifestsDir, target);
161
+ }
162
+ const session = openSession([...cacheTargets.values()], registryUrl);
49
163
  let totalErrors = 0;
50
164
  let totalWarns = 0;
51
165
  for (const p of argv.paths) {
52
- const { errorCount, warnCount } = await checkOne(p, registryUrl, log);
53
- totalErrors += errorCount;
54
- totalWarns += warnCount;
166
+ const cacheTarget = cacheTargetFor(resolveEntryPath(p));
167
+ let outcome = await checkOne(p, registryUrl, session, cacheTarget, cacheWrite, null, log);
168
+ if (outcome.staleFiles.length > 0) {
169
+ // A mutable tag moved under the cache. Drop just those entries — file,
170
+ // loader memo, and served record — so every other path's resolution
171
+ // survives, then re-check. Revalidation is off on the retry: the digests
172
+ // were established a moment ago, and the reload cannot be stale because
173
+ // the entries it would have used are gone.
174
+ for (const file of outcome.staleFiles) {
175
+ await dropStaleEntry(file, session, log);
176
+ }
177
+ outcome = await checkOne(p, registryUrl, session, cacheTarget, cacheWrite, outcome.digests, log);
178
+ }
179
+ totalErrors += outcome.errorCount;
180
+ totalWarns += outcome.warnCount;
55
181
  }
56
182
  if (totalErrors === 0 && totalWarns === 0) {
57
183
  console.log(log.ok("✓") + " No issues found");
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}