## Phase 1-3: Control Plane + Contract System - awooop_phase1_control_plane_2026-05-04.sql: 12 張核心表 + RLS - awooop_phase1_batch1_rls_2026-05-04.sql: 全部 FORCE RLS + GRANT - packages/awooop-contracts/: 六合約 JSON Schema + golden fixtures - src/models/awooop_contracts.py: Pydantic v2 contract models(extra=forbid) - src/repositories/contract_repository.py: contract lifecycle(draft→published→active) - src/services/contract_service.py: HMAC publish sig + Redis multi-sig activate - src/services/schema_validator.py: LLM output validator(retry×3, E-SCHEMA-001) ## Phase 2: Tenant Isolation - awooop_phase2_budget_ledger_2026-05-04.sql: budget_ledger + RLS - src/services/budget_service.py: Token Budget Hard Kill 三層防線 - src/core/context.py: PROJECT_ID ContextVar(31 background loop 自動繼承) - src/db/base.py + models.py: project_id 欄位 + RLS set_config 注入 - src/hermes/nl_gateway.py: project_id Redis key 前綴(Phase A 雙寫) - src/services/anomaly_counter.py: per-project 改造(Phase A fallback) ## Phase 4: Platform Shell in Shadow Mode - awooop_phase4_run_state_2026-05-04.sql: run_state + step_journal + idempotency - src/services/run_state_machine.py: 8-state FSM + SKIP LOCKED + stale reaper - src/services/platform_runtime.py: UUID v7 + W3C trace_id + shadow_execute - src/services/audit_sink.py: PII/secret redaction 9 patterns - src/api/v1/platform/runs.py: POST/GET /v1/platform/runs(Router→Service 架構) - src/workers/platform_worker.py: SKIP LOCKED worker + heartbeat + reaper loop - src/main.py: platform router + lifespan worker start/stop ## Phase 5: MCP Gateway 五閘門 - awooop_phase5_mcp_gateway_2026-05-04.sql: 4 表 + RLS - src/plugins/mcp/gateway.py: McpGateway(Gate 1~5, E-MCP-GATE-001~009) - src/plugins/mcp/redaction_middleware.py: 雙層 redaction + 16K 截斷 - src/plugins/mcp/registry.py: __provider name mangling(ADR-116) - src/plugins/mcp/credential_resolver.py: k8s secret ref 解析 - tests/test_mcp_credential_isolation.py: 10 個迴歸測試(secret leak 防再現) ## Phase 6-8: EwoooC + Channel Hub + Approval Token - awooop_phase6_ewoooc_onboarding_2026-05-04.sql: ewoooc tenant + 4 read-only MCP tools - awooop_phase7_channel_hub_2026-05-04.sql: conversation_event + outbound_message - src/services/provider_proxy.py: ProviderProxy + PlatformEnvelope(ADR-115) - src/services/channel_hub.py: Telegram inbound mirror + Progressive Feedback(30s) - src/services/awooop_approval_token.py: HS256 + jti NX replay 防護 + suggest mode Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
67 lines
2.8 KiB
SQL
67 lines
2.8 KiB
SQL
-- AwoooP Phase 2.6: budget_ledger 建表 + 欄位定義
|
||
-- 2026-05-04 ogt + Claude Sonnet 4.6(ADR-120 D5 實作)
|
||
--
|
||
-- 防止 $47k 事故的三層 Hard Kill 架構中的 accounting 層:
|
||
-- - 每次 LLM call 完成後寫入一筆 ledger record
|
||
-- - 供 Tenant Budget Cache 計算 / 儀表板消費統計 / 告警閾值觸發
|
||
--
|
||
-- Phase 1 Control Plane migration 必須先執行(awooop_projects 表存在)
|
||
-- awooop_run_state 欄位在 Phase 3 SAGA 實作後補加
|
||
|
||
-- =========================================================
|
||
-- STEP 1: 建立 budget_ledger 表
|
||
-- =========================================================
|
||
CREATE TABLE IF NOT EXISTS budget_ledger (
|
||
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||
project_id VARCHAR(64) NOT NULL DEFAULT 'awoooi',
|
||
agent_id VARCHAR(128),
|
||
run_id UUID,
|
||
model VARCHAR(64),
|
||
provider VARCHAR(32),
|
||
prompt_tokens INT,
|
||
completion_tokens INT,
|
||
cost_usd NUMERIC(10, 4) NOT NULL DEFAULT 0.0000,
|
||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
COMMENT ON TABLE budget_ledger IS 'ADR-120: 每次 LLM call 的 token/cost accounting 記錄';
|
||
COMMENT ON COLUMN budget_ledger.cost_usd IS 'prompt + completion token 的估算費用(USD)';
|
||
|
||
-- =========================================================
|
||
-- STEP 2: Index(分析 + 查詢效率)
|
||
-- =========================================================
|
||
CREATE INDEX IF NOT EXISTS idx_budget_ledger_project_date
|
||
ON budget_ledger(project_id, recorded_at DESC);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_budget_ledger_run
|
||
ON budget_ledger(run_id)
|
||
WHERE run_id IS NOT NULL;
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_budget_ledger_agent
|
||
ON budget_ledger(project_id, agent_id, recorded_at DESC)
|
||
WHERE agent_id IS NOT NULL;
|
||
|
||
-- =========================================================
|
||
-- STEP 3: RLS(ADR-118 多租戶隔離)
|
||
-- =========================================================
|
||
ALTER TABLE budget_ledger ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE budget_ledger FORCE ROW LEVEL SECURITY;
|
||
|
||
DROP POLICY IF EXISTS budget_ledger_tenant_isolation ON budget_ledger;
|
||
CREATE POLICY budget_ledger_tenant_isolation ON budget_ledger
|
||
FOR ALL TO awooop_app
|
||
USING (project_id = current_setting('app.project_id', TRUE))
|
||
WITH CHECK (project_id = current_setting('app.project_id', TRUE));
|
||
|
||
-- =========================================================
|
||
-- STEP 4: GRANT
|
||
-- =========================================================
|
||
GRANT SELECT, INSERT ON budget_ledger TO awooop_app;
|
||
|
||
-- =========================================================
|
||
-- 驗收查詢
|
||
-- =========================================================
|
||
-- SELECT tablename, rowsecurity FROM pg_tables WHERE tablename = 'budget_ledger';
|
||
-- -- 結果:rowsecurity = true
|
||
-- SELECT count(*) FROM budget_ledger; -- = 0(剛建)
|