fix(nexus-db): UTF8-Encoding zur Installationszeit erzwingen (#8) #9

Merged
l.kirchner merged 2 commits from fix/nexus-db-utf8-encoding into main 2026-06-13 14:38:58 +02:00
Member

Closes #8

Behebt #8 (nexus-db SQL_ASCII-Härtung).

Realer Vorfall: Ein vor dem K-114-locale-Fix provisionierter nexus-db-LXC lief bei initdb unter LANG=C → Cluster/DB entstand mit SQL_ASCII. Folge: psql unauffällig, aber psycopg3 liefert Text als bytes ⇒ SQLAlchemy crasht bei der Server-Versions-Erkennung, App meldet db: unreachable. Encoding ist bei initdb eingefroren — nicht nachträglich änderbar.

Änderungen (lib/install.func als Muster für künftige DB-Installer + install/nexus-db-install.sh):

  1. Locale aktiv zum initdb-Zeitpunktensure_utf8_locale_active: generiert en_US.UTF-8 (idempotent) und exportiert LANG/LC_ALL für den Install-Prozess, bevor das Server-Paket sein automatisches initdb fährt; bricht ab, wenn die Locale danach nicht in locale -a auftaucht (generiert ≠ aktiv).
  2. Explizite DB-Anlage mit ENCODING 'UTF8' LC_COLLATE/LC_CTYPE 'en_US.UTF-8' TEMPLATE template0 — unabhängig vom Cluster-Default.
  3. Post-Install-Checkassert_db_encoding_utf8: SELECT pg_encoding_to_char(encoding) … WHERE datname='nexus' muss UTF8 liefern, sonst Abbruch mit handlungsweisender Meldung. Fängt auch eine alte SQL_ASCII-DB beim Re-Run.
  4. Doku auf su - postgres -c … (Credentials-Datei + README) — die minimalen LXCs haben kein sudo.

Mini-CI lokal grün: bash -n über alle Scripts, check_ct_source.sh, test_validation.sh (50/50).

Lessons-Log-Eintrag (Wiki) folgt mit dem Merge: „Encoding wird bei initdb eingefroren — eine kaputte Locale zur Installationszeit ist Datenbank-Schaden, kein Schönheitsfehler."

Closes #8 Behebt #8 (nexus-db SQL_ASCII-Härtung). **Realer Vorfall:** Ein vor dem K-114-locale-Fix provisionierter nexus-db-LXC lief bei initdb unter `LANG=C` → Cluster/DB entstand mit `SQL_ASCII`. Folge: psql unauffällig, aber psycopg3 liefert Text als bytes ⇒ SQLAlchemy crasht bei der Server-Versions-Erkennung, App meldet `db: unreachable`. Encoding ist bei initdb eingefroren — nicht nachträglich änderbar. **Änderungen** (`lib/install.func` als Muster für künftige DB-Installer + `install/nexus-db-install.sh`): 1. **Locale aktiv zum initdb-Zeitpunkt** — `ensure_utf8_locale_active`: generiert en_US.UTF-8 (idempotent) **und** exportiert `LANG/LC_ALL` für den Install-Prozess, **bevor** das Server-Paket sein automatisches initdb fährt; bricht ab, wenn die Locale danach nicht in `locale -a` auftaucht (generiert ≠ aktiv). 2. **Explizite DB-Anlage** mit `ENCODING 'UTF8' LC_COLLATE/LC_CTYPE 'en_US.UTF-8' TEMPLATE template0` — unabhängig vom Cluster-Default. 3. **Post-Install-Check** — `assert_db_encoding_utf8`: `SELECT pg_encoding_to_char(encoding) … WHERE datname='nexus'` muss `UTF8` liefern, sonst Abbruch mit handlungsweisender Meldung. Fängt auch eine alte SQL_ASCII-DB beim Re-Run. 4. **Doku auf `su - postgres -c …`** (Credentials-Datei + README) — die minimalen LXCs haben kein sudo. **Mini-CI lokal grün:** `bash -n` über alle Scripts, `check_ct_source.sh`, `test_validation.sh` (50/50). Lessons-Log-Eintrag (Wiki) folgt mit dem Merge: *„Encoding wird bei initdb eingefroren — eine kaputte Locale zur Installationszeit ist Datenbank-Schaden, kein Schönheitsfehler."*
claude-bot added 1 commit 2026-06-13 14:30:57 +02:00
fix(nexus-db): enforce UTF8 encoding at install time (issue #8)
CI / Shell-Lint (bash -n, source-check, Validierungs-Tests) (pull_request) Successful in 1s
bd4293f53e
A PostgreSQL cluster/database freezes its encoding at initdb / CREATE
DATABASE time; a C (non-UTF-8) locale yields a SQL_ASCII cluster, which
makes psycopg3 return bytes and crashes SQLAlchemy. Harden the installer
and add a reusable pattern for future DB installers:

- ensure_utf8_locale_active: generate AND activate en_US.UTF-8 for the
  install process before the server package runs initdb; abort if the
  locale is not actually available
- create the database explicitly with TEMPLATE template0 ENCODING 'UTF8'
  LC_COLLATE/LC_CTYPE 'en_US.UTF-8' instead of inheriting the cluster
  default
- assert_db_encoding_utf8: post-install guard, abort with an actionable
  message if pg_encoding_to_char is not UTF8 (catches old SQL_ASCII DBs
  on re-run too)
- credentials/README docs use su - postgres -c (minimal LXCs have no sudo)
l.kirchner added 1 commit 2026-06-13 14:34:36 +02:00
fix(nexus-db): address codex review — early encoding guard, robust helpers
CI / Shell-Lint (bash -n, source-check, Validierungs-Tests) (pull_request) Successful in 2s
6543fd77d8
- assert encoding BEFORE role/password mutation on re-run, so an old
  SQL_ASCII DB aborts with no side effects (codex finding 1)
- ensure_utf8_locale_active honours its locale argument consistently in
  match, locale.gen line and export (codex finding 2)
- assert_db_encoding_utf8 uses argv-clean runuser psql with :'db' literal
  binding instead of nested su -c shell; docs keep su - postgres -c
  (codex finding 3)
Author
Member

Codex-Cross-Review (Triage)

Zwei Runden Codex-Review über MCP. Erste Runde: kein ≥80-Blocker, drei sinnvolle Findings — alle billig und direkt im Scope, daher sofort gefixt (Commit 6543fd7):

Score Finding Fix
70 Encoding-Guard lief erst nach Role-/Passwort-Recovery → Re-Run gegen alte SQL_ASCII-DB rotierte Credentials, bevor er abbrach Früher Guard direkt nach run_psql(): existiert die DB, läuft assert_db_encoding_utf8 vor jeder Role/Passwort-Mutation; Post-Create-Assert in den Create-Zweig verschoben (kein Doppellauf)
55 ensure_utf8_locale_active parametrisiert, prüfte aber hart en_US.UTF-8 Match/locale.gen-Zeile/Export leiten jetzt alle aus $loc ab; Normalisierung (lowercase, Dashes raus) matcht en_US.UTF-8 gegen locale -a-Form en_US.utf8
40 assert_db_encoding_utf8 mit nested su -c-Shell (Quoting vom Caller abhängig) argv-clean runuser -- psql -v db=… :'db'-Literal-Binding; Doku-Beispiele behalten bewusst su - postgres -c (kein sudo auf den LXCs)

Zweite Runde (Delta bd4293f..6543fd7): keine Findings — alle drei sauber erledigt, keine Regressionen (frühe-Guard-Logik lückenlos, Locale-Match korrekt, :'db'-Binding sauber, leeres Ergebnis läuft in den <not found>-Fehlerpfad).

Mini-CI lokal grün (bash -n, source-check, test_validation 50/50). Merge-Go liegt bei Lutz; Issue #8 wird nach Merge geschlossen.

## Codex-Cross-Review (Triage) Zwei Runden Codex-Review über MCP. Erste Runde: **kein ≥80-Blocker**, drei sinnvolle Findings — alle billig und direkt im Scope, daher sofort gefixt (Commit 6543fd7): | Score | Finding | Fix | |---|---|---| | 70 | Encoding-Guard lief erst nach Role-/Passwort-Recovery → Re-Run gegen alte SQL_ASCII-DB rotierte Credentials, bevor er abbrach | Früher Guard direkt nach `run_psql()`: existiert die DB, läuft `assert_db_encoding_utf8` **vor** jeder Role/Passwort-Mutation; Post-Create-Assert in den Create-Zweig verschoben (kein Doppellauf) | | 55 | `ensure_utf8_locale_active` parametrisiert, prüfte aber hart `en_US.UTF-8` | Match/`locale.gen`-Zeile/Export leiten jetzt alle aus `$loc` ab; Normalisierung (lowercase, Dashes raus) matcht `en_US.UTF-8` gegen `locale -a`-Form `en_US.utf8` | | 40 | `assert_db_encoding_utf8` mit nested `su -c`-Shell (Quoting vom Caller abhängig) | argv-clean `runuser -- psql -v db=… :'db'`-Literal-Binding; Doku-Beispiele behalten bewusst `su - postgres -c` (kein sudo auf den LXCs) | Zweite Runde (Delta bd4293f..6543fd7): **keine Findings** — alle drei sauber erledigt, keine Regressionen (frühe-Guard-Logik lückenlos, Locale-Match korrekt, `:'db'`-Binding sauber, leeres Ergebnis läuft in den `<not found>`-Fehlerpfad). Mini-CI lokal grün (bash -n, source-check, test_validation 50/50). Merge-Go liegt bei Lutz; Issue #8 wird nach Merge geschlossen.
l.kirchner merged commit 6fadb27080 into main 2026-06-13 14:38:58 +02:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: luki-net/proxmox-scripts#9