feat(code): 新增通用 code 零件(sandbox inline JS)—— Arcrun#10 設計+PoC
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
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
canonical_id: "code"
|
||||
display_name: "程式碼(沙箱 inline JS)"
|
||||
category: "logic"
|
||||
version: "v1"
|
||||
wasi_target: "preview1"
|
||||
stability: "experimental"
|
||||
runtime_compat:
|
||||
- "cf-workers"
|
||||
- "workerd"
|
||||
constraints:
|
||||
max_size_kb: 2048
|
||||
max_cold_start_ms: 80
|
||||
no_network_syscall: true
|
||||
no_filesystem_syscall: true
|
||||
io_model: "stdin_stdout_json"
|
||||
# --- 沙箱資源上限(可被節點 config 的 limits 覆蓋,但不得放寬過硬上限)---
|
||||
sandbox_limits:
|
||||
timeout_ms: 1000
|
||||
memory_bytes: 16777216 # 16 MiB
|
||||
max_stack_bytes: 524288 # 512 KiB
|
||||
max_output_bytes: 1048576 # 1 MiB
|
||||
max_code_bytes: 262144 # 256 KiB
|
||||
input_schema:
|
||||
type: object
|
||||
required: [code]
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
description: "一段 inline JS(函式體)。可讀綁定的 `input`,以 `return` 回傳一個 JSON-able 值。碰不到網路/檔案/env/secret。"
|
||||
input:
|
||||
description: "上游資料(任意 JSON),在沙箱內綁為全域 `input`。"
|
||||
limits:
|
||||
type: object
|
||||
description: "選填,覆蓋預設資源上限(不得超過契約 sandbox_limits 硬上限)。"
|
||||
properties:
|
||||
timeout_ms: { type: number }
|
||||
memory_bytes: { type: number }
|
||||
max_output_bytes: { type: number }
|
||||
output_schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
data:
|
||||
description: "user code 的回傳值(success=true 時)。"
|
||||
error:
|
||||
type: string
|
||||
description: "success=false 時的錯誤訊息。"
|
||||
error_type:
|
||||
type: string
|
||||
enum: [UserCodeError, TimeoutError, ResourceError, ContractError, SandboxError]
|
||||
gherkin_tests:
|
||||
- scenario: "基本 sum"
|
||||
given: '{"code":"return {sum: input.a + input.b};","input":{"a":2,"b":40}}'
|
||||
then_contains: '"sum":42'
|
||||
- scenario: "沙箱隔離:碰不到 fetch"
|
||||
given: '{"code":"return typeof fetch;","input":{}}'
|
||||
then_contains: '"data":"undefined"'
|
||||
- scenario: "user code 拋錯 → 結構化 error"
|
||||
given: '{"code":"throw new Error(\"boom\");","input":{}}'
|
||||
then_contains: '"success":false'
|
||||
tags: [builtin, logic, code, sandbox, javascript, escape-hatch]
|
||||
description: >
|
||||
通用「程式碼逃生口」。跑一段 sandbox inline JS(n8n Code node 式):
|
||||
config 帶 `code`(inline JS 函式體),stdin 帶 `input`(上游 JSON),
|
||||
stdout 回 `{success, data}` 或 `{success:false, error, error_type}`。
|
||||
user code 在 QuickJS-wasm 沙箱內執行,只有純 ECMAScript 內建 + host 明確注入的
|
||||
curated builtin(目前:純函式 sha256),碰不到網路/檔案/env/secret/Worker 物件圖。
|
||||
用於一次性/小段程式邏輯(如卡片→envelope 文字處理),避免各自鑄 domain 零件。
|
||||
config_example: |
|
||||
my_code: # 節點名稱(可自訂)
|
||||
code: | # inline JS 函式體(必填);讀 input、return 一個 JSON-able 值
|
||||
const doubled = input.items.map(x => x * 2);
|
||||
return { doubled, count: doubled.length };
|
||||
input: # 上游資料(選填;workflow 可用引用注入)
|
||||
items: [1, 2, 3]
|
||||
limits: # 資源上限覆蓋(選填)
|
||||
timeout_ms: 2000
|
||||
Reference in New Issue
Block a user