60f5f10ba5
n8n Code node 式逃生口:config 帶 inline JS、stdin 帶 input JSON、
stdout 回 {success,data}|{success:false,error,error_type}。
沙箱=QuickJS-wasm:user JS 跑在 QuickJS context,global 只有純 ECMAScript
內建 + 唯一 curated builtin sha256(純函式);碰不到網路/檔案/env/secret/
Worker 物件圖。資源上限:timeout(interrupt)/memory/stack/output/code size。
本輪=設計+PoC,未部署 leo21c。sandbox.mjs + test/ 為 Node/vitest 可跑實作
(12 測試全綠,含 card→envelope 與原模組 planCard 逐欄全等)。index.ts 為
Worker host 骨架、DESIGN.md 記錄機制/安全性質/生產路徑/設計岔路(A/B)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJiLCRUU2o3aSpPEzVCt2o
48 lines
2.0 KiB
TypeScript
48 lines
2.0 KiB
TypeScript
/**
|
||
* arcrun `code` 零件 —— Worker host(骨架,尚未部署驗證)
|
||
*
|
||
* POST / → { code, input, limits? } → QuickJS-wasm 沙箱 → { success, data } | { success:false, error, error_type }
|
||
*
|
||
* 與其他 logic 零件的差異:
|
||
* - 其他零件 = 一顆「arcrun 自建 TinyGo→wasm」,靜態 bundle 進 Worker([[wasm_modules]]),
|
||
* 跑在 component-worker-template 的 WASI-preview1 shim 上。
|
||
* - `code` 零件 = 載入「QuickJS(JS 直譯器)編成的 wasm」,把 user 的 inline JS 當「資料」
|
||
* 餵進去跑。QuickJS 的 wasm 由 quickjs-emscripten 提供(有 Cloudflare Workers 相容 variant)。
|
||
*
|
||
* ⚠️ 此檔為設計骨架。PoC 的可執行 + 受測實作在 ./sandbox.mjs(Node/vitest 綠燈)。
|
||
* live 化差異見 DESIGN.md「② 生產路徑」與「curated builtins(sha256)」。
|
||
*/
|
||
|
||
import { Hono } from 'hono';
|
||
import { cors } from 'hono/cors';
|
||
import { getQuickJS } from 'quickjs-emscripten';
|
||
|
||
const app = new Hono();
|
||
app.use('*', cors());
|
||
app.get('/', (c) => c.json({ ok: true, component: 'code' }));
|
||
|
||
app.post('/', async (c) => {
|
||
let body: { code?: unknown; input?: unknown; limits?: Record<string, number> };
|
||
try {
|
||
body = await c.req.json();
|
||
} catch {
|
||
return c.json({ success: false, error: 'request body must be JSON', error_type: 'ContractError' }, 400);
|
||
}
|
||
// runCode 語義與簽章同 ./sandbox.mjs(PoC 已受測)。生產版把 sha256 curated builtin
|
||
// 換成「純 JS SHA-256 prelude」(無 host call、Node/Worker 皆決定性),見 DESIGN.md。
|
||
const result = await runCodeInWorker(String(body.code ?? ''), body.input, body.limits);
|
||
return c.json(result);
|
||
});
|
||
|
||
export default app;
|
||
|
||
// 生產實作(待補:把 sandbox.mjs 的 runCode 移植成 Worker 版)。
|
||
declare function runCodeInWorker(
|
||
code: string,
|
||
input: unknown,
|
||
limits?: Record<string, number>,
|
||
): Promise<unknown>;
|
||
|
||
// 保留 import 以標示相依(bundler 不 tree-shake 掉):
|
||
void getQuickJS;
|