Zum Hauptinhalt springen

Anbieter-Registrierung

[admin] [signup]

Self-Service-Registrierung unter https://admin.licensio.io/register. Die Registrierung legt einen kostenfreien Zugang an — keine Kreditkarte, keine Planauswahl, keine Portal-Adresse. Ein neuer Anbieter ist in unter zwei Minuten startklar.

Hinweis: Die öffentliche Marketing-Site unter https://licensio.io (eigene Next.js-App apps/marketing, separates Vercel-Deployment, i18n EN/DE mit Flaggen-Dropdown im Header) verlinkt aus Header (Sign up) und Hero (Start for free →) auf https://admin.licensio.io/register?lang=<locale>. Die Sprache wird in das Register-Formular übernommen. Die Kontakt-Sektion öffnet mailto:malte@licensio.io.

Sprache auf der Register-Seite: Auflösungsreihenfolge ?lang=en|de (URL-Param) > LocalStorage licensio_locale > Default en. Ein Flaggen-Dropdown oben rechts erlaubt den manuellen Wechsel; die Wahl wird im Admin-LocalStorage gespeichert. Formular-Labels, Buttons und Fehlermeldungen sind übersetzt.

Lebenszyklus nach der Registrierung​

  1. Anbieter + Auth-User + tenant_users-Verknüpfung werden in /api/register angelegt (Self-Service-Signup, E-Mail direkt bestätigt). Der Tenant wird auf dem kostenfreien Zugang angelegt (Plan-Wert free), inkl. akzeptierter AGB-Version + Zeitstempel (terms_accepted_at, terms_version).
  2. Bei der Registrierung wird keine Portal-Subdomain angelegt. tenants.slug bleibt NULL, bis das Anbieter-Modul aktiviert wird (App Store, später); erst dann wird eine Subdomain gewählt und provisioniert. Bis dahin arbeitet der Anbieter vollständig im Admin.
  3. Welcome-E-Mail an die Registrierungs-Adresse (Resend, from: noreply@licensio.io): „Willkommen bei licensio.io 🎉" + CTA auf admin.licensio.io. Best-effort (die Registrierung schlägt nicht fehl, wenn Resend down ist).
  4. Weiterleitung auf /onboarding. Es gibt keinen Stripe-Checkout auf dem Registrierungs-Pfad — ein Upgrade auf einen kostenpflichtigen Tarif passiert später im Admin unter Einstellungen → Abonnement.

Passwort vergessen / zurücksetzen​

  • /forgot-password (wartungs-ausgenommen): E-Mail-Eingabe → POST /api/auth/forgot-password ruft supabase.auth.resetPasswordForEmail(email, { redirectTo: '/reset-password' }). Die Antwort ist immer { success: true } (kein Info-Leak).
  • /reset-password (wartungs-ausgenommen): wartet auf das Supabase-PASSWORD_RECOVERY-Event, ruft dann clientseitig updateUser({ password }). Die Recovery-Session kommt automatisch über den E-Mail-Link; kein separater Server-Endpunkt nötig.

Für wen​

Neue Anbieter, die mit licensio starten wollen.

Schritt für Schritt​

1. Account-Felder ausfüllen​

Das Register-Formular fragt genau diese Felder ab — sonst nichts:

  • Vorname + Nachname: die ersten beiden Pflichtfelder (eine Zeile, zwei Spalten), gespeichert auf tenant_users (Migration 096), Anrede in Willkommens- und Login-OTP-Mail.
  • Firmenname
  • E-Mail: primärer Login
  • Passwort: min. 8 Zeichen (+ Bestätigung)
  • Land des Unternehmens: ein Profilfeld (tenants.country) für Abrechnungswährung und Compliance. Es legt kein Stripe-Konto an und setzt an dieser Stelle keine Portal-Adresse.
  • Branche (NACE Rev. 2.1): Pflicht. Zweistufige Auswahl (Sektion A–V → Abteilung, 87 Abteilungen, DE/EN-Labels aus der amtlichen Eurostat-Quelle). Bis zu 3 Branchen, die erste ist die Hauptbranche. Gespeichert in tenants.industry_codes (Migration 093), serverseitig gegen die Referenztabelle nace_divisions validiert.
  • AGB + Datenschutz akzeptieren (Pflicht-Checkbox)

Es gibt keine Planauswahl, keine Tarif-Karten und kein Shop-/Subdomain-Feld.

2. Absenden​

Das Backend (/api/register) führt aus:

  1. Validierung (Vor-/Nachname nicht leer + max 80, E-Mail-Format, Passwortlänge, Firmenname ≥ 3 Zeichen, unterstütztes Land, mindestens ein gültiger NACE-Branchencode, AGB akzeptiert — siehe apps/admin/lib/register-validate.ts + validateIndustryCodes)
  2. Cloudflare-Turnstile-Captcha-Prüfung (fail-open solange TURNSTILE_SECRET_KEY ungesetzt ist)
  3. E-Mail-Eindeutigkeitsprüfung
  4. auth.admin.createUser({ email_confirm: true }): Account direkt aktiv ohne Mail-Bestätigung
  5. tenants INSERT: Plan free, slug: NULL, industry_codes, Abrechnungswährung aus dem Land abgeleitet, Default-Branding (primary_color: #0070F3, button_style: rounded), terms_accepted_at + terms_version
  6. tenant_users INSERT mit role='admin', first_name, last_name
  7. Weiterleitung: mit Anbieter-Absicht auf /onboarding/provider, sonst /onboarding (dazwischen Post-Register-OTP zur E-Mail-Bestätigung)

Bei Fehlern werden Auth-User + Tenant-Eintrag zurückgerollt.

3. Onboarding-Wizard​

Nach erfolgreicher Registrierung führt ein Wizard durch Branding, Stripe Connect und das erste Produkt:

  1. Willkommen: Überblick über die nächsten Schritte.
  2. Branding: Firmenname + Primärfarbe (Logo + weitere Farben später im Dashboard)
  3. Stripe Connect: Klick auf „Stripe verbinden" startet das Express-Onboarding über /api/stripe/connect/authorize?return=onboarding. Nach dem Stripe-Setup landet man zurück auf /onboarding?step=4&stripe=connected.
  4. Erstes Produkt: Direktlink zur Produkterstellung (oder überspringen)
  5. Fertig: Überblick „Wie geht's weiter", Link ins Dashboard

Ein Fortschrittsbalken oben + ein Schrittzähler unten zeigen den Fortschritt. Der URL-Parameter ?step=N springt zum jeweiligen Schritt (z. B. nach der Stripe-Connect-Rückkehr).

4. Plan-Gates im Admin​

Features, die im aktuellen Plan nicht enthalten sind, werden ausgeblendet statt gesperrt (seit 2026-05-29, kein Lock-Banner / 🔒-Badge / Upgrade-CTA mehr):

  • Die Widget- + Domain-Tabs in den Einstellungen sowie die zugehörigen Advanced-Kacheln erscheinen nur, wenn der Plan das Feature hat
  • Bulk-Import, API, PrintFarm ebenso: der Nav-Eintrag fehlt ohne das Feature komplett
  • Direktes Öffnen einer Feature-Seite ohne Berechtigung → 404 (notFound())
  • Feature-Promotion läuft über Newsletter + App Store (Phase 4), nicht mehr über Lock-Hinweise

Die Sichtbarkeitslogik liegt in apps/admin/lib/plans.ts (isFeatureAvailable + has_*-Flags). apps/admin/components/PlanGate.tsx rendert null, wenn ein Feature fehlt (defensiver Content-Layer, future-proof). Backend-API-Routen prüfen den Plan zusätzlich serverseitig (403).

Häufige Fragen​

Welche Felder fragt die Registrierung ab? Firmenname, E-Mail, Passwort, Land des Unternehmens, Branche (NACE Rev. 2.1, Pflicht) und die AGB-Checkbox. Sonst nichts — keine Planauswahl, keine Tarif-Karten, keine Subdomain.

Wann bekomme ich eine Portal-Adresse (<name>.licensio.io)? Beim Aktivieren des Anbieter-Moduls (App Store, später). Erst dann wird eine Subdomain gewählt und provisioniert. Admin-Aktionen, die einen Portal-Link versenden würden (Kunde einladen, Freischalten, Mail senden, Registrierung erneut senden, Passwort zurücksetzen, Newsletter, Benachrichtigung senden), sind bis dahin deaktiviert.

Kann ich auf einen kostenpflichtigen Tarif upgraden? Ja, später im Admin unter Einstellungen → Abonnement. Die Registrierung startet immer mit dem kostenfreien Zugang.

Werden Daten bei Account-Löschung DSGVO-konform behandelt? Die Anbieter-Löschung läuft über eine Support-Anfrage. DSGVO Art. 17 wird durch Löschen von tenant_users + tenants erfüllt; Kundendaten in deleted_customers werden anonymisiert archiviert.

Verwandt​