import { defineCommand } from "citty"; import { apiRequest, type ApiRequestInit } from "../lib/api"; import { toTable } from "../lib/format"; export type AuditApiRequest = ( path: string, init?: ApiRequestInit, ) => Promise; type AuditEvent = { metadata: { name: string; creationTimestamp: string }; spec: { actor: { username: string }; action: string; workspaceId?: string; operationId?: string; outcome: string; }; }; export async function listAuditEvents( workspace?: string, request: AuditApiRequest = apiRequest, ): Promise { const path = workspace ? `/audit?${new URLSearchParams({ workspaceId: workspace })}` : "/audit"; const response = await request<{ items: AuditEvent[] }>(path); if (response.items.length === 0) return "No audit events"; return toTable( response.items.map((event) => ({ timestamp: event.metadata.creationTimestamp, actor: event.spec.actor.username, action: event.spec.action, workspace: event.spec.workspaceId, outcome: event.spec.outcome, operation: event.spec.operationId, })), ); } const list = defineCommand({ meta: { name: "ls", description: "List audit events" }, args: { workspace: { type: "string", alias: "w", description: "Filter by workspace", }, }, async run({ args }) { console.log(await listAuditEvents(args.workspace ?? args._[0])); }, }); export const audit = defineCommand({ meta: { name: "audit", description: "Inspect the audit log" }, subCommands: { ls: list }, });