import type { DeploymentDrainDefinition } from './deploy'; import { type RuntimeDrainResult } from './runtime-transition'; import { type BootstrapInventoryPlan, type BootstrapInventoryPlanGuest } from '@forgezero/runtime/bootstrap-inventory'; /** Typed host runtime plans used by `fz bootstrap platform`. */ export type PlatformSoftwareProfile = 'platform-db-api' | 'platform-api'; export type PlatformDatabaseRole = 'master' | 'joiner' | 'none'; export type ApiSlot = 'blue' | 'green'; /** Explicit planning phase; the API live seed requires ReviewedBootstrapInventorySchema. */ export type PlatformInitialInventoryCompute = BootstrapInventoryPlanGuest; export type PlatformInitialInventory = BootstrapInventoryPlan; export type PlatformBootstrapEmail = { provider: 'smtp'; host: string; port: number; user: string; from: string; } | { provider: 'jetemail'; from: string; eu: boolean; }; export interface PlatformSharedEnvironment { softwareProfile: PlatformSoftwareProfile; databaseRole: PlatformDatabaseRole; databaseCoordinators: string[]; databaseReadPreferredCoordinators?: string[]; databaseAddress?: string; databaseMaster?: string; databaseNetworkMode: 'private-lan'; databaseReplicationFactor: number; databaseWriteConcern: number; databaseUser: string; nodeHostname: string; nodeRegion: string; nodeRole: 'guest'; appOrigin: string; apiOrigin: string; publicApiPort: number; sharedDirectory: string; seedSyncPeers: string[]; /** Exact physical API host identities participating in this seed epoch. */ seedSyncMembers: string[]; seedSyncEpoch: string; concurrencyLimit: number; drainDeadlineMs: number; otlpEndpoint: 'http://127.0.0.1:4318'; otlpCollectorUnit: string; agentOtlpEndpoint: string; otlpFlushIntervalMs: number; otlpTraceSampleRatio: number; custodianEmail?: string; email?: PlatformBootstrapEmail; backup?: { endpoint: string; region: string; bucket: string; accessKeyId: string; }; cloudflare?: { accountId: string; zoneId: string; kvNamespaceId: string; tunnelId: string; tunnelService: string; }; realtime?: { workerScriptName: string; endpoint: string; producer: string; }; deployProfile: string; /** Exact reviewed generation-one inventory; live API boot never reconstructs it from an environment name. */ initialInventory?: PlatformInitialInventory; } export declare function validatePlatformInitialInventory(input: unknown): PlatformInitialInventory; export declare function validatePlatformSharedEnvironment(input: PlatformSharedEnvironment): PlatformSharedEnvironment; /** Render only non-secret runtime coordinates. Passwords/tokens have no field in this contract. */ export declare function renderPlatformSharedEnvironment(input: PlatformSharedEnvironment): string; export interface SystemdCredentialSpec { name: 'arangodb-jwt' | 'arangodb-root-password' | 'seed-sync-root' | 'fz_smtp.password' | 'fz_jetemail.apiKey' | 'CF_API_TOKEN' | 'CF_TUNNEL_TOKEN' | 'REALTIME_PUBLISH_SECRET' | 'REALTIME_TICKET_SECRET' | 'REALTIME_PRODUCER_IDENTITY' | 'REALTIME_EDGE_PUBLIC_KEYS'; encryptedPath: string; required: boolean; } export declare function platformApiCredentialSpecs(options: { emailProvider?: PlatformBootstrapEmail['provider']; cloudflareKv: boolean; realtime: boolean; }): SystemdCredentialSpec[]; export interface ApiRuntimeRenderOptions { serviceUser: string; sharedDirectory: string; sharedEnvironmentFile: string; slotsDirectory: string; bluePort: number; greenPort: number; collectorUnit: string; credentials: SystemdCredentialSpec[]; /** Root-owned calibration override, loaded after the ordinary shared environment. */ capacityEnvironmentFile?: string; /** Root-owned signed deployment topology, absent until post-genesis reconciliation. */ topologyEnvironmentFile?: string; } /** Durable root-owned slot identity. API services must remain restartable after a host reboot. */ export declare const PLATFORM_RUNTIME_CONTROL_DIRECTORY = "/etc/forgezero/runtime-control"; export declare function renderPlatformApiUnits(input: ApiRuntimeRenderOptions): { template: string; dropIns: Record; }; export declare function renderPlatformNginx(input: { publicPort: number; initialSlotPort: number; concurrencyLimit?: number; workerDrainSeconds?: number; }): { upstream: string; site: string; }; export interface ActivationBoundary { command: '/usr/local/lib/forgezero/agent/fz-agent'; argv: ['platform-activate', '--config=/etc/forgezero/deploy-activation.json', string]; runAs: 'root'; invoker: 'forgezero-runner'; } /** The caller passes an immutable release path, never a shell command. */ export declare function planPlatformActivation(releasesDirectory: string, releasePath: string): ActivationBoundary; export interface PlatformActivationConfig { root: string; serviceUser: string; /** Stable loopback listener served by nginx/cloudflared. */ publicPort: number; bluePort: number; greenPort: number; /** * Runtime-owned handoff acknowledgement endpoints. The Agent never reads or * transfers runtime state; it only gates traffic switching on these probes. */ runtimeHandoff: { address: string; residentPath: string; readyPath: string; }; healthPath: string; keepReleases: number; drainDeadlineMs?: number; runtimeDrain?: DeploymentDrainDefinition; } /** * Render the fixed privilege boundary used by the credential-free deployment * runner. Repository data supplies one release path; it never supplies shell. */ export declare function renderPlatformActivationFiles(input: PlatformActivationConfig): { environment: string; helper: string; sudoers: string; }; export interface PlatformActivationCommandResult { exitCode: number; output: string; } export type PlatformActivationExec = (argv: readonly string[]) => Promise; export interface PlatformReleaseIdentity { revision: string; artifactDigest: `sha256:${string}`; } export interface PlatformActivationResult extends PlatformReleaseIdentity { release: string; slot: ApiSlot; switchedAtTs: number; drain: RuntimeDrainResult & { oldSlotRetired: boolean; }; } export declare const assertReleaseLinksContained: (path: string) => void; /** Agent-native blue/green activation with health and nginx rollback. */ export declare function activatePlatformRelease(config: PlatformActivationConfig, requestedRelease: string, options?: { exec?: PlatformActivationExec; fetch?: typeof fetch; sleep?: (ms: number) => Promise; /** Test seam; production always uses the root-owned nginx include. */ upstreamPath?: string; /** Test seam; production always uses the root-owned volatile directory. */ runtimeControlDirectory?: string; /** Test seam; production always writes the directory and files as root. */ runtimeControlOwner?: { uid: number; gid: number; }; expectedIdentity?: PlatformReleaseIdentity; expectedDrain?: DeploymentDrainDefinition; inspectRelease?: (release: string) => Promise; }): Promise; export interface LocalOtlpProofPlan { unitCheck: { command: 'systemctl'; argv: ['is-active', '--quiet', string]; }; receiverCheck: { command: 'curl'; argv: string[]; acceptedStatus: '2xx'; }; } export declare function planLocalOtlpProof(endpoint: string, collectorUnit: string): LocalOtlpProofPlan;