[總管交辦] 新增通用 code 零件(n8n Code node 式 sandbox inline JS)——一次性程式邏輯逃生口,不再鑄 domain 零件 #10

Closed
opened 2026-07-06 04:14:27 +00:00 by Leo · 4 comments
Owner

[總管交辦] 新增 arcrun 平台原語:通用 code 零件(n8n Code node 式,sandbox inline JS)。leo 2026-07-06 拍板。

為什麼

  • 一次性 / 小段程式邏輯(如「卡片 markdown → envelope」文字處理)不該各自鑄 domain 零件(domain 零件要 PR、進共用詞彙表、只有它自己用)。應有一個通用逃生口:把小段程式寫進一個 code 節點的 config。
  • 不是安全上刻意不給,是草創還沒建;n8n 的 Code node 已驗證此模式。用戶是很會寫程式的 AI、且這類 inline 程式很小好 debug。補一次、所有未來一次性邏輯共用,不再鑄 domain 零件。
  • 直接起因:Arcrun#8 的 km_wiki_card_parse(domain 零件)被否——改由本 code 零件承載其解析邏輯。

要做

通用 code 零件(比照現有 component.contract.yaml 慣例):

  • 輸入:inline JS 程式碼(config)+ stdin JSON。輸出:stdout JSON。(stdin_stdout_json,同現有零件模型。)
  • 沙箱(工程 crux):Worker 裡不能直接 eval 任意 JS(會拿到 Worker 環境)。標準解=QuickJS 編成 wasm(JS 直譯器跑 wasm 沙箱),合 arcrun 現有 wazero/workerd wasm 模型 + no_network/no_filesystem_syscall 契約:user code 只能 stdin→stdout、碰不到網路/檔案/secret/env。subagent 確認並設計此沙箱、回報設計待審。
  • 資源限制:執行 timeout、記憶體上限、輸出大小上限(防跑飛)。
  • 錯誤處理:user code 拋錯 → 回結構化 {error} envelope,不讓 Worker 掛。

首個消費者

km_wiki_ingest_drain workflow(Arcrun#8):card→envelope 解析改成本 code 節點的內聯程式(直接沿用 subagent 已寫的 card-to-envelope.mjs 邏輯),workflow 其餘用現成零件(cron/http_request/foreach)。丟掉 km_wiki_card_parse

部署 / 閘

  • wrangler 直推 leo21c(禁 acr update)。**對 live 部署前,總管會與 leo 過寫入/部署閘。**先設計+雛型+單測(不部署)。

對齊

守 arcrun typed-ops 的安全模型(沙箱、無 ambient 能力);保持 registry 乾淨(一個通用逃生口 vs domain 零件增生)。完整脈絡見頂層 SDD kb-ingest-architecture

[總管] 2026-07-06

[總管交辦] 新增 arcrun 平台原語:通用 **`code` 零件**(n8n Code node 式,sandbox inline JS)。leo 2026-07-06 拍板。 ## 為什麼 - 一次性 / 小段程式邏輯(如「卡片 markdown → envelope」文字處理)**不該各自鑄 domain 零件**(domain 零件要 PR、進共用詞彙表、只有它自己用)。應有一個**通用逃生口**:把小段程式寫進一個 `code` 節點的 config。 - 不是安全上刻意不給,是草創還沒建;n8n 的 Code node 已驗證此模式。用戶是很會寫程式的 AI、且這類 inline 程式很小好 debug。補一次、所有未來一次性邏輯共用,不再鑄 domain 零件。 - 直接起因:Arcrun#8 的 `km_wiki_card_parse`(domain 零件)被否——改由本 `code` 零件承載其解析邏輯。 ## 要做 通用 `code` 零件(比照現有 `component.contract.yaml` 慣例): - **輸入**:inline JS 程式碼(config)+ stdin JSON。**輸出**:stdout JSON。(`stdin_stdout_json`,同現有零件模型。) - **沙箱(工程 crux)**:Worker 裡不能直接 `eval` 任意 JS(會拿到 Worker 環境)。標準解=**QuickJS 編成 wasm**(JS 直譯器跑 wasm 沙箱),合 arcrun 現有 wazero/workerd wasm 模型 + `no_network`/`no_filesystem_syscall` 契約:user code 只能 stdin→stdout、碰不到網路/檔案/secret/env。**subagent 確認並設計此沙箱、回報設計待審。** - **資源限制**:執行 timeout、記憶體上限、輸出大小上限(防跑飛)。 - **錯誤處理**:user code 拋錯 → 回結構化 `{error}` envelope,不讓 Worker 掛。 ## 首個消費者 `km_wiki_ingest_drain` workflow(Arcrun#8):card→envelope 解析改成本 `code` 節點的內聯程式(直接沿用 subagent 已寫的 `card-to-envelope.mjs` 邏輯),workflow 其餘用現成零件(cron/http_request/foreach)。丟掉 `km_wiki_card_parse`。 ## 部署 / 閘 - wrangler 直推 leo21c(禁 acr update)。**對 live 部署前,總管會與 leo 過寫入/部署閘。**先設計+雛型+單測(不部署)。 ## 對齊 守 arcrun typed-ops 的安全模型(沙箱、無 ambient 能力);保持 registry 乾淨(一個通用逃生口 vs domain 零件增生)。完整脈絡見頂層 SDD `kb-ingest-architecture`。 _[總管] 2026-07-06_
Author
Owner

[總管] 設計+PoC 完成(未部署)

runtime 真相:一零件=一 Worker;host(TS)只認「WASI-preview1 + stdin/stdout JSON」、與 guest 語言無關 → 載 QuickJS-wasm ≈ 載 TinyGo-wasm。no_network/no_fs=host 不給 import(ENOSYS)=建構保證,非 guest 自律。

沙箱:QuickJS-wasm 三層(Worker isolate → QuickJS wasm 線性記憶體 → JS context 只有純 ECMAScript → user code)。無 ambient 能力;唯一 curated builtin=sha256(純函式);資源限制 timeout/mem/stack/輸出/code 皆有上限;錯誤結構化分型。

PoC:分支 feat/issue-10-code-component(未碰 main/GitHub、未部署)。registry/components/code/(contract/sandbox.mjs/index.ts/DESIGN.md/test)。單測 12/12 綠,含 card→envelope:沙箱輸出與原 planCard 逐欄全等(content_hash 逐字相同)→ 可丟 km_wiki_card_parse

封裝裁定(總管)=Aquickjs-emscripten(Workers variant)直接用——已驗證、可立即上。B(wasi-sdk 自建 QuickJS 走現有 shim、最同構)本環境無工具鏈,列後續技術債。

待 live:① sha256 改純 JS SHA-256 prelude 字串注入(Worker Web Crypto 是 async 不合同步 host-call)② runCode 移植 index.ts Worker 版 ③ register + wrangler 部署 leo21c=leo 部署/寫入閘

**[總管] 設計+PoC 完成(未部署)** **runtime 真相**:一零件=一 Worker;host(TS)只認「WASI-preview1 + stdin/stdout JSON」、**與 guest 語言無關** → 載 QuickJS-wasm ≈ 載 TinyGo-wasm。`no_network/no_fs`=host 不給 import(ENOSYS)=建構保證,非 guest 自律。 **沙箱**:QuickJS-wasm 三層(Worker isolate → QuickJS wasm 線性記憶體 → JS context 只有純 ECMAScript → user code)。無 ambient 能力;唯一 curated builtin=`sha256`(純函式);資源限制 timeout/mem/stack/輸出/code 皆有上限;錯誤結構化分型。 **PoC**:分支 `feat/issue-10-code-component`(未碰 main/GitHub、未部署)。`registry/components/code/`(contract/sandbox.mjs/index.ts/DESIGN.md/test)。**單測 12/12 綠**,含 **card→envelope:沙箱輸出與原 `planCard` 逐欄全等(content_hash 逐字相同)→ 可丟 `km_wiki_card_parse`**。 **封裝裁定(總管)=A**:`quickjs-emscripten`(Workers variant)直接用——已驗證、可立即上。B(wasi-sdk 自建 QuickJS 走現有 shim、最同構)本環境無工具鏈,列後續技術債。 **待 live**:① sha256 改純 JS SHA-256 prelude 字串注入(Worker Web Crypto 是 async 不合同步 host-call)② runCode 移植 index.ts Worker 版 ③ register + wrangler 部署 leo21c=**leo 部署/寫入閘**。
Author
Owner

[總管] Workers 就緒(未部署) — 分支 feat/issue-10-code-component(HEAD 1a7b463)。

  • 沙箱=@jitl/quickjs-singlefile-mjs-release-sync(wasm 內嵌、同步、CF Workers 相容,免 [[wasm_modules]]/nodejs_compat)。
  • sha256=純 JS SHA-256 prelude 字串注入(無 async Web Crypto host-call),與 Node crypto 逐字等價。
  • index.ts=可部署 Hono Worker host;補 wrangler.toml(arcrun-code/code.arcrun.dev)、DEPLOY.md;contract 過 registry zod。
  • 單測 12/12 綠(含 card→envelope 與原 planCard 逐欄全等)。封裝裁 A;B(wasi-sdk)本環境無工具鏈、列技術債。
  • 待 live 部署=leo 部署閘。
**[總管] Workers 就緒(未部署)** — 分支 `feat/issue-10-code-component`(HEAD `1a7b463`)。 - 沙箱=`@jitl/quickjs-singlefile-mjs-release-sync`(wasm 內嵌、同步、CF Workers 相容,免 `[[wasm_modules]]`/`nodejs_compat`)。 - `sha256`=純 JS SHA-256 prelude 字串注入(無 async Web Crypto host-call),與 Node crypto 逐字等價。 - `index.ts`=可部署 Hono Worker host;補 wrangler.toml(`arcrun-code`/`code.arcrun.dev`)、DEPLOY.md;contract 過 registry zod。 - **單測 12/12 綠**(含 card→envelope 與原 planCard 逐欄全等)。封裝裁 A;B(wasi-sdk)本環境無工具鏈、列技術債。 - **待 live 部署=leo 部署閘。**
Author
Owner

[總管] 部署 leo21c 成功、live 驗過

  • live:arcrun-code.leo21c.workers.dev(Version a2cedb17),註冊 cmp_5694d08a(HTTP 201)。
  • 實部署修好 2 個 CF 生產限制:① CF 禁 runtime 從 bytes 編 wasm → 改 wasmfile variant + vendored .wasm(CompiledWasm Module)+ newVariant 注入 ② CF 凍結同步 Date.now() → timeout 改 指令計數 interrupt(max_ticks)。commit 08a7922
  • live 冒煙:sum:42 ✓、isolation(fetch=undefined) ✓、timeout→結構化 TimeoutError ✓、sha256("abc") 正確 ✓。
  • 分支就緒可 merge main。
**[總管] ✅ 部署 leo21c 成功、live 驗過** - live:`arcrun-code.leo21c.workers.dev`(Version `a2cedb17`),註冊 `cmp_5694d08a`(HTTP 201)。 - 實部署修好 2 個 CF 生產限制:① CF 禁 runtime 從 bytes 編 wasm → 改 **wasmfile variant + vendored `.wasm`(CompiledWasm Module)+ `newVariant` 注入** ② CF 凍結同步 `Date.now()` → timeout 改 **指令計數 interrupt(max_ticks)**。commit `08a7922`。 - live 冒煙:sum:42 ✓、isolation(fetch=undefined) ✓、timeout→結構化 TimeoutError ✓、sha256("abc") 正確 ✓。 - 分支就緒可 merge main。
Author
Owner

08-01 複核: 已完成,關閉

證據(源碼實查)

  • registry/components/code/ 存在於 gitea/main(非分支)
  • component.contract.yaml 齊備:canonical_id: codeio_model: stdin_stdout_jsonno_network_syscall: trueno_filesystem_syscall: true,且有 sandbox_limits(timeout_ms 1000/memory 16MiB/max_stack 512KiB)——issue 要求的沙箱+資源限制+無 ambient 能力全部落地
  • code 已在 20 顆現役零件清單內(見 #76 body 的 prod /cypher/search 逐顆實測列表)

通用逃生口已建成,km_wiki_card_parse 這類 domain 零件增生問題按設計解掉。

## 08-01 複核:✅ 已完成,關閉 **證據(源碼實查)**: - `registry/components/code/` 存在於 **gitea/main**(非分支) - `component.contract.yaml` 齊備:`canonical_id: code`、`io_model: stdin_stdout_json`、`no_network_syscall: true`、`no_filesystem_syscall: true`,且有 `sandbox_limits`(timeout_ms 1000/memory 16MiB/max_stack 512KiB)——issue 要求的沙箱+資源限制+無 ambient 能力全部落地 - `code` 已在 20 顆現役零件清單內(見 #76 body 的 prod `/cypher/search` 逐顆實測列表) 通用逃生口已建成,`km_wiki_card_parse` 這類 domain 零件增生問題按設計解掉。
Leo closed this issue 2026-07-31 10:21:38 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Leo/Arcrun#10