Files
ToolCTRL-website/README.md
T

167 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ToolCTRL — Website
Mehrseitige Website im Visitenkarten-Stil: Landing Page mit Lead-Formular,
TechDay-2026-Seite, AI-GameJam-Seite mit Datei-Upload sowie Impressum und
Datenschutz. Monochrom (weiß / schwarz), an die ToolCTRL Brand Identity
angelehnt. Der Server läuft ohne npm-Pakete (nur Node-Standardbibliothek).
## Starten
```bash
node server.js
```
Der Server sucht automatisch einen freien Port (zuerst `4317`) und gibt lokale
und Netzwerk-URL aus. Stoppen mit `Strg + C`.
Voraussetzung: Node.js (getestet mit v26).
Qualitätschecks:
```bash
npm run check
npm test
```
## Aufbau
```
public/ statische Website
index.html Landing Page + Kontaktformular
techday.html TechDay Bruchsal 2026
gamejam.html AI GameJam (eigenes Styling, Spiel-Upload)
impressum.html Impressum
datenschutz.html Datenschutzerklärung
styles.css Designsystem
script.js Formular-Logik & Mobile-Navigation
assets/ Logos, Emblem, Favicon, Icons, Schriften, Mockups
server.js abhängigkeitsfreier Node-HTTP-Server + API
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.
## Plattform-Leads
`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)
`POST /api/gamejam/upload` nimmt eine `.html`-Datei entgegen (max. 5 MB).
**Jede hochgeladene Datei wird vor dem Speichern per ClamAV auf Viren
geprüft.** Befund → Ablehnung; ist der Scanner nicht erreichbar, wird der
Upload ebenfalls abgelehnt (fail-closed, kein ungeprüftes Speichern).
Der Server spricht den ClamAV-Daemon `clamd` direkt über sein Socket-Protokoll
an — keine zusätzliche Abhängigkeit. Voraussetzung: ClamAV ist installiert und
`clamd` läuft. Beim Start meldet der Server `Virenscan: aktiv` bzw. eine
Warnung, falls `clamd` nicht erreichbar ist.
### ClamAV einrichten — macOS
```bash
brew install clamav
cd "$(brew --prefix)/etc/clamav"
cp freshclam.conf.sample freshclam.conf
cp clamd.conf.sample clamd.conf
# In BEIDEN Dateien die Zeile "Example" entfernen oder auskommentieren.
# In clamd.conf zusätzlich diese zwei Zeilen aktivieren (Raute entfernen):
# TCPSocket 3310
# TCPAddr 127.0.0.1
freshclam # Virendefinitionen laden (einmalig)
clamd # Daemon starten
```
### ClamAV einrichten — Linux (Debian/Ubuntu)
```bash
sudo apt install clamav clamav-daemon
# In /etc/clamav/clamd.conf: TCPSocket 3310 und TCPAddr 127.0.0.1 setzen
sudo systemctl restart clamav-daemon
```
### Konfiguration
Host/Port und An/Aus stehen in `server.js` im Objekt `CLAMAV`. Mit
`enabled: false` läuft der Upload ohne Virenscan (nur für lokale Tests
ohne ClamAV gedacht).
Per Environment kann der Runtime-Betrieb konfiguriert werden:
```bash
PORT=3000
HOST=0.0.0.0
DATA_DIR=/app/data
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 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
Eine Datei mit der EICAR-Testsignatur hochladen — `clamd` meldet dann
`Eicar-Test-Signature FOUND`, der Upload wird abgelehnt.
## Hinweis für die Messe
Für den QR-Code am Stand muss der Rechner im selben WLAN erreichbar sein.
Soll die Seite öffentlich laufen, hinter einen Reverse-Proxy mit HTTPS setzen
oder bei einem Hoster bereitstellen — `tool-ctrl.de`.
## Deployment
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: vollständiger, unveränderlicher Commit-SHA und `main`.
4. Coolify-App `toolctrl-website` (`ocwtt7rd2zijtlszgua005k9`) zieht
`: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`.