import type { ProvisioningAction } from './provisioning.js'; import type { LaunchRecipeSummary } from './deployment-plan.js'; export const provisioningPhases = [ 'requested', 'eligibility', 'startup-queue', 'prepare', 'container-action', 'cleanup', 'verify-container', 'verify-game', 'verify-map', 'verify-plutonium', 'verify-stopped' ] as const; export type ProvisioningPhase = (typeof provisioningPhases)[number]; export type EvidenceResult = 'pass' | 'waiting' | 'fail' | 'unknown'; export type EvidenceSource = 'agent' | 'rcon' | 'telemetry' | 'combined' | 'manifest' | null; export interface ProvisioningCheck { key: | 'container' | 'game' | 'map' | 'plutonium-release' | 'plutonium-version' | 'occupancy' | 'stopped'; label: string; result: EvidenceResult; source: EvidenceSource; checkedAt: string; receivedAt: string | null; expected: string | number | null; actual: string | number | null; message: string | null; } export interface ProvisioningBlocker { code: string; message: string; automatic: boolean; href?: string | null; label?: string | null; } export interface ProvisioningCheckpoint { key: string; label: string; at: string; phase: ProvisioningPhase | null; } export interface RecoveryObservation { state: 'held' | 'released' | 'transferred' | 'unknown'; at: string; message: string; operationId?: string | null; } export interface ProvisioningProgress { version: 1; phase: ProvisioningPhase | null; phaseStartedAt: string | null; observedAt: string | null; blocker: ProvisioningBlocker | null; checks: ProvisioningCheck[]; checkpoints: ProvisioningCheckpoint[]; command: { state: 'attempted' | 'accepted' | 'rejected' | 'uncertain'; at: string; message: string; } | null; recovery: RecoveryObservation | null; recipeStatus: 'queued' | 'attempted' | null; } export interface ProvisioningEvent { id: number; created_at: string; message: string; kind?: string | null; phase_key?: string | null; details_json?: string | null; } export interface ProvisioningDeployment { id: string; server: string; server_deleted_at: string | null; action: ProvisioningAction; state: string; stage: string; started_at: string; finished_at: string | null; submitted_at?: string | null; checked_at?: string | null; players?: number | null; triggered_by: string; requested_by?: string | null; error: string | null; warnings: string; server_exists: number; expected_map?: string | null; } export interface ProvisioningSource { kind: 'campaign' | 'beta' | 'maintenance' | 'watchdog' | 'autoscaling' | 'rebalance'; source_id: string; server?: string; label: string; href: string | null; } export interface ProvisioningCapacity { evaluatedAt: string; pools: { kind: 'startup' | 'restart'; limit: number; used: number; holders: { id: string | null; server: string }[]; requestOrder: number | null; ownsSlot: boolean; }[]; } export interface ProvisioningDetail { canOverrideSafety?: boolean; safetyOverrideUnavailableReason?: string | null; safetyOverride?: { actorId: string; actorName: string; confirmedAt: string } | null; canCancel?: boolean; canCancelCreation?: boolean; canRetryWithRebuild?: boolean; cancellation?: { cleanupId: string; state: string; stage: string; error: string | null } | null; backend?: 'native'; workerActivity?: WorkerActivity[]; agentOperation?: { id: string; hostId: string; state: string; updatedAt: string; createdAt: string; error: string | null; } | null; deployment: ProvisioningDeployment; events: ProvisioningEvent[]; activity: { total: number; latestId: number | null; failureExcerpt: ProvisioningEvent | null }; sources: ProvisioningSource[]; recipe: LaunchRecipeSummary | null; blueprintName: string | null; canResumeVerification: boolean; canResumeCleanup: boolean; canResumeRebuild: boolean; canCancelRemoval: boolean; collection: { id: string; name: string } | null; progress: ProvisioningProgress | null; capacity: ProvisioningCapacity; warningMessages: string[]; generatedAt: string; } export interface WorkerActivity { key: string; label: string; startedAt: string; } export interface ProvisioningEventPage { events: ProvisioningEvent[]; total: number; totalEvents: number; latestId: number | null; watermark: number; nextCursor: number | null; }