Files
thandClaude Opus 4.7 7bce6a3a36 v2.0.12 — support channel: relay + hyprcrd plugin
Central support desk for the Oumta project. Tickets arrive through a
self-hostable support-relay (public form, SMTP out), hyprcrd pulls
them in as cards, replies go back out through the relay, and KB
fragments are plain hyprcrd cards so the board + search + tags
machinery handles them for free.

support-relay/ (standalone PHP/SQLite service)
- Public form + submit endpoint with IP rate-limit, honeypot, and an
  email-matched reply path so users can follow up by typing their
  OUMTA-n issue id — mismatched email falls back to a fresh ticket
  so a hostile submitter can't hijack someone else's thread.
- One-shot setup wizard configures branding, issue-id prefix, public
  URL, mail footer template, SMTP creds (stored AES-256-GCM at rest),
  and generates the X-Support-Key API token shown exactly once.
- Hyprcrd-facing API: GET /api/hyprcrd/tickets?since=<iso>, POST
  …/reply (sends via SMTP, flips status to answered), PATCH
  …/status, DELETE, GET /ping, plus GET/POST /api/hyprcrd/settings
  exposing brand/public_url/mail_footer for post-setup edits.
- Minimal dependency-free SMTP client covering STARTTLS/TLS/none,
  AUTH LOGIN, RFC 2047 subject encoding, dot-stuffing. Extended to
  emit multipart/alternative (plain+HTML) + multipart/related so
  outbound mails carry the branded logo via Content-ID embedding;
  plain-text fallback stays intact for older clients.
- Mail footer template supports {brand}, {issue_id}, {public_url}
  placeholders. Lines with an empty placeholder are dropped, so the
  "Reply via …" line vanishes cleanly when no public URL is set.
- Favicon on all public pages. Logo (SVG by default, PNG preferred
  when both exist) picked up from logo2026col.* at send time.
- Docker: Dockerfile + docker-compose.yml for a stand-alone test
  container, plus a support-relay service in the main compose
  (profile "support") so hyprcrd can reach it at http://support-relay
  without host-networking shenanigans.

public/plugins/support (hyprcrd client)
- Full-screen Support overlay: ticket list (status-filterable),
  active ticket thread, reply composer with KB-fragment search +
  click-to-insert, "Save as fragment" button, "Close ticket" shortcut.
- KB fragments are regular cards in a configurable bucket. The
  composer just adds a fast search-and-insert path on top.
- Sync-tick hook auto-polls the relay alongside the existing CalDAV
  + relay-mail cycle.
- Settings tab in the main overlay: relay URL, API key, inbox / KB
  bucket pickers, connection test, and a "Relay config" subsection
  that round-trips to /api/hyprcrd/settings so the mail footer and
  branding can be edited without touching the relay's DB.
- Local cache tables support_tickets + support_replies mirror the
  relay's authoritative data keyed by relay_id.

Tooling
- dev.sh now opts into both relay + support profiles.
- dev-down.sh wipes support-relay volumes and bind-mount data for a
  clean re-setup. Hyprcrd + relay data is preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 10:41:19 +02:00

5.7 KiB

Support-Relay — Setup

Nimmt anonyme Support-Anfragen per Web-Formular entgegen, legt sie in einer lokalen SQLite-DB ab, versendet Bestätigungs- und Antwort-Mails per SMTP. Hyprcrd zieht sich die Tickets und antwortet durch diesen Relay hindurch. Single-user — ein Admin, ein API-Key.

Lokal testen mit Docker (einfachster Weg)

cd support-relay
docker compose up -d --build

Danach http://localhost:8090/ im Browser öffnen → Setup-Wizard. Kein Host-Setup nötig. Die DB und der master-key landen im lokalen ./data/-Ordner und überleben docker compose down.

Zum Rücksetzen (neuer API-Key, leere DB):

rm -f data/support.db data/support.db-* data/master.key
docker compose restart

Stoppen: docker compose down.


Was du für Production brauchst

  • Eine Subdomain, z.B. support.oumta.de
  • PHP ≥ 8.1 mit pdo_sqlite und openssl
  • Apache mit mod_rewrite (oder nginx mit äquivalentem Rewrite)
  • Einen SMTP-Zugang (Mailserver, Mailtrap, Office365, was auch immer)

1. Upload

Den kompletten Ordner support-relay/ als Document-Root der Subdomain hochladen. Die Struktur sollte am Host so aussehen:

support.oumta.de/
├── index.php
├── .htaccess
├── inc/
├── ui/
└── data/          ← muss vom Webserver schreibbar sein!

data/ schreibbar machen (SSH):

chmod 755 data

Der Webserver legt dort support.db und master.key an. master.key kriegt automatisch chmod 600.


2. Erster Aufruf → Setup-Wizard

https://support.oumta.de/ im Browser öffnen. Wenn data/ schreibbar ist, erscheint automatisch der Setup-Wizard. Ausfüllen:

Feld Was eintragen
Display name Oumta Support (wird Absendername, Subject-Präfix, Footer)
Issue-prefix OUMTA (Tickets heißen dann OUMTA-1, OUMTA-2, …)
Host z.B. smtp.office365.com / smtp.mailtrap.io / eigener Mailserver
Port 587 (STARTTLS — Standard)
Encryption STARTTLS (587) lassen, außer dein Server will was anderes
Username SMTP-User
Password SMTP-Passwort (wird verschlüsselt abgelegt)
From address z.B. support@oumta.de
From name Oumta Support

Speichern drücken. Die nächste Seite zeigt einen langen API-Key. Kopieren und sicher aufheben — wird exakt einmal angezeigt.

Nach dem Setup ist diese Seite nicht mehr erreichbar. Stattdessen zeigt / jetzt das öffentliche Support-Formular.


3. Hyprcrd verbinden

In hyprcrd:

  1. Zwei Buckets anlegen (falls noch nicht vorhanden):
    • Support Inbox — hier landen eingehende Tickets als Karten
    • Support KB — hier liegen deine wiederverwendbaren Antwort-Bausteine
  2. Settings (Zahnrad) öffnen → Tab support
  3. Eintragen:
    • Relay URL: https://support.oumta.de
    • API key: der gerade kopierte Key
    • Inbox bucket: Support Inbox
    • KB bucket: Support KB
  4. Save → Test connection → muss grün zurückkommen (OK — relay says "Oumta Support")

4. Smoke-Test

a) Ticket einreichen

In einem Inkognito-Tab https://support.oumta.de/ öffnen, eine Testanfrage absenden. Erwartung:

  • Grüner Banner: Received. Your issue id is OUMTA-1.
  • Bestätigungsmail im Posteingang

b) Ticket in hyprcrd

Oben rechts den Support-Button im Header klicken → Overlay auf. Auf den Reload-Knopf (↻) klicken, dann erscheint das Ticket in der Liste. Im "Support Inbox"-Bucket liegt eine Karte mit derselben Info.

c) Antworten

Ticket anklicken → ins Textfeld tippen → Send reply. Erwartung:

  • Status wechselt auf answered
  • Mail landet im Posteingang des Absenders

d) Fragment speichern

Nach dem Tippen Save as fragment → Titel vergeben → die Antwort taucht im KB-Bucket als Karte auf und wird ab sofort im Suchfeld über dem Composer gefunden.


5. Normaler Betrieb

  • Neue Tickets sehen: Support-Overlay in hyprcrd. Pollt automatisch bei jedem Sync-Tick; manueller Pull per ↻-Knopf.
  • Antworten: aus dem Composer heraus, SMTP läuft über den Relay.
  • Status setzen: open → answered (automatisch bei Reply) → closed (manuell per Button).
  • User antwortet auf eine Mail: er muss seine Issue-ID (OUMTA-n) erneut ins Formular eintragen. Dann wird die Nachricht an das bestehende Ticket gehängt (nur wenn die Email matcht, sonst wird daraus ein neues Ticket).

Troubleshooting

Setup-Wizard kommt nicht data/ ist nicht schreibbar. → chmod 755 data/ (oder 775) und neu laden.

"Test connection" schlägt fehl Relay-URL falsch (Trailing-Slash ist OK, aber HTTPS muss stimmen) oder API-Key nicht exakt übernommen.

Confirmation-Mail kommt nicht SMTP-Creds falsch oder Port blockiert. Direkt vom Host testen:

php -r '
  require "inc/bootstrap.php"; require "inc/SmtpClient.php";
  $c = supportRelaySmtpConfig(Database::connect(), $MASTER_KEY);
  $r = (new SmtpClient($c))->send("du@example.com", $c["from_name"], $c["from"],
    "ping", ["Subject" => "SMTP ping"]);
  print_r($r);
'

Der log-Array zeigt die SMTP-Konversation.

Alles kaputt, von vorn anfangen data/support.db und data/master.key löschen. Nächster Aufruf startet wieder im Setup-Wizard — der API-Key ändert sich dann, musst du in hyprcrd neu eintragen.


Dateien

Pfad Zweck
index.php Entry-Point + Routing
inc/bootstrap.php DB-Schema, Settings, Helpers
inc/SmtpClient.php Minimaler SMTP-Client
inc/routes/*.php Public / Setup / Hyprcrd-API
ui/*.php Form, Setup-Wizard, Status-Seite
ui/style.css Styling
data/support.db SQLite DB (tickets, replies, settings)
data/master.key Verschlüsselt SMTP-Passwort (chmod 600)

Gute Nacht 🌙