@jini-ai/platform 0.1.2 → 0.3.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/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # `@jini-ai/platform`
2
+
3
+ Generic OS/platform primitives: process exec and lifecycle, filesystem containment, HTTP
4
+ readiness polling, toolchain discovery, blob storage, AWS signing, and an SSRF-safe asset cache.
5
+ This is the Node-only substrate a daemon host needs to spawn and supervise child processes, wait
6
+ for a port to come up, resolve a user's installed toolchains, manage terminal (PTY) sessions, and
7
+ store blobs — all without depending on `@jini-ai/daemon` or any product code. Ported mostly
8
+ verbatim from Open Design's own `packages/platform` plus several generic daemon-support files
9
+ that were split out of OD's monolithic daemon (see `source-map.md` for the full per-file trail).
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ npm install @jini-ai/platform
15
+ ```
16
+
17
+ No peer dependencies. `undici` is a regular dependency (used by the SSRF-safe asset cache's
18
+ connection-time DNS-rebinding guard). Interactive terminal sessions (`createTerminalService`)
19
+ need a `PtySpawn` implementation supplied by the caller — this package defines the `PtyProcess`/
20
+ `PtySpawn` port only, it does not depend on `node-pty` itself, so bring your own adapter (or use
21
+ `@jini-ai/daemon`'s, which wires a real `node-pty` behind the same port).
22
+
23
+ ## What you get
24
+
25
+ - **Process lifecycle** — `spawnBackgroundProcess`, `spawnLoggedProcess`, `stopProcesses`,
26
+ `waitForProcessExit`, `isProcessAlive`, `listProcessSnapshots`, process-stamp encode/match
27
+ helpers (`createProcessStampArgs`, `readProcessStamp`, `matchesProcessStamp`).
28
+ - **Command construction** — `createCommandInvocation`, `createPackageManagerInvocation`
29
+ (cross-platform `.bat`/`.cmd` shim quoting).
30
+ - **Shell execution** — `execFileBuffered`, `execCommandViaLoginShell` (re-enters the login shell
31
+ so profile-only `PATH` entries are visible).
32
+ - **Filesystem** — `pathContains`, `atomicCopyFile`, `removePathBestEffort`, `readLogTail`.
33
+ - **HTTP readiness** — `waitForHttpOk`.
34
+ - **Toolchain discovery** — `wellKnownUserToolchainBins` (npm/pnpm/bun/cargo/deno/go/pyenv,
35
+ asdf/volta/mise/nvm/fnm shims).
36
+ - **Proxy-aware env** — `resolveSystemProxyEnv`, `mergeProxyAwareEnv` (macOS `scutil` / Windows
37
+ registry discovery).
38
+ - **Sandboxed execution env** — `resolveSandboxRuntimeConfig(FromEnv)`, `ensureSandboxRuntimeDirs`,
39
+ `applySandboxRuntimeEnv`, `isSandboxModeEnabled`.
40
+ - **Resource paths** — `resolveDaemonCliPath`, `resolveDaemonResourceRoot`, `resolveDataDir`,
41
+ `resolveProcessResourcesPath` — daemon CLI/resource-root/data-dir resolution for a packaged app.
42
+ - **Terminal sessions** — `createTerminalService` (in-memory PTY session manager: spawn, write,
43
+ resize, kill, `attach`/`detach` transport-neutral streaming via `TerminalSseSink`).
44
+ - **Managed downloads** — `managedDownload`, `inspectManagedDownload`, `pruneManagedDownloads`,
45
+ `downloadCopyAndClear` (atomic, resumable, checksum-verified, with cross-process locking and
46
+ retention pruning).
47
+ - **AWS SigV4 signing** — `signSigV4`, `encodeS3PathSegment` (no `@aws-sdk/*` dependency).
48
+ - **Blob storage** — `LocalBlobStorage` and `S3BlobStorage`, both implementing the `BlobStorage`
49
+ port, plus `StorageError`.
50
+ - **SSRF-safe asset cache** — `createAssetCache`, `isCacheableExternalUrl`, `isPrivateAddress`,
51
+ `assertSafePublicUrl` — a same-origin disk cache/proxy for external media any sandboxed-content
52
+ renderer (an iframe preview, an embedded document) needs.
53
+
54
+ ## Usage
55
+
56
+ ```ts
57
+ import { waitForHttpOk, pathContains, spawnBackgroundProcess, LocalBlobStorage } from '@jini-ai/platform';
58
+
59
+ await waitForHttpOk('http://127.0.0.1:4317/api/daemon/status', { timeoutMs: 15000 });
60
+
61
+ if (!pathContains('/workspace/project', requestedPath)) {
62
+ throw new Error('path escapes project root');
63
+ }
64
+
65
+ const proc = spawnBackgroundProcess({ command: 'node', args: ['server.js'] });
66
+
67
+ const blobs = new LocalBlobStorage('/var/lib/app/blobs');
68
+ await blobs.writeFile('tenant-42', 'avatar.png', Buffer.from([]));
69
+ ```
70
+
71
+ ## What's swappable
72
+
73
+ `BlobStorage` is a port with two concrete implementations shipped (`LocalBlobStorage`,
74
+ `S3BlobStorage`) — swap in your own by implementing the same interface. `PtySpawn`/`PtyProcess`
75
+ are ports too: `createTerminalService` takes a `loadSpawnPty: () => Promise<PtySpawn>` factory
76
+ rather than importing `node-pty` directly, so a caller supplies a real adapter or a fake for
77
+ tests. `TerminalSseSink` (`{ send, end }`) decouples terminal streaming from any specific
78
+ transport (Express, SSE, WebSocket) — everything else (process spawning, command construction,
79
+ the asset cache's SSRF guard chain, download resume logic) is fixed, concrete implementation.
80
+
81
+ ## Runtime
82
+
83
+ Node-only.
84
+ ESM only — ships `"type": "module"` with no CommonJS `require` build.
85
+
86
+ ## Provenance
87
+
88
+ See [source-map.md](./source-map.md) for per-file provenance and scope decisions. Apache-2.0.
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @module fetch-with-timeout
3
+ *
4
+ * The shared timeout wrapper for every outbound `fetch()` call this monorepo makes to a remote
5
+ * service — see the 2026-08-16 Jini failure-mode audit, Finding 2: 101 raw `fetch()` call sites
6
+ * repo-wide (corrected from the audit's own initial "67" — re-count before trusting any figure in
7
+ * a handoff), across devops deploy providers, agent-runtime providers, media-provider dispatch,
8
+ * github-client, and llm-provider, most already protected in some ad hoc way. A remote that accepts
9
+ * the TCP connection but
10
+ * never responds — a stalled load balancer, a provider having a bad day, a firewall black-holing the
11
+ * request — leaves `await fetch(...)` unresolved forever; whatever awaits it hangs indefinitely, with
12
+ * nothing to alert on. A hang like that is worse than a crash: a crash is loud.
13
+ *
14
+ * Deliberately ONE helper, not 67 call sites each hand-rolling a slightly different
15
+ * `AbortController`/`setTimeout` idiom — a caller who already has their own `AbortSignal` (a
16
+ * user-initiated cancel, a parent request's own deadline) can still supply it via `init.signal`;
17
+ * `AbortSignal.any` composes it with the timeout so either one aborts the call, and the thrown
18
+ * `FetchTimeoutError` vs. the caller's own abort reason stay distinguishable (see `fetchWithTimeout`'s
19
+ * own doc).
20
+ *
21
+ * `FETCH_TIMEOUT_MS` gives call sites a small, documented, shared vocabulary instead of inventing a
22
+ * number each time — a deploy-provider API call, an image byte-fetch, and a large asset upload
23
+ * genuinely have different reasonable ceilings. `timeoutMs` is never hidden inside the helper as an
24
+ * undocumented default with no parameter, though: every call site names one explicitly (usually one
25
+ * of these constants), because a caller reading its own code should see the number, not have to go
26
+ * find it.
27
+ *
28
+ * Deliberately excludes anything meant to stay open for a long time independent of transfer size —
29
+ * Server-Sent Events, WebSockets, long-poll. None of the 67 flagged call sites are that shape (the
30
+ * audit traced this: the repo's real streaming transports are `EventSource` on the browser side and
31
+ * a hand-rolled SSE channel server-side, both entirely separate from `fetch()`), but a future caller
32
+ * reaching for this helper for one of those would be reaching for the wrong tool — `AbortSignal.timeout`
33
+ * bounds the WHOLE call, body included, so it would sever a deliberately long-lived stream partway
34
+ * through exactly like the bug this fixes, just self-inflicted instead of accidental.
35
+ *
36
+ * **Also exported as its own subpath, `@jini-ai/platform/fetch-with-timeout`, deliberately.** This
37
+ * module has zero imports of its own — no `node:*` builtin, no `undici` — unlike the package's root
38
+ * barrel (`index.ts`), which re-exports sibling modules (`process.ts`, `fs.ts`, `terminal.ts`,
39
+ * `asset-cache.ts`, …) that import `node:child_process`, `node:fs`, `undici`'s `Agent`, etc.
40
+ * Importing from the root barrel in browser-bundled code is silently fine in a *production* build
41
+ * through Vite/Rollup — tree-shaking (this package sets `sideEffects: false`) proves the Node-only
42
+ * re-exports are unused and drops them before the `node:*` imports are ever resolved — but it is
43
+ * NOT fine in `vite dev` or any other unbundled-native-ESM serving mode: there is no tree-shaking on
44
+ * that path, so the browser eagerly loads and evaluates every sibling the barrel re-exports, and
45
+ * `process.ts`'s very first statement destructures `execFile`/`spawn` off `node:child_process` —
46
+ * which Vite's dev server serves as a `Proxy` that throws on first property access. The whole module
47
+ * graph fails to evaluate the instant anything imports the barrel, regardless of which export is
48
+ * actually used. Verified empirically (`esbuild --bundle --platform=browser` on the barrel: 154
49
+ * resolution errors; `vite build`: clean, 5.92kB, zero Node-only code in the output; `vite dev`
50
+ * serving `index.js`: throws at import time) — see the 2026-08-17 Jini hardening report. Browser
51
+ * call sites should import from this subpath, never the root barrel.
52
+ */
53
+ /** Thrown in place of the platform's generic abort error specifically when the timeout — not a
54
+ * caller-supplied `init.signal` — is what ended the call, so a caller can tell "this took too long"
55
+ * apart from "I cancelled it myself" without string-matching an error message. */
56
+ export declare class FetchTimeoutError extends Error {
57
+ readonly url: string;
58
+ readonly timeoutMs: number;
59
+ constructor(url: string, timeoutMs: number);
60
+ }
61
+ /**
62
+ * Shared, documented timeout classes for outbound `fetch()` calls. Every call site names one
63
+ * explicitly (or its own justified number) rather than relying on an unstated default.
64
+ */
65
+ export declare const FETCH_TIMEOUT_MS: {
66
+ /** A single metadata/status/API-read call expected to return quickly: a model catalog listing, a
67
+ * connection test, a GitHub API read, an LLM provider's non-streaming completion call. */
68
+ readonly QUICK: 15000;
69
+ /** A deploy-provider API call that may involve real backend work on the provider's side — site
70
+ * creation, DNS record lookups, deployment status polling. */
71
+ readonly DEPLOY: 30000;
72
+ /** A large-payload transfer: an asset/blob upload, a generated-media byte fetch. */
73
+ readonly UPLOAD: 120000;
74
+ /** A media-generation API call whose response only arrives once the vendor has actually finished
75
+ * generating the image/video/audio server-side — routinely minutes, not seconds. Matches the
76
+ * value OpenAI's and OpenRouter's own image providers already hardcode locally
77
+ * (`OPENAI_IMAGE_*_TIMEOUT_MS`/`OPENROUTER_IMAGE_TIMEOUT_MS`); used as the shared dispatch-level
78
+ * backstop in `@jini-ai/integrations`' `dispatchVendorRequest` for every OTHER vendor that (as of
79
+ * 2026-08-16) sets no timeout of its own at all. Deliberately NOT the same as `UPLOAD`: a backstop
80
+ * shorter than a vendor's own already-correct 10-minute generation timeout would abort a
81
+ * legitimately still-generating request early. */
82
+ readonly GENERATE: number;
83
+ };
84
+ export interface FetchWithTimeoutOptions {
85
+ /** Milliseconds before the call is aborted. Pick one of {@link FETCH_TIMEOUT_MS}, or a specific
86
+ * justified number for a call site that doesn't fit those classes. */
87
+ timeoutMs: number;
88
+ }
89
+ /**
90
+ * `fetch`, but aborted after `options.timeoutMs` if it hasn't settled by then. If `init.signal` is
91
+ * already set, the call aborts on EITHER that signal or the timeout, via `AbortSignal.any` — a
92
+ * caller's own cancellation (e.g. a user-initiated cancel button) keeps working exactly as it did
93
+ * without this wrapper.
94
+ *
95
+ * @param url - Same as `fetch`'s first argument.
96
+ * @param init - Same as `fetch`'s second argument. `init.signal`, if present, is combined with the
97
+ * timeout rather than replaced.
98
+ * @param options - See {@link FetchWithTimeoutOptions}.
99
+ * @returns The same `Promise<Response>` `fetch` itself would return.
100
+ * @throws {@link FetchTimeoutError} if the timeout fires before the call settles and the caller's own
101
+ * `init.signal` (if any) did not itself already abort. Any other rejection (a caller's own abort, a
102
+ * genuine network error) propagates unchanged.
103
+ */
104
+ export declare function fetchWithTimeout(url: string | URL, init: RequestInit | undefined, options: FetchWithTimeoutOptions): Promise<Response>;
105
+ //# sourceMappingURL=fetch-with-timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-with-timeout.d.ts","sourceRoot":"","sources":["../src/fetch-with-timeout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH;;kFAEkF;AAClF,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM3C;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B;8FAC0F;;IAE1F;kEAC8D;;IAE9D,oFAAoF;;IAEpF;;;;;;;sDAOkD;;CAET,CAAC;AAE5C,MAAM,WAAW,uBAAuB;IACtC;0EACsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,EAAE,WAAW,YAAK,EACtB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,QAAQ,CAAC,CAgBnB"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * @module fetch-with-timeout
3
+ *
4
+ * The shared timeout wrapper for every outbound `fetch()` call this monorepo makes to a remote
5
+ * service — see the 2026-08-16 Jini failure-mode audit, Finding 2: 101 raw `fetch()` call sites
6
+ * repo-wide (corrected from the audit's own initial "67" — re-count before trusting any figure in
7
+ * a handoff), across devops deploy providers, agent-runtime providers, media-provider dispatch,
8
+ * github-client, and llm-provider, most already protected in some ad hoc way. A remote that accepts
9
+ * the TCP connection but
10
+ * never responds — a stalled load balancer, a provider having a bad day, a firewall black-holing the
11
+ * request — leaves `await fetch(...)` unresolved forever; whatever awaits it hangs indefinitely, with
12
+ * nothing to alert on. A hang like that is worse than a crash: a crash is loud.
13
+ *
14
+ * Deliberately ONE helper, not 67 call sites each hand-rolling a slightly different
15
+ * `AbortController`/`setTimeout` idiom — a caller who already has their own `AbortSignal` (a
16
+ * user-initiated cancel, a parent request's own deadline) can still supply it via `init.signal`;
17
+ * `AbortSignal.any` composes it with the timeout so either one aborts the call, and the thrown
18
+ * `FetchTimeoutError` vs. the caller's own abort reason stay distinguishable (see `fetchWithTimeout`'s
19
+ * own doc).
20
+ *
21
+ * `FETCH_TIMEOUT_MS` gives call sites a small, documented, shared vocabulary instead of inventing a
22
+ * number each time — a deploy-provider API call, an image byte-fetch, and a large asset upload
23
+ * genuinely have different reasonable ceilings. `timeoutMs` is never hidden inside the helper as an
24
+ * undocumented default with no parameter, though: every call site names one explicitly (usually one
25
+ * of these constants), because a caller reading its own code should see the number, not have to go
26
+ * find it.
27
+ *
28
+ * Deliberately excludes anything meant to stay open for a long time independent of transfer size —
29
+ * Server-Sent Events, WebSockets, long-poll. None of the 67 flagged call sites are that shape (the
30
+ * audit traced this: the repo's real streaming transports are `EventSource` on the browser side and
31
+ * a hand-rolled SSE channel server-side, both entirely separate from `fetch()`), but a future caller
32
+ * reaching for this helper for one of those would be reaching for the wrong tool — `AbortSignal.timeout`
33
+ * bounds the WHOLE call, body included, so it would sever a deliberately long-lived stream partway
34
+ * through exactly like the bug this fixes, just self-inflicted instead of accidental.
35
+ *
36
+ * **Also exported as its own subpath, `@jini-ai/platform/fetch-with-timeout`, deliberately.** This
37
+ * module has zero imports of its own — no `node:*` builtin, no `undici` — unlike the package's root
38
+ * barrel (`index.ts`), which re-exports sibling modules (`process.ts`, `fs.ts`, `terminal.ts`,
39
+ * `asset-cache.ts`, …) that import `node:child_process`, `node:fs`, `undici`'s `Agent`, etc.
40
+ * Importing from the root barrel in browser-bundled code is silently fine in a *production* build
41
+ * through Vite/Rollup — tree-shaking (this package sets `sideEffects: false`) proves the Node-only
42
+ * re-exports are unused and drops them before the `node:*` imports are ever resolved — but it is
43
+ * NOT fine in `vite dev` or any other unbundled-native-ESM serving mode: there is no tree-shaking on
44
+ * that path, so the browser eagerly loads and evaluates every sibling the barrel re-exports, and
45
+ * `process.ts`'s very first statement destructures `execFile`/`spawn` off `node:child_process` —
46
+ * which Vite's dev server serves as a `Proxy` that throws on first property access. The whole module
47
+ * graph fails to evaluate the instant anything imports the barrel, regardless of which export is
48
+ * actually used. Verified empirically (`esbuild --bundle --platform=browser` on the barrel: 154
49
+ * resolution errors; `vite build`: clean, 5.92kB, zero Node-only code in the output; `vite dev`
50
+ * serving `index.js`: throws at import time) — see the 2026-08-17 Jini hardening report. Browser
51
+ * call sites should import from this subpath, never the root barrel.
52
+ */
53
+ /** Thrown in place of the platform's generic abort error specifically when the timeout — not a
54
+ * caller-supplied `init.signal` — is what ended the call, so a caller can tell "this took too long"
55
+ * apart from "I cancelled it myself" without string-matching an error message. */
56
+ export class FetchTimeoutError extends Error {
57
+ url;
58
+ timeoutMs;
59
+ constructor(url, timeoutMs) {
60
+ super(`fetch timed out after ${timeoutMs}ms: ${url}`);
61
+ this.name = "FetchTimeoutError";
62
+ this.url = url;
63
+ this.timeoutMs = timeoutMs;
64
+ }
65
+ }
66
+ /**
67
+ * Shared, documented timeout classes for outbound `fetch()` calls. Every call site names one
68
+ * explicitly (or its own justified number) rather than relying on an unstated default.
69
+ */
70
+ export const FETCH_TIMEOUT_MS = {
71
+ /** A single metadata/status/API-read call expected to return quickly: a model catalog listing, a
72
+ * connection test, a GitHub API read, an LLM provider's non-streaming completion call. */
73
+ QUICK: 15_000,
74
+ /** A deploy-provider API call that may involve real backend work on the provider's side — site
75
+ * creation, DNS record lookups, deployment status polling. */
76
+ DEPLOY: 30_000,
77
+ /** A large-payload transfer: an asset/blob upload, a generated-media byte fetch. */
78
+ UPLOAD: 120_000,
79
+ /** A media-generation API call whose response only arrives once the vendor has actually finished
80
+ * generating the image/video/audio server-side — routinely minutes, not seconds. Matches the
81
+ * value OpenAI's and OpenRouter's own image providers already hardcode locally
82
+ * (`OPENAI_IMAGE_*_TIMEOUT_MS`/`OPENROUTER_IMAGE_TIMEOUT_MS`); used as the shared dispatch-level
83
+ * backstop in `@jini-ai/integrations`' `dispatchVendorRequest` for every OTHER vendor that (as of
84
+ * 2026-08-16) sets no timeout of its own at all. Deliberately NOT the same as `UPLOAD`: a backstop
85
+ * shorter than a vendor's own already-correct 10-minute generation timeout would abort a
86
+ * legitimately still-generating request early. */
87
+ GENERATE: 10 * 60_000,
88
+ };
89
+ /**
90
+ * `fetch`, but aborted after `options.timeoutMs` if it hasn't settled by then. If `init.signal` is
91
+ * already set, the call aborts on EITHER that signal or the timeout, via `AbortSignal.any` — a
92
+ * caller's own cancellation (e.g. a user-initiated cancel button) keeps working exactly as it did
93
+ * without this wrapper.
94
+ *
95
+ * @param url - Same as `fetch`'s first argument.
96
+ * @param init - Same as `fetch`'s second argument. `init.signal`, if present, is combined with the
97
+ * timeout rather than replaced.
98
+ * @param options - See {@link FetchWithTimeoutOptions}.
99
+ * @returns The same `Promise<Response>` `fetch` itself would return.
100
+ * @throws {@link FetchTimeoutError} if the timeout fires before the call settles and the caller's own
101
+ * `init.signal` (if any) did not itself already abort. Any other rejection (a caller's own abort, a
102
+ * genuine network error) propagates unchanged.
103
+ */
104
+ export async function fetchWithTimeout(url, init = {}, options) {
105
+ const { timeoutMs } = options;
106
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
107
+ const signal = init.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal;
108
+ try {
109
+ return await fetch(url, { ...init, signal });
110
+ }
111
+ catch (error) {
112
+ // `timeoutSignal` is the original object this function created, not the (possibly composed)
113
+ // signal handed to `fetch` — checking its own `.aborted` tells us specifically whether OUR
114
+ // timeout fired, independent of whether a caller-supplied signal also exists or also aborted.
115
+ if (timeoutSignal.aborted && !init.signal?.aborted) {
116
+ throw new FetchTimeoutError(String(url), timeoutMs);
117
+ }
118
+ throw error;
119
+ }
120
+ }
121
+ //# sourceMappingURL=fetch-with-timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-with-timeout.js","sourceRoot":"","sources":["../src/fetch-with-timeout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH;;kFAEkF;AAClF,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,GAAG,CAAS;IACZ,SAAS,CAAS;IAE3B,YAAY,GAAW,EAAE,SAAiB;QACxC,KAAK,CAAC,yBAAyB,SAAS,OAAO,GAAG,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B;8FAC0F;IAC1F,KAAK,EAAE,MAAM;IACb;kEAC8D;IAC9D,MAAM,EAAE,MAAM;IACd,oFAAoF;IACpF,MAAM,EAAE,OAAO;IACf;;;;;;;sDAOkD;IAClD,QAAQ,EAAE,EAAE,GAAG,MAAM;CACoB,CAAC;AAQ5C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAiB,EACjB,OAAoB,EAAE,EACtB,OAAgC;IAEhC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAE3F,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4FAA4F;QAC5F,2FAA2F;QAC3F,8FAA8F;QAC9F,IAAI,aAAa,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAiB,EAAE,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAc3G"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAiB,EAAE,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB3G"}
package/dist/http.js CHANGED
@@ -6,6 +6,7 @@
6
6
  * copy so it owns no cross-module runtime surface.
7
7
  */
8
8
  import { setTimeout as sleep } from "node:timers/promises";
9
+ import { fetchWithTimeout } from "./fetch-with-timeout.js";
9
10
  /** @internal Extract a human-readable message from an unknown thrown value. */
10
11
  function errorMessage(error) {
11
12
  return error instanceof Error ? error.message : String(error);
@@ -24,7 +25,15 @@ export async function waitForHttpOk(url, { timeoutMs = 20000 } = {}) {
24
25
  let lastError = null;
25
26
  while (Date.now() - startedAt < timeoutMs) {
26
27
  try {
27
- const response = await fetch(url, { cache: "no-store" });
28
+ // Each attempt gets its own bounded timeout — capped at what's left of the OVERALL
29
+ // `timeoutMs`, floored at 1ms so a caller who deliberately passes `timeoutMs: 0` still gets a
30
+ // schedulable (if immediately-expiring) signal rather than `AbortSignal.timeout(0)`'s
31
+ // undefined-ish edge behavior. Without this, a single stalled attempt could hang past the
32
+ // `timeoutMs` this function promises to the caller: the outer `while` can only re-check the
33
+ // clock once `await fetch(...)` itself returns, so an unbounded fetch call defeats the loop's
34
+ // own deadline exactly like Finding 2 of the 2026-08-16 audit describes.
35
+ const remaining = timeoutMs - (Date.now() - startedAt);
36
+ const response = await fetchWithTimeout(url, { cache: "no-store" }, { timeoutMs: Math.max(1, remaining) });
28
37
  if (response.ok)
29
38
  return true;
30
39
  lastError = new Error(`HTTP ${response.status} from ${url}`);
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAM3D,+EAA+E;AAC/E,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,EAAE,SAAS,GAAG,KAAK,KAAsB,EAAE;IAC1F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,SAAS,GAAiB,IAAI,CAAC;IACnC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;YACzD,IAAI,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAC7B,SAAS,GAAG,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/F,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAM3D,+EAA+E;AAC/E,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,EAAE,SAAS,GAAG,KAAK,KAAsB,EAAE;IAC1F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,SAAS,GAAiB,IAAI,CAAC;IACnC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,mFAAmF;YACnF,8FAA8F;YAC9F,sFAAsF;YACtF,0FAA0F;YAC1F,4FAA4F;YAC5F,8FAA8F;YAC9F,yEAAyE;YACzE,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;YAC3G,IAAI,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAC7B,SAAS,GAAG,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/F,CAAC"}
package/dist/index.d.ts CHANGED
@@ -9,6 +9,8 @@
9
9
  * - `proxy-env` — system proxy discovery and proxy-aware env merging.
10
10
  * - `fs` — filesystem containment, atomic copy, removal, log tails.
11
11
  * - `http` — HTTP readiness polling.
12
+ * - `fetch-with-timeout` — the shared `AbortSignal`-timeout wrapper every outbound `fetch()` call
13
+ * in this monorepo is meant to go through (2026-08-16 failure-mode audit, Finding 2).
12
14
  * - `toolchain` — user-level toolchain bin discovery.
13
15
  * - `asset-cache` — SSRF-safe same-origin cache/proxy for sandboxed content's
14
16
  * external media references.
@@ -37,6 +39,8 @@ export type { AtomicCopyFileOptions, AtomicCopyFileResult, RemovePathBestEffortO
37
39
  export { atomicCopyFile, pathContains, readLogTail, removePathBestEffort } from "./fs.js";
38
40
  export type { HttpWaitOptions } from "./http.js";
39
41
  export { waitForHttpOk } from "./http.js";
42
+ export type { FetchWithTimeoutOptions } from "./fetch-with-timeout.js";
43
+ export { FETCH_TIMEOUT_MS, FetchTimeoutError, fetchWithTimeout } from "./fetch-with-timeout.js";
40
44
  export type { WellKnownUserToolchainOptions } from "./toolchain.js";
41
45
  export { wellKnownUserToolchainBins } from "./toolchain.js";
42
46
  export type { BufferedCommandResult } from "./shell.js";
@@ -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
@@ -9,6 +9,8 @@
9
9
  * - `proxy-env` — system proxy discovery and proxy-aware env merging.
10
10
  * - `fs` — filesystem containment, atomic copy, removal, log tails.
11
11
  * - `http` — HTTP readiness polling.
12
+ * - `fetch-with-timeout` — the shared `AbortSignal`-timeout wrapper every outbound `fetch()` call
13
+ * in this monorepo is meant to go through (2026-08-16 failure-mode audit, Finding 2).
12
14
  * - `toolchain` — user-level toolchain bin discovery.
13
15
  * - `asset-cache` — SSRF-safe same-origin cache/proxy for sandboxed content's
14
16
  * external media references.
@@ -32,6 +34,7 @@ export { mergeProxyAwareEnv, parseMacosScutilProxyOutput, parseWindowsInternetSe
32
34
  export { collectProcessTreePids, createProcessStampArgs, isProcessAlive, listProcessSnapshots, matchesProcessStamp, matchesStampedProcess, readFlagValue, readProcessStamp, readProcessStampFromCommand, spawnBackgroundProcess, spawnLoggedProcess, stopProcesses, waitForProcessExit, } from "./process.js";
33
35
  export { atomicCopyFile, pathContains, readLogTail, removePathBestEffort } from "./fs.js";
34
36
  export { waitForHttpOk } from "./http.js";
37
+ export { FETCH_TIMEOUT_MS, FetchTimeoutError, fetchWithTimeout } from "./fetch-with-timeout.js";
35
38
  export { wellKnownUserToolchainBins } from "./toolchain.js";
36
39
  export { execCommandViaLoginShell, execFileBuffered } from "./shell.js";
37
40
  export { AssetCacheError, assertSafePublicUrl, assetCacheKey, assetCacheRewriteUrl, createAssetCache, createValidatingLookup, isCacheableExternalUrl, isPrivateAddress, } from "./asset-cache.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAGvF,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,uCAAuC,EACvC,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,2BAA2B,EAC3B,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAG1F,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAG5D,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGnF,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,mCAAmC,EACnC,oBAAoB,EACpB,2BAA2B,EAC3B,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,EACzB,2CAA2C,GAC5C,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EACL,oBAAoB,EACpB,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EACzB,cAAc,EACd,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAc7B,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAiB5H,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAGvF,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,uCAAuC,EACvC,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAWxB,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,2BAA2B,EAC3B,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAQtB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAG1F,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhG,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAG5D,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGnF,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,mCAAmC,EACnC,oBAAoB,EACpB,2BAA2B,EAC3B,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,EACzB,2CAA2C,GAC5C,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EACL,oBAAoB,EACpB,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EACzB,cAAc,EACd,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC;AAc7B,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAiB5H,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@jini-ai/platform",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
+ "description": "Generic OS/platform primitives: process exec and lifecycle, filesystem containment, HTTP readiness polling, toolchain discovery, blob storage, AWS signing, and an SSRF-safe asset cache.",
4
5
  "license": "Apache-2.0",
5
6
  "repository": {
6
7
  "type": "git",
@@ -10,10 +11,10 @@
10
11
  "jini": {
11
12
  "domain": "platform",
12
13
  "kind": "abstraction",
13
- "runtime": "node",
14
- "admission": "locked"
14
+ "runtime": "node"
15
15
  },
16
16
  "type": "module",
17
+ "sideEffects": false,
17
18
  "main": "./dist/index.js",
18
19
  "types": "./dist/index.d.ts",
19
20
  "exports": {
@@ -21,6 +22,11 @@
21
22
  "types": "./dist/index.d.ts",
22
23
  "import": "./dist/index.js",
23
24
  "default": "./dist/index.js"
25
+ },
26
+ "./fetch-with-timeout": {
27
+ "types": "./dist/fetch-with-timeout.d.ts",
28
+ "import": "./dist/fetch-with-timeout.js",
29
+ "default": "./dist/fetch-with-timeout.js"
24
30
  }
25
31
  },
26
32
  "files": [