feat(exposure): 完全移除 acr push 暴露 consent 閘 (Arcrun#13 P1)
leo 2026-06-29 拍板:arcrun 是給 AI 用的系統,push/暴露不再需要人類確認。 - 刪 cypher-executor/src/lib/exposure-consent.ts(server 閘,MCP push 的真正擋點) - 刪 cli/src/lib/exposure-warning.ts(CLI 互動 + 非 TTY 拒絕) - recipes.ts / webhooks-named.ts:移除 checkExposureConsent 403 閘,直接放行 - recipe.ts / push.ts:移除 obtainExposureConsent 呼叫,不再 prompt/拒絕 - init-seed / seed-api-recipes:移除種子層級 consent - exposure_consent 欄位降為向後相容(讀舊 record 不報錯,不再寫入/檢查) 不補審計線索、不做替代防護(leo:先拿掉,出問題再設置)。 tsc 全綠(cypher-executor + cli)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,8 +30,6 @@ import type { GraphNode } from '../types';
|
||||
import { extractCronExpr } from '../lib/cron-match';
|
||||
import { updateCronIndexEntry, CRON_INDEX_KEY } from '../lib/cron-index';
|
||||
import { recordTelemetry } from '../lib/telemetry';
|
||||
import { checkExposureConsent, resolveConsentForRecord } from '../lib/exposure-consent';
|
||||
import type { ExposureConsent } from '../lib/exposure-consent';
|
||||
|
||||
export const webhooksNamedRouter = new Hono<{ Bindings: Bindings }>();
|
||||
|
||||
@@ -44,9 +42,8 @@ type NamedWorkflowRecord = {
|
||||
// 若首節點是 cron 零件,extract cron_expr 存進來供 scheduled() 比對
|
||||
// 對應 SDD: arcrun.md 三-A P1 #3
|
||||
cron_expr?: string;
|
||||
// 資料外流警示:部署 webhook = 把 workflow 變對外可呼叫 endpoint(暴露面)。
|
||||
// 存人類明示同意憑證(法律憑證,可審)。SDD: data-exfil-warning §7
|
||||
exposure_consent?: ExposureConsent;
|
||||
// 暴露 consent 閘已移除(leo 2026-06-29,Arcrun#13)。保留欄位只為向後相容舊 KV record。
|
||||
exposure_consent?: unknown;
|
||||
};
|
||||
|
||||
function kvKey(apiKey: string, name: string): string {
|
||||
@@ -103,7 +100,6 @@ webhooksNamedRouter.post('/webhooks/named', async (c) => {
|
||||
graph?: Record<string, unknown>;
|
||||
config?: Record<string, unknown>;
|
||||
description?: string;
|
||||
exposure_consent?: ExposureConsent;
|
||||
} | null;
|
||||
|
||||
if (!body?.name || !body.graph) {
|
||||
@@ -125,14 +121,7 @@ webhooksNamedRouter.post('/webhooks/named', async (c) => {
|
||||
return c.json({ error: 'workflow name 只能包含英文字母、數字、底線和連字號' }, 400);
|
||||
}
|
||||
|
||||
// 資料外流警示:部署 webhook = 把 workflow 變對外可呼叫 endpoint(暴露面)。
|
||||
// 首次部署某 workflow 需人類明示同意;已同意(含 suppress_future)則放行(§3 首次問記住)。
|
||||
const priorRaw = await c.env.WEBHOOKS.get(kvKey(apiKey, name));
|
||||
const priorRecord = priorRaw ? (JSON.parse(priorRaw) as NamedWorkflowRecord) : null;
|
||||
const consentError = checkExposureConsent(body.exposure_consent, priorRecord?.exposure_consent);
|
||||
if (consentError !== null) {
|
||||
return c.json({ error: consentError, requires: 'exposure_consent' }, 403);
|
||||
}
|
||||
// 暴露 consent 閘已移除(leo 2026-06-29,Arcrun#13):部署 webhook 不再需要人類確認,直接放行。
|
||||
|
||||
// 偵測首節點是 cron 零件 → 抽 cron_expr 存進 record + 建輕量 index 給 scheduled()
|
||||
const cronExpr = extractCronExpr(body.graph);
|
||||
@@ -144,8 +133,6 @@ webhooksNamedRouter.post('/webhooks/named', async (c) => {
|
||||
description: body.description.trim(), // R1:已驗非空(見上),存 trim 後的值
|
||||
created_at: new Date().toISOString(),
|
||||
cron_expr: cronExpr ?? undefined,
|
||||
// 法律憑證:存人類明示同意(本次新同意或沿用既有)
|
||||
exposure_consent: resolveConsentForRecord(body.exposure_consent, priorRecord?.exposure_consent),
|
||||
};
|
||||
|
||||
const start = Date.now();
|
||||
|
||||
Reference in New Issue
Block a user