Wiki mit semantischer Suche ueber pgvector, Diktat ueber faster-whisper, Berichtsassistent und Belegerfassung — alles gegen selbst betriebene Modelle. Dazu zwei Protokollansichten: was die Maschine getan hat und was Menschen getan haben. Nichts, was ein Modell erzeugt, gelangt ungeprueft in einen Nachweis. Jede Ausgabe ist zuerst ein eigener Datensatz, gekennzeichnet, mit zwei gleich grossen Knoepfen davor. Die Datenbank haelt gegen: Eingabe, Ausgabe und Modell sind unveraenderlich, geloescht wird nicht, entschieden wird einmal. Kein Rueckfall auf einen Anbieter: fehlen die Container, fehlt die Funktion. Dafuer bleibt alles andere ohne Modell vollstaendig benutzbar — geprueft von vierzehn E2E-Tests, die ohne laufendes Modell durchlaufen. Postgres bringt jetzt PostGIS und pgvector mit (eigenes Image), Ollama und faster-whisper stehen im Compose-Profil "ki". 73 neue Unit-Tests, 14 neue E2E-Tests, Version 0.9.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
82 lines
3.9 KiB
Bash
82 lines
3.9 KiB
Bash
#!/bin/bash
|
|
# =============================================================================
|
|
# Läuft EINMALIG beim allerersten Start des Postgres-Containers (leeres
|
|
# Datenverzeichnis). Richtet ein:
|
|
# - die benötigten Erweiterungen (PostGIS, pgvector, pgcrypto, citext,
|
|
# unaccent, pg_trgm)
|
|
# - den Anwendungsbenutzer "florian_app" OHNE BYPASSRLS
|
|
# - Vorgabeprivilegien, damit künftige Tabellen automatisch nutzbar sind
|
|
#
|
|
# Wichtig zum Verständnis der Mandantentrennung:
|
|
# Der Eigentümer der Tabellen (POSTGRES_USER) umgeht Row Level Security —
|
|
# das ist gewollt, damit Migrationen und das Seed-Skript arbeiten können.
|
|
# Die Anwendung verbindet sich ausschließlich als "florian_app"; für den
|
|
# greift RLS, und ohne gesetztes app.current_organisation sieht er nichts.
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
APP_ROLE="florian_app"
|
|
APP_PASSWORD="${POSTGRES_APP_PASSWORD:?POSTGRES_APP_PASSWORD muss gesetzt sein}"
|
|
# Einfache Anführungszeichen im Passwort für SQL verdoppeln.
|
|
APP_PASSWORD_SQL="${APP_PASSWORD//\'/\'\'}"
|
|
|
|
echo "[florian-init] Richte Erweiterungen und Anwendungsrolle ein ..."
|
|
|
|
# Erweiterungen. Reines SQL, keine Variablen nötig.
|
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-'EOSQL'
|
|
CREATE EXTENSION IF NOT EXISTS postgis; -- Koordinaten, Einsatzorte
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- gen_random_uuid(), digest()
|
|
CREATE EXTENSION IF NOT EXISTS citext; -- E-Mail ohne Gross/Klein
|
|
CREATE EXTENSION IF NOT EXISTS unaccent; -- Suche ueber Umlaute hinweg
|
|
CREATE EXTENSION IF NOT EXISTS pg_trgm; -- unscharfe Namenssuche
|
|
CREATE EXTENSION IF NOT EXISTS vector; -- semantische Suche im Wiki
|
|
EOSQL
|
|
|
|
# Anwendungsrolle anlegen. Bewusst OHNE DO-Block: psql ersetzt seine Variablen
|
|
# nicht innerhalb dollar-quotierter Zeichenketten. Stattdessen erzeugt die
|
|
# Abfrage den CREATE-Befehl als Text, den \gexec dann ausführt — und zwar nur,
|
|
# wenn die Rolle noch nicht existiert.
|
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
|
SELECT format(
|
|
'CREATE ROLE %I LOGIN PASSWORD %L NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOBYPASSRLS',
|
|
'${APP_ROLE}', '${APP_PASSWORD_SQL}'
|
|
)
|
|
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${APP_ROLE}')
|
|
\gexec
|
|
|
|
ALTER ROLE "${APP_ROLE}" PASSWORD '${APP_PASSWORD_SQL}';
|
|
ALTER ROLE "${APP_ROLE}" SET timezone TO 'Europe/Berlin';
|
|
EOSQL
|
|
|
|
# Rechtevergabe. Hier funktionieren psql-Variablen, weil kein DO-Block im Spiel
|
|
# ist.
|
|
psql -v ON_ERROR_STOP=1 \
|
|
--username "$POSTGRES_USER" \
|
|
--dbname "$POSTGRES_DB" \
|
|
-v app_role="$APP_ROLE" \
|
|
-v datenbank="$POSTGRES_DB" \
|
|
-v owner="$POSTGRES_USER" <<-'EOSQL'
|
|
GRANT CONNECT ON DATABASE :"datenbank" TO :"app_role";
|
|
GRANT USAGE ON SCHEMA public TO :"app_role";
|
|
|
|
-- Rechte auf alles, was heute schon existiert (bei Erstinstallation leer).
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO :"app_role";
|
|
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO :"app_role";
|
|
|
|
-- Und auf alles, was der Eigentuemer kuenftig anlegt (Prisma-Migrationen).
|
|
ALTER DEFAULT PRIVILEGES FOR ROLE :"owner" IN SCHEMA public
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO :"app_role";
|
|
ALTER DEFAULT PRIVILEGES FOR ROLE :"owner" IN SCHEMA public
|
|
GRANT USAGE, SELECT ON SEQUENCES TO :"app_role";
|
|
ALTER DEFAULT PRIVILEGES FOR ROLE :"owner" IN SCHEMA public
|
|
GRANT EXECUTE ON FUNCTIONS TO :"app_role";
|
|
|
|
-- Die Anwendung darf keine Tabellen anlegen oder loeschen.
|
|
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
|
REVOKE CREATE ON SCHEMA public FROM :"app_role";
|
|
|
|
ALTER DATABASE :"datenbank" SET timezone TO 'Europe/Berlin';
|
|
EOSQL
|
|
|
|
echo "[florian-init] Anwendungsrolle '$APP_ROLE' eingerichtet (RLS wirksam)."
|