docs(auth): use trim_ws in spec
Refs #1 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6891b7cb03
commit
3158abc344
1 changed files with 3 additions and 3 deletions
|
|
@ -76,13 +76,13 @@ Nur additiv: `create or replace function` und neue Objekte, keine Änderung an b
|
|||
|
||||
| Tabelle/Objekt | Spalte | Typ | Hinweis |
|
||||
|---|---|---|---|
|
||||
| `public.profiles` | `display_name` | text | **neuer Check** `profiles_display_name_not_blank`: `char_length(btrim(display_name)) between 1 and 30`. Er gilt auch für KTO-02 (Updates). Bestehende Seed-Zeilen erfüllen ihn. **Zweiter Check** `profiles_display_name_no_zwsp`: `strpos(display_name, chr(8203)) = 0` (U+200B verboten, Update → 23514). Seeds und Bestand enthalten kein U+200B. |
|
||||
| `public.profiles` | `display_name` | text | **neuer Check** `profiles_display_name_not_blank`: `char_length(public.trim_ws(display_name)) between 1 and 30`. Er gilt auch für KTO-02 (Updates). Bestehende Seed-Zeilen erfüllen ihn. **Zweiter Check** `profiles_display_name_no_zwsp`: `strpos(display_name, chr(8203)) = 0` (U+200B verboten, Update → 23514). Seeds und Bestand enthalten kein U+200B. |
|
||||
| `public.profiles` | `terms_version` | text, nullable | **neue Spalte** (F5): Version der zugestimmten Rechtstexte, z. B. `2026-11-draft`. Check `terms_version is null or char_length(terms_version) between 1 and 50`. Nullable nur wegen bereits vorhandener Zeilen (nur Entwicklung); für neue Konten erzwingt der Trigger einen Wert. **Nicht** in den Update-Rechten von `authenticated`, der Nutzer kann sie also nicht ändern. Der Zeitstempel der Zustimmung steht bereits in `terms_accepted_at` (Trigger setzt `now()`). Eine erneute Zustimmung nach einer Änderung der Rechtstexte ist nicht Teil von R1 (siehe 9.4). |
|
||||
| `public.profiles` | `locale` | text | **Standard geändert** auf `'en'` (`alter column locale set default 'en'`, F6). Der Check `('de','en')` bleibt. |
|
||||
| `public.handle_new_user()` | – | Trigger-Funktion | **ersetzt** (`create or replace`). Neue Regeln: (a) Alter und Zustimmung wie bisher. (b) `terms_version := btrim(meta->>'terms_version')`; ist der Wert `null`, leer oder länger als 50 Zeichen, wirft der Trigger `terms_version_required` (P0001). (c) `display_name := btrim(meta->>'display_name')`. Ist der Wert `null`, leer, länger als 30 Codepoints oder enthält U+200B, wirft der Trigger `display_name_invalid` (SQLSTATE P0001). **Kein Rückgriff auf das E-Mail-Präfix, kein Kürzen.** (d) Der getrimmte Name und `terms_version` werden gespeichert, `terms_accepted_at` und `age_confirmed_at` = `now()`. (e) `locale` aus `meta->>'locale'`, wenn `de`/`en`, **sonst `'en'`** (F6). |
|
||||
| `public.handle_new_user()` | – | Trigger-Funktion | **ersetzt** (`create or replace`). Neue Regeln: (a) Alter und Zustimmung wie bisher. (b) `terms_version := public.trim_ws(meta->>'terms_version')`; ist der Wert `null`, leer oder länger als 50 Zeichen, wirft der Trigger `terms_version_required` (P0001). (c) `display_name := public.trim_ws(meta->>'display_name')`. Ist der Wert `null`, leer, länger als 30 Codepoints oder enthält U+200B, wirft der Trigger `display_name_invalid` (SQLSTATE P0001). **Kein Rückgriff auf das E-Mail-Präfix, kein Kürzen.** (d) Der getrimmte Name und `terms_version` werden gespeichert, `terms_accepted_at` und `age_confirmed_at` = `now()`. (e) `locale` aus `meta->>'locale'`, wenn `de`/`en`, **sonst `'en'`** (F6). |
|
||||
| `public.sync_profile_locale_to_auth()` | – | Trigger-Funktion, `security definer`, `search_path = ''` | `after update of locale on public.profiles`, wenn sich der Wert ändert: `update auth.users set raw_user_meta_data = coalesce(raw_user_meta_data,'{}') \|\| jsonb_build_object('locale', new.locale) where id = new.id`. Ausführen nur für den Trigger: `revoke all … from public, anon, authenticated`. |
|
||||
|
||||
**Trim-Regel (verbindlich für Client und Server, auch KTO-02):** Leerraum am Anfang und Ende wird entfernt. Danach muss der Name 1 bis 30 **Unicode-Codepoints** lang sein. Der Server prüft mit `char_length(btrim(…))`, der Client mit `value.trim().runes.length`, **nicht** mit `String.length` (UTF-16). Bekannte Abweichung: Dart-`trim()` entfernt auch Unicode-Leerraum (z. B. NBSP), `btrim` nur Leerzeichen. Der Client sendet bereits getrimmte Werte, die Abweichung ist deshalb nur über die rohe API erreichbar und unkritisch. **Verbotenes Zeichen (Entscheidung Chris):** Ein Anzeigename, der U+200B (Zero Width Space) an irgendeiner Stelle enthält, ist ungültig (Server: `display_name_invalid` bzw. Check `profiles_display_name_no_zwsp`, 23514). U+200B wird nicht getrimmt, sondern abgelehnt. U+200C/U+200D (ZWJ steckt in Emoji-Sequenzen) und U+FEFF (wird getrimmt) sind davon nicht betroffen.
|
||||
**Trim-Regel (verbindlich für Client und Server, auch KTO-02):** Leerraum am Anfang und Ende wird entfernt. Danach muss der Name 1 bis 30 **Unicode-Codepoints** lang sein. Der Server prüft mit `char_length(public.trim_ws(…))`, der Client mit `value.trim().runes.length`, **nicht** mit `String.length` (UTF-16). Bekannte Abweichung: Dart-`trim()` entfernt auch Unicode-Leerraum (z. B. NBSP), `btrim` nur Leerzeichen. Der Client sendet bereits getrimmte Werte, die Abweichung ist deshalb nur über die rohe API erreichbar und unkritisch. **Verbotenes Zeichen (Entscheidung Chris):** Ein Anzeigename, der U+200B (Zero Width Space) an irgendeiner Stelle enthält, ist ungültig (Server: `display_name_invalid` bzw. Check `profiles_display_name_no_zwsp`, 23514). U+200B wird nicht getrimmt, sondern abgelehnt. U+200C/U+200D (ZWJ steckt in Emoji-Sequenzen) und U+FEFF (wird getrimmt) sind davon nicht betroffen.
|
||||
|
||||
**Keine neuen Tabellen.** `auth.users` und `auth.sessions` verwaltet GoTrue.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue