UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

93 lines (92 loc) 4.03 kB
import { u as openLocalFileSafely } from "./fs-safe-B6pvPGnf.js"; import { i as registerSecretValueForRedaction } from "./secret-redaction-registry-BOLC6DkF.js"; import { i as generateSecureToken } from "./secure-random-Ds4AFLgz.js"; import "./worker-bundle-limits-CF239rpc.js"; //#region src/gateway/worker-environments/artifact-transfer-service.ts const TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/u; const SHA256_PATTERN = /^[a-f0-9]{64}$/u; function createArtifactTransferService(options = {}) { const now = options.now ?? Date.now; const generateToken = options.generateToken ?? generateSecureToken; const capabilities = /* @__PURE__ */ new Map(); const revokeCapability = (capability) => { if (capabilities.get(capability.token) === capability) capabilities.delete(capability.token); capability.stopWatching?.(); capability.abortController.abort(/* @__PURE__ */ new Error("Worker artifact transfer authority closed")); }; const hasAuthority = (capability) => { try { if (capabilities.get(capability.token) === capability && capability.expiresAtMs > now() && !capability.abortController.signal.aborted && capability.isAuthorized()) return true; } catch {} revokeCapability(capability); return false; }; const isCurrent = (capability) => hasAuthority(capability) && capability.state === "serving"; return { prepare(params) { if (!Number.isSafeInteger(params.artifact.tarballBytes) || params.artifact.tarballBytes < 1 || params.artifact.tarballBytes > 536870912 || !SHA256_PATTERN.test(params.artifact.tarballSha256) || !SHA256_PATTERN.test(params.artifactKey)) throw new Error("Worker artifact archive is invalid or exceeds the transfer limit"); const token = generateToken(32); if (!TOKEN_PATTERN.test(token) || capabilities.has(token)) throw new Error("Worker artifact transfer token generator returned an invalid bearer"); registerSecretValueForRedaction(token); const capability = { token, artifactKey: params.artifactKey, artifact: { ...params.artifact }, expiresAtMs: now() + params.ttlMs, state: "ready", abortController: new AbortController(), isAuthorized: params.isAuthorized }; capabilities.set(token, capability); const revoke = () => revokeCapability(capability); const timeout = setTimeout(revoke, params.ttlMs); timeout.unref(); params.signal?.addEventListener("abort", revoke, { once: true }); capability.stopWatching = () => { clearTimeout(timeout); params.signal?.removeEventListener("abort", revoke); }; if (params.signal?.aborted) revoke(); if (!hasAuthority(capability)) throw new Error("Worker artifact transfer authority is unavailable"); return { token, expiresAtMs: capability.expiresAtMs }; }, authorize(params) { const capability = capabilities.get(params.token); if (!capability || !hasAuthority(capability) || capability.state !== "ready" || capability.artifactKey !== params.artifactKey) return; capability.state = "serving"; return capability; }, isAuthorizationCurrent: isCurrent, authorizationSignal(capability) { return capability.abortController.signal; }, async openFile(capability) { if (!isCurrent(capability)) return null; const { handle, stat } = await openLocalFileSafely({ filePath: capability.artifact.tarballPath }); let accepted = false; try { if (stat.size !== capability.artifact.tarballBytes || !isCurrent(capability)) return null; accepted = true; return { handle, bytes: capability.artifact.tarballBytes, sha256: capability.artifact.tarballSha256 }; } finally { if (!accepted) await handle.close(); } }, revoke(capabilityOrToken) { const capability = typeof capabilityOrToken === "string" ? capabilities.get(capabilityOrToken) : capabilityOrToken; if (capability) revokeCapability(capability); }, closeAll() { for (const capability of capabilities.values()) revokeCapability(capability); } }; } //#endregion export { createArtifactTransferService as t };