Commit Graph

2 Commits

Author SHA1 Message Date
b8f9a50731 White-Label Phase 1: Host→Tenant-Auflösung + Branding
- Domain-Entity polymorph (Reseller ODER Firma)
- TenantResolver: Host → Plattform / reseller.portal / firma.reseller.portal
  / verifizierte Custom-Domain
- Öffentliches GET /api/branding (Name, Ebene, Farben, Logo) nach Host
- TLS-Gate nutzt TenantResolver (nur bekannte Hosts → Zertifikat)
- Frontend: Branding-Store lädt vor Mount, färbt Theme um, TenantBrand-
  Komponente (Logo/Name je Tenant), Login zeigt Tenant
- Vite-Proxy reicht Original-Host durch (lokales White-Label-Testing)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 12:58:20 +02:00
79e996ab03 Deployment: Caddy-Edge (TLS + On-Demand für Custom-Domains) + Hetzner DNS
- Caddy ersetzt den Hetzner-LB: terminiert TLS (Portal-Domain automatisch) und
  load-balanced per reverse_proxy über die App-Nodes. Für Custom-Domains (§11)
  On-Demand-TLS, autorisiert über GET /internal/tls-allowed.
- TlsCheckController + DomainRepository::findVerifiedByHostname: erlaubt Zertifikate
  nur für Portal-Domain oder verifizierte Domains (Schutz vor Cert-Flooding).
- Terraform: hcloud_load_balancer entfernt, Caddy-Server + Firewall (80/443) +
  cloud-init-caddy (Caddyfile templated mit Upstreams/Domain/ACME).
- Optional Hetzner DNS via API (manage_dns): A-Record Portal + Wildcard → Caddy.
- nginx.prod: /internal zu Symfony geroutet; APP_PORTAL_DOMAIN-Env.

Validiert: Caddyfile (caddy validate), Terraform (validate), /internal/tls-allowed (200/403/400).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:13:29 +02:00