Wofür das Modul gedacht ist
Transaktionen ist Teil des aktiven Modul-Katalogs und deckt einen klaren Ausschnitt des Produktalltags ab.
Banktransaktionen zuweisen, prüfen und in den Finanzfluss einordnen. Im tenantweiten Kontext sorgt der Bereich dafür, dass wiederkehrende Entscheidungen, Stammdaten oder Übersichten nicht in Nebensysteme ausweichen müssen.
Transaktionen ist als eigenständiger Produktbaustein gedacht. Gerade deshalb lohnt sich ein Blick darauf, wie der Bereich mit Rollen, Datenkontext und angrenzenden Modulen zusammenspielt.
Typische Einsatzfälle
Diese Situationen zeigen, wann der Bereich in einem sauberen Rollout oder im laufenden Betrieb konkret Mehrwert liefert.
Finanzstatus im Blick halten
Transaktionen macht wirtschaftliche Signale dort sichtbar, wo Entscheidungen vorbereitet werden.
Freigaben sauber führen
Gerade bei Zahlungen, Budgets oder Rechnungen sorgt das Modul für nachvollziehbare Schritte statt lose Absprachen.
Mit dem Projektkontext arbeiten
Finanzmodule entfalten ihren Wert, wenn Projektstatus, Belege, Zahlungen und Verantwortlichkeiten zusammenspielen.
Wie das Modul mit anderen Bereichen zusammenspielt
struct-i-vio ist als zusammenhängende Plattform gedacht. Diese Module liegen fachlich am nächsten bei diesem Bereich.
Finanzen
Finanzen ergänzt Transaktionen, weil beide Bereiche im Alltag direkt aufeinander aufbauen oder dieselben Verantwortlichen berühren.
DetailsProjekt-Zahlungen
Projekt-Zahlungen ergänzt Transaktionen, weil beide Bereiche im Alltag direkt aufeinander aufbauen oder dieselben Verantwortlichen berühren.
DetailsUnternehmenstopf
Unternehmenstopf ergänzt Transaktionen, weil beide Bereiche im Alltag direkt aufeinander aufbauen oder dieselben Verantwortlichen berühren.
DetailsBerechtigungen und Sichtbarkeit
Die öffentliche Dokumentation beschreibt die Logik auf Produktniveau - nicht als technische Policy-Liste, sondern als Rollout-Leitfaden.
Best Practices
So bleibt der Bereich bei Einführung und Nutzung anschlussfähig an den restlichen Produktfluss.
Entwickler Info
Empirisch erhobene Befunde aus Stage-2-Isolations-Probe inkl. 4-Schichten-Enforcement-Scan. Das Modul ist ein gutes Beispiel für mehrschichtige Verteidigung: Permissions werden teils im API-Code, teils in SECURITY-DEFINER-RPCs und überwiegend in RLS-Policies durchgesetzt — manche Actions an mehreren Stellen gleichzeitig.
Entwickler-Info aufklappen (8)
⚠ KRITISCHModul-Page /guv/transactions ist Gateway zu drei Modulen
pages/guv/transactions.tsx hostet nicht nur die Transaktions-Tabelle, sondern lädt Banking-Settings (banking_settings) und Finmap-Settings (finmap_settings) als Komponenten in eigenen Tabs. Die Page ist gegated auf hasAccess('guv_transactions') (Modul-Visibility). Wer also banking_settings oder finmap_settings einrichten soll, braucht zwingend Modul-Visibility auf guv_transactions — auch wenn ihm die Transaktions-Permissions selbst weggenommen werden. Andersrum: wer guv_transactions-Modul-Visibility hat, sieht die Banking-/Finmap-Tabs (welche dann ihre eigenen Action-Permissions prüfen).
pages/guv/transactions.tsx:165 (Gate-Check)pages/guv/transactions.tsx:19-23 (Banking/Finmap-Komponenten-Imports)
⚡ MERKWÜRDIGview_transactions ist RLS-only — Tabelle filtert, kein 403
Die SELECT-Policy fact_transactions_select prüft can_perform_action(view_transactions). API-Endpoints (/api/guv-transactions GET) haben keinen Pre-Check — wer die Permission nicht hat, sieht eine leere Liste statt eines Fehlers. Klassischer Stillschweigend-Filter.
RLS: public.fact_transactions :: fact_transactions_selectpages/api/guv-transactions/index.ts:21-22 (kein API-Gate auf GET)
⚡ MERKWÜRDIGview ist getrennt von view_transactions — verschiedene Tabellen
Die beiden Lese-Permissions wirken auf unterschiedliche Tabellen: view_transactions gates fact_transactions, view gates transaction_splits. Sie sind nicht redundant, leicht zu verwechseln. transaction_splits hat zusätzlich einen Cross-Module-Fallback: Splits mit target_type=company_fund sind sichtbar, wenn der User company_fund.link_transaction ODER unlink_transaction hat.
RLS: public.transaction_splits :: transaction_splits_selectscripts/probes/probe-guv-transactions-module.js
⚠ KRITISCHassign verlangt bei Topf-Splits zwei company_fund-Permissions (versteckte Cross-Module-Kopplung)
split_transaction_to_projects (SECURITY DEFINER) prüft zusätzlich company_fund.link_transaction sobald ein Split target_type=company_fund hat, und unlink_transaction wenn ein bestehender Topf-Anteil reduziert/entfernt wird. Ein Bauleiter, der "nur Projekt-Splits anlegen darf", arbeitet mit Level X auf assign — kann aber kein gemischtes Aufteilen machen, ohne dass die Geschäftsführung beide Topf-Permissions ebenfalls auf gleichem Level freigibt. Reine Projekt-Splits funktionieren standalone.
RPC: split_transaction_to_projectsRPC: unsplit_transactionlib/permission-dependencies.ts (cross_module conditional couplings)
⚡ MERKWÜRDIGdelete ist vestigial — kein App-Pfad triggert die Policy
Die DELETE-Policy auf transaction_splits prüft can_perform_action(delete). Alle App-Flows zum Löschen von Splits laufen jedoch über unsplit_transaction (SECURITY DEFINER, BYPASSRLS), wodurch die Policy nie greift. Die Permission existiert daher als Schutz gegen direkte PostgREST-DELETE-Anfragen — die in normalem Betrieb nicht vorkommen.
RLS: public.transaction_splits :: transaction_splits_delete
map_transactions: API-enforced + RLS (defence in depth)
API-Endpoints attachment-links.ts (Zeile 26) und upload-attachment.ts (Zeile 88) prüfen can_perform_action explizit am Handler-Eingang → 403. Zusätzlich liegt die Permission auf RLS-UPDATE-Policies von fact_transactions sowie auf transaction_attachment_links/attachments INSERT/UPDATE/DELETE. Doppelte Verteidigung — Verweigerung wirkt sofort als 403, ohne den DB-Layer zu erreichen.
pages/api/guv-transactions/attachment-links.ts:26pages/api/guv-transactions/upload-attachment.ts:88
sync_transactions: RLS-only auf INSERT/DELETE
Banking-Sync legt fact_transactions-Zeilen an. Die WITH_CHECK-Policy verlangt sync_transactions; Verweigerung führt zu RLS-Violation (HTTP 500/403 je nach Endpoint), nicht zu sauberem 403. Über /api/guv-transactions POST wird der gleiche Pfad ausgelöst. Es gibt keinen API-Pre-Check — die DB ist die einzige Verteidigung.
RLS: public.fact_transactions :: fact_transactions_insert + fact_transactions_deletepages/api/guv-transactions/index.ts:23-24 (createTransactions ohne Pre-Check)
⚠ KRITISCHBackdoor: project_payments.view erlaubt Sicht auf zugeordnete Transaktionen
Eine zweite SELECT-Policy fact_transactions_project_member_select erlaubt Sicht auf Transaktionen mit nicht-NULL project_id, wenn der User project_payments.view für genau dieses Projekt hat. Wer view_transactions verweigert bekommt aber project_payments.view auf einem Projekt hat, sieht damit eine Teilmenge der Transaktionen.
RLS: public.fact_transactions :: fact_transactions_project_member_select
