ACC-71: Ownergebundenes PostgreSQL-Schema und FinanceDataV1-Reader - #21
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Zusammenfassung
Diese PR implementiert ACC-71 und schafft den vollständigen PostgreSQL-Lesepfad für
FinanceDataV1, ohne den produktiven Datenfluss bereits von Google Sheets auf PostgreSQL umzustellen.Enthalten sind:
FinanceDataV1;FinanceDataV1-Stand rekonstruiert;Der bisherige Sheets-Pfad bleibt vollständig produktiv. Diese PR importiert keine bestehenden Daten und verändert
/api/financenicht.Motivation
Google Sheets ist aktuell gleichzeitig Bearbeitungsoberfläche und produktive Finanzquelle. ACC-71 bereitet den kontrollierten Wechsel zu PostgreSQL vor, ohne dabei den bewährten Domänenvertrag oder die bestehende Finanzlogik zu verändern.
Die Persistenz soll dabei:
FinanceDataV1an Selektoren und View-Models liefern.Datenbankschema
Die neue Migration
002_finance_data_v1.sqlwird nach001_google_connections.sqlausgeführt und läuft vollständig in einer Transaktion.Sie legt folgende Tabellen an:
ownersfinance_metaaccountsaccount_snapshotspocketspocket_snapshotsbudget_itemsdebtsdebt_snapshotsdebt_milestonesrelief_milestonesOwner-Modell
ownersverwendet eine interne UUID und ordnet sie eindeutig einem Googlesubzu.Zwischen
ownersundgoogle_connectionsbesteht bewusst kein Foreign Key. Dadurch kann ein späterer Google-Disconnect nicht versehentlich Finanzdaten entfernen.Jede Finance-Tabelle besitzt ein nicht-nullbares
owner_id. Fachliche Primär- und Fremdschlüssel enthalten den Owner, beispielsweise:(owner_id, id)(owner_id, account_id, as_of)(owner_id, id)(owner_id, account_id)(owner_id, debt_id, as_of)Damit können unterschiedliche Owner dieselben fachlichen IDs verwenden, während ownerübergreifende Referenzen von PostgreSQL abgewiesen werden.
Es wurden keine automatischen Lösch-Cascades zwischen Finance-Entitäten eingeführt.
Constraints und Typen
Das Schema erzwingt unter anderem:
BIGINTin Cents;NULLoder nicht leere optionale Notizen;salary_dayunddue_dayzwischen 1 und 31 oderNULL;1;EUR;CHECK-Constraints;Negative Finanzbeträge bleiben erlaubt, da der bestehende v1-Vertrag sie zulässt.
Abgeleitete Werte wie aktuelle Summen,
safeToSpend, Budgetstatus oder ausgewählte Snapshots werden nicht gespeichert.Meilensteinpräzision
Debt- und Relief-Meilensteine speichern:
milestone_date DATEdate_precisionalsmonthoderdayBei Monatspräzision muss der gespeicherte Tag der Monatserste sein. Der Reader rekonstruiert daraus wieder exakt:
YYYY-MMfür Monatspräzision;YYYY-MM-DDfür Tagespräzision.Relief-Meilensteine verwenden eine interne UUID, weil der v1-Vertrag dort keine eindeutige fachliche ID verlangt und doppelte Ereignisse erlaubt.
Gemeinsamer PostgreSQL-Zugang
Mit
api/_lib/database.tsgibt es jetzt einen zentralen, lazy erzeugten PostgreSQL-Pool jeDATABASE_URL.Die bestehende Konfiguration bleibt erhalten:
max: 1idle_timeout: 20connect_timeout: 10prepare: falseDas bestehende Google-Connection-Repository und das neue Finance-Repository verwenden denselben Pool. Dadurch entstehen in einer Vercel-Function-Instanz keine unabhängigen Pools für dieselbe Datenbankverbindung.
Finance-Repository
Das neue Repository implementiert folgenden Vertrag:
Identitäts- und Sicherheitsgrenze
Das Repository nimmt ausschließlich Google
subentgegen. Die Owner-UUID bleibt intern und wird nicht vom Browser geliefert.Der Ablauf ist:
subzuowners.idauflösen.FinanceDataV1zurückgeben.Fehlt der Owner oder besitzt er kein
finance_meta, liefert das Repositorynull. Es wird kein künstlicher leerer Finanzstand erzeugt.Konsistenter Read
Der vollständige Lesevorgang läuft in einer:
Transaktion.
Dadurch stammen Meta-Daten, Entitäten, Snapshots und Meilensteine aus demselben konsistenten Datenbankstand.
Das Repository liest sämtliche gespeicherten Snapshots – einschließlich alter und zukünftiger Einträge. Die fachliche Auswahl des gültigen Snapshots bleibt weiterhin Aufgabe der bestehenden Selektoren.
Deterministische Reihenfolge
Die Ausgabe wird stabil sortiert:
display_orderund ID;Die Reihenfolge ist deterministisch, bildet aber bewusst keine ursprüngliche Sheet-Zeilenreihenfolge nach.
Sichere Typabbildung
PostgreSQL-
BIGINT-Werte werden explizit aus ihrer Stringdarstellung gelesen.Die Mappingfunktion:
number;Number.isSafeInteger;DATE-Werte werden bereits in SQL als ISO-Text formatiert. Dadurch laufen reine Kalendertage nicht durch lokale JavaScript-Zeitzonen.Abschlussvalidierung
Das rekonstruierte Objekt wird vollständig mit
financeDataV1Schemavalidiert.Zusätzlich prüft das Repository, dass jedes aktive Konto, Pocket und jede aktive Schuld mindestens einen Snapshot mit Datum kleiner oder gleich
finance_meta.as_ofbesitzt. Dies entspricht der bestehenden Parserregel, ohne einen komplexen SQL-Trigger einzuführen.Integritätsfehler verwenden einen eigenen internen Fehlertyp und enthalten keine:
Eine neue HTTP-Fehlerabbildung wurde bewusst nicht ergänzt, da der produktive Endpoint in ACC-71 unverändert bleibt.
PostgreSQL-Integrationstests
Die neue dedizierte Suite läuft gegen eine echte PostgreSQL-Instanz und verwendet keine SQL-Mocks.
Pro Lauf wird ein isoliertes, zufällig benanntes Testschema angelegt. Die Suite führt Migration 001 und anschließend Migration 002 aus und entfernt das Schema nach dem Test wieder.
Abgedeckt sind:
owner_id-Spalten in allen Finance-Tabellen;FinanceDataV1;NULL, Aktivstatus und historischen Snapshots;nullbei fehlendem Owner oder fehlendemfinance_meta;npm testbleibt datenbankunabhängig. Die PostgreSQL-Suite wird separat gestartet:Ohne
POSTGRES_TEST_URLbricht sie absichtlich ab und wird nicht still übersprungen.CI
Die GitHub-CI enthält einen neuen separaten Job mit PostgreSQL 17 als temporärem Service.
Der Job:
pg_isreadyauf deren Bereitschaft;npm run test:postgresaus.Normale Unit-, Build-, Lint- und Browser-Jobs bleiben unverändert getrennt.
Betriebs- und Neon-Dokumentation
Die Dokumentation unterscheidet jetzt ausdrücklich:
DATABASE_URL;Für die spätere Runtime-Rolle ist dokumentiert:
google_connections;SELECTauf Owner- und Finance-Tabellen für ACC-71;Vor ACC-66 bleiben folgende Betriebsaufgaben ausdrücklich offen:
Es wurde bewusst keine vermutete Region in
vercel.jsoneingetragen und keine externe Datenbank migriert.ADR 0013 dokumentiert zusätzlich Convex als geprüfte, aber wegen des abweichenden Backend-Modells und der fehlenden unveränderten Abbildung zusammengesetzter relationaler Owner-Fremdschlüssel verworfene Alternative.
Zusätzliche Konfigurationsbereinigung
Die zuvor dokumentierte, aber fehlende
.env.examplewurde mit ausschließlich synthetischen Platzhaltern ergänzt.Die widersprüchliche
.gitignore-Regel wurde bereinigt, sodass lokale.env-Dateien weiterhin ignoriert werden, während.env.exampleund weitere explizite Beispielvorlagen eingecheckt werden können.Bewusst nicht enthalten
Diese PR enthält ausdrücklich nicht:
/api/finance;Der aktuelle produktive Pfad bleibt:
Der neue, noch nicht produktiv angeschlossene Pfad ist:
Verifikation
Folgende Prüfungen wurden erfolgreich ausgeführt:
npm run docs:checknpm testnpm run test:postgresnpm run lintnpm run licenses:checknpm run buildgit diff --check/api/finance-ÄnderungenAuswirkungen und nächste Schritte
Für Nutzer ändert sich mit dieser PR noch nichts. Der produktive Finanzstand wird weiterhin aus Google Sheets gelesen.
Die vorgesehene weitere Reihenfolge bleibt:
ACC-29 kann auf dem neuen Reader und den Integrationstests aufbauen, um die vollständige Parität zwischen Sheet-Parser, PostgreSQL-Persistenz und bestehenden Selektoren nachzuweisen.
Greptile Summary
Der PR ergänzt das ownergebundene PostgreSQL-Schema und einen noch nicht produktiv angeschlossenen Reader für vollständige
FinanceDataV1-Daten.Confidence Score: 5/5
Der PR erscheint sicher zum Mergen; es wurden keine konkreten geänderten Codepfade mit einem veröffentlichungswürdigen Fehler gefunden.
Das Schema erzwingt die vorgesehene Owner-Isolation, der Reader filtert sämtliche Abfragen über die intern aufgelöste Owner-ID und validiert den konsistent gelesenen Datenstand vor der Rückgabe.
Important Files Changed
Sequence Diagram
sequenceDiagram participant Caller as Interner Server-Caller participant Repo as FinanceRepository participant DB as PostgreSQL participant Schema as financeDataV1Schema Caller->>Repo: readForGoogleSub(verifiedGoogleSub) Repo->>DB: BEGIN READ ONLY, REPEATABLE READ Repo->>DB: Google sub → owners.id alt Owner oder finance_meta fehlt DB-->>Repo: Kein vollständiger Datenstand Repo-->>Caller: null else Datenstand vorhanden Repo->>DB: Owner-gefilterte Entitäten, Snapshots und Meilensteine DB-->>Repo: Konsistenter Snapshot Repo->>Schema: BIGINT-Mapping und Laufzeitvalidierung Repo->>Repo: Aktuelle Snapshots aktiver Entitäten prüfen Repo-->>Caller: FinanceDataV1 endReviews (1): Last reviewed commit: "Implement ACC-71 PostgreSQL finance read..." | Re-trigger Greptile