feat(leads): submit contact requests to native platform intake
This commit is contained in:
1 parent
41664c3d0d
commit
079764d93d
12 files changed
+760
-154
No files matched your search
@@ -16,6 +16,13 @@ und Netzwerk-URL aus. Stoppen mit `Strg + C`.
|
||||
|
||||
Voraussetzung: Node.js (getestet mit v26).
|
||||
|
||||
Qualitätschecks:
|
||||
|
||||
```bash
|
||||
npm run check
|
||||
npm test
|
||||
```
|
||||
|
||||
## Aufbau
|
||||
|
||||
```
|
||||
@@ -29,18 +36,46 @@ public/ statische Website
|
||||
script.js Formular-Logik & Mobile-Navigation
|
||||
assets/ Logos, Emblem, Favicon, Icons, Schriften, Mockups
|
||||
server.js abhängigkeitsfreier Node-HTTP-Server + API
|
||||
leads/ gesammelte Kontaktanfragen (wird automatisch angelegt)
|
||||
leads/ historische NDJSON/CSV-Leads (nur noch Backfill-Quelle)
|
||||
gamejam/ GameJam-Einreichungen, Metadaten (wird automatisch angelegt)
|
||||
```
|
||||
|
||||
`leads/`, `gamejam/` und hochgeladene Spiele sind per `.gitignore` vom Repo
|
||||
ausgeschlossen.
|
||||
|
||||
## Leads
|
||||
## Plattform-Leads
|
||||
|
||||
`POST /api/lead` (JSON, Pflichtfelder `name`, `email`, `nachricht`). Jede
|
||||
Anfrage landet sofort lokal in `leads/leads.csv` **und** `leads.ndjson` — so
|
||||
geht auf der Messe nichts verloren. Ein Honeypot-Feld fängt einfache Bots ab.
|
||||
`POST /api/lead` validiert das Kontaktformular serverseitig und sendet die
|
||||
Anfrage an HiveGrids nativen Endpoint `POST /v1/platform/leads`. Pflichtfelder
|
||||
sind `name`, `email`, `nachricht` und die vom Browser erzeugte `submissionId`.
|
||||
Ein Honeypot-Feld fängt einfache Bots ab.
|
||||
|
||||
Der Browser behält die Submission-ID nach einem fehlgeschlagenen Versuch mit
|
||||
semantisch gleichem Payload bei. Wird das Formular inhaltlich geändert, bindet er
|
||||
vor dem nächsten Senden eine neue ID. Der Server verwendet dieselbe ID als
|
||||
`externalId`, `metadata.submissionId` und `Idempotency-Key`; auch der einmalige
|
||||
Netzwerk-/5xx-Retry verwendet exakt denselben Key und Payload. Dem Formular wird
|
||||
nur dann Erfolg gemeldet, wenn die Plattform den Lead mit `201` angenommen hat.
|
||||
API-, Netzwerk- und Konfigurationsfehler bleiben Fehler.
|
||||
|
||||
Die bisherige Zuordnung `Messe — Landing Page` bleibt im nativen Vertrag als
|
||||
`sourceDetail` und `utmCampaign=messe-landing-page` erhalten.
|
||||
|
||||
Erforderliche Runtime-Variablen:
|
||||
|
||||
```bash
|
||||
PLATFORM_LEADS_API_URL=https://api.hivegrid.de
|
||||
PLATFORM_LEADS_API_KEY=<source-spezifischer Key für toolctrl-website, 32–512 Zeichen>
|
||||
```
|
||||
|
||||
Der Bearer-Key gehört ausschließlich in die Server-Runtime (Coolify), nie ins
|
||||
Repository oder nach `public/`. Ohne gültige Konfiguration liefert die Route
|
||||
`503` und `/readyz` bleibt nicht bereit.
|
||||
|
||||
Die bestehenden Dateien `leads/leads.ndjson` und `leads/leads.csv` sind
|
||||
Legacy-Bestände für den kontrollierten R-LEADS-Backfill. Der laufende Producer
|
||||
erstellt oder verändert sie nicht mehr und meldet bei Plattformfehlern keinen
|
||||
lokalen Ersatz-Erfolg.
|
||||
|
||||
## GameJam-Upload & Virenscan (ClamAV)
|
||||
|
||||
@@ -93,11 +128,15 @@ CLAMAV_HOST=127.0.0.1
|
||||
CLAMAV_PORT=3310
|
||||
CLAMAV_ENABLED=true
|
||||
APP_REVISION=<git-sha>
|
||||
PLATFORM_LEADS_API_URL=https://api.hivegrid.de
|
||||
PLATFORM_LEADS_API_KEY=<Runtime-Secret>
|
||||
```
|
||||
|
||||
`/healthz` ist die leichte Liveness-Probe für Container und Coolify.
|
||||
`/readyz` prüft zusätzlich Schreibzugriff auf die Datenverzeichnisse und,
|
||||
falls aktiv, die Erreichbarkeit von ClamAV.
|
||||
`/readyz` prüft zusätzlich die Plattform-Lead-Konfiguration, Schreibzugriff auf
|
||||
die GameJam-Datenverzeichnisse und, falls aktiv, die Erreichbarkeit von ClamAV.
|
||||
Der Container-Healthcheck verwendet `/readyz`, damit eine fehlende
|
||||
Plattform-Lead-Konfiguration einen Deploy nicht gesund erscheinen lässt.
|
||||
|
||||
### Funktion testen
|
||||
|
||||
@@ -117,9 +156,11 @@ Deployment folgt dem Gitea-Infra-Standard aus `toolctrl-labs/infra`:
|
||||
1. Push auf `main` triggert `.gitea/workflows/deploy.yml`.
|
||||
2. Gitea Actions baut das Docker-Image und pusht es nach
|
||||
`git.tool-ctrl.de/toolctrl-labs/toolctrl-website`.
|
||||
3. Tags: kurzer Commit-SHA und `main`.
|
||||
3. Tags: vollständiger, unveränderlicher Commit-SHA und `main`.
|
||||
4. Coolify-App `toolctrl-website` (`ocwtt7rd2zijtlszgua005k9`) zieht
|
||||
`:main` auf der Marketing-VM und startet neu.
|
||||
`:main` per erzwungenem Pull-Deploy auf der Marketing-VM.
|
||||
5. Der Workflow wartet anschließend, bis `/readyz` erfolgreich ist und exakt
|
||||
den ausgelieferten Commit-SHA als `revision` meldet.
|
||||
|
||||
Die Coolify-App läuft im Projekt `Marketing`, Environment `production`, Server
|
||||
`marketing-vm`, Port `3000`, mit persistentem Storage auf `/app/data`.
|
||||
Reference in new issue
Block a user