Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/docs/deploy/DEMO-PRO-SEED.md
T

11 KiB
Raw Blame History

Normale Rhein-Main-Staging-Daten für demo-pro-crm

Der Seed baut den Staging-Tenant als synthetischen SHK-Betrieb mit 50 Mitarbeitern (17 im Büro, 33 im Baustellen-/Kundendienst), 783 Kontakten, 537 Projekten und den dazugehörigen operativen Datensätzen auf. Die 33 Feldmitarbeiter arbeiten in 15 Zweier-Kolonnen und einer Dreier-Kolonne. Das Büro besteht aus Geschäftsführung (1), Vertriebsleitung (1), Vertrieb (3), Backoffice (4), Marketing (1) und Projekt-/Bauleitung (7). Der Seed ist bewusst nicht an SEED_ON_BOOT gekoppelt.

Die fachlichen Datensätze werden dabei wie normale Betriebsdaten gespeichert (isDemoData=false). Der technische Slug bindet den Reset an den richtigen Tenant; deterministische IDs und interne Import-Metadaten halten die Herkunft nachvollziehbar. Kontakte, Projekte, Aufgaben und Dateien müssen deshalb ohne demo=show oder einen Demo-Schalter sichtbar sein.

Der Staging-Deploy setzt auf dem Web-Resource zusätzlich SEED_DEMO_PRO_MANAGED=true. Dadurch überspringt der bestehende Boot-Demo-Seed demo-pro-crm vollständig: Er verändert dort weder Mitgliedschaften noch Plan, ProductCore, Buchungen, Projekte oder Automationen. Starter und Business bleiben im bisherigen Boot-Seed. Das Flag darf nicht auf Production gesetzt werden und muss auf Staging aktiv bleiben, damit spätere Deploys den hier verifizierten Pro-Datensatz nicht wieder mit Legacy-Fixtures vermischen.

Bedienung

pnpm seed:demo-pro --dry-run

SENTRY_ENVIRONMENT=staging \
SEED_DEMO_PRO_ALLOWED=true \
SEED_DEMO_PRO_EXPECTED_TENANT_ID='<exakte-staging-tenant-id>' \
SEED_DEMO_PRO_EXPECTED_DATABASE='<exakter-staging-datenbankname>' \
SEED_DEMO_PRO_EXPECTED_DATABASE_HOST='<exakter-host:port>' \
SEED_DEMO_PRO_EXPECTED_STORAGE_BUCKET='hivegrid-staging-media' \
SEED_DEMO_PRO_EXPECTED_STORAGE_ENDPOINT='<exakter-staging-s3-endpoint>' \
SEED_DEMO_PRO_WORKERS_DRAINED=true \
SEED_DEMO_PRO_OUTBOUND_SANDBOX=true \
SEED_DEMO_USER_PASSWORD='<starkes-zufaelliges-secret-aus-dem-secret-store>' \
pnpm seed:staging-data --apply --confirm=demo-pro-crm

SENTRY_ENVIRONMENT=staging pnpm seed:demo-pro --verify

SENTRY_ENVIRONMENT=staging \
SEED_DEMO_PRO_ALLOWED=true \
SEED_DEMO_PRO_EXPECTED_TENANT_ID='<exakte-staging-tenant-id>' \
SEED_DEMO_PRO_EXPECTED_DATABASE='<exakter-staging-datenbankname>' \
SEED_DEMO_PRO_EXPECTED_DATABASE_HOST='<exakter-host:port>' \
SEED_DEMO_PRO_EXPECTED_STORAGE_BUCKET='hivegrid-staging-media' \
SEED_DEMO_PRO_EXPECTED_STORAGE_ENDPOINT='<exakter-staging-s3-endpoint>' \
SEED_DEMO_PRO_WORKERS_DRAINED=true \
SEED_DEMO_PRO_OUTBOUND_SANDBOX=true \
pnpm seed:staging-data --cleanup --confirm=demo-pro-crm

apply und cleanup verweigern jeden anderen Tenant sowie jede Umgebung außer Staging. Zusätzlich müssen Tenant-ID, Datenbankname, Datenbank-Host mit Port, S3-Provider, Bucket und Endpoint mit den im Staging-Secret-Store hinterlegten Bindings exakt übereinstimmen. Lokaler Storage und fremde S3-Buckets werden vor der ersten Mutation abgelehnt. Der Apply-Lauf wartet standardmäßig bis zu 300 Sekunden auf die Search-Outbox. SEED_DEMO_PRO_WAIT_MS ist nur für lokale Integrationsprüfungen gedacht; auf Staging bleibt der Standard bestehen.

Vor dem ersten Staging-Apply muss der neue Web-/Worker-Stand vollständig deployed und gesund sein. Erst dieser Stand versteht die Search-Batch-Aktionen und hält den Legacy-Boot-Seed über SEED_DEMO_PRO_MANAGED=true dauerhaft aus dem Pro-Tenant heraus.

Nach dem Outbox-Drain pollt der Lauf alle registrierten Meilisearch-Indizes mit Tenant-Filter. Der Tenant wird erst aktiviert, wenn CRM (976), Projekte (537), Aufgaben (1.684), Dateien (917) und Nutzer (50) vollständig sichtbar und alle anderen Tenant-Slices leer sind. Für die vollständig über die Search-API abrufbaren Slices bis 1.000 Dokumente wird zusätzlich die exakte ID-Menge geprüft. Der Aufgaben-Slice überschreitet Meilisearchs standardmäßige maxTotalHits-Grenze und wird deshalb fail-closed über die exakte Tenant-Facette und den vollständigen Count verifiziert.

Damit sich die geseedeten Demo-Konten anschließend auch anmelden können, muss auf der Staging-Web-Ressource STAGING_DEMO_LOGIN_ENABLED=true gesetzt sein (wirkt nur zusammen mit SENTRY_ENVIRONMENT=staging). Der Login-Schalter ist bewusst vom Seeding getrennt und trägt kein SEED_-Präfix: Der RLS-Deploy-Vertrag weist jeden SEED_*-Schlüssel auf Runtime-Ressourcen ab, weshalb der Login sonst nicht freischaltbar wäre.

Das gemeinsame Staging-Login-Passwort wird ausschließlich zur Laufzeit aus dem Secret-Store gelesen, muss mindestens 20 Zeichen lang und ausreichend zufällig sein und darf weder in Git noch in Deployment-Logs landen. Nur für den vom Owner explizit verlangten gemeinsamen Staging-Zugang akzeptiert der CLI exakt den vereinbarten Testwert, wenn zusätzlich SEED_DEMO_PRO_ALLOW_SHARED_STAGING_PASSWORD=true gesetzt ist. Das Flag gehört nicht in die Coolify-Runtime-Umgebung und erlaubt keinen anderen schwachen Wert. Der Seed nutzt in beiden Fällen denselben Argon2id-Hasher wie die App.

Vor dem Setzen von SEED_DEMO_PRO_WORKERS_DRAINED=true müssen Outbound- und Automations-Worker in Coolify pausiert und ihre aktiven Queue-Jobs vollständig abgearbeitet sein. SEED_DEMO_PRO_OUTBOUND_SANDBOX=true ist eine operative Nichtzustellbarkeits-Bestätigung und darf nur in einer der folgenden Lagen gesetzt werden:

  1. Mail, SMS, Webhooks und Push zeigen nachweislich auf nicht zustellbare Test-Sinks.
  2. Fail-closed Isolation: Alle BullMQ-Queues außer outbox.search-index sind global pausiert, für jede pausierte Queue ist active=0 bestätigt und die Coolify-Apps worker-mail, worker-import, worker-webhook und worker-plugin sind gestoppt. worker-general bleibt ausschließlich für DB-Outbox und Search-Acks aktiv; seine übrigen Queues bleiben ebenfalls global pausiert.

Die Isolation muss vor dem Apply erneut geprüft und bis zum erfolgreichen --verify gehalten werden. Der DB-Outbox-Reset kann bereits an BullMQ übergebene DONE-Jobs nicht zurückholen. Danach werden zuerst die pausierten Queues fortgesetzt und anschließend die vier Worker-Apps wieder gestartet. Der Search-Pfad bleibt für beide Search-Ack-Phasen durchgehend verfügbar.

Der Reset erhält Tenant, Subscription, Pro-Entitlements und globale Kataloge. Er ersetzt die fachlichen Projekt-, CRM-, Lead-, Aufgaben-, Datei-, Kalender-, Buchungs- und Search-Daten sowie die Tenant-Mitgliedschaften. Die 50 synthetischen Nutzer bleiben globale User-Zeilen und werden beim nächsten Lauf sicher aktualisiert. Die sieben SHK-Template-Rollen werden ebenfalls aus dem exakten Berechtigungskatalog neu aufgebaut, damit keine alte manuelle Zusatzberechtigung auf neue Testnutzer übergeht. Anschließend invalidiert der Lauf die Permission-Caches aller 50 Nutzer über den gemeinsamen Cache-Bus, bevor der Tenant wieder aktiviert werden kann.

Während apply und cleanup hält der Prozess eine DB-seitige Lease und setzt den Tenant in Wartung. Ein Heartbeat erneuert die Lease während aller Seed-, Outbox- und Search-Phasen; verliert der Prozess den Besitz, bricht er fail-closed ab. Nur ein vollständig verifizierter Apply-Lauf aktiviert den Tenant wieder. Nach Abbruch oder Fehler bleibt er absichtlich deaktiviert; zur Recovery denselben Apply-Befehl erneut ausführen. cleanup hinterlässt den leeren Tenant ebenfalls deaktiviert.

Datenschutz und Zustellsicherheit

  • Sämtliche E-Mail-Adressen liegen unter .example.test.
  • Sämtliche Telefonnummern liegen im offiziellen Frankfurter Drama-Number-Block +49 69 90009 000–999.
  • Orte und PLZ sind real; Straßen und Hausnummern sind synthetisch.
  • Die 917 Datei-Datensätze besitzen deterministisch erzeugte, minimale PDF-Objekte unter tenants/{tenantId}/files/{fileId}/original. Größe und SHA-256-Prüfsumme stammen aus den exakten Bytes. Da die PDFs ausschließlich im vertrauenswürdigen Seed-Prozess entstehen und nie Nutzereingaben oder Remote-Inhalte enthalten, werden sie als clean gespeichert; der AV-Gate für untrusted Uploads bleibt unverändert fail-closed. Vor jedem Reset löscht der Lauf den gesamten tenant-eigenen files/-Prefix, einschließlich verwaister Objekte aus älteren Katalogen oder abgebrochenen Läufen, in begrenzten Seiten von höchstens 1.000 Keys. Die Abschlussprüfung verlangt die exakte erwartete Key-Menge und lehnt auch zusätzliche Objekte im verwalteten Prefix ab.
  • Direkte Dokumentbezüge werden nur bei eindeutiger Fachsemantik gesetzt: 81 Rechnungen verweisen eins-zu-eins auf das gleichnamige Rechnungs-PDF und 13 Abnahmen auf das Abnahmeprotokoll ihres Projekts. Checklisten-Fotos bleiben leer, weil der Katalog keine Bilddateien erzeugt. Plantafelzeilen erhalten nur dann calendarEventId/synced, wenn Projekt, Mitarbeiter und Zeitfenster exakt mit einem Kalendereintrag übereinstimmen; die getrennten Besprechungstermine des aktuellen Katalogs werden nicht als Montageeinsatz ausgegeben und deshalb nicht künstlich verknüpft.
  • Der Seed erzeugt keine E-Mails, SMS, Webhooks oder Push-Nachrichten.
  • Buchungsseiten bleiben unveröffentlicht, damit der öffentliche Staging-Tenant keine realen Terminanfragen oder Folge-E-Mails annimmt.

Markt- und Geodaten

Die Verteilungen basieren auf folgenden Quellen:

Der Geodaten-Check läuft getrennt vom Seed:

pnpm seed:demo-pro:geodata

Am 13.07.2026 wurden 92.178 amtliche hessische Straßennamen geprüft. Die 60 generierten Straßenmuster hatten keine Kollision. Snapshot-Hash: 3678fccbbf62820aecc0a9c7c253e960123e2131a555aa7d4a3b0b2464a1fce3. Da sich amtliche Daten ändern, ist der Check vor einem neuen Seed-Katalog erneut auszuführen.

Verifikation

--verify prüft die vereinbarten Zielmengen einschließlich 17 Büro- und 33 Feldmitarbeitern, die exakte Identitäts-, Rollen- und Dateimatrix in PostgreSQL, alle registrierten Meilisearch-Indizes sowie jedes der 917 realen S3-Objekte bytegenau gegen Größe und SHA-256. Dazu gehören drei Buchungsseiten, 35 Verfügbarkeitsregeln und 79 verknüpfte Buchungstermine. Ein erfolgreicher Apply-Lauf erzeugt außerdem 4.164 permission-aware Search-Projektionen und die entsprechenden, auf maximal 250 Dokumente gebündelten Outbox-Ereignisse für Meilisearch. Dadurch entstehen statt tausender Einzeljobs nur wenige Dutzend tenant-isolierte Batch-Jobs.

Zusätzlich schlägt die Verifikation fehl, sobald irgendein aktuelles tenant-bezogenes Modell mit isDemoData noch markierte Datensätze enthält, der sichtbare Tenant-Name nicht RheinMain Gebäudetechnik GmbH lautet oder die SHK-Rollen vom exakten Berechtigungskatalog abweichen.