feat(credentials): T8 回填端點 + T9 治理端點/CLI (credential-store-migration)

- POST /credentials/migrate-to-workers-secrets:舊 KV credential 逐筆解密回填 D1+Workers
  Secrets,冪等可審,重用 wasi-shim 唯一合法 crypto_decrypt 呼叫點
- GET /credentials 改讀 D1(與既有 /credentials/catalog 共用查詢);DELETE 改為新家優先、
  舊 KV fallback,避免孤兒資料
- acr creds list/replace/delete 三支 CLI 薄殼指令;順手修好過期的 acr creds push(舊
  client 端加密格式已被 T5 取代)
- 新增 cypher-executor/tests/credentials.test.ts + D1 test fixture

T6/T7(讀取/注入路徑、雙讀 fallback)需要重新編譯 registry/components/auth_static_key
的 TinyGo WASM,本環境無 tinygo 且 proxy 擋 github.com 下載,卡在工具鏈缺口,詳細分析
記錄在 credential-store-migration.md。

端到端驗證:部署到 leo21c 帳號真實跑過 GET/POST/DELETE 三分支 + migrate 端點(對真實
既存的兩筆 credential 跑,發現 cypher-executor 自己的 ENCRYPTION_KEY secret 疑似為空,
誠實記錄為待 leo/總管裁決的不可逆風險項,未擅自重設)。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-07-04 23:00:07 +00:00
parent 1db8a13a3a
commit 1d19d46161
9 changed files with 588 additions and 99 deletions
+19 -4
View File
@@ -13,7 +13,7 @@ import { dirname, join } from 'node:path';
import { cmdInit } from './commands/init.js';
import { cmdConfig } from './commands/config.js';
import { cmdWhoami } from './commands/whoami.js';
import { cmdCredsPush } from './commands/creds.js';
import { cmdCredsPush, cmdCredsList, cmdCredsReplace, cmdCredsDelete } from './commands/creds.js';
import { cmdPush } from './commands/push.js';
import { cmdRun } from './commands/run.js';
import { cmdValidate } from './commands/validate.js';
@@ -79,12 +79,27 @@ program
.option('--json', '結構化輸出(給 AI / 腳本讀取)')
.action((options: { json?: boolean }) => cmdWhoami(options));
// acr creds push [credentials.yaml]
const credsCmd = program.command('creds').description('Credential 管理');
// acr creds push/list/replace/delete — credential-store-migration T9(治理端點 CLI 薄殼)
const credsCmd = program.command('creds').description('Credential 管理D19:只能看目錄/replace/delete,讀不回值)');
credsCmd
.command('push [file]')
.description('加密上傳 credentials.yaml 至你的 CF KV不經過 arcrun.dev')
.description('批次上傳 credentials.yaml(明文經 TLS,值存進你的 Workers Secrets不經過 arcrun.dev')
.action((file: string) => cmdCredsPush(file ?? 'credentials.yaml'));
credsCmd
.command('list')
.description('列出已存的 credential 目錄(name/service/sensitivity/last_used,不含值)')
.action(() => cmdCredsList());
credsCmd
.command('replace <name> <value>')
.description('整筆覆寫一個 credential 的值(只能整筆換,不能局部編輯)')
.option('--service <service>', '對應 service 名(如 telegram')
.option('--sensitivity <level>', 'standard | high')
.action((name: string, value: string, options: { service?: string; sensitivity?: string }) =>
cmdCredsReplace(name, value, options));
credsCmd
.command('delete <name>')
.description('刪除一個 credential(目錄 row + Workers Secret 本體)')
.action((name: string) => cmdCredsDelete(name));
// acr push <workflow.yaml>
program