feat(registry): component_hash_id — stable id system for workflow references
Problem: canonical_id is readable but mutable; if a component is renamed,
all workflows referencing it by canonical_id break.
Solution: dual-id system
- component_hash_id: cmp_{sha256(canonical_id).slice(0,8)}, derived deterministically,
never changes, safe for workflow references
- canonical_id: human-readable name, used for search and display
- idx:{canonical_id} KV key: reverse-lookup index for resolving canonical_id → hash_id
Changes:
- types.ts: SandboxResult.component_id → component_hash_id + canonical_id,
added 'data' to category enum
- submitComponent.ts: deriveHashId(), writes idx: reverse-lookup on submit
- queryComponents.ts: full rewrite — removed KBDB dependency, uses SUBMISSIONS_KV;
supports both cmp_* and canonical_id as query id; Phase 0 keyword search
with note to upgrade to Vectorize in Phase 2
- sandboxAcceptance.ts: updated field names, fixed TextDecoder TS type
- ensureTemplate.ts: removed KBDB dependency, now a KV health check
- tests: updated component_id → canonical_id
- CONTRIBUTING.md: explain hash_id derivation and dual-id workflow reference syntax
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+12
-4
@@ -7,8 +7,11 @@ import { z } from 'zod';
|
||||
export type Bindings = {
|
||||
WASM_BUCKET: R2Bucket;
|
||||
AI: Ai;
|
||||
SUBMISSIONS_KV: KVNamespace; // 零件元數據 + 可見性狀態(key = comp:{id}:{version})
|
||||
ANALYTICS_KV: KVNamespace; // 執行統計匯總(key = stats:{id}:{version})
|
||||
// KV key 格式:
|
||||
// comp:{hash_id}:{version} → 零件元數據(hash_id = cmp_ + sha256 前 8 碼)
|
||||
// idx:{canonical_id} → canonical_id → hash_id 反查索引
|
||||
SUBMISSIONS_KV: KVNamespace;
|
||||
ANALYTICS_KV: KVNamespace; // 執行統計匯總(key = stats:{hash_id}:{version})
|
||||
ENVIRONMENT: string;
|
||||
};
|
||||
|
||||
@@ -28,9 +31,12 @@ export const GherkinTestSchema = z.object({
|
||||
});
|
||||
|
||||
export const ComponentContractSchema = z.object({
|
||||
// canonical_id:提交者填寫的可讀名稱(小寫底線),用於搜尋與 workflow 引用
|
||||
// component_hash_id:由 Registry 在提交時派發,格式 cmp_{8碼hex},workflow 引用此 id 才能保證永久不壞
|
||||
// 兩者都可以在 workflow 中引用,Registry 會互相解析
|
||||
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']),
|
||||
category: z.enum(['logic', 'api', 'ui', 'style', 'anim', 'data']),
|
||||
version: z.string().min(1).regex(/^v\d+$/, 'version 格式必須為 vN'),
|
||||
wasi_target: z.literal('preview1'),
|
||||
stability: z.enum(['floating', 'stable', 'pinned']),
|
||||
@@ -64,7 +70,9 @@ export interface SandboxResult {
|
||||
failed_step?: SandboxStep;
|
||||
reason?: string;
|
||||
guide_anchor?: string;
|
||||
component_id: string;
|
||||
// 驗收通過後回傳兩個 id:
|
||||
component_hash_id: string; // cmp_{8碼hex},workflow 引用用,永久不變
|
||||
canonical_id: string; // 可讀名稱,搜尋用
|
||||
version: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user