Rechte der Anwendungsrolle als Migration, Traefik-Konfiguration ins Repo
Some checks failed
CI / Lint, Typen, Tests, Build (push) Failing after 6m2s
CI / Integrationstests (echtes Postgres) (push) Failing after 5m22s

Der Umzug in einen eigenen Container hat zwei Luecken aufgedeckt:

1. Die Rechte von alpenwerk_app standen in keiner Migration — sie waren
   auf Supabase von Hand im Dashboard vergeben worden. Auf einer leeren
   Datenbank scheiterte die Anwendung deshalb mit 'permission denied for
   table profiles', bevor die Anmeldeseite erschien.

2. docker-compose.traefik.yml lag nur auf dem Server. Ein frischer Clone
   haette die Anwendung ohne Routing hochgefahren. Zusaetzlich haengt app
   jetzt im Netz 'default', sonst findet es den db-Container nicht.
This commit is contained in:
2026-08-26 10:26:47 +00:00
parent e958bb5c6b
commit af947f094d
3 changed files with 99 additions and 0 deletions

4
.gitignore vendored
View File

@@ -54,3 +54,7 @@ next-env.d.ts
# Datenbank-Sicherungen (enthalten Personendaten) – nie committen.
.backups/
# Datenabzuege aus dem Umzug – enthalten Personendaten
supabase-daten-*.sql
supabase-voll-*.sql

View File

@@ -0,0 +1,22 @@
services:
app:
# Entfernt die Portfreigabe aus der ursprünglichen Datei
ports: !reset []
networks:
- proxy
- default
labels:
traefik.enable: "true"
traefik.docker.network: proxy
traefik.http.routers.alpenwerk.rule: "Host(`${HOST}`)"
traefik.http.routers.alpenwerk.entrypoints: websecure
traefik.http.routers.alpenwerk.tls: "true"
traefik.http.routers.alpenwerk.tls.certresolver: letsencrypt
traefik.http.services.alpenwerk.loadbalancer.server.port: "3000"
networks:
proxy:
external: true
name: proxy

View File

@@ -0,0 +1,73 @@
-- Rechte der Anwendungsrolle alpenwerk_app.
--
-- Auf Supabase wurden diese Rechte von Hand im Dashboard vergeben und standen
-- deshalb in keiner Migration. Beim Umzug in einen eigenen Container fiel das
-- auf: das Schema entstand vollstaendig aus den Migrationen, die Rolle hatte
-- aber weder Tabellen- noch Funktionsrechte — die Anwendung scheiterte mit
-- "permission denied for table profiles", bevor die Anmeldeseite erschien.
--
-- Ohne diese Datei laesst sich das Projekt auf einer leeren Datenbank nicht
-- in Betrieb nehmen. Genau das ist aber das Ziel: ein Container, den der
-- Kunde selbst hochfaehrt.
--
-- Die Rolle bleibt **ohne BYPASSRLS**. Diese Rechte sagen nur, welche Objekte
-- sie ueberhaupt anfassen darf; welche Zeilen sie sieht, entscheiden weiterhin
-- die 58 RLS-Policies.
-- ── Tabellen und Sequenzen ────────────────────────────────────────────
grant select, insert, update, delete on all tables in schema public to alpenwerk_app;
grant usage, select, update on all sequences in schema public to alpenwerk_app;
-- Damit kuenftige Migrationen mit neuen Tabellen nicht dieselbe Panne
-- ausloesen.
alter default privileges in schema public grant select, insert, update, delete on tables to alpenwerk_app;
alter default privileges in schema public grant usage, select, update on sequences to alpenwerk_app;
-- ── Funktionen ────────────────────────────────────────────────────────
-- Bewusst die einzeln aufgezaehlte Liste aus dem Supabase-Bestand und kein
-- pauschales "on all routines": 20260727150000 hat EXECUTE bei einem Teil der
-- SECURITY-DEFINER-Funktionen absichtlich entzogen. Eine Pauschalvergabe
-- machte das rueckgaengig.
grant execute on function public.add_employee_dependent(payload jsonb) to alpenwerk_app;
grant execute on function public.add_employee_note(payload jsonb) to alpenwerk_app;
grant execute on function public.adjust_karenz_return(payload jsonb) to alpenwerk_app;
grant execute on function public.app_aenderung(p_liste jsonb, p_feld text, p_vorher text, p_nachher text) to alpenwerk_app;
grant execute on function public.app_aenderungsfelder(p_liste jsonb) to alpenwerk_app;
grant execute on function public.app_current_user_id() to alpenwerk_app;
grant execute on function public.app_feld_karte() to alpenwerk_app;
grant execute on function public.app_upsert_user(p_external_id text, p_email text, p_full_name text) to alpenwerk_app;
grant execute on function public.apply_due_pending_changes() to alpenwerk_app;
grant execute on function public.change_employee_data(payload jsonb) to alpenwerk_app;
grant execute on function public.complete_employee_note(payload jsonb) to alpenwerk_app;
grant execute on function public.create_position(payload jsonb) to alpenwerk_app;
grant execute on function public.current_actor_name() to alpenwerk_app;
grant execute on function public.current_hr_user_id() to alpenwerk_app;
grant execute on function public.delete_employee_dependent(payload jsonb) to alpenwerk_app;
grant execute on function public.delete_history_entry(payload jsonb) to alpenwerk_app;
grant execute on function public.delete_position(payload jsonb) to alpenwerk_app;
grant execute on function public.fn_check_history_not_before_entry() to alpenwerk_app;
grant execute on function public.fn_touch_profiles_updated_at() to alpenwerk_app;
grant execute on function public.fn_touch_updated_at() to alpenwerk_app;
grant execute on function public.fn_validate_employee_svnr() to alpenwerk_app;
grant execute on function public.generate_company_email(p_first_name text, p_last_name text) to alpenwerk_app;
grant execute on function public.hire_employee(payload jsonb) to alpenwerk_app;
grant execute on function public.is_hr_admin() to alpenwerk_app;
grant execute on function public.is_hr_user() to alpenwerk_app;
grant execute on function public.is_valid_svnr(p_svnr text, p_birth_date date) to alpenwerk_app;
grant execute on function public.next_position_number() to alpenwerk_app;
grant execute on function public.om_reporting_lines(p_as_of date) to alpenwerk_app;
grant execute on function public.promote_employee(payload jsonb) to alpenwerk_app;
grant execute on function public.record_karenz_return(payload jsonb) to alpenwerk_app;
grant execute on function public.rehire_employee(payload jsonb) to alpenwerk_app;
grant execute on function public.require_hr_admin() to alpenwerk_app;
grant execute on function public.rls_auto_enable() to alpenwerk_app;
grant execute on function public.set_offboarding_task(payload jsonb) to alpenwerk_app;
grant execute on function public.set_onboarding_task(payload jsonb) to alpenwerk_app;
grant execute on function public.set_position_cost_center(payload jsonb) to alpenwerk_app;
grant execute on function public.start_karenz(payload jsonb) to alpenwerk_app;
grant execute on function public.start_offboarding(payload jsonb) to alpenwerk_app;
grant execute on function public.start_onboarding(payload jsonb) to alpenwerk_app;
grant execute on function public.terminate_employee(payload jsonb) to alpenwerk_app;
grant execute on function public.transfer_employee(payload jsonb) to alpenwerk_app;
grant execute on function public.update_history_entry(payload jsonb) to alpenwerk_app;
grant execute on function public.update_position(payload jsonb) to alpenwerk_app;