import type { RenderedCliResult } from "../output"; import type { SecretSyncOptions } from "./options"; import { displayValue, renderTable } from "./options"; import { record, stringOrNull } from "./utils"; const MAX_PLAN_ITEMS = 14; const MAX_TARGET_SECRETS = 4; const MAX_ACTIVATION_RESOURCES = 4; export function renderAgentRunSecretSyncResult(result: Record, options: SecretSyncOptions): RenderedCliResult { const command = "agentrun control-plane secret-sync"; if (options.full || options.raw) return renderSecretSyncMachine(command, result, options.output === "yaml" && !options.raw ? "yaml" : "json"); const payload = compactAgentRunSecretSyncPayload(result); if (options.output === "json" || options.output === "yaml") return renderSecretSyncMachine(command, payload, options.output); return { ok: result.ok !== false, command, renderedText: `${renderAgentRunSecretSyncText(payload)}\n`, contentType: "text/plain", }; } export function compactAgentRunSecretSyncPayload(result: Record): Record { const target = record(result.target); const targetNode = record(target.node); const identity = { node: boundedText(targetNode.id ?? target.node), lane: boundedText(target.lane), namespace: boundedText(target.namespace ?? record(target.runtime).namespace), valuesPrinted: false, }; const plan = record(result.plan); const rawItems = records(plan.items); const planItems = rawItems.slice(0, MAX_PLAN_ITEMS).map((item) => compactSecretPlanItem(item, identity)); const requestedSecretIds = record(result.filter).secretIds; const secretIds = Array.isArray(requestedSecretIds) ? requestedSecretIds.map((item) => boundedText(item)).filter((item): item is string => item !== null) : []; const baseCommand = secretSyncBaseCommand(identity, secretIds); const activationPreflight = record(result.activationPreflight); return { apiVersion: "unidesk.pikastech.local/v1alpha1", kind: "AgentRunSecretSyncPlan", identity, status: { ok: result.ok !== false, status: boundedText(result.status ?? (result.ok === false ? "blocked" : "ready")), mode: boundedText(result.mode), reason: boundedText(result.degradedReason), blockedBeforeMutation: result.blockedBeforeMutation === true, secretSyncStarted: result.secretSyncStarted === true || result.mutation === true, mutation: result.mutation === true, valuesPrinted: false, }, selection: { requestedSecretIds: secretIds, selectedCount: rawItems.length, valuesPrinted: false, }, plan: { secretCount: numberOr(plan.secretCount, rawItems.length), readyCount: numberOrNull(plan.readyCount), unavailableCount: numberOrNull(plan.unavailableCount), items: planItems, omittedCount: Math.max(0, numberOr(plan.secretCount, rawItems.length) - planItems.length), valuesPrinted: false, }, activationFence: Object.keys(activationPreflight).length === 0 ? null : compactActivationFence(activationPreflight, identity), execution: compactExecution(record(result.execution)), next: { secretById: `${secretSyncBaseCommand(identity, [])} --secret-id --dry-run -o json`, observeRunners: boundedText(record(result.next).observeRunners), retryDryRun: boundedText(record(result.next).retryDryRun), retryAfterManagerFence: boundedText(record(result.next).retryAfterManagerFence), confirm: boundedText(record(result.next).confirm), status: boundedText(record(result.next).status), full: `${baseCommand} --dry-run --full -o json`, raw: `${baseCommand} --dry-run --raw`, valuesPrinted: false, }, redaction: { secretValues: "omitted", runtimeSecretValuesDecoded: false, valuesPrinted: false, }, valuesPrinted: false, }; } export function renderAgentRunSecretSyncText(payload: Record): string { const identity = record(payload.identity); const status = record(payload.status); const plan = record(payload.plan); const planItems = records(plan.items); const fence = record(payload.activationFence); const next = record(payload.next); const lines = [ "AGENTRUN SECRET SYNC", renderTable( ["NODE", "LANE", "NAMESPACE", "STATUS", "MODE", "MUTATION", "VALUES"], [[ displayValue(identity.node), displayValue(identity.lane), displayValue(identity.namespace), displayValue(status.status), displayValue(status.mode), String(status.mutation === true), "false", ]], ), `Reason: ${displayValue(status.reason)}`, "", `SECRET PLAN count=${displayValue(plan.secretCount)} omitted=${displayValue(plan.omittedCount)}`, planItems.length === 0 ? "-" : renderTable(["ID", "TARGET", "KEY", "SOURCE", "PRESENT", "FINGERPRINT", "STATUS"], planItems.map((item) => { const source = record(item.source); const target = record(item.target); return [ displayValue(item.id), displayValue(target.identity), displayValue(target.key), displayValue(source.mode), displayValue(source.present), shortFingerprint(source.fingerprint), source.present === true ? "ready" : "unavailable", ]; })), ]; if (Object.keys(fence).length > 0) { const authority = record(fence.authority); const observation = record(fence.observation); const targetSecrets = records(fence.targetSecrets); const resources = records(fence.resources); lines.push( "", "ACTIVATION FENCE", renderTable(["IDENTITY", "TYPE", "STATUS", "REASON", "RISKS", "ATOMIC"], [[ displayValue(fence.identity), displayValue(fence.type), displayValue(fence.status), displayValue(fence.reason), displayValue(fence.resourceCount), displayValue(authority.atomicFenceAvailable), ]]), `Observation: targets=${displayValue(observation.targetSecretObservationComplete)} runners=${displayValue(observation.runnerObservationComplete)} mutations=${displayValue(observation.providerSecretMutationCount)} noOp=${displayValue(observation.providerSecretDataNoOp)}`, ); if (targetSecrets.length > 0) { lines.push( "", "FENCE TARGET SECRETS", renderTable(["IDENTITY", "KEYS", "PRESENT", "STATUS", "MUTATIONS"], targetSecrets.map((item) => [ displayValue(item.identity), stringList(item.desiredKeys), displayValue(item.present), displayValue(item.status), displayValue(item.mutationCount), ])), ); } if (resources.length > 0) { lines.push( "", "FENCE RESOURCES", renderTable(["IDENTITY", "STATUS", "RUN", "COMMAND", "CLASSIFICATION"], resources.map((item) => [ displayValue(item.identity), displayValue(item.status), displayValue(item.runId), displayValue(item.commandId), displayValue(item.classification), ])), ...resources.flatMap((item) => records(item.drillDown).map((entry) => ` ${displayValue(item.identity)}: ${displayValue(entry.command)}`)), ); } } const nextLines = ["secretById", "observeRunners", "retryDryRun", "retryAfterManagerFence", "confirm", "status", "full", "raw"] .map((key) => boundedText(next[key])) .filter((value): value is string => value !== null); lines.push("", "NEXT", ...nextLines.map((line) => ` ${line}`), "", "VALUES PRINTED false"); return lines.join("\n"); } function compactSecretPlanItem(item: Record, identity: Record): Record { const id = boundedText(item.id); const namespace = boundedText(item.namespace); const secret = boundedText(item.secret); const key = boundedText(item.key); void identity; return { id, target: { identity: namespace === null || secret === null ? null : `secret/${namespace}/${secret}`, key, }, source: { mode: boundedText(item.sourceMode), present: item.present === true, fingerprint: boundedText(item.fingerprint, 96), ...(boundedText(item.degradedReason) === null ? {} : { reason: boundedText(item.degradedReason) }), }, }; } function compactActivationFence(preflight: Record, identity: Record): Record { const authority = record(preflight.managerAuthority); const nestedAuthority = record(preflight.activationAuthority); const targetSecrets = records(preflight.targetSecrets).slice(0, MAX_TARGET_SECRETS).map(compactFenceTargetSecret); const rawRisks = records(preflight.activationRisks); const resources = rawRisks.slice(0, MAX_ACTIVATION_RESOURCES).map((risk, index) => compactFenceResource(risk, identity, index)); return { apiVersion: "unidesk.pikastech.local/v1alpha1", kind: "ProviderSecretActivationFence", identity: `providersecretactivationfence/${displayValue(identity.node)}/${displayValue(identity.lane)}`, type: "provider-secret-activation", status: boundedText(preflight.status ?? (preflight.ok === true ? "ready" : "blocked")), reason: boundedText(preflight.reason), requiresManagerFence: preflight.requiresManagerFence === true, authority: { owner: boundedText(authority.owner ?? nestedAuthority.owner), atomicFenceAvailable: authority.atomicFenceAvailable === true || nestedAuthority.atomicFenceAvailable === true, mutationAuthorized: authority.mutationAuthorized === true || preflight.providerSecretMutationAuthorized === true, noOpOnly: authority.noOpOnly !== false && nestedAuthority.noOpOnly !== false, trackingIssue: boundedText(authority.trackingIssue), }, observation: { targetSecretObservationComplete: preflight.targetSecretObservationComplete === true, runnerObservationComplete: preflight.runnerObservationComplete === true, allObservationsComplete: preflight.allObservationsComplete === true, providerSecretMutationCount: numberOrNull(preflight.providerSecretMutationCount), providerSecretDataNoOp: preflight.providerSecretDataNoOp === true, }, targetSecretCount: numberOr(preflight.targetSecretCount, targetSecrets.length), targetSecrets, targetSecretOmittedCount: Math.max(0, numberOr(preflight.targetSecretCount, targetSecrets.length) - targetSecrets.length), resourceCount: numberOr(preflight.activationRiskCount, rawRisks.length), resources, resourceOmittedCount: Math.max(0, numberOr(preflight.activationRiskCount, rawRisks.length) - resources.length), valuesPrinted: false, }; } function compactFenceTargetSecret(item: Record): Record { const namespace = boundedText(item.namespace); const name = boundedText(item.name); const mutations = records(item.mutations).slice(0, 6).map((mutation) => { const id = boundedText(mutation.id); return { id, key: boundedText(mutation.key), changeKind: boundedText(mutation.changeKind), desiredFingerprintSuffix: boundedText(mutation.desiredFingerprintSuffix ?? mutation.desiredEncodedFingerprint, 24)?.slice(-12) ?? null, runtimeFingerprintSuffix: boundedText(mutation.runtimeFingerprintSuffix ?? mutation.runtimeEncodedFingerprint, 24)?.slice(-12) ?? null, }; }); const queryOk = item.queryOk === true; const mutationCount = numberOr(item.mutationCount, mutations.length); return { kind: "Secret", identity: namespace === null || name === null ? null : `secret/${namespace}/${name}`, namespace, name, desiredKeys: stringArray(item.desiredKeys, 8), queryOk, present: typeof item.present === "boolean" ? item.present : null, status: !queryOk ? "observation-incomplete" : mutationCount === 0 ? "ready-no-op" : "mutation-pending", mutationCount, mutations, }; } function compactFenceResource(risk: Record, identity: Record, index: number): Record { const namespace = boundedText(identity.namespace); const runId = boundedText(risk.runId); const commandId = boundedText(risk.commandId); const runnerJobId = boundedText(risk.runnerJobId); const jobName = boundedText(risk.jobName); const pod = boundedText(risk.pod); const resourceIdentity = runnerJobId !== null ? `runnerjob/${runnerJobId}` : jobName !== null && namespace !== null ? `job/${namespace}/${jobName}` : pod !== null && namespace !== null ? `pod/${namespace}/${pod}` : `activationrisk/${index + 1}`; const drillDown = fenceResourceDrillDown(identity, { runId, commandId, runnerJobId }); return { identity: resourceIdentity, status: boundedText(risk.phase), classification: boundedText(risk.classification), runId, commandId, runnerJobId, waitingReasons: stringArray(risk.waitingReasons, 4), dependencies: records(risk.dependencies).slice(0, 3).map((dependency) => ({ identity: boundedText(dependency.name) === null || namespace === null ? null : `secret/${namespace}/${boundedText(dependency.name)}`, source: boundedText(dependency.source), affectedKeys: stringArray(dependency.affectedDesiredKeys, 6), mutationKinds: stringArray(dependency.mutationKinds, 4), reason: boundedText(dependency.reason), })), drillDown, }; } function fenceResourceDrillDown( identity: Record, resource: { runId: string | null; commandId: string | null; runnerJobId: string | null }, ): Record[] { const nodeLane = nodeLaneArgs(identity); const result: Record[] = []; if (resource.runId !== null && resource.runnerJobId !== null) { result.push({ kind: "RunnerJob", identity: `runnerjob/${resource.runnerJobId}`, command: `bun scripts/cli.ts agentrun describe runnerjob/${resource.runnerJobId} --run ${resource.runId}${nodeLane}` }); } if (resource.runId !== null && resource.commandId !== null) { result.push({ kind: "Command", identity: `command/${resource.commandId}`, command: `bun scripts/cli.ts agentrun describe command/${resource.commandId} --run ${resource.runId}${nodeLane}` }); } if (resource.runId !== null) { result.push({ kind: "Run", identity: `run/${resource.runId}`, command: `bun scripts/cli.ts agentrun events run/${resource.runId} --after-seq 0 --limit 100${nodeLane}` }); } return result.slice(0, 3); } function compactExecution(value: Record): Record { return { providerSecretClassification: boundedText(value.providerSecretClassification), providerSecretWritePolicy: boundedText(value.providerSecretWritePolicy), providerSecretWriteBlockedCount: numberOrNull(value.providerSecretWriteBlockedCount), providerSecretWriteSkippedCount: numberOrNull(value.providerSecretWriteSkippedCount), writableNonProviderSecretCount: numberOrNull(value.writableNonProviderSecretCount), secretSyncStarted: value.secretSyncStarted === true, }; } function secretSyncBaseCommand(identity: Record, secretIds: readonly string[]): string { const node = boundedText(identity.node) ?? ""; const lane = boundedText(identity.lane) ?? ""; return [ "bun scripts/cli.ts agentrun control-plane secret-sync", `--node ${node}`, `--lane ${lane}`, ...secretIds.map((id) => `--secret-id ${id}`), ].join(" "); } function nodeLaneArgs(identity: Record): string { const node = boundedText(identity.node); const lane = boundedText(identity.lane); return node === null || lane === null ? "" : ` --node ${node} --lane ${lane}`; } function renderSecretSyncMachine(command: string, value: unknown, mode: "json" | "yaml"): RenderedCliResult { return { ok: record(value).ok !== false && record(record(value).status).ok !== false, command, renderedText: mode === "json" ? `${JSON.stringify(value)}\n` : `${Bun.YAML.stringify(value)}\n`, contentType: mode === "json" ? "application/json" : "application/yaml", }; } function records(value: unknown): Record[] { return Array.isArray(value) ? value.map(record).filter((item) => Object.keys(item).length > 0) : []; } function boundedText(value: unknown, max = 240): string | null { const text = stringOrNull(value); if (text === null) return null; const oneLine = text.replace(/\s+/gu, " ").trim(); return oneLine.length <= max ? oneLine : `${oneLine.slice(0, Math.max(0, max - 3))}...`; } function stringArray(value: unknown, max: number): string[] { if (!Array.isArray(value)) return []; return value.map((item) => boundedText(item, 120)).filter((item): item is string => item !== null).slice(0, max); } function numberOr(value: unknown, fallback: number): number { return typeof value === "number" && Number.isFinite(value) ? value : fallback; } function numberOrNull(value: unknown): number | null { return typeof value === "number" && Number.isFinite(value) ? value : null; } function shortFingerprint(value: unknown): string { const fingerprint = boundedText(value, 96); if (fingerprint === null) return "-"; return fingerprint.length <= 20 ? fingerprint : `${fingerprint.slice(0, 7)}…${fingerprint.slice(-12)}`; } function stringList(value: unknown): string { return Array.isArray(value) && value.length > 0 ? value.map(String).join(",") : "-"; }