feat(abrechnung): Monatskontingent in Credits mit festen Sätzen, Hard-Stop und Warnschwelle

Portierung aus dem Lokal-Fork (AegisSight-Monitor-Local, Commit d2b9168,
per Cherry-Pick übernommen und an den Server-Stand angepasst).

- Feste Sätze je Aktion (BILLING_MODE=flat) statt echter Kosten geteilt
  durch cost_per_credit. Sätze auf die am 23.07.2026 beschlossenen
  Verkaufswerte gesetzt. Live-Lauf 45, Recherche je Durchlauf 40,
  Studio-Bausteine 12, Chat/Beschreibung/Globe 1. Per ENV überschreibbar,
  der alte Modus bleibt als BILLING_MODE=actual erhalten.
- Abrechnungsperiode. licenses.credits_period trennt monthly von total,
  träger Monatsreset bei der nächsten Lizenzprüfung, optionaler Übertrag
  (credits_rollover, gedeckelt auf ein Monatskontingent). Bestandslizenzen
  ohne Periodenmarke behalten ihren Verbrauch.
- Hard-Stop gegen das verfügbare Monatskontingent (Kontingent plus
  Übertrag) statt gegen das Lebenszeit-Total.
- Warnschwelle budget_warning_percent (Default 80 Prozent) wird erstmals
  ausgewertet, einmalige Meldung an alle aktiven Nutzer der Organisation.
- DB-Migration additiv und idempotent (credits_period, credits_period_start,
  credits_rollover, credits_carried, budget_warning_sent, unlimited_budget).
- /api/auth/me liefert credits_available als Bezugsgröße plus
  credits_period, das Credits-Widget zeigt "Credits diesen Monat".
- Wortlaut überall Credits (nicht Guthaben/Einheiten), docs/ABRECHNUNG.md
  auf den Online-Stand gebracht.

Abweichungen zur Fork-Vorlage. Die Takt-Änderungen (Untergrenze 30 Min,
Kostenvorschau im Anlege-Dialog, Fork-Commit 5b0b578) sind bewusst NICHT
enthalten, die Sätze stehen auf 45/40 statt der Fork-Defaults 24/33.

Getestet gegen eine Kopie der Staging-DB, 20 Prüfungen bestanden.
Migration, Flat-Buchung adhoc/research/chat, Warnschwelle einmalig,
Hard-Stop, Monatsreset, Übertrag gedeckelt, Bestandslizenz ohne Marke.
Die vier Live-Lizenzen stehen auf unlimited_budget und sind unbeeinflusst.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-07-25 12:26:54 +00:00
Ursprung ecfc208f22
Commit 1bbbd891ef
13 geänderte Dateien mit 534 neuen und 50 gelöschten Zeilen

Datei anzeigen

@@ -63,12 +63,12 @@
</div>
<div id="credits-section" class="credits-section" style="display: none;">
<div class="credits-divider"></div>
<div class="credits-label">Credits</div>
<div class="credits-label" id="credits-label" data-i18n="credits.label">Credits</div>
<div class="credits-bar-container">
<div id="credits-bar" class="credits-bar"></div>
</div>
<div class="credits-info">
<span><span id="credits-remaining">0</span> von <span id="credits-total">0</span></span>
<span><span id="credits-remaining">0</span> <span data-i18n="credits.of">von</span> <span id="credits-total">0</span></span>
<span class="credits-percent" id="credits-percent"></span>
</div>
</div>
@@ -807,13 +807,13 @@
<script src="/static/vendor/leaflet.js"></script>
<script src="/static/vendor/leaflet.markercluster.js"></script>
<script src="/static/js/i18n.js?v=20260513a"></script>
<script src="/static/js/api.js?v=20260522f"></script>
<script src="/static/js/api.js?v=20260725b"></script>
<script src="/static/js/ws.js?v=20260316b"></script>
<script src="/static/js/components.js?v=20260723a"></script>
<script src="/static/js/layout.js?v=20260513f"></script>
<script src="/static/js/pipeline.js?v=20260513d"></script>
<script src="/static/js/a11y.js?v=20260725a"></script>
<script src="/static/js/app.js?v=20260725a"></script>
<script src="/static/js/app.js?v=20260725b"></script>
<script src="/static/js/cluster-data.js?v=20260322f"></script>
<script src="/static/js/tutorial.js?v=20260316z"></script>
<script src="/static/js/chat.js?v=20260514e"></script>