Migration

Vendor Migration Guide

Du hast bereits ein eigenes Lizenz-Schema oder JWT-Signing? Diese Anleitung zeigt dir, wie du in unter einer Stunde auf xcess.ch migrierst.

Für wen ist dieser Guide?

Software-Vendoren, die heute selbstgebaute Lizenz-Server oder JWT-Tooling betreiben und auf eine gehostete LaaS-Plattform umstellen wollen.

  • Du signierst aktuell JWTs mit einem privaten Schlüssel auf deinem Server.
  • Du hast Customer-spezifische Lizenz-Strings in einer Datenbank oder Datei.
  • Du verwaltest Schlüssel-Rotation manuell oder gar nicht.
  • Du brauchst Audit-Trail, Heartbeat und Webhook-Events, ohne sie selbst zu bauen.

Migrations-Checkliste

  1. 1. Vendor-Account auf xcess.ch anlegen
    Self-Service-Signup unter /vendor/signup. Subscription-Tier wählen, API-Token kopieren (xv_live_*).
  2. 2. Erstes Signing-Key-Pair erstellen
    Dashboard → Signing Keys → New Key. Algorithmus wählen (RS256, ES256 oder EdDSA). xcess hostet die privaten Schlüssel sicher.
  3. 3. SDK installieren
    JS/TS, Python, Java, .NET, Go oder C++ — siehe /docs für Install-Befehl.
  4. 4. Code-Änderungen: Issue + Verify
    Eigenes JWT-Sign durch xcess.issueLicense() ersetzen, eigene Verify-Funktion durch xcess.verifyLicense() ersetzen.
  5. 5. Bestehende Lizenzen migrieren
    Customer und neue Lizenzen via xcess ausstellen, alte JWTs parallel weiterverifizieren bis zur Expiry.
  6. 6. Cutover & Monitoring
    Webhook für LICENSE_CREATED/UPDATED registrieren, eigenes Lizenz-System abschalten sobald letzte Alt-Lizenz abgelaufen ist.

Vendor-Account anlegen

Dauert weniger als 2 Minuten. Du erhältst sofort ein API-Token, mit dem du Lizenzen ausstellen kannst.

# Self-Service Vendor signup
# https://xcess.ch/vendor/signup
# After signup: copy your API token (xv_live_*)
# starting from the response (it is shown ONCE).
export XCESS_TOKEN="xv_live_*****"
export XCESS_VENDOR_CODE="acme"

Vorher / Nachher

Beispielhafte Issue-Funktion vor und nach der Migration.

Vorher: Eigenes JWT-Signing

// Self-managed JWT signing (Node.js)
import jwt from 'jsonwebtoken';
import fs from 'fs';

const privateKey = fs.readFileSync('./private.pem');

function issueLicense({ customerId, productId, validUntil }) {
  return jwt.sign(
    {
      sub: customerId,
      product: productId,
      exp: Math.floor(new Date(validUntil).getTime() / 1000),
    },
    privateKey,
    { algorithm: 'RS256', keyid: 'main' },
  );
}

Nachher: xcess.ch SDK

// xcess.ch SDK (Node.js)
import { Xcess } from '@xcess/sdk';

const xcess = new Xcess({
  apiBaseUrl: 'https://xcess.ch',
  token: process.env.XCESS_TOKEN!,
  vendorCode: process.env.XCESS_VENDOR_CODE!,
});

async function issueLicense({ customerCode, customerName, customerEmail, productCode, productName, validUntil }) {
  const { license, licenseJwt } = await xcess.issueLicense({
    productCode,
    productName,
    customerCode,
    customerName,
    customerEmail,
    validUntil,
  });
  return { id: license.id, licenseNumber: license.licenseNumber, jwt: licenseJwt };
}

Customer-seitige Verifikation

In allen unterstützten Sprachen identisch: SDK lädt JWKS, prüft Signatur und exp/nbf Claims.

Node.js / TypeScript

import { Xcess } from '@xcess/sdk';

const xcess = new Xcess({ apiBaseUrl: 'https://xcess.ch', vendorCode: 'acme' });

const result = await xcess.verifyLicense({ jwt: licenseJwt });
if (!result.valid) throw new Error(result.reason);
console.log(result.claims.sub);

Python

from xcess import Xcess

client = Xcess(api_base_url='https://xcess.ch', vendor_code='acme')
result = client.verify_license(jwt=license_jwt)
if not result.valid:
    raise RuntimeError(result.reason)
print(result.claims['sub'])

Java

import ch.xcess.sdk.Xcess;
import ch.xcess.sdk.VerifyResult;

Xcess xcess = Xcess.builder()
    .apiBaseUrl("https://xcess.ch")
    .vendorCode("acme")
    .build();
VerifyResult result = xcess.verifyLicense(licenseJwt);
if (!result.isValid()) throw new IllegalStateException(result.getReason());

.NET / C#

using Xcess.Sdk;

var client = new XcessClient(new XcessConfig {
    ApiBaseUrl = "https://xcess.ch",
    VendorCode = "acme",
});
var result = await client.VerifyLicenseAsync(licenseJwt);
if (!result.Valid) throw new InvalidOperationException(result.Reason);

Cutover-Strategie

Empfohlene Vorgehensweise für eine reibungslose Umstellung ohne Customer-Impact.

  • Phase 1 (Tag 0-30): Neue Lizenzen via xcess, alte JWTs weiterhin verifizieren.
  • Phase 2 (Tag 30-60): Renewals von Bestandskunden über xcess abwickeln.
  • Phase 3 (Tag 60-90): Schrittweise Migration aller aktiven Lizenzen via Bulk-API.
  • Phase 4 (Tag 90+): Eigenes Lizenz-System abschalten, nur xcess weiter verwenden.

Häufige Fallstricke

  • Token nur einmal beim Signup angezeigt — sicher speichern (Vault, AWS Secrets Manager).
  • Customer-Codes bleiben deine eigene Domäne — xcess verlangt sie als Input.
  • JWKS-Caching: 1 Stunde Cache + stale-while-revalidate. Bei Rotation kein sofortiger Effekt — daher 90-Tage-Karenzzeit.
  • Algorithmus-Wahl: RS256 (Default), ES256 (kompakter), EdDSA (schnellster). Wähle bewusst, sehr selten zu wechseln.