Anwendungsfälle
Widerrufen, verlängern & Ablauf behandeln
Zugang beenden, eine Laufzeit ohne neuen Schlüssel verlängern und genau wissen, was die Anwendung beim Ablauf, während der Kulanzfrist und nach dem Widerruf sieht — und wie sich das von einer selbst gehosteten Instanz unterscheidet, die sich selbst lizenziert.
Ziel. Sie müssen den Zugang eines Kunden sofort beenden (eine Rückbuchung, Missbrauch, eine versehentliche Ausstellung), die Laufzeit eines zahlenden Kunden verlängern, ohne seinen Schlüssel neu auszustellen, und genau verstehen, was die laufende Anwendung anzeigt, während eine Laufzeit ausläuft.
Wann einsetzen
- Nutzen Sie dies, wenn Sie befristete Lizenzen (Jahreslizenz/Abonnement) verkaufen und verlängern oder jemals einen Schlüssel widerrufen müssen.
- Nutzen Sie dies, wenn Sie entscheiden, wie aggressiv der Ausfall sein soll — wie schnell ein Widerruf oder Ablauf eine Maschine erreicht, die gerade offline ist.
- Nicht nutzen, wenn Sie nur unbefristete Lizenzen ausliefern, die nie ablaufen und nie widerrufen werden — dann ist diese Seite nur der Widerrufspfad für den Notfall. Einen Platz zwischen Maschinen zu verschieben ist Aktivierung & Deaktivierung, kein Widerruf.
Zwei Lebenszyklen teilen sich diese Seite und dürfen nicht verwechselt werden. Der Lebenszyklus der Kundenlizenz (die Schlüssel Ihrer Endnutzer) verhält sich gleich, egal ob Sie auf der Cloud oder selbst gehostet laufen. Der Lebenszyklus der selbst gehosteten Instanz ist etwas anderes — der eigene Schlüssel der Instanz, der ihr das Recht zum Betrieb gewährt — und wird am Ende sowie unter Lizenzierung & Editionen behandelt.
Was Sie tun (Anbieterseite)
Alle drei Aktionen signieren die Lizenz serverseitig neu; der Kunde behält den gleichen Schlüssel und aktiviert einfach erneut (in der Regel automatisch beim Start), um die Änderung zu übernehmen.
Widerrufen — einen Schlüssel sperren:
curl -X POST $BASE/admin/licenses/LIC-…/revoke -H "X-Admin-Token: $TOKEN"
# the dashboard's per-row Revoke action does the same. Many at once: POST /admin/licenses/bulk-revoke
Verlängern / Laufzeit erweitern — den Ablauf nach hinten verschieben (und optional die Plätze ändern), ohne neuen Schlüssel:
curl -X POST $BASE/admin/licenses/LIC-…/renew -H "X-Admin-Token: $TOKEN" -H "content-type: application/json" \
-d '{"expiryUtc":"2028-10-12T00:00:00Z"}'
# seats can be changed here too; a renewal re-signs the license in place. The key is unchanged.
Beides finden Sie auf der eigenen Seite der Lizenz: Renew sitzt in der Aktionszeile, Revoke in der Danger zone.
Ablauf ist schlicht das Erreichen des expiryUtc der Lizenz ohne Verlängerung — Sie tun nichts; das unten beschriebene Verhalten setzt von selbst ein. (Eine Rückerstattung/Kündigung aus einem Shop-Webhook widerruft automatisch — siehe Schlüssel automatisch aus einem Shop ausstellen.)
Jeder Zustand dieses Lebenszyklus erscheint in der Liste Licenses, sodass Sie einen widerrufenen, abgelaufenen oder bald ablaufenden Schlüssel auf einen Blick erkennen:
LicenseInfo.Status liest.Wie schnell eine Änderung die Maschine erreicht
Ein Widerruf oder eine Verlängerung wird bei der nächsten Online-Prüfung des Geräts angewendet, denn zwischen den Prüfungen läuft die Anwendung offline gegen einen zwischengespeicherten Lease. Die Lease-TTL (Standard 14 Tage, KEYRIGHT_LEASE_TTL_DAYS) ist genau die Stellschraube: Eine verbundene Anwendung, die beim Start erneut aktiviert, übernimmt einen Widerruf innerhalb ihres Aktualisierungsrhythmus; eine Maschine, die offline war, sieht ihn erst, wenn sie wieder online ist — und spätestens dann, wenn die Kulanzfrist ihres Lease verstreicht und sie zur erneuten Prüfung gezwungen wird. Verkürzen Sie die TTL, damit Widerrufe und Platzänderungen schneller greifen, auf Kosten geringerer Offline-Toleranz. Für die Offline-Durchsetzung ganz ohne Netzwerk liefern Sie eine signierte Widerrufsliste mit Ihrem Build aus (RevocationListJson / RevocationListPath), damit auch eine rein offline laufende Anwendung einen Widerruf respektiert.
In Ihrem Code
Ihre Anwendung liest alles aus LicenseInfo — sie parst nie einen Schlüssel. Die relevanten Member, in jedem SDK und über reines HTTP:
.NET
LicenseInfo info = await License.ActivateAsync(key, ct); // or License.Validate() offline; both fail closed
// Status is the single source of truth — branch on it.
switch (info.Status)
{
case LicenseStatus.Valid: break; // licensed; fall through to the badge below
case LicenseStatus.Expired: return ShowRenewPrompt(info.Message); // term ended, or trial over
case LicenseStatus.Revoked: return ShowUnlicensed(info.Message); // key was revoked
default: return ShowUnlicensed(info.Message); // NoLicense, SeatLimit, SignatureInvalid, …
}
// While valid, surface the countdown and nudge before renewal.
if (info.IsExpiringSoon()) // true inside the renewal window
ShowRenewBanner($"{info.DaysRemaining} days left"); // DaysRemaining counts down to expiryUtc
string badge = info.ExpiryUtc is null
? "Licensed — perpetual" // no expiry
: $"Licensed — expires {info.ExpiryUtc:d}";
Node.js
const { info } = license.validate(); // or: info = await license.activate(key)
switch (info.status) {
case 'valid': break; // licensed
case 'expired': return showRenewPrompt(info.message); // term ended, or trial over
case 'revoked': return showUnlicensed(info.message); // key was revoked
default: return showUnlicensed(info.message); // no_license, machine_mismatch, …
}
if (info.daysRemaining != null && info.daysRemaining <= 14) // nudge before renewal
showRenewBanner(`${info.daysRemaining} days left`);
const badge = info.expiryUtc ? `Licensed — expires ${info.expiryUtc.toLocaleDateString()}`
: 'Licensed — perpetual';
Python
info = license.validate_info() # or: info = license.activate(key)
if info.status == LicenseStatus.VALID:
pass # licensed
elif info.status == LicenseStatus.EXPIRED:
return show_renew_prompt(info.message) # term ended, or trial over
elif info.status == LicenseStatus.REVOKED:
return show_unlicensed(info.message) # key was revoked
else:
return show_unlicensed(info.message) # NO_LICENSE, MACHINE_MISMATCH, …
if info.days_remaining is not None and info.days_remaining <= 14:
show_renew_banner(f"{info.days_remaining} days left")
badge = "Licensed — perpetual" if info.expiry_utc is None else f"Licensed — expires {info.expiry_utc:%x}"
Java
LicenseInfo info = client.validateInfo(); // or: info = client.activate(key)
switch (info.status) {
case VALID: break; // licensed
case EXPIRED: return showRenewPrompt(info.message); // term ended, or trial over
case REVOKED: return showUnlicensed(info.message); // key was revoked
default: return showUnlicensed(info.message); // NO_LICENSE, MACHINE_MISMATCH, …
}
if (info.isExpiringSoon(14)) // nudge before renewal
showRenewBanner(info.daysRemaining() + " days left");
String badge = info.expiryUtc == null ? "Licensed — perpetual"
: "Licensed — expires " + info.expiryUtc;
Jede Sprache (reines HTTP)
curl -s -X POST "$BASE/v1/validate" -H "content-type: application/json" \
-d '{"key":"LIC-…","machineId":"<stable-machine-id>","product":"acme-app"}'
# status "revoked" -> drop to Free; "expired" -> prompt to renew; "ok" -> verify the lease and read
# licenseExpiryUtc for the countdown. Fail closed on anything but a valid, in-date lease.
Was jede Variante anzeigt, während die Laufzeit ausläuft:
DaysRemainingzählt bisexpiryUtcherunter;IsExpiringSoon()wird innerhalb des Verlängerungsfensters wahr, sodass Sie den Nutzer ansprechen können, bevor der Zugang endet.- Beim Ablauf oder nach einem Widerruf wird
IsPaidfalse, und die Anwendung fällt in ihren Free-/unlizenzierten Zustand zurück — Keyright verhält sich fail-closed, es wirft keine Ausnahme.Statussagt Ihnen, was zutrifft (ExpiredoderRevoked), damit Sie die Meldung passend formulieren können („verlängern“ vs. „kontaktieren Sie uns“). - Nach einer Verlängerung liefert das nächste
ActivateAsync/Validate()das spätereExpiryUtc— keine erneute Schlüsseleingabe, kein Reaktivierungsdialog.
Es gibt keine In-App-„Kulanzfrist“ für eine befristete Lizenz: Sobald expiryUtc überschritten ist (und die Maschine das nächste Mal validiert), ist die Anwendung Expired. Das 14-Tage-Fenster des Lease ist ein Konnektivitäts-Puffer — es lässt eine Maschine offline gegen eine noch gültige Laufzeit laufen — und keine zusätzliche Kulanz nach Ende der bezahlten Laufzeit. Wenn ältere Versionen nach dem Auslaufen eines Abonnements weiterlaufen sollen, ist das das Abonnement mit Fallback der Release-Abdeckung, keine Ablaufkulanz.
Nutzer von reinem HTTP sehen denselben Lebenszyklus über das Feld status von /v1/validate (revoked, expired) und das licenseExpiryUtc des Lease — verifizieren Sie den Lease und verhalten Sie sich fail-closed bei allem außer einem gültigen, nicht abgelaufenen Lease, wie unter Die HTTP-API direkt nutzen beschrieben.
Lebenszyklus der Kundenlizenz vs. Lebenszyklus der selbst gehosteten Instanz
Das sind zwei getrennte Schlüssel mit unterschiedlichen Regeln. Halten Sie sie auseinander:
| Kundenlizenz (Ihre Endnutzer) | Lizenz der selbst gehosteten Instanz (Ihr eigener Schlüssel) | |
|---|---|---|
| Wessen | Die Schlüssel Ihrer Kunden, von Ihnen ausgestellt | Das Betriebsrecht Ihrer Instanz, von Delta1 ausgestellt |
| Gilt für | Cloud und Self-Hosting gleichermaßen | Nur Self-Hosting |
| Kulanz beim Ablauf | Keine — Expired, sobald die Laufzeit verstrichen ist | Bezahlt: 15 Tage Nur-Lese-Kulanzfrist nach dem Ablauf; Testversion: keine |
| Beim Stopp | Anwendung fällt fail-closed auf Free zurück | Instanz sperrt — 402 auf den meisten Pfaden; Status-Endpunkte bleiben erreichbar |
| Steuerung über | /revoke, /renew, expiryUtc | KEYRIGHT_SELF_LICENSE tauschen + Neustart |
Alles oberhalb der Tabelle ist der Kunden-Lebenszyklus — identisch auf der Cloud und bei Self-Hosting. Der eigene Schlüssel der Instanz ist eine andere Geschichte: Ein selbst gehostetes Deployment lizenziert sich selbst, eine bezahlte Instanz erhält nach ihrem eigenen Ablauf eine 15-tägige Nur-Lese-Kulanzfrist, bevor sie sperrt, und eine Testinstanz stoppt in dem Moment, in dem sie abläuft. Dieser Lebenszyklus — Installation, Verlängerung, das Feld phase auf /admin/self-license und was „gesperrt“ bedeutet — wird vollständig unter Lizenzierung & Editionen behandelt. Verwechseln Sie nicht das Auslaufen des Abonnements eines Kunden (seine Anwendung geht auf Free) mit dem Auslaufen der Lizenz Ihrer Instanz (Ihr gesamter Issuing-Service wird nur-lesend und stoppt dann).
Cloud vs. Self-Hosting
$BASE/$TOKEN. Cloud:https://keyright.delta1labs.com+ ein Sitzungs-Token. Self-Hosting: die URL Ihrer Instanz +KEYRIGHT_ADMIN_TOKEN.- Widerruf, Verlängerung und Ablauf von Kunden-Lizenzen sind in beiden Betriebsarten identisch — gleiche Endpunkte, gleiches SDK-Verhalten.
- Die Lease-TTL können Sie auf einer selbst gehosteten Instanz selbst einstellen (
KEYRIGHT_LEASE_TTL_DAYS); auf der Cloud gilt der Standardwert des Service. - Der Instanz-Lebenszyklus existiert nur bei Self-Hosting (siehe oben).
Prüfen
- Stellen Sie sich selbst einen befristeten Schlüssel aus, der in ein, zwei Tagen abläuft; aktivieren Sie ihn. Das Badge zeigt den Ablauf und
DaysRemaining. - Widerrufen Sie ihn, verbinden Sie sich erneut und lassen Sie den Lease aktualisieren (oder rufen Sie
ActivateAsyncauf): Die Anwendung fällt mitStatus == Revokedauf Free zurück. - Stellen Sie einen frischen Schlüssel aus, aktivieren Sie ihn, verlängern Sie ihn dann auf ein späteres Datum; aktivieren Sie erneut —
ExpiryUtcverschiebt sich nach hinten, gleicher Schlüssel, kein Dialog. - Lassen Sie einen kurzfristigen Schlüssel ablaufen und validieren Sie erneut:
Status == Expired,IsPaid == false, die Verlängerungsaufforderung erscheint. - Offline-Timing: Widerrufen Sie einen Schlüssel, während diese Maschine offline ist — bestätigen Sie, dass sie weiterläuft, bis sie sich wieder verbindet (oder ihr Lease-Fenster endet), und dann auf Free zurückfällt. Verkürzen Sie
KEYRIGHT_LEASE_TTL_DAYS, wenn das zu langsam ist.
Siehe auch
- Aktivierung & Deaktivierung — Leases, Kulanzfristen, Plätze zwischen Maschinen verschieben.
- Sicherheit & das Lease-Modell — warum sich ein Widerruf nicht wegbearbeiten lässt und wie die Lease-TTL die Verbreitung steuert.
- Schlüssel automatisch aus einem Shop ausstellen — Rückerstattungen, die automatisch widerrufen.
- Lizenzierung & Editionen — der eigene Lizenz-Lebenszyklus der selbst gehosteten Instanz.
- Release-Abdeckung — ältere Versionen nach dem Auslaufen eines Abonnements lauffähig halten.