CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username TEXT NOT NULL UNIQUE, race_key TEXT NOT NULL DEFAULT 'human', created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS planets ( id SERIAL PRIMARY KEY, user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, name TEXT NOT NULL, class_key TEXT NOT NULL, planet_seed INT NOT NULL DEFAULT 0, temperature_c INT NOT NULL DEFAULT 0, modifiers TEXT NOT NULL, resources TEXT NOT NULL, last_resource_update_at TIMESTAMP NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS planet_buildings ( id SERIAL PRIMARY KEY, planet_id INT NOT NULL REFERENCES planets(id) ON DELETE CASCADE, building_key TEXT NOT NULL, count INT NOT NULL DEFAULT 0, level INT NOT NULL DEFAULT 0, UNIQUE (planet_id, building_key) ); CREATE TABLE IF NOT EXISTS build_jobs ( id SERIAL PRIMARY KEY, planet_id INT NOT NULL REFERENCES planets(id) ON DELETE CASCADE, building_key TEXT NOT NULL, mode TEXT NOT NULL, delta_count INT, target_level INT, started_at TIMESTAMP NOT NULL, finish_at TIMESTAMP NOT NULL, slot_index INT NOT NULL ); CREATE TABLE IF NOT EXISTS roles ( id SERIAL PRIMARY KEY, key TEXT NOT NULL UNIQUE, name TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS permissions ( id SERIAL PRIMARY KEY, key TEXT NOT NULL UNIQUE, module TEXT NOT NULL, description TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS role_permissions ( role_id INT NOT NULL REFERENCES roles(id) ON DELETE CASCADE, permission_id INT NOT NULL REFERENCES permissions(id) ON DELETE CASCADE, PRIMARY KEY (role_id, permission_id) ); CREATE TABLE IF NOT EXISTS user_roles ( user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, role_id INT NOT NULL REFERENCES roles(id) ON DELETE CASCADE, PRIMARY KEY (user_id, role_id) ); CREATE TABLE IF NOT EXISTS user_permission_overrides ( user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, permission_id INT NOT NULL REFERENCES permissions(id) ON DELETE CASCADE, effect TEXT NOT NULL CHECK (effect IN ('allow', 'deny')), PRIMARY KEY (user_id, permission_id) );