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):
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).
Explizite DB-Anlage mit ENCODING 'UTF8' LC_COLLATE/LC_CTYPE 'en_US.UTF-8' TEMPLATE template0 — unabhängig vom Cluster-Default.
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.
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."*
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)
- 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)
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_utf8vor 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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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 mitSQL_ASCII. Folge: psql unauffällig, aber psycopg3 liefert Text als bytes ⇒ SQLAlchemy crasht bei der Server-Versions-Erkennung, App meldetdb: unreachable. Encoding ist bei initdb eingefroren — nicht nachträglich änderbar.Änderungen (
lib/install.funcals Muster für künftige DB-Installer +install/nexus-db-install.sh):ensure_utf8_locale_active: generiert en_US.UTF-8 (idempotent) und exportiertLANG/LC_ALLfür den Install-Prozess, bevor das Server-Paket sein automatisches initdb fährt; bricht ab, wenn die Locale danach nicht inlocale -aauftaucht (generiert ≠ aktiv).ENCODING 'UTF8' LC_COLLATE/LC_CTYPE 'en_US.UTF-8' TEMPLATE template0— unabhängig vom Cluster-Default.assert_db_encoding_utf8:SELECT pg_encoding_to_char(encoding) … WHERE datname='nexus'mussUTF8liefern, sonst Abbruch mit handlungsweisender Meldung. Fängt auch eine alte SQL_ASCII-DB beim Re-Run.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."
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):run_psql(): existiert die DB, läuftassert_db_encoding_utf8vor jeder Role/Passwort-Mutation; Post-Create-Assert in den Create-Zweig verschoben (kein Doppellauf)ensure_utf8_locale_activeparametrisiert, prüfte aber harten_US.UTF-8locale.gen-Zeile/Export leiten jetzt alle aus$locab; Normalisierung (lowercase, Dashes raus) matchten_US.UTF-8gegenlocale -a-Formen_US.utf8assert_db_encoding_utf8mit nestedsu -c-Shell (Quoting vom Caller abhängig)runuser -- psql -v db=… :'db'-Literal-Binding; Doku-Beispiele behalten bewusstsu - 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.