Files
govoplan-core/docs/INTEGRITY_PERFORMANCE_CONTRACT.md
T
zemion 6591aaa3fd
Module Package Release / publish-packages (push) Successful in 13s
fix(core): preserve data integrity and bound shared UI and response work
Release v0.1.46. Coordinated integrity review: GovOPlaN/govoplan-core#298.
2026-09-08 12:30:38 +02:00

6.0 KiB
Executable File

Integrity-preserving performance contracts

These are implementation guarantees and regression-test boundaries, not a security certification or production load-test result. Feature-specific policies and help remain in the owning modules' English and German documentation topics.

Refreshes, edits and table rendering

The shell runs at most one module-load refresh per authority generation. Multiple invalidations coalesce into one trailing refresh; stale results and errors cannot replace a newer generation. Focus refreshes are throttled to five seconds and focus/visibility refreshes on hidden pages are suppressed; explicit module invalidations still trigger a read. Authentication/tenant reset disposes the previous controller. Authentication and authorization checks are not cached away.

Editable modules must reconcile a save against the submitted draft and accepted server revision: edits made while a request is pending remain dirty. Completion must be fenced by security-relevant authority and selection, not merely an auth object's reference identity. A harmless profile refresh must not discard an accepted newly created ID and invite a duplicate create. An old account's mutation continuation must not reload its catalogue into the current account's page.

DataGrid precomputes first-occurrence row indices once for client sorting and filtering. Duplicate object references, primitive values, NaN and sparse arrays retain Array.indexOf behavior. Comparator order, visible pagination, server-side pagination, sizing and resize rules are unchanged. Do not replace this with a last-occurrence map or change ordering as a side effect of an optimization.

Conditional responses

The shared JSON GET middleware performs route handling, including authorization, before considering If-None-Match. It buffers only responses up to 1 MiB for a body-derived ETag. Known larger responses bypass buffering; an unknown-length stream crossing that limit replays its exact prefix and streams the remainder. No data is truncated and no large joined copy is created. The crossing chunk is already producer-owned: this is not a process-wide or route-output memory limit. Empty chunks do not accumulate. Large responses may no longer receive a middleware-generated ETag/304; explicit route ETags remain intact. Small-response cache semantics and credential/language/context Vary fields are retained.

Shared helpers and concurrency

Central helpers replace exact live-code duplicates only. Actor precedence, whitespace handling and service-account differences remain explicit owner choices; historical migration code is not redirected to mutable runtime helpers. Connector search ACL token projection keeps its first-seen ordering and existing 500-token cap, stopping work once that cap is reached. Provider schemas are inferred in one pass without storing a second list of every column value.

The keyed-list three-way merge retains insertion anchors when unrelated fields change. Concurrent additions use deterministic ordering; contradictory anchors produce a collection-order conflict instead of silently relocating an item. No existing endpoint is newly opted into merge behavior by this change.

SQL JSON authorization predicates support the explicitly tested SQLite and PostgreSQL dialects, retain exact string membership and reject unsupported dialects. Apply tenant and authorization predicates before counting/pagination; never page a broader result first and filter away unauthorized records afterward. SQLite execution and PostgreSQL SQL compilation are not substitutes for a deployment's PostgreSQL concurrency and representative-data load tests.

Migration connection URLs

Alembic preserves the configured database URL exactly in online and offline migration modes, including percent-encoded credentials and PostgreSQL Unix-socket paths. Escaping applies only at its ConfigParser boundary; operators must not double-escape % in DATABASE_URL or alter working connection credentials to work around interpolation errors. This does not change the target database, authentication, TLS policy, or migration contents.

Deutsch: Integrität vor Geschwindigkeit

Der zentrale Modul-Refresh bündelt gleichzeitige Auslöser und verwirft veraltete Ergebnisse einschließlich Fehlermeldungen. Ein Wechsel von Anmeldung oder Mandant beendet die bisherige Generation. Fokusaktualisierungen sind auf einen Auslöser je fünf Sekunden begrenzt. Berechtigungsprüfungen bleiben erhalten.

Speicherantworten dürfen zwischenzeitliche Bearbeitungen nicht überschreiben. Ein unveränderter Berechtigungskontext mit einem neuen Profilobjekt darf eine bereits bestätigte neue ID oder Revision nicht verwerfen. Umgekehrt dürfen alte Anfragen nach einem Kontowechsel keine Daten in den neuen Kontext übernehmen. Die DataGrid-Optimierung erhält Reihenfolge, Filter-, Seiten- und Größenverhalten.

Die ETag-Middleware puffert höchstens 1 MiB Nutzdaten zuzüglich eines bereits vom Erzeuger gelieferten Grenz-Chunks. Größere Antworten werden vollständig weitergereicht, nicht abgeschnitten; automatisch erzeugte ETags können dabei entfallen. Autorisierung läuft auch bei bedingten Anfragen. Das ist keine allgemeine Speicherbegrenzung für Routen oder Prozesse.

Gemeinsame Helfer erhalten die bisherigen fachlichen Unterschiede. Listen-Merges bewahren Einfügepositionen oder melden widersprüchliche Reihenfolgen explizit als Konflikt. Datenbankseitige Autorisierung erfolgt vor Zählung und Seitenauswahl. Regressionstests belegen diese Verträge; reale Provider-, PostgreSQL- und Lasttests in einer repräsentativen Umgebung bleiben Teil der Betriebsfreigabe.

Alembic übernimmt die konfigurierte Datenbank-URL in Online- und Offline-Läufen unverändert, einschließlich prozentkodierter Zugangsdaten und PostgreSQL- Unix-Socket-Pfade. Die Maskierung erfolgt ausschließlich an der ConfigParser- Grenze; % in DATABASE_URL nicht doppelt maskieren und funktionierende Zugangsdaten nicht als Umgehung ändern. Zieldatenbank, Anmeldung, TLS-Vorgaben und Migrationsinhalte bleiben unverändert.