-- Gebos Postgres bootstrap.
-- Runs once via services.postgresql.initialScript on db-host.
--
-- Sets up:
--   * Extensions Supabase + TimescaleDB need
--   * Supabase's expected schemas and admin roles
--   * The gebos_ingest role (BYPASSRLS) used by the MQTT ingester
--   * A telemetry hypertable with tenant_id column for RLS
--
-- TODO: split into ordered files once it grows. For the skeleton, one file is fine.

create extension if not exists timescaledb;
create extension if not exists pgcrypto;
create extension if not exists pgjwt;
create extension if not exists pg_graphql;
create extension if not exists pgsodium;
-- create extension if not exists supabase_vault;   -- TODO: vendor or package

-- Supabase schemas
create schema if not exists auth;
create schema if not exists storage;
create schema if not exists _analytics;
create schema if not exists _supavisor;

-- Roles Supabase services connect as. Passwords come from secrets.env, not here.
do $$ begin
  create role anon nologin noinherit;
exception when duplicate_object then null; end $$;

do $$ begin
  create role authenticated nologin noinherit;
exception when duplicate_object then null; end $$;

do $$ begin
  create role service_role nologin noinherit bypassrls;
exception when duplicate_object then null; end $$;

do $$ begin
  create role authenticator noinherit login;
  grant anon, authenticated, service_role to authenticator;
exception when duplicate_object then null; end $$;

do $$ begin
  create role supabase_admin login createrole createdb replication bypassrls;
exception when duplicate_object then null; end $$;

do $$ begin
  create role supabase_auth_admin login createrole;
  grant usage on schema auth to supabase_auth_admin;
exception when duplicate_object then null; end $$;

-- Ingester writes telemetry; bypasses RLS because at write time no user is
-- authenticated. Trust boundary is the broker ACL ("who can publish to what
-- tenant's topic"), not the database.
do $$ begin
  create role gebos_ingest login bypassrls;
exception when duplicate_object then null; end $$;

-- Telemetry hypertable. Tenant lives on the row so standard RLS works.
create table if not exists public.telemetry (
  ts          timestamptz not null,
  tenant_id   uuid        not null,
  device_id   uuid        not null,
  metric      text        not null,
  value       double precision,
  payload     jsonb
);

select create_hypertable('public.telemetry', 'ts', if_not_exists => true);

create index if not exists telemetry_tenant_device_ts_idx
  on public.telemetry (tenant_id, device_id, ts desc);

alter table public.telemetry enable row level security;

create policy telemetry_tenant_isolation on public.telemetry
  for select
  using (tenant_id = current_setting('app.tenant_id', true)::uuid);

grant select on public.telemetry to authenticated;
grant insert on public.telemetry to gebos_ingest;
