feat(approval-gate): wire gateDestructive into live destructive handlers (Phase 4b) #2382
Reference in New Issue
Block a user
Delete Branch "feat/platform-agent-gate-wiring"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 4b — activates the merged 4a approval-gate infra (#2372).
Scope (the design decision, made explicit)
The gate must NOT blanket every caller — that would force every workspace delete/secret-write platform-wide through async approval. Scope is centralized in
gateDestructive:MOLECULE_PLATFORM_APPROVAL_GATE(mirrors 3a/3c; inert until the platform agent ships, protecting existing org-token automation).org_token_id); ordinary workspace-token agents + human CP sessions (cp_session_actor— the approvers) are NOT gated. Realises the file-header trust boundary ("anything holding an org-admin token still goes through the gate") without gating everyone.Wired
WorkspaceHandler.Delete→delete_workspaceSecretsHandler.Set→secret_write(context includes the key, so an approval for one secret cant authorise another)requireApproval/gateDestructivenow take theevents.EventEmitterinterface and tolerate a nil emitter (SecretsHandler has no broadcaster) — the pending row is still persisted, only the live canvas push is skipped.Tests
3 new unit tests (default-off, org-token detection, scope short-circuits) + existing approval/secret/delete suites green; golangci-lint clean. Full flag-on→202 path covered by the real-PG approval_gate_integration_test.go.
Deferred (documented)
org_token_mint(OrgTokenHandler is org-scoped — no workspace_id to key the approval; needs the org→platform-agent-workspace mapping) anddeprovision_workspace(no workspace-server handler — CP-side).🤖 Generated with Claude Code
Activates the merged 4a approval-gate infra. Scope is centralized in gateDestructive so each handler is a one-liner, and the policy is uniform + testable: - default-OFF rollout flag MOLECULE_PLATFORM_APPROVAL_GATE (mirrors 3a/3c default-off; protects existing org-token automation until the platform agent ships); - ONLY org-token callers are gated. The platform agent runs with MOLECULE_API_KEY=<org-admin token> (auth middleware sets org_token_id); ordinary workspace-token agents and human CP-session operators are NOT gated, so normal operation is byte-identical. Realises the file-header trust boundary without gating everyone. Wired: WorkspaceHandler.Delete (delete_workspace) + SecretsHandler.Set (secret_write). requireApproval/gateDestructive now take the events.EventEmitter interface and tolerate a nil emitter (SecretsHandler is broadcaster-less) — the pending approval row is still persisted, only the live canvas push is skipped. 3 new unit tests (flag default-off, org-token detection, scope short-circuits) + existing approval/secret/delete suites green; golangci-lint clean. Deferred (documented follow-on): org_token_mint (OrgTokenHandler is org-scoped, no workspace_id to key the approval) + deprovision_workspace (no workspace-server handler — lives CP-side). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Independent review confirmed: scope is centralized + default-off (MOLECULE_PLATFORM_APPROVAL_GATE) + org-token-only (org_token_id), so ordinary workspace/CP callers are byte-identical; nil EventEmitter handled (pending row still persisted); context-sensitive request_hash (key/name); 3 unit tests + existing suites green. Approving.
Security review: gate is fail-safe default-off, scoped to org-admin-token callers per the trust boundary; secret-write approval keyed by secret key (no cross-secret authorization); no regression to normal ops. Approving.