import { ONLINE_MAX_MS } from '../../server-freshness.js'; import { monitoringIdentity } from '../fleet/health-observations.js'; import { getServer, setServerFields, type ServerRow } from '../fleet/servers.js'; import { latestGameSubmission, telemetryReport, type VerifiedGameStatus } from '../fleet/status-evidence.js'; import { serverObservation } from '../fleet/status.js'; import { activityFields, successfulStatusFields } from '../fleet/status-updates.js'; /** Called inside the completion transaction; evidence must still describe this process. */ export function handoffVerifiedHealth( server: string, identity: string, container: { state: string; observedAt: string }, game: VerifiedGameStatus ): boolean { const current = getServer(server); if (!current || current.desired_state !== 'running' || monitoringIdentity(server) !== identity) return false; const fresh = (at: string) => { const age = Date.now() - Date.parse(at); return age >= 0 && age <= ONLINE_MAX_MS; }; const gameAt = game.source === 'telemetry' ? game.receivedAt : game.observedAt; const submission = latestGameSubmission(server); if (!fresh(container.observedAt) || !fresh(gameAt) || (submission && gameAt <= submission)) return false; const updates: Partial = {}; if (!current.container_checked_at || current.container_checked_at <= container.observedAt) { updates.container_state = container.state; updates.container_checked_at = container.observedAt; } if ( game.source === 'rcon' && (!current.last_checked_at || current.last_checked_at <= game.observedAt) ) { Object.assign(updates, successfulStatusFields(game.rcon, game.observedAt)); } const candidate = { ...current, ...updates }; // Evaluate the health readers will see after the operation and recovery slot // complete. Newer contradictory evidence must keep verification pending. const status = serverObservation(candidate, { provisioning: false, settling: false, submission, telemetry: telemetryReport(server) }); if (status.health !== 'online') return false; setServerFields(server, { ...updates, ...activityFields(candidate, status) }); return true; }