feat(FN-4915): complete Step 2-3 — add secret audit emitters and approval audits

Fusion-Task-Id: FN-4915
Fusion-Task-Lineage: d5c49dae-6069-4998-b632-aca52cc312dc
This commit is contained in:
Fusion (runfusion.ai)
2026-05-17 13:40:09 -07:00
committed by gsxdsm
parent 8ef3f52cf5
commit abb0f63aae
5 changed files with 273 additions and 7 deletions

View File

@@ -6,7 +6,7 @@ import {
type ApprovalRequestActorSnapshot,
type ApprovalRequestStatus,
} from "@fusion/core";
import { executeApprovedAgentProvisioning, executeApprovedWorktrunkInstall } from "@fusion/engine";
import { assertNoSecretPlaintext, executeApprovedAgentProvisioning, executeApprovedWorktrunkInstall } from "@fusion/engine";
import { ApiError, badRequest, conflict, notFound } from "../api-error.js";
import type { ApiRoutesContext } from "./types.js";
import { emitApprovalSseEvent } from "../sse.js";
@@ -139,6 +139,42 @@ function emitProvisioningDecisionAudit(params: {
scopedStore.recordRunAuditEvent(event);
}
function emitSecretsAccessDecisionAudit(params: {
scopedStore: import("@fusion/core").TaskStore;
request: ApprovalRequest;
decision: "approve" | "deny";
}): void {
const { scopedStore, request, decision } = params;
if (request.targetAction.category !== "secrets_access") return;
const context = request.targetAction.context ?? {};
const scope = typeof context.scope === "string" ? context.scope : undefined;
const key = typeof context.key === "string" ? context.key : undefined;
const policySource = typeof context.policySource === "string" ? context.policySource : undefined;
const target = scope && key ? `${scope}:${key}` : request.targetAction.resourceId;
const metadata = {
approvalRequestId: request.id,
key,
scope,
policySource,
requesterAgentId: request.requester.actorId,
};
assertNoSecretPlaintext(metadata);
const event: Parameters<typeof scopedStore.recordRunAuditEvent>[0] = {
agentId: request.requester.actorId,
domain: "filesystem",
mutationType: decision === "approve" ? "secret:approval-granted" : "secret:approval-denied",
target,
metadata,
runId: request.id,
};
if (request.taskId) event.taskId = request.taskId;
if (request.runId) event.runId = request.runId;
scopedStore.recordRunAuditEvent(event);
}
function emitSandboxProvisioningDecisionAudit(params: {
scopedStore: import("@fusion/core").TaskStore;
request: ApprovalRequest;
@@ -330,6 +366,8 @@ export function registerApprovalRoutes(ctx: ApiRoutesContext): void {
}
}
emitSecretsAccessDecisionAudit({ scopedStore, request: updated, decision: body.decision });
if (updated.targetAction.category === "sandbox_provisioning") {
if (body.decision === "approve") {
if (sandboxProvisioningExecutor) {