docs: Auftrag fuer Etappe 3 der Mandantentrennung, gemessen statt erinnert
This commit is contained in:
+77
-18
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"timestamp": "2026-09-11T13:00:00.000Z",
|
||||
"timestamp": "2026-09-11T14:30:00.000Z",
|
||||
"phase": null,
|
||||
"phase_name": "Mandantentrennung wirksam machen (Etappenarbeit ausserhalb der Phasen, ueber Quick-Tasks)",
|
||||
"phase_dir": null,
|
||||
@@ -9,30 +9,89 @@
|
||||
"total_tasks": 4,
|
||||
"status": "paused",
|
||||
"completed_tasks": [
|
||||
{"id": 1, "name": "Etappe 1 / forTenant() repariert, Anmeldeweg ueber SECURITY DEFINER, 227 Zugriffe klassifiziert", "status": "done", "commit": "5228f28"},
|
||||
{"id": 2, "name": "Etappe 2 / alle zwoelf Bereiche gebunden, jeder einzeln verifiziert (260909-ipc .. 260911-gwh)", "status": "done", "commit": "1240932"},
|
||||
{"id": 3, "name": "Zwischendurch auf Anweisung des Users: drei Datenbankregeln geschlossen (260910-jab)", "status": "done", "commit": "03fb3bf"}
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Etappe 1 / forTenant() repariert, Anmeldeweg ueber SECURITY DEFINER, 227 Zugriffe klassifiziert",
|
||||
"status": "done",
|
||||
"commit": "5228f28"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Etappe 2 / alle zwoelf Bereiche gebunden, jeder einzeln verifiziert (260909-ipc .. 260911-gwh)",
|
||||
"status": "done",
|
||||
"commit": "1240932"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Zwischendurch auf Anweisung des Users: drei Datenbankregeln geschlossen (260910-jab)",
|
||||
"status": "done",
|
||||
"commit": "03fb3bf"
|
||||
}
|
||||
],
|
||||
"remaining_tasks": [
|
||||
{"id": 4, "name": "WINDOWS #27 schliessen: Relations-Blindstelle der Bestandsaufnahme (include:/_count: in fremde Tabellen) — ZWINGEND vor Etappe 4", "status": "not_started"},
|
||||
{"id": 5, "name": "Etappe 3a: Anmeldenamen pro Mandant eindeutig (Produktentscheidung User 2026-09-10) — Schema @@unique([tenantId, username/email]), Anmeldeweg kennt Mandant VOR der Suche, SECURITY-DEFINER-Funktionen mit zwei Gleichheitsbedingungen", "status": "not_started"},
|
||||
{"id": 6, "name": "Etappe 3b: Benutzerdimension in den Regeln (Produktentscheidung User 2026-09-10) — app.current_user/current_user_id(), forTenant() um userId erweitern, Regeln der zehn nutzerbezogenen Tabellen", "status": "not_started"},
|
||||
{"id": 7, "name": "Etappe 3c: Systemkontext fuer die sechs Hintergrunddienst-Faelle (#21 dkv, #30 settings, vier beides-Uebergaben aus tenders/ldap)", "status": "not_started"},
|
||||
{"id": 8, "name": "Etappe 4: Scharfschalten (DATABASE_URL auf tessera_app) mit rls-preflight.mjs — Vorabpruefung muss die stillen Leere-Faelle #23/#25/#26/#28/#31/#32 abdecken. USER WILL HIER GEFRAGT WERDEN.", "status": "not_started"}
|
||||
{
|
||||
"id": 4,
|
||||
"name": "WINDOWS #27: Quick 260911-mkj — Plan 261e736 gueltig und geprueft, Executor gestartet; git log und .planning/quick/260911-mkj-*/ pruefen ob abgeschlossen",
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Etappe 3b: Benutzerdimension in den Regeln — VOLLSTAENDIGER AUFTRAG in docs/mandantentrennung-etappe3-auftrag.md (Reihenfolge 3b -> 3a -> 3c)",
|
||||
"status": "not_started"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Etappe 3a: Anmeldenamen pro Mandant — siehe docs/mandantentrennung-etappe3-auftrag.md; enthaelt EINE offene Produktfrage (Mandant per Subdomain oder Login-Wahl)",
|
||||
"status": "not_started"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Etappe 3c: Systemkontext fuer die sechs Hintergrunddienst-Faelle — siehe docs/mandantentrennung-etappe3-auftrag.md",
|
||||
"status": "not_started"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Etappe 4: Scharfschalten — USER WILL GEFRAGT WERDEN. Nicht noetig fuer das Live-Gehen am Dienstag 2026-09-15.",
|
||||
"status": "not_started"
|
||||
}
|
||||
],
|
||||
"blockers": [
|
||||
{"description": "Etappe 4 darf erst nach Etappe 3 und nach Schliessen von WINDOWS #27 laufen. Der User hat ausdruecklich verlangt, beim Scharfschalten angehalten und gefragt zu werden.", "type": "process", "workaround": "Reihenfolge einhalten"}
|
||||
{
|
||||
"description": "Etappe 4 darf erst nach Etappe 3 und nach Schliessen von WINDOWS #27 laufen. Der User hat ausdruecklich verlangt, beim Scharfschalten angehalten und gefragt zu werden.",
|
||||
"type": "process",
|
||||
"workaround": "Reihenfolge einhalten"
|
||||
}
|
||||
],
|
||||
"async_jobs": [],
|
||||
"human_actions_pending": [],
|
||||
"decisions": [
|
||||
{"decision": "Anmeldenamen pro Mandant eindeutig, nicht plattformweit", "rationale": "Produktentscheidung des Users am 2026-09-10 — m.schmidt darf es bei Firma A und B geben", "phase": "Etappe 3"},
|
||||
{"decision": "Kollegen derselben Firma strikt getrennt — Benutzerdimension in die Datenbankregeln", "rationale": "Produktentscheidung des Users am 2026-09-10; heute trennt nur der Anwendungscode, die Datenbank kennt nur den Mandanten", "phase": "Etappe 3"},
|
||||
{"decision": "req.tenantPrisma entfernt, Middleware geloescht", "rationale": "Bei jeder Anfrage gebaut, nirgends gelesen; Middleware war nirgends registriert; neun Bereiche haben dienst-internes forTenant() als Konvention festgelegt", "phase": "260911-e2s"},
|
||||
{"decision": "Datenbankregeln VOR Abschluss von Etappe 2 vorgezogen", "rationale": "Ausdrueckliche Anweisung des Users am 2026-09-10 — offene Loecher werden vergessen", "phase": "260910-jab"},
|
||||
{"decision": "Datenverlust in der Datenbank ist derzeit hinnehmbar", "rationale": "User 2026-09-09: nichts laeuft produktiv. Gilt nur solange das so bleibt.", "phase": "Etappe 4 (Vorgriff)"}
|
||||
{
|
||||
"decision": "Anmeldenamen pro Mandant eindeutig, nicht plattformweit",
|
||||
"rationale": "Produktentscheidung des Users am 2026-09-10 — m.schmidt darf es bei Firma A und B geben",
|
||||
"phase": "Etappe 3"
|
||||
},
|
||||
{
|
||||
"decision": "Kollegen derselben Firma strikt getrennt — Benutzerdimension in die Datenbankregeln",
|
||||
"rationale": "Produktentscheidung des Users am 2026-09-10; heute trennt nur der Anwendungscode, die Datenbank kennt nur den Mandanten",
|
||||
"phase": "Etappe 3"
|
||||
},
|
||||
{
|
||||
"decision": "req.tenantPrisma entfernt, Middleware geloescht",
|
||||
"rationale": "Bei jeder Anfrage gebaut, nirgends gelesen; Middleware war nirgends registriert; neun Bereiche haben dienst-internes forTenant() als Konvention festgelegt",
|
||||
"phase": "260911-e2s"
|
||||
},
|
||||
{
|
||||
"decision": "Datenbankregeln VOR Abschluss von Etappe 2 vorgezogen",
|
||||
"rationale": "Ausdrueckliche Anweisung des Users am 2026-09-10 — offene Loecher werden vergessen",
|
||||
"phase": "260910-jab"
|
||||
},
|
||||
{
|
||||
"decision": "Datenverlust in der Datenbank ist derzeit hinnehmbar",
|
||||
"rationale": "User 2026-09-09: nichts laeuft produktiv. Gilt nur solange das so bleibt.",
|
||||
"phase": "Etappe 4 (Vorgriff)"
|
||||
}
|
||||
],
|
||||
"uncommitted_files": [],
|
||||
"next_action": "WINDOWS #27 schliessen (Relations-Blindstelle), dann Etappe 3 planen. NICHT direkt scharfschalten.",
|
||||
"context_notes": "Etappe 2 lief ueber zwoelf Quick-Tasks plus einen Regel-Durchlauf, jeder mit Planer, Plan-Pruefer, Executor, Verifizierer. ZEHN Lieferungen wurden vom jeweils NAECHSTEN Schritt gefangen, nie vom eigenen: vier geschrumpfte Zaehlungen, zwei nicht committete Messungen, zwei Zusammenfassungen mit N statt N-1, handgepflegte Dokumentstellen uebersprungen, Falsifizierungsnachweise nur in Commit-Nachrichten, eine Wegwerf-Tabelle ohne createdAt/updatedAt, ein Selbstwiderspruch, ein Pruefer der etwas als plausibel durchwinkte, ein still fehlgeschlagener git add, und zwei Agenten die am Sitzungslimit NACH getaner Arbeit abbrachen (dkv-Executor, gwh-Planer — beide Male lag die Arbeit vollstaendig auf der Platte; git status ist die Wahrheit, nicht der Bericht). Die vollstaendige Liste steht in jedem Planer-Auftrag der spaeten Bereiche. Nebenfunde ohne Mandantenbezug, alle behoben: DKV-Download-Luecke, drohender DKV-Passwortverlust, Selbstloesch-Riegel der nie griff, Startfehler bei Neuinstallation, adminResetPassword ohne Mandanten- und Rollenpruefung, Widget-Besitzriegel bei Favoriten, sechs luegende Kommentare, und fuenf Bereiche ohne jede Testdatei."
|
||||
}
|
||||
"next_action": "1. Pruefen ob 260911-mkj fertig ist (git status, git log, SUMMARY vorhanden?) — wenn ja verifizieren, abbuchen, pushen. 2. docs/mandantentrennung-etappe3-auftrag.md lesen. 3. Etappe 3b als /gsd-quick --validate starten. NICHT nachfragen ausser beim Scharfschalten.",
|
||||
"context_notes": "USER-ANWEISUNG 2026-09-11: 'mach #27 und dann Etappe 3, nicht nachfragen. du machst alles, was ohne mich geht. am dienstag geht eine voll funktionsfaehige version live.' Live-Gehen braucht den Schalter NICHT (ein Mandant, BYPASSRLS-Stand laeuft heute auf alpha). Etappe 3 darf das Live-Gehen nicht blockieren. Nach jedem Durchlauf pushen. Die vorige Sitzung endete mit ~65% Kontext waehrend #27 lief; der Etappe-3-Auftrag wurde deshalb als eigenes Dokument geschrieben, gemessen statt erinnert. Etappe 2 lief ueber zwoelf Quick-Tasks plus einen Regel-Durchlauf, jeder mit Planer, Plan-Pruefer, Executor, Verifizierer. ZEHN Lieferungen wurden vom jeweils NAECHSTEN Schritt gefangen, nie vom eigenen: vier geschrumpfte Zaehlungen, zwei nicht committete Messungen, zwei Zusammenfassungen mit N statt N-1, handgepflegte Dokumentstellen uebersprungen, Falsifizierungsnachweise nur in Commit-Nachrichten, eine Wegwerf-Tabelle ohne createdAt/updatedAt, ein Selbstwiderspruch, ein Pruefer der etwas als plausibel durchwinkte, ein still fehlgeschlagener git add, und zwei Agenten die am Sitzungslimit NACH getaner Arbeit abbrachen (dkv-Executor, gwh-Planer — beide Male lag die Arbeit vollstaendig auf der Platte; git status ist die Wahrheit, nicht der Bericht). Die vollstaendige Liste steht in jedem Planer-Auftrag der spaeten Bereiche. Nebenfunde ohne Mandantenbezug, alle behoben: DKV-Download-Luecke, drohender DKV-Passwortverlust, Selbstloesch-Riegel der nie griff, Startfehler bei Neuinstallation, adminResetPassword ohne Mandanten- und Rollenpruefung, Widget-Besitzriegel bei Favoriten, sechs luegende Kommentare, und fuenf Bereiche ohne jede Testdatei."
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
# Mandantentrennung — Etappe 3: Auftrag fuer die naechste Sitzung
|
||||
|
||||
Geschrieben am 2026-09-11 am Ende der Sitzung, die Etappe 2 abgeschlossen hat.
|
||||
Zweck: Eine frische Sitzung soll Etappe 3 ohne Rueckfrage und ohne Neuermittlung
|
||||
der Grundlagen beginnen koennen. Alles hier ist gemessen, nicht erinnert.
|
||||
|
||||
## Randbedingungen vom User (2026-09-11)
|
||||
|
||||
- **Dienstag, 2026-09-15, geht die erste voll funktionsfaehige Version live.**
|
||||
Live-Gehen braucht den Schalter NICHT — heute laeuft alpha mit dem
|
||||
BYPASSRLS-Stand und einem Mandanten, und das ist fuer den Betrieb
|
||||
unerheblich. Etappe 3 darf das Live-Gehen nicht blockieren.
|
||||
- **Nicht nachfragen.** Alles machen, was ohne den User geht. Was nicht ohne
|
||||
ihn geht, am Ende benennen.
|
||||
- **Beim Scharfschalten (Etappe 4) anhalten und fragen.** Das ist die einzige
|
||||
Ausnahme, und sie steht seit dem 2026-09-09.
|
||||
- **Nach jedem abgeschlossenen Durchlauf pushen** (`git push` genuegt, die
|
||||
Push-URL zeigt auf localhost:3002).
|
||||
|
||||
## Stand beim Einstieg
|
||||
|
||||
- Etappe 2 abgeschlossen, alle zwoelf Bereiche gebunden, jeder einzeln
|
||||
verifiziert. Endstand 994 Tests / 62 Dateien, 137 Live-Pruefungen,
|
||||
Klassifikation 65 Paare / 68 ungebunden / 178 gebunden.
|
||||
- WINDOWS #27 (Relations-Blindstelle der Bestandsaufnahme) ist als Quick-Task
|
||||
`260911-mkj` in Arbeit oder abgeschlossen — `git log` und
|
||||
`.planning/quick/260911-mkj-*/` pruefen. Nach dessen Abschluss: 72 Paare.
|
||||
- Der Schalter ist AUS. `DATABASE_URL` zeigt auf Rolle `tessera`.
|
||||
|
||||
## Die zwei Produktentscheidungen (User, 2026-09-10)
|
||||
|
||||
1. **Anmeldenamen pro Mandant eindeutig**, nicht plattformweit. `m.schmidt`
|
||||
darf es bei Firma A und Firma B geben.
|
||||
2. **Kollegen derselben Firma strikt getrennt.** Jeder sieht nur seine eigenen
|
||||
gespeicherten Suchen, Favoriten, Dashboard-Anordnung.
|
||||
|
||||
## Etappe 3 in drei Teilen — empfohlene Reihenfolge
|
||||
|
||||
### 3b zuerst: Benutzerdimension in den Regeln
|
||||
|
||||
Warum zuerst: reiner Datenbank- und Helfer-Umbau, beruehrt den Anmeldeweg
|
||||
NICHT, und schliesst die Klasse von Befunden, die in sieben Bereichen als
|
||||
"Policy hat keine Benutzerdimension" festgehalten wurde.
|
||||
|
||||
Gemessene Grundlagen:
|
||||
- `forTenant(prisma, tenantId)` in `apps/api/src/prisma/prisma-tenant.extension.ts:111`
|
||||
setzt genau EINE Sitzungsvariable: `set_config('app.current_tenant', ..., true)`.
|
||||
`current_tenant_id()` ist in `20260618112133_rls_policies` definiert.
|
||||
- Es gibt KEIN `app.current_user` und KEIN `current_user_id()` — nirgends in
|
||||
Migrationen oder Quelltext.
|
||||
- **14 Modelle tragen eine `userId`-Spalte:** CalendarSource, DashboardLayout,
|
||||
FavoriteLink, GroupMembership, ModuleGrant, PasswordResetToken, SearchProvider,
|
||||
TenderEmailConfig, TenderMatch, TenderNotificationPref, TenderRssFeedSource,
|
||||
TenderSavedSearch, TenderTriage, WidgetInstance. NICHT alle davon sind
|
||||
"persoenliche Daten": GroupMembership und ModuleGrant sind
|
||||
Verwaltungsobjekte (ein Admin darf sie fuer andere sehen),
|
||||
PasswordResetToken ist ein Anmelde-Artefakt, TenderMatch wird vom
|
||||
Hintergrunddienst je Treffer geschrieben. Die Benutzerdimension gehoert
|
||||
auf die ZEHN echten Nutzerobjekte; welche das sind, ist je Modell zu
|
||||
entscheiden und am Ort zu begruenden — Vorgabe aus den Bereichs-Kritiken:
|
||||
CalendarSource, DashboardLayout, FavoriteLink, SearchProvider (persoenliche
|
||||
Zeilen), TenderEmailConfig, TenderNotificationPref, TenderRssFeedSource
|
||||
(persoenliche Zeilen), TenderSavedSearch, TenderTriage, WidgetInstance.
|
||||
- Der Anwendungscode trennt heute bereits korrekt nach Benutzer (in jedem
|
||||
Bereich stichprobenartig belegt, Besitzpruefungen in ldap/dkv/dashboard/
|
||||
calendar/favorites/auth als Tests festgenagelt). Die Datenbank tut es
|
||||
nicht. Das zweite Netz fehlt.
|
||||
|
||||
Bauform, an der es sich zu orientieren gilt:
|
||||
- Zweite Sitzungsvariable `app.current_user`, Funktion `current_user_id()`
|
||||
nach dem Muster von `current_tenant_id()`.
|
||||
- `forTenant()` bekommt einen optionalen dritten Parameter `userId` (oder
|
||||
ein Schwesterhelfer `forTenantAndUser()` — Entscheidung im Plan, mit
|
||||
Begruendung; Praezedenz fuer "Helfer erweitern statt zweiten bauen" ist
|
||||
`withTenantTransaction()`). Hintergrunddienste und Verwaltungswege rufen
|
||||
weiter ohne userId; nur die Nutzer-CRUD-Wege setzen ihn.
|
||||
- Regeln der zehn Tabellen: Lesen `tenantId = current_tenant_id() AND
|
||||
(current_user_id() IS NULL OR userId = current_user_id())` — damit ein
|
||||
Aufruf OHNE gesetzten Benutzer (Admin, Hintergrunddienst) weiter alles
|
||||
des Mandanten sieht. Schreiben analog. Das IS-NULL-Muster ist die Form aus
|
||||
der #19-Loesung (260910-jab), dort fuer plattformweite Zeilen.
|
||||
- Messen, nicht annehmen: `rls-scratch-check.mjs` bekommt einen Abschnitt
|
||||
je umgestellter Tabelle, ueber den GENERIERTEN Client, mit
|
||||
schemagleicher Wegwerf-Tabelle (Spaltenvergleich zur Laufzeit —
|
||||
`createdAt`/`updatedAt`-Falle aus 260910-krx).
|
||||
- Die drei loch-behauptenden Pruefungen aus `tenders` und `dashboard`
|
||||
("Policies haben keine Benutzerdimension", z. B.
|
||||
`tendersavedsearch-fremder-nutzer-desselben-mandanten-sichtbar`)
|
||||
UMDREHEN, nicht loeschen — Muster aus 260910-jab.
|
||||
|
||||
### 3a danach: Anmeldenamen pro Mandant
|
||||
|
||||
Warum danach: aendert das Schema UND den Anmeldeweg, ist der riskanteste
|
||||
Teil, und braucht 3b nicht.
|
||||
|
||||
Gemessene Grundlagen:
|
||||
- `User.username String @unique` und `User.email String? @unique`
|
||||
(`schema.prisma:31-32`) — plattformweit.
|
||||
- Die drei SECURITY-DEFINER-Funktionen in
|
||||
`20260909160000_auth_lookup_functions`: `auth_lookup_user_by_username(p_username)`,
|
||||
`auth_lookup_user_by_email(p_email)`, `auth_lookup_reset_token(p_token)`.
|
||||
Jede sucht ueber EINE Gleichheitsbedingung mit `LIMIT 1`. Der Mandant
|
||||
kommt erst AUS der gefundenen Zeile.
|
||||
- Aufrufer: `auth.service.ts:95,110,218` und `user.service.ts:33`.
|
||||
- Bewusst ungebundene Stellen, die genau an dieser plattformweiten
|
||||
Eindeutigkeit haengen und mit 3a fallen: `ldap.service.ts`
|
||||
`resolveEmailForWrite` (260909-ipc, Befund A), die P2002-Kollisionskette in
|
||||
`tenders`/`user` (unsichtbare Zeile -> falsches "frei" -> harter Fehler),
|
||||
`user.service.ts` `findByUsername` (null Aufrufer, 260910-das).
|
||||
|
||||
Bauform:
|
||||
- Schema: `@@unique([tenantId, username])`, `@@unique([tenantId, email])`
|
||||
statt `@unique`. Migration mit Datenpruefung davor (heute ein Mandant,
|
||||
also keine Kollision moeglich — trotzdem messen).
|
||||
- Der Anmeldeweg muss den Mandanten kennen, BEVOR er die Zeile sucht.
|
||||
Zwei uebliche Wege: (i) eigene Adresse je Mandant (Subdomain
|
||||
`firma-a.tessera.ctl.de` -> Mandant aus dem Host), (ii) Mandantenwahl
|
||||
beim Login. **Das ist eine Produktfrage, die der User NICHT beantwortet
|
||||
hat.** Empfehlung fuer die Planung: (i), weil Tessera hinter Nginx Proxy
|
||||
Manager laeuft und Subdomains dort trivial sind, und weil (ii) den
|
||||
Anmeldenamen als Geheimnis schwaecht. Wenn die Planung das anders sieht,
|
||||
ist es einer der Punkte, die am Ende dem User genannt werden.
|
||||
- Die drei Funktionen bekommen eine zweite Gleichheitsbedingung
|
||||
(`p_tenant_id`) — ENGER, nicht weiter. Die Kopfkommentare in
|
||||
`docs/mandantentrennung-datenbankrolle.md` nachziehen.
|
||||
- Bis der Mandant vor der Suche bekannt ist, laesst sich 3a NICHT
|
||||
scharfschalten. Deshalb ist 3a fuer Dienstag NICHT noetig: mit einem
|
||||
Mandanten ist plattformweit = pro Mandant.
|
||||
|
||||
### 3c zuletzt: Systemkontext fuer die Hintergrunddienste
|
||||
|
||||
Sechs Faelle, alle im Abschnitt "Der Hintergrunddienst als Falle" der
|
||||
Klassifikation und in den Bereichs-Kritiken:
|
||||
- `dkv-scheduler` / `loadAnyActiveConfigForScheduler()` (WINDOWS #21) —
|
||||
heute bereits falsch (willkuerlicher Mandant).
|
||||
- `mail.module` / `loadAnySmtpConfigForStartupTransport()` (WINDOWS #30) —
|
||||
dieselbe Form.
|
||||
- `ldap-config.service` `getAllActiveConfigs()` / `onApplicationBootstrap`
|
||||
— heute korrekt, verstummt spaeter.
|
||||
- `tender-digest.scheduler`, `tender-matching.service` — uebergreifende
|
||||
Haelften an Etappe 3 uebergeben (260909-laa).
|
||||
- `admin-seed.service` `ensureDefaultGroupsForAllTenants` — Schleife ueber
|
||||
alle Mandanten, Rumpf bereits gebunden.
|
||||
|
||||
Bauform: Ein benannter Systemkontext (z. B. `forSystem(prisma)`), der eine
|
||||
DRITTE Sitzungsvariable `app.system_context = 'true'` setzt, und Regeln,
|
||||
die diesen Kontext fuer LESENDE Zugriffe zulassen (`OR current_setting(
|
||||
'app.system_context', true) = 'true'`). Schreibzugriffe innerhalb der
|
||||
Schleife bleiben je Mandant gebunden. Der DKV- und der SMTP-Startpfad
|
||||
werden dann zu "einmal-abfragen-viele-bedienen" — das ist die in 07-04
|
||||
zurueckgestellte Mehrmandanten-Planung und der einzige echte
|
||||
Funktionsausbau in Etappe 3.
|
||||
|
||||
## Was NICHT ohne den User geht
|
||||
|
||||
- **3a, Weg (i) vs. (ii):** wie der Mandant beim Login bestimmt wird.
|
||||
- **Etappe 4:** Scharfschalten. Ausdruecklich.
|
||||
|
||||
## Werkzeuge und Fallen (aus Etappe 2, jede mindestens einmal erlebt)
|
||||
|
||||
- `git status` ist die Wahrheit, nicht der Agentenbericht. Zwei Agenten
|
||||
brachen am Sitzungslimit NACH getaner Arbeit ab.
|
||||
- Ein `grep -c` ist eine Behauptung. Vier Kopfzahlen schrumpften beim
|
||||
Hineinsehen.
|
||||
- Eine nicht committete Messung ist kein Beleg (zweimal passiert).
|
||||
- Zusammenfassungen behaupten N, wo N-1 geliefert ist (zweimal passiert).
|
||||
- Handgepflegte Dokumentstellen werden uebersprungen — Gates ABLEITEN.
|
||||
- Roh-SQL ist nicht der generierte Client (Wegwerf-Tabelle ohne
|
||||
`createdAt`/`updatedAt`).
|
||||
- Ein Plan-Pruefer, der "plausibel" sagt, hat nicht geprueft.
|
||||
- `git add` mit mehreren Pfaden, einer davon geloescht, scheitert still.
|
||||
- Der Datenbank-Container hat keinen Host-Port: IP per `docker inspect`
|
||||
frisch ermitteln, `tessera:tessera_dev`. Prisma-Binary aus
|
||||
`apps/api/node_modules/.bin/prisma`, NICHT `npx prisma` (zieht Prisma 8).
|
||||
- Kein `mailhog` lokal — `ENOTFOUND mailhog` ist Umgebung, kein Defekt.
|
||||
- Backticks in Heredoc-Python werden von der Shell ausgewertet — Skripte
|
||||
in eine Datei schreiben, dann ausfuehren.
|
||||
|
||||
## Einstieg
|
||||
|
||||
`/gsd-resume-work`, dann `/gsd-quick` fuer 3b mit `--validate`. Planer,
|
||||
Plan-Pruefer, Executor, Verifizierer — die Kette vollstaendig, jede
|
||||
Lieferung wurde in Etappe 2 vom jeweils naechsten Schritt gefangen, nie
|
||||
vom eigenen.
|
||||
Reference in New Issue
Block a user