License server (separate repo, Go + SQLite on VPS) #25

Closed
opened 2026-07-25 16:26:09 +00:00 by Cordy · 2 comments
Owner

ARCHITECTURE §8.1. Issues signed license files and exposes POST /v1/validate for the optional online path (revocation, renewal reminders, activation counts). Separate repo, Go + SQLite behind Caddy on the existing VPS.

Optional online complement to the offline file verification; must never be load-bearing for customer availability.

ARCHITECTURE §8.1. Issues signed license files and exposes `POST /v1/validate` for the optional online path (revocation, renewal reminders, activation counts). Separate repo, Go + SQLite behind Caddy on the existing VPS. Optional online complement to the offline file verification; must never be load-bearing for customer availability.
Author
Owner

Scope expanded (Nikola, 2026-07-26). Repo created: http://192.168.10.245/Cordy/cairn-license-server

Go + SQLite on the VPS. Three surfaces:

  1. Customer accounts — registration/login for the landing page (cairn-site is the frontend; this server owns accounts + sessions). A purchased license is linked to the account, so customers can log in and see/re-download their license key.
  2. Purchase → issuance — payment provider webhook (provider TBD — Stripe/Paddle decision needed, Paddle handles EU VAT as merchant-of-record which likely matters for CH/EU) → generate license (org, seats, expiry), sign with the private Ed25519 key (lives ONLY on this server / in Nikola's custody — never in the Cairn repo), store, email/show to customer.
  3. Check-in APIPOST /v1/checkin with license ID + instance fingerprint: returns valid/revoked/expired. Called by cairnd monthly, only for >50-user deployments (see #24 for the client-side cadence/grace rules). Keep it dumb and boring: no telemetry beyond what enforcement needs (license ID, seat count, version).

Client-side verification stays fully offline (#24); this server exists for issuance, account linkage, and the monthly revocation check.

**Scope expanded (Nikola, 2026-07-26). Repo created: http://192.168.10.245/Cordy/cairn-license-server** Go + SQLite on the VPS. Three surfaces: 1. **Customer accounts** — registration/login for the landing page (cairn-site is the frontend; this server owns accounts + sessions). A purchased license is linked to the account, so customers can log in and see/re-download their license key. 2. **Purchase → issuance** — payment provider webhook (provider TBD — Stripe/Paddle decision needed, Paddle handles EU VAT as merchant-of-record which likely matters for CH/EU) → generate license (org, seats, expiry), sign with the **private** Ed25519 key (lives ONLY on this server / in Nikola's custody — never in the Cairn repo), store, email/show to customer. 3. **Check-in API** — `POST /v1/checkin` with license ID + instance fingerprint: returns valid/revoked/expired. Called by cairnd monthly, only for >50-user deployments (see #24 for the client-side cadence/grace rules). Keep it dumb and boring: no telemetry beyond what enforcement needs (license ID, seat count, version). Client-side verification stays fully offline (#24); this server exists for issuance, account linkage, and the monthly revocation check.
Author
Owner

The companion repo is feature-complete and live at license.swisscairn.ch, with zero open issues as of 2026-07-30:

  • Ed25519 issuance (CAIRN1 keys), monthly check-in with grace, revocation
  • Paddle webhook (signature-verified, idempotent), monthly + yearly cycles with cycle-derived validity (#2 there)
  • Renewal refresh — same license id re-signed and extended on every renewal payment; check-in returns the current key and Cairn ≥v0.3.13 installs it automatically (#3 there / #58 here)
  • Customer accounts (PBKDF2, bearer sessions) with organizations: roles, email invites, last-admin rail (#6 there)
  • Self-service: labels, password change, forgot-password via SMTP (no-reply@swisscairn.ch, live-verified), billing/receipts via the Paddle API (#4/#5 there)

Only launch-time work remains (Paddle sandbox→live swap), tracked in #26. Closing this umbrella.

The companion repo is feature-complete and live at license.swisscairn.ch, with **zero open issues** as of 2026-07-30: - Ed25519 issuance (`CAIRN1` keys), monthly check-in with grace, revocation - Paddle webhook (signature-verified, idempotent), monthly + yearly cycles with cycle-derived validity (#2 there) - **Renewal refresh** — same license id re-signed and extended on every renewal payment; check-in returns the current key and Cairn ≥v0.3.13 installs it automatically (#3 there / #58 here) - Customer accounts (PBKDF2, bearer sessions) with **organizations**: roles, email invites, last-admin rail (#6 there) - Self-service: labels, password change, forgot-password via SMTP (`no-reply@swisscairn.ch`, live-verified), billing/receipts via the Paddle API (#4/#5 there) Only launch-time work remains (Paddle sandbox→live swap), tracked in #26. Closing this umbrella.
Cordy closed this issue 2026-07-30 01:03:40 +00:00
Sign in to join this conversation.
No labels
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#25
No description provided.