// 沙盒驗收流程:五個步驟依序執行 // Requirements: 2.1, 2.2, 2.3 import { FORBIDDEN_SYSCALLS } from '../types'; import type { ComponentContract, SandboxResult, SandboxStep } from '../types'; // ── 步驟 (a):體積檢查 ──────────────────────────────────────────────────────── function checkSize(wasmBytes: Uint8Array, contract: ComponentContract): string | null { const maxSizeKb = contract.constraints.max_size_kb; const actualKb = wasmBytes.byteLength / 1024; if (actualKb > maxSizeKb) { return `體積 ${actualKb.toFixed(1)}KB 超過上限 ${maxSizeKb}KB`; } return null; } // ── 步驟 (b):冷啟動時間(Phase 0 mock 0ms)──────────────────────────────────── function checkColdStart(_wasmBytes: Uint8Array, _contract: ComponentContract): string | null { // Phase 0:mock 通過,記錄 0ms // Phase 2 再實作真實測量 return null; } // ── 步驟 (c):syscall 掃描 ──────────────────────────────────────────────────── function scanSyscalls(wasmBytes: Uint8Array): string | null { // 將 .wasm binary 轉為文字,搜尋禁止的 import 字串 // WASM binary 中 import section 的函數名稱以 UTF-8 字串形式存在 const text = new TextDecoder('utf-8', { fatal: false }).decode(wasmBytes); for (const syscall of FORBIDDEN_SYSCALLS) { if (text.includes(syscall)) { return `發現禁止的 syscall:${syscall}`; } } return null; } // ── 步驟 (d):Gherkin 測試(Phase 0 mock 通過)──────────────────────────────── function runGherkinTests(_wasmBytes: Uint8Array, _contract: ComponentContract): string | null { // Phase 0:mock 通過 // Phase 1 再實作真實 Gherkin 執行 return null; } // ── 步驟 (e):runtime 相容測試(Phase 0 mock 通過)──────────────────────────── function checkRuntimeCompat(_wasmBytes: Uint8Array, _contract: ComponentContract): string | null { // Phase 0:mock 通過 // Phase 2 再實作真實多 runtime 測試 return null; } // ── 主流程 ──────────────────────────────────────────────────────────────────── interface StepDef { name: SandboxStep; run: (wasmBytes: Uint8Array, contract: ComponentContract) => string | null; guideAnchor: string; } const STEPS: StepDef[] = [ { name: 'size_check', run: checkSize, guideAnchor: '#common-errors' }, { name: 'cold_start', run: checkColdStart, guideAnchor: '#common-errors' }, { name: 'syscall_scan', run: scanSyscalls, guideAnchor: '#syscall-constraints' }, { name: 'gherkin_tests', run: runGherkinTests, guideAnchor: '#local-testing' }, { name: 'runtime_compat', run: checkRuntimeCompat, guideAnchor: '#contract-example' }, ]; export function runSandboxAcceptance( wasmBytes: Uint8Array, contract: ComponentContract, ): SandboxResult { for (const step of STEPS) { const error = step.run(wasmBytes, contract); if (error !== null) { return { success: false, failed_step: step.name, reason: error, guide_anchor: step.guideAnchor, component_id: contract.canonical_id, version: contract.version, }; } } return { success: true, component_id: contract.canonical_id, version: contract.version, }; }