Zum Artikel springen
PlanToCodeDocsApp herunterladen

HandbuchMitwirken

Server, Datenbankrollen und Betrieb

Der Konto- und Relay-Dienst, die PostgreSQL-Rolleninvariante, die Konfiguration, die ein Entwicklungsserver braucht, und was über HTTP-Health hinaus zu prüfen ist.

Gegen den Quellcode geprüft am 17. September 2026

Auf dieser Seite

Der Server besitzt Account- und Relay-Zuständigkeiten

Die Actix-Anwendung initialisiert beim Start gemeinsame Dienste: Datenbankpools, Kontoauthentifizierung, Verbindungsverwaltung und konfigurierte Anbieter- und Push-Integrationen. Der DeviceConnectionManager wird von allen HTTP-Workern des Prozesses geteilt. Seine Live-Sockets, Verbindungsgenerationen und ausstehenden RPC-Einträge sind Prozesszustand, und der Relay-Sitzungsspeicher hinter Resume-Tokens liegt ebenfalls im Arbeitsspeicher, mit 24 Stunden TTL und einem 5-Minuten-Durchlauf. Redis ist für den gemeinsamen Anmeldezustand, die Ratenbegrenzung und Guthabenreservierungen für kostenpflichtige Anfragen erforderlich, und der Prozess beendet sich beim Start ohne Redis. Es macht ein Live-Socket-Register nicht zwischen Serverprozessen portabel.

Beide Geräte und ihre ausstehende Anfrage müssen diesen Connection-Manager erreichen, deshalb läuft in Produktion ein Relay-Prozess pro Region mit explizitem Verbindungsabbau; das Kapitel zum Geräte-Routing erklärt, warum eine Round-Robin-Replik das Routing zerstören würde.

PostgreSQL-Rollen sind eine Start-Invariante

Der Server beendet sich beim Start, wenn seine zwei Datenbank-Logins nicht getrennt und durch Zeilensicherheit begrenzt sind
Der Server beendet sich beim Start, wenn seine zwei Datenbank-Logins nicht getrennt und durch Zeilensicherheit begrenzt sindIn PostgreSQL besitzt die Migrationsrolle die Tabellen, und 27 davon müssen Zeilensicherheit aktiviert und erzwungen haben. Der Server verbindet sich über zwei Logins, das System-Login plantocode und das Tenant-Login authenticated. Beim Start prüft er, dass keines der Logins Superuser ist, Zeilensicherheit umgeht, Rollen erbt oder Tabellen besitzt, dass keines das andere ist oder Mitglied des anderen oder des Tabellenbesitzers, und dass das Tenant-Login ohne Benutzer-ID aus 16 Tenant-Tabellen keine Zeilen liest. Jeder Fehler beendet den Prozess, bevor er auf Anfragen lauscht. Jeder Serverprozess öffnet einen eigenen System-Pool mit 8 und einen Tenant-Pool mit 16 Verbindungen, die seine HTTP-Worker teilen.
PostgreSQL
Tabellenbesitzerplantocode_migrator · SUPERUSER
27 TabellenZeilensicherheit aktiviert und erzwungen
System-Loginplantocode
Tenant-Loginauthenticated
Mitglied des Besitzers
dasselbe Login oder Mitglied des anderen
liest ohne Benutzer-ID 0 Zeilen aus 16 Tabellen
beide: NOSUPERUSER · NOBYPASSRLS · NOINHERIT · besitzen keine Tabellen
Jeder Serverprozess
System-Pool 8
Tenant-Pool 16
für alle seine HTTP-Worker
Eine durchgestrichene Linie, eine Tabelle ohne FORCE oder eine sichtbare Zeile: create_dual_pools schlägt fehl, und der Prozess endet, bevor er auf Anfragen lauscht.
Die Produktion öffnet außerdem ACCOUNT_CONTROL_DATABASE_URL, mit eigener Least-Privilege-Prüfung, und METRICS_DATABASE_URL.
  • Laufzeit-LoginsDATABASE_SYSTEM_URL · DATABASE_USER_URL

    assert_runtime_boundary prüft die Principals, als die sich diese URLs verbinden, nicht die URLs. Schon vor dem Verbinden lehnt create_dual_pools zwei identische URLs ab.

  • Tenant-Kontextapp.current_user_id

    Mit set_config für eine Transaktion gesetzt, sodass eine Verbindung im Pool ihn am Ende der Transaktion vergisst. Zeilensicherheits-Policies, die für jedes Login geschrieben sind, entscheiden, was es anfassen darf.

  • PoolsDB_POOL_SYSTEM_MAX · DB_POOL_USER_MAX

    Einmal pro Serverprozess geöffnet und von allen seinen HTTP-Workern geteilt. Jeder weitere Prozess, auch die zweite Farbe während einer Blue-Green-Umschaltung, öffnet eigene.

create_dual_pools öffnet beide Pools und führt assert_runtime_boundary für die Principals aus, als die sie tatsächlich verbunden sind, sodass eine URL mit der falschen Rolle an denselben Prüfungen scheitert.

Die Pools sind standardmäßig 8 System- und 16 Tenant-Verbindungen mit Minima von 2 und 4, 2 Sekunden Acquire-Timeout, 60 Sekunden Leerlauf und 1.800 Sekunden maximaler Lebensdauer. Jede Verbindung setzt UTC, einen application_name plantocode-system oder plantocode-user und Statement-, Idle-in-Transaction- und Lock-Timeouts von 30, 60 und 5 Sekunden für die Systemrolle und 8, 10 und 2 Sekunden für die Tenant-Rolle; Verbindungsaufbauten werden fünfmal mit linearem Ein-Sekunden-Backoff wiederholt. Jeder Serverprozess öffnet eigene Pools, die seine HTTP-Worker teilen, deshalb vervielfachen weitere Prozesse, auch während einer Blue-Green-Umschaltung, die Verbindungen und brauchen zuerst eine Prüfung der Datenbankkapazität.

Lokalen Server konfigurieren

  1. Kopieren Sie server/.env.example nach server/.env und konfigurieren Sie eine lokale Datenbank, eine Redis-URL, Einstellungen zur Verschlüsselung von JWT- und Refresh-Tokens sowie Auth0-Werte.
  2. Legen Sie getrennte Migrations- und Runtime-Principals gegen eine lokale Entwicklungsdatenbank an.
  3. Wenden Sie server/scripts/run-migrations.sh mit der benötigten Migrationsumgebung an; server/README.md beschreibt die Rollenbereitstellung und die Erhaltungsrichtlinie.
Aus dem Repository-Root lesen und ausführen
cp server/.env.example server/.env
# Configure the local services and database roles first.
pnpm server:check
pnpm dev:server

Der Migrationsläufer verarbeitet infrastructure/ansible/playbooks/plantocode/migration-execution-plan.yml, denselben geordneten Plan, den die Bereitstellung nutzt. Die Migrationsrolle muss ein Superuser sein, der keiner von postgres, plantocode oder authenticated ist und in DATABASE_RUNTIME_ROLES fehlt. Als execution once markierte Dateien werden per sha256 in plantocode_internal.migration_execution_ledger gesperrt, das Laufzeitrollen nicht lesen können; eine Prüfsummenabweichung, eine once-Datei mit mehreren Transaktionen oder eine ungeplante .sql-Datei scheitert geschlossen, und PRESERVE_EXISTING_DATABASE_IDENTITIES=true wird nur für die expand-Phase akzeptiert. Ersetzen Sie ihn nicht durch sqlx migrate run.

KonfigurationsfamilieErforderlich für
DATABASE_SYSTEM_URL, DATABASE_USER_URL, REDIS_URLZentrale Datenbank- und gemeinsam genutzte Anmeldedienste.
AUTH0_DOMAIN, AUTH0_API_AUDIENCE, AUTH0_ALLOWED_CLIENT_IDSDie konfigurierte Vertrauensgrenze für Konto-Logins.
Einstellungen zur Verschlüsselung von JWT- und Refresh-Tokens in .env.exampleAusstellen von App-Anmeldedaten und Speichern von Refresh-Material.
Provider-API-SchlüsselNur die entsprechenden konfigurierten Provider-Routen.
Stripe-, APNs-, FCM-, E-Mail- und weitere IntegrationseinstellungenIhre jeweiligen Konto- oder Benachrichtigungsfunktionen.
METRICS_DATABASE_URL, ACCOUNT_CONTROL_DATABASE_URLOptional, aber jede zieht Begleiter nach sich: SERVICE_HEALTH_REGION und SERVICE_HEALTH_RELEASE, oder WORKSPACE_PREVIEW_HMAC_SECRET.
PLANTOCODE_DEPLOYMENT_TOKENDer geschützte Endpunkt /health/deployment und seine Abbauaktion.

Verhalten jenseits des HTTP-Health-Checks verifizieren

GET /health prüft den grundlegenden Serverzustand. Das geschützte /health/deployment unterstützt die Deployment-Inspektion. Verifizieren Sie anschließend einen Konto-Login, zwei Geräteregistrierungen, einen schreibgeschützten Desktop-RPC und eine kontrollierte Outbox-Operation. Ein fehlerfreier HTTP-Listener allein testet weder die Trennung von Datenbankrollen noch native Callbacks, Provider-Konfigurationen oder das Relay-Routing.

Eine nützliche Relay-Spur folgt der Anfrage-ID, dem Quell-Client, dem Ziel-Desktop, der Methode und der Verbindungsgeneration. Der Weiterleitungscode extrahiert den W3C-Trace-Kontext und injiziert den Kindkontext in den nächsten Hop. Bei mehrdeutiger Zustellung prüfen Sie den remote_rpc_idempotency-Anspruch des Desktops und seine codex_chat_operation_ledger-Zeilen, bevor Sie schließen, ob Arbeit gelaufen ist.

Die Produktion nutzt den Ansible-Blue-Green-Ablauf des Repositorys mit getrennten Phasen für Datenbankerweiterung, Binary-Aktivierung, Verifikation und Kontraktion; Inventar und Geheimnisse sind Betreiberkonfiguration.