2707fca32b
Phase 1-5 complete per .agents/specs/u6u-core-mvp/: **Phase 1 — Cherry-pick & cleanup** - Create arcrun/ from cypher-executor, credentials, builtins, registry - Remove 9 InkStone Service Bindings (KBDB, REGISTRY, CLINIC_*, AICEO, MINI_ME) - Rewrite component-loader: 3-layer (builtin → WASM_BUCKET R2 → error) - Remove autoPublishMissing.ts, proxy.ts (AICEO), execution-logger.ts (KBDB) - Clean all KV namespace IDs and InkStone internal URLs from config files **Phase 2 — contract.yaml completeness** - Add credentials_required to gmail, google_sheets, telegram, line_notify - Add config_example to all 21 components with annotated field descriptions **Phase 3 — Credential injection** - Add credential-injector.ts: AES-GCM decrypt from CREDENTIALS_KV - Integrate into GraphExecutor before WASM execution - Structured errors with repair instructions when credential missing **Phase 4 — CLI (acr)** - cli/package.json: arcrun package, bin: acr, deps: commander/js-yaml/chalk/ora - 8 commands: init, creds push, push, run, validate, parts, list, logs - Standard mode: writes directly to user's CF KV via CF REST API - acr init: interactive setup with arcrun.dev API Key registration **Phase 5 — Open source release prep** - README.md: 5-minute quickstart, component table, workflow YAML syntax - CONTRIBUTING.md: TinyGo dev env, component scaffolding, submission flow - Security audit: no InkStone internal URLs/IDs in committed files - .gitignore: exclude credentials.yaml, .wrangler, *.wasm https://claude.ai/code/session_01BnCdSLVH8tUed9VrrPavgT
100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
// Component Registry Worker 型別定義
|
||
|
||
import { z } from 'zod';
|
||
|
||
// ── Cloudflare Bindings ──────────────────────────────────────────────────────
|
||
|
||
export type Bindings = {
|
||
WASM_BUCKET: R2Bucket;
|
||
AI: Ai;
|
||
KBDB_URL: string;
|
||
KBDB_INTERNAL_TOKEN: string;
|
||
ENVIRONMENT: string;
|
||
};
|
||
|
||
// ── Component Contract Schema(Zod)─────────────────────────────────────────
|
||
|
||
export const ConstraintsSchema = z.object({
|
||
max_size_kb: z.number().positive().max(2048),
|
||
max_cold_start_ms: z.number().positive().max(50),
|
||
no_network_syscall: z.boolean(),
|
||
io_model: z.literal('stdin_stdout_json'),
|
||
});
|
||
|
||
export const GherkinTestSchema = z.object({
|
||
scenario: z.string().min(1),
|
||
given: z.string().min(1),
|
||
then_contains: z.string().min(1),
|
||
});
|
||
|
||
export const ComponentContractSchema = z.object({
|
||
canonical_id: z.string().min(1).regex(/^[a-z][a-z0-9_]*$/, 'canonical_id 必須為小寫底線格式'),
|
||
display_name: z.string().min(1),
|
||
category: z.enum(['logic', 'api', 'ui', 'style', 'anim']),
|
||
version: z.string().min(1).regex(/^v\d+$/, 'version 格式必須為 vN'),
|
||
wasi_target: z.literal('preview1'),
|
||
stability: z.enum(['floating', 'stable', 'pinned']),
|
||
runtime_compat: z.array(z.enum(['cf-workers', 'workerd', 'wazero'])).min(1),
|
||
constraints: ConstraintsSchema,
|
||
input_schema: z.record(z.unknown()),
|
||
output_schema: z.record(z.unknown()),
|
||
gherkin_tests: z.array(GherkinTestSchema).min(2, '至少需要一個 happy path 和一個 error path'),
|
||
// 選填欄位
|
||
component_type: z.enum(['wasm', 'service_binding']).optional(),
|
||
max_size_kb: z.number().optional(),
|
||
max_cold_start_ms: z.number().optional(),
|
||
no_network_syscall: z.boolean().optional(),
|
||
service_binding_key: z.string().optional(),
|
||
description: z.string().optional(),
|
||
tags: z.array(z.string()).optional(),
|
||
});
|
||
|
||
export type ComponentContract = z.infer<typeof ComponentContractSchema>;
|
||
|
||
// ── 沙盒驗收步驟 ─────────────────────────────────────────────────────────────
|
||
|
||
export type SandboxStep = 'size_check' | 'cold_start' | 'syscall_scan' | 'gherkin_tests' | 'runtime_compat';
|
||
|
||
export interface SandboxResult {
|
||
success: boolean;
|
||
failed_step?: SandboxStep;
|
||
reason?: string;
|
||
guide_anchor?: string;
|
||
component_id: string;
|
||
version: string;
|
||
}
|
||
|
||
// ── KBDB Block 格式 ──────────────────────────────────────────────────────────
|
||
|
||
export interface KbdbBlock {
|
||
block_id: string;
|
||
template_id: string;
|
||
user_id?: string;
|
||
page_name?: string;
|
||
}
|
||
|
||
export interface KbdbSlots {
|
||
[key: string]: string;
|
||
}
|
||
|
||
// ── 禁止的 WASM syscall(網路 + 檔案系統)────────────────────────────────────
|
||
|
||
export const FORBIDDEN_SYSCALLS = [
|
||
'sock_connect',
|
||
'sock_accept',
|
||
'sock_recv',
|
||
'sock_send',
|
||
'sock_shutdown',
|
||
'fd_open',
|
||
'path_open',
|
||
'path_create_directory',
|
||
'path_remove_directory',
|
||
'path_rename',
|
||
'path_unlink_file',
|
||
'path_filestat_get',
|
||
'path_filestat_set_times',
|
||
'path_link',
|
||
'path_readlink',
|
||
'path_symlink',
|
||
] as const;
|