export interface MirrorWebhookDisclosureSelection { repoKey: string | null; deliveryId: string | null; } export function rawMirrorWebhookStatus(result: Record): Record { return { ok: result.ok === true, action: "platform-infra-gitea-mirror-webhook-status", mutation: false, view: "raw", target: result.target, raw: record(result.remote), safety: { explicitRawRequired: true, valuesPrinted: false, stdoutGuard: "The YAML-configured stdout guard remains active; oversized raw evidence is written once to the protected dump path.", }, }; } export function buildMirrorWebhookStatusDisclosure( result: Record, selection: MirrorWebhookDisclosureSelection, ): Record { const target = record(result.target); const targetId = stringValue(target.id, ""); const webhook = record(result.webhook); const webhookRetry = record(webhook.ingressRetry); const webhookHookReconcile = record(webhook.hookReconcile); const webhookBridge = record(webhook.bridge); const bridge = record(result.bridge); const durableInbox = record(bridge.durableInbox); const failedDeliveryRecovery = record(durableInbox.failedDeliveryRecovery); const allRecoveryEntries = arrayRecords(failedDeliveryRecovery.entries); const allRepositories = arrayRecords(result.repositories); const inboxDeliveries = arrayRecords(durableInbox.deliveries); const bridgeLogs = record(result.bridgeLogs); const allLogEvents = arrayRecords(bridgeLogs.events); const aggregateView = selection.repoKey === null && selection.deliveryId === null; let selectedRepoKey = selection.repoKey; let effectiveDeliveryId = selection.deliveryId; let selectedInbox = selection.deliveryId === null ? undefined : inboxDeliveries.find((item) => stringValue(item.deliveryId, "") === selection.deliveryId && (selection.repoKey === null || stringValue(item.repo, "") === selection.repoKey)); if (selectedRepoKey === null && selectedInbox !== undefined) selectedRepoKey = stringValue(selectedInbox.repo, "") || null; if (selectedRepoKey === null && selection.deliveryId !== null) { const event = allLogEvents.find((item) => stringValue(item.deliveryId, "") === selection.deliveryId); selectedRepoKey = event === undefined ? null : stringValue(event.repo, "") || null; } let selectedRepository = selectedRepoKey === null ? undefined : allRepositories.find((item) => stringValue(item.key, "") === selectedRepoKey); if (selectedRepository === undefined && selection.deliveryId !== null) { selectedRepository = allRepositories.find((item) => stringValue(item.deliveryId, "") === selection.deliveryId); if (selectedRepoKey === null && selectedRepository !== undefined) selectedRepoKey = stringValue(selectedRepository.key, "") || null; } if (effectiveDeliveryId === null && selectedRepository !== undefined) effectiveDeliveryId = stringValue(selectedRepository.deliveryId, "") || null; if (selectedInbox === undefined && effectiveDeliveryId !== null) { selectedInbox = inboxDeliveries.find((item) => stringValue(item.deliveryId, "") === effectiveDeliveryId && (selectedRepoKey === null || stringValue(item.repo, "") === selectedRepoKey)); } if (selectedInbox === undefined && selectedRepository !== undefined) { const repositoryInbox = record(selectedRepository.durableInboxRecord); if (stringValue(repositoryInbox.deliveryId, "") === (effectiveDeliveryId ?? "")) selectedInbox = repositoryInbox; } const repositories = selectedRepoKey === null ? allRepositories : allRepositories.filter((item) => stringValue(item.key, "") === selectedRepoKey); const selectedRepositoryName = selectedRepository === undefined ? null : stringValue(selectedRepository.repository, "") || null; const recoveryEntries = allRecoveryEntries.filter((item) => { if (selectedRepositoryName !== null && stringValue(item.repository, "") !== selectedRepositoryName) return false; if (effectiveDeliveryId !== null && stringValue(item.deliveryId, "") !== effectiveDeliveryId) return false; return true; }); const matchingLogEvents = allLogEvents.filter((item) => { if (selectedRepoKey !== null && stringValue(item.repo, "") !== selectedRepoKey) return false; if (effectiveDeliveryId !== null && stringValue(item.deliveryId, "") !== effectiveDeliveryId) return false; return true; }); const selectedLogEvents = matchingLogEvents.slice(aggregateView ? -3 : -4).map(webhookLogEventSummary); const deliveryFound = effectiveDeliveryId !== null && ( selectedInbox !== undefined || (selectedRepository !== undefined && stringValue(selectedRepository.deliveryId, "") === effectiveDeliveryId) || matchingLogEvents.length > 0 ); const selectionError = selection.repoKey !== null && selectedRepository === undefined ? "repository-not-observed" : selection.deliveryId !== null && !deliveryFound ? "delivery-not-observed-in-retained-evidence" : null; const selectedDelivery = selectedInbox === undefined ? null : webhookDeliverySummary(selectedInbox); const currentDeliveries = repositories .map((repo) => record(repo.durableInboxRecord)) .filter((item) => stringValue(item.deliveryId, "") !== "") .map(webhookDeliveryAggregateSummary); const firstError = firstWebhookStatusError({ repository: selectedRepository ?? allRepositories.find((repo) => compactErrorValue(repo.error) !== null), delivery: selectedInbox, logEvents: matchingLogEvents, durableInbox, bridgeLogs, mirrorStatus: record(result.mirrorStatus), }); const selectorArgs = [ selectedRepoKey === null ? "" : ` --repo ${selectedRepoKey}`, effectiveDeliveryId === null ? "" : ` --delivery-id ${effectiveDeliveryId}`, ].join(""); const commandBase = `bun scripts/cli.ts platform-infra gitea mirror webhook status --target ${targetId}${selectorArgs}`; const repoCommands = allRepositories.slice(0, 8).map((repo) => { const key = stringValue(repo.key, ""); return { key, deliveryId: stringValue(repo.deliveryId, "") || null, command: `bun scripts/cli.ts platform-infra gitea mirror webhook status --target ${targetId} --repo ${key}`, }; }); return { ok: result.ok === true && selectionError === null, action: "platform-infra-gitea-mirror-webhook-status", mutation: false, view: selection.deliveryId !== null ? "delivery-drill-down" : selection.repoKey !== null ? "repository-drill-down" : "domain-aggregate", target: { id: target.id, route: target.route, namespace: target.namespace, role: target.role, }, selection: { requestedRepoKey: selection.repoKey, selectedRepoKey, requestedDeliveryId: selection.deliveryId, effectiveDeliveryId, repositoryFound: selection.repoKey === null || selectedRepository !== undefined, deliveryFound: selection.deliveryId === null || deliveryFound, error: selectionError, }, webhook: { enabled: webhook.enabled === true, direction: webhook.direction, publicUrlSha256: webhookHookReconcile.desiredUrlSha256, events: webhook.events, responseBudgetMs: webhook.responseBudgetMs, ingressAttemptBudgetMs: webhook.ingressAttemptBudgetMs, ingressResponseHeaderTimeoutMs: webhook.ingressResponseHeaderTimeoutMs, retry: { enabled: webhookRetry.enabled === true, maxAttempts: webhookRetry.maxAttempts, initialDelayMs: webhookRetry.initialDelayMs, maxDelayMs: webhookRetry.maxDelayMs, }, bridge: { deploymentName: webhookBridge.deploymentName, serviceName: webhookBridge.serviceName, }, hookReconcile: { enabled: webhookHookReconcile.enabled === true, ownerTargetId: webhookHookReconcile.ownerTargetId, runningOnTarget: webhookHookReconcile.runningOnTarget === true, intervalMs: webhookHookReconcile.intervalMs, requestTimeoutMs: webhookHookReconcile.requestTimeoutMs, topologySha256: webhookHookReconcile.topologySha256, }, }, bridge: { deployment: bridge.deployment, ready: bridge.ready === true, readyReplicas: bridge.readyReplicas, serviceExists: bridge.serviceExists === true, durableInbox: { ready: durableInbox.ready === true, storageReady: durableInbox.storageReady === true, capacityAvailable: durableInbox.capacityAvailable === true, counts: durableInbox.counts, retainedDeliveryCount: inboxDeliveries.length, totalBytes: durableInbox.totalBytes, maxBytes: durableInbox.maxBytes, errorType: durableInbox.errorType ?? null, journal: durableInbox.journal, failedDeliveryRecovery: { enabled: failedDeliveryRecovery.enabled === true, ready: failedDeliveryRecovery.ready === true, state: failedDeliveryRecovery.state, counts: failedDeliveryRecovery.counts, entries: recoveryEntries.map(failedDeliveryRecoveryEntrySummary), }, }, }, repositories: repositories.map(webhookRepositorySummary), deliveries: selection.repoKey === null && selection.deliveryId === null ? currentDeliveries : selectedDelivery === null ? [] : [selectedDelivery], retry: selectedInbox === undefined ? null : { state: selectedInbox.state, totalAttempts: selectedInbox.totalAttempts, cycleAttempt: selectedInbox.cycleAttempt, nextAttemptAt: selectedInbox.nextAttemptAt ?? null, lastError: compactErrorValue(selectedInbox.lastError), }, logs: { exitCode: bridgeLogs.exitCode, matched: matchingLogEvents.length, returned: selectedLogEvents.length, omitted: Math.max(0, matchingLogEvents.length - selectedLogEvents.length), events: selectedLogEvents, errorTail: compactErrorValue(bridgeLogs.errorTail), }, diagnostics: { mirrorStatus: { exitCode: record(result.mirrorStatus).exitCode, errorTail: compactErrorValue(record(result.mirrorStatus).errorTail), }, firstError, }, disclosure: { rawOmitted: true, retainedInboxRecords: inboxDeliveries.length, rawRequiresExplicitFlag: true, valuesPrinted: false, }, next: { repositories: repoCommands, full: `${commandBase} --full`, raw: `${commandBase} --raw`, }, }; } function failedDeliveryRecoveryEntrySummary(item: Record): Record { return { repository: item.repository, hookId: item.hookId, deliveryId: item.deliveryId, state: item.state, attempts: item.attempts, cooldownMs: item.cooldownMs, nextAt: item.nextAt ?? null, updatedAt: item.updatedAt, lastStatusCode: item.lastStatusCode ?? null, completionReason: item.completionReason ?? null, }; } function webhookRepositorySummary(repo: Record): Record { const selected = record(repo.selectedPushDelivery); const topology = record(repo.hookTopology); return { key: repo.key, repository: repo.repository, branch: repo.branch, hookReady: repo.hookReady === true, githubHead: repo.githubHead, branchCommit: repo.branchCommit, snapshotCommit: repo.snapshotCommit, authorityMatches: repo.authorityMatches === true, stale: repo.bridgeEventStale === true, staleReason: repo.staleReason ?? null, deliveryId: selected.deliveryId ?? null, deliveryAccepted: repo.deliveryAccepted === true, selectedDelivery: { deliveryId: selected.deliveryId ?? null, hookId: selected.hookId ?? null, status: selected.status ?? null, statusCode: selected.statusCode ?? null, deliveredAt: selected.deliveredAt ?? null, accepted: repo.deliveryAccepted === true, }, hookTopology: { ready: topology.ready === true, desiredUrlSha256: topology.desiredUrlSha256 ?? null, desiredTopologyUrlSha256: Array.isArray(topology.desiredTopologyUrlSha256) ? topology.desiredTopologyUrlSha256 : [], observedManagedUrlSha256: Array.isArray(topology.observedManagedUrlSha256) ? topology.observedManagedUrlSha256 : [], driftTypes: Array.isArray(topology.driftTypes) ? topology.driftTypes : [], }, durableState: repo.durableInboxState, durableCommitted: repo.durableInboxCommitted === true, error: compactErrorValue(repo.error), }; } function webhookDeliverySummary(delivery: Record): Record { const result = record(delivery.result); return { deliveryId: delivery.deliveryId, repo: delivery.repo, repository: delivery.repository, ref: delivery.ref, requestedCommit: delivery.requestedCommit, state: delivery.state, acceptedSequence: delivery.acceptedSequence, totalAttempts: delivery.totalAttempts, cycleAttempt: delivery.cycleAttempt, nextAttemptAt: delivery.nextAttemptAt ?? null, updatedAt: delivery.updatedAt, result: { sourceCommit: result.sourceCommit, authorityCommit: result.authorityCommit, snapshotRef: result.snapshotRef, disposition: result.disposition, }, lastError: compactErrorValue(delivery.lastError), }; } function webhookDeliveryAggregateSummary(delivery: Record): Record { const result = record(delivery.result); return { deliveryId: delivery.deliveryId, repo: delivery.repo, state: delivery.state, totalAttempts: delivery.totalAttempts, updatedAt: delivery.updatedAt, requestedCommit: delivery.requestedCommit, sourceCommit: result.sourceCommit, disposition: result.disposition, lastError: compactErrorValue(delivery.lastError), }; } function webhookLogEventSummary(event: Record): Record { return { event: event.event, repo: event.repo, deliveryId: event.deliveryId, ok: event.ok === true, terminal: event.terminal === true, syncAttempt: event.syncAttempt, disposition: event.disposition, sourceCommit: event.sourceCommit, authorityCommit: event.authorityCommit, elapsedMs: event.elapsedMs, errorType: event.errorType ?? null, error: compactErrorValue(event.error), }; } function firstWebhookStatusError(input: { repository?: Record; delivery?: Record; logEvents: Record[]; durableInbox: Record; bridgeLogs: Record; mirrorStatus: Record; }): Record | null { const candidates: Array<[string, unknown]> = [ ["repository", input.repository?.error], ["durable-inbox-record", input.delivery?.lastError], ["bridge-event", input.logEvents.find((event) => compactErrorValue(event.error) !== null)?.error], ["durable-inbox", input.durableInbox.errorType], ["bridge-logs", Number(input.bridgeLogs.exitCode) === 0 ? null : input.bridgeLogs.errorTail], ["mirror-status", Number(input.mirrorStatus.exitCode) === 0 ? null : input.mirrorStatus.errorTail], ]; for (const [domain, value] of candidates) { const message = compactErrorValue(value); if (message !== null) return { domain, message }; } return null; } function compactErrorValue(value: unknown): string | null { if (value === null || value === undefined || value === "") return null; const text = typeof value === "string" ? value : JSON.stringify(value); const compact = text.replace(/\s+/gu, " ").trim(); if (compact === "" || compact === "null" || compact === "{}") return null; return compact.length > 240 ? `${compact.slice(0, 237)}...` : compact; } function record(value: unknown): Record { return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record : {}; } function arrayRecords(value: unknown): Record[] { return Array.isArray(value) ? value.filter((item) => typeof item === "object" && item !== null && !Array.isArray(item)) as Record[] : []; } function stringValue(value: unknown, fallback = "-"): string { if (typeof value === "string" && value.length > 0) return value; if (typeof value === "number" || typeof value === "boolean") return String(value); return fallback; }