-- Schema bootstrap for the kerbal-rt Postgres + Timescale install. -- Runs automatically on first container start. -- -- See kerbalrealtime-clone-plan.md §Component B for the full data model. -- This is the Phase 0 minimum; Phase 1 fills in the rest. CREATE EXTENSION IF NOT EXISTS timescaledb; CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Bodies (celestial body catalog; small, mostly static) CREATE TABLE IF NOT EXISTS bodies ( id TEXT PRIMARY KEY, name TEXT NOT NULL, kind TEXT NOT NULL CHECK (kind IN ('star','planet','moon','asteroid','comet')), parent_id TEXT REFERENCES bodies(id), radius DOUBLE PRECISION NOT NULL, sphere_of_influence DOUBLE PRECISION NOT NULL, gravitational_parameter DOUBLE PRECISION NOT NULL, rotation_period DOUBLE PRECISION NOT NULL, axial_tilt DOUBLE PRECISION NOT NULL, elements JSONB NOT NULL ); -- Vessels (slowly-changing dimension) CREATE TABLE IF NOT EXISTS vessels ( id TEXT PRIMARY KEY, name TEXT NOT NULL, type TEXT, owner TEXT, status TEXT NOT NULL CHECK (status IN ('ACTIVE','DECOMMISSIONED','LOST')) DEFAULT 'ACTIVE', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), retired_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS vessels_status_idx ON vessels(status); -- Telemetry snapshots (high-volume time series) CREATE TABLE IF NOT EXISTS telemetry_snapshots ( ts TIMESTAMPTZ NOT NULL, ut DOUBLE PRECISION NOT NULL, payload JSONB NOT NULL ); SELECT create_hypertable('telemetry_snapshots', 'ts', if_not_exists => TRUE); CREATE INDEX IF NOT EXISTS telemetry_snapshots_ut_idx ON telemetry_snapshots(ut DESC); -- Mission events CREATE TABLE IF NOT EXISTS mission_events ( id BIGSERIAL PRIMARY KEY, mission TEXT NOT NULL, vessel_id TEXT REFERENCES vessels(id), title TEXT NOT NULL, description TEXT, scheduled_at TIMESTAMPTZ NOT NULL, ut_at_event DOUBLE PRECISION, duration_s INTEGER, kind TEXT NOT NULL CHECK (kind IN ('LAUNCH','BURN','FLYBY','LANDING','DOCKING','EVA','ECLIPSE','OPERATION','OTHER')), created_by TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS mission_events_scheduled_idx ON mission_events(scheduled_at); -- Media CREATE TABLE IF NOT EXISTS media ( id BIGSERIAL PRIMARY KEY, kind TEXT NOT NULL CHECK (kind IN ('image','youtube')), url TEXT NOT NULL, thumbnail_url TEXT, caption TEXT, tags TEXT[] NOT NULL DEFAULT '{}', mission_id TEXT, vessel_id TEXT REFERENCES vessels(id), created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS media_tags_idx ON media USING GIN(tags); CREATE INDEX IF NOT EXISTS media_created_idx ON media(created_at DESC); -- Ground stations CREATE TABLE IF NOT EXISTS ground_stations ( id TEXT PRIMARY KEY, name TEXT NOT NULL, body_id TEXT NOT NULL REFERENCES bodies(id), lat DOUBLE PRECISION NOT NULL, lon DOUBLE PRECISION NOT NULL, alt DOUBLE PRECISION NOT NULL );