Zum Hauptinhalt springen

Release Notes — 3. April 2026

Diese Version vervollständigt das Downgrade-Over-Limit-Durchsetzungssystem – die vollständige Reihe von Backend-, Frontend-, E-Mail- und UI-Änderungen, die sicherstellen, dass die App Situationen korrekt behandelt, in denen die vorhandenen Daten einer Unit die Limits des neuen (niedrigeren) Plans nach einem Abonnement-Downgrade überschreiten.


Downgrade-Durchsetzung: Vollständige Over-Limit-Ressourcenbehandlung

Übersicht

Wenn ein Arbeitsbereich-Eigentümer von PRO auf FREE (oder von ENTERPRISE auf PRO) downgradet, können die vorhandenen Daten die Limits des neuen Plans überschreiten. Diese Version stellt sicher, dass jede Schicht des Systems – API, UI, Benachrichtigungen – diese Limits korrekt durchsetzt und kommuniziert.

Betroffene Limits:

RessourceFREE-LimitPRO-Limit
Teammitglieder320
Projekte (pro Arbeitsbereich)3Unbegrenzt
Aufgaben (pro Arbeitsbereich)1570
Zeiteinträge (pro Arbeitsbereich)1001.000

Backend-Durchsetzung

Schreibsperre für gesperrte Benutzer

Alle Schreib-Endpunkte (POST, PUT, PATCH, DELETE) für Projekte, Aufgaben, Teams und Zeiteinträge sind jetzt durch die requireNotOverLimitLocked-Middleware geschützt. Benutzer, deren Konto aufgrund eines Downgrades gesperrt wurde, erhalten bei jedem Schreibversuch eine 403 ACCOUNT_LOCKED-Antwort.

Timer-Start-Sperre

Der startTimer()-Endpunkt erzwingt das Zeiteintrags-Limit für den Arbeitsbereich. Der Versuch, einen neuen Timer zu starten, wenn der Arbeitsbereich sein Zeiteintrags-Limit erreicht oder überschritten hat, gibt 403 LIMIT_EXCEEDED zurück.

Team-Einladungssperre

Der inviteUser()-Endpunkt prüft maxTeamMembers gegen das aktuelle Tier, bevor eine Einladung gesendet wird. Einladungen, die das Limit überschreiten, geben 403 LIMIT_EXCEEDED zurück.

Mitglieder-Sperre bei Downgrade (Webhook)

Wenn ein customer.subscription.updated- oder customer.subscription.deleted-Ereignis empfangen wird und das Tier sinkt, wird markExcessMembersAsLocked() automatisch ausgeführt:

  • Fragt alle active- und pending-Mitglieder ab (beide zählen zur Nutzung)
  • Sperrt die neuesten Mitglieder, die das neue Limit überschreiten
  • Sendet Benachrichtigungs-E-Mails an jedes gesperrte Mitglied

E-Mail-Benachrichtigungen

Downgrade-Zusammenfassungs-E-Mail (Eigentümer)

Der Arbeitsbereich-Eigentümer erhält sofort beim Downgrade eine E-Mail mit allen Over-Limit-Ressourcen:

  • Anzahl gesperrter Teammitglieder
  • Anzahl überschüssiger Projekte
  • Links zur Behebung jedes Problems (Team, Projekte, Upgrade)

Zugriff-eingeschränkt-E-Mail (Gesperrte Mitglieder)

Jedes Mitglied, dessen Zugriff gesperrt ist, erhält eine persönliche Benachrichtigungs-E-Mail mit:

  • Konto wurde downgegradet
  • Zugriff ist jetzt eingeschränkt
  • Wen kontaktieren, um den vollen Zugriff wiederherzustellen

Frontend: Over-Limit-UI

Globales Banner für gesperrte Benutzer

Benutzer mit isOverLimitLocked: true sehen ein dauerhaftes Warnbanner in der gesamten Anwendung (gerendert in AppShell):

„Ihr Kontozugriff ist aufgrund eines Plan-Downgrades eingeschränkt. Kontaktieren Sie den Arbeitsbereich-Eigentümer, um den Zugriff wiederherzustellen."

Over-Limit-Banner auf allen Ressourcenseiten

SeiteBanner-Bedingung
Projektecurrent > max Projekte
Aufgabencurrent >= max Aufgaben
Zeiterfassungcurrent >= max Zeiteinträge
Teammitgliedercurrent > max Mitglieder (Fix: war >=)

Alle Banner enthalten einen Upgrade-Aktionsbutton.

Überschüssige Projekt-Nur-Lesen-Banner

  • Projektdetailseite — ein Warnbanner erscheint, wenn das Projekt als isExcessProject: true markiert ist
  • Projektaufgaben-Tab — Aufgabenerstellung ist deaktiviert mit einem erklärenden Banner

Fehlerbehebungen

Mitglieder-Sperrabfrage: Ausstehende Mitglieder eingeschlossen

markExcessMembersAsLocked() fragte zuvor nur status: 'active'-Mitglieder ab. Da pending-Mitglieder auch zum Nutzungslimit zählen, verursachte dies eine Unstimmigkeit.

Fix: Die Abfrage verwendet jetzt { status: { $in: ['active', 'pending'] } }.

Unit-Modell-Tier-Limits korrigiert

Der Pre-Save-Hook des Unit-Modells hatte hartcodierte Werte (FREE: 5 Mitglieder, PRO: 25 Mitglieder), die mit den maßgebenden Werten in tiers.config.ts kollidierten.

Fix: Pre-Save-Hook verwendet jetzt die korrekten Werte: FREE: 3, PRO: 20.


Zusammenfassung

BereichÄnderung
BackendrequireNotOverLimitLocked-Middleware auf alle Schreibrouten angewendet
BackendmarkExcessMembersAsLocked enthält jetzt auch pending-Mitglieder
BackendUnit.model.ts Pre-Save-Hook-Limits korrigiert (FREE: 3, PRO: 20)
BackendDowngrade-Webhook sendet Zusammenfassungs-E-Mail an Eigentümer
FrontendTeammitglieder-Banner: >=> (strikt über Limit)
FrontendAppShell.tsx: globales dauerhaftes Banner für gesperrte Benutzer
Scriptsmanual-downgrade-to-free.mjs hinzugefügt
Scriptstest-downgrade-enforcement.mjs hinzugefügt

Verfügbarkeit: Alle Pläne (Durchsetzung gilt automatisch bei Downgrade)