create table if not exists public.operations_stop_aliases ( id text primary key default public.gen_hash_id() check (id ~ '^[0-9a-f]{16}$'), channel_id text not null references public.channels(id) on delete cascade, raw_stop_name text not null, raw_stop_name_normalized text generated always as (lower(btrim(raw_stop_name))) stored, alias_stop_name text not null, created_by uuid not null references auth.users(id) on delete restrict, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), constraint operations_stop_aliases_alias_not_blank check (char_length(btrim(alias_stop_name)) > 0), unique (channel_id, raw_stop_name_normalized) ); create index if not exists idx_operations_stop_aliases_channel on public.operations_stop_aliases(channel_id); alter table public.operations_stop_aliases enable row level security; drop policy if exists "operations_stop_aliases_select_visible" on public.operations_stop_aliases; create policy "operations_stop_aliases_select_visible" on public.operations_stop_aliases for select to authenticated using (public.can_access_channel(channel_id)); drop policy if exists "operations_stop_aliases_insert_admins" on public.operations_stop_aliases; create policy "operations_stop_aliases_insert_admins" on public.operations_stop_aliases for insert to authenticated with check ( created_by = auth.uid() and exists ( select 1 from public.channels c where c.id = channel_id and c.type = 'operations' and public.org_role(c.organization_id) in ('owner', 'admin') ) ); drop policy if exists "operations_stop_aliases_update_admins" on public.operations_stop_aliases; create policy "operations_stop_aliases_update_admins" on public.operations_stop_aliases for update to authenticated using ( exists ( select 1 from public.channels c where c.id = channel_id and c.type = 'operations' and public.org_role(c.organization_id) in ('owner', 'admin') ) ) with check ( exists ( select 1 from public.channels c where c.id = channel_id and c.type = 'operations' and public.org_role(c.organization_id) in ('owner', 'admin') ) ); drop policy if exists "operations_stop_aliases_delete_admins" on public.operations_stop_aliases; create policy "operations_stop_aliases_delete_admins" on public.operations_stop_aliases for delete to authenticated using ( exists ( select 1 from public.channels c where c.id = channel_id and c.type = 'operations' and public.org_role(c.organization_id) in ('owner', 'admin') ) ); drop trigger if exists trg_operations_stop_aliases_updated_at on public.operations_stop_aliases; create trigger trg_operations_stop_aliases_updated_at before update on public.operations_stop_aliases for each row execute procedure public.tg_set_updated_at();