On-demand license refresh: forced check-in endpoint + panel button #88

Merged
Cordy merged 3 commits from feat/lic-refresh into main 2026-07-31 01:21:06 +00:00
Owner

Closes #86
Closes #87

#86. Manager.ForceCheckin runs the existing check-in immediately, outside the monthly schedule: same request, same state updates (a success also resets the grace window), same same-id guard on the returned key. Exposed as admin-gated POST /api/v1/license/refresh — 409 when no license/check-in URL is configured, 502 on connectivity or revocation, with the current status in every response. The License panel gains a Refresh license button that calls it and reloads the status. Pull-only by design, per the discussion with Nikola: the instance always initiates; a license server that reaches into self-hosted deployments would contradict everything Cairn promises.

Tests: forced check-in installs a re-signed same-id key (60→65 visible immediately); connectivity failure returns ErrUnreachable and provably leaves the installed license and state untouched; no-license returns ErrNoLicense.

#87 closed as no-defect after code inspection: SetKey (manual PUT /api/v1/license) has no same-id or same-key short-circuit — it always verifies and installs. The observed "re-ingest didn't take" was the webhook async gap: the key was copied from the account page before Paddle's transaction completed, so the pre-change key was installed — correctly. The Refresh button removes the reason to hand-copy keys at all, and a companion cairn-site change makes the account page reload the key automatically after a seat change.

Closes #86 Closes #87 **#86.** `Manager.ForceCheckin` runs the existing check-in immediately, outside the monthly schedule: same request, same state updates (a success also resets the grace window), same same-id guard on the returned key. Exposed as admin-gated `POST /api/v1/license/refresh` — 409 when no license/check-in URL is configured, 502 on connectivity or revocation, with the current status in every response. The License panel gains a **Refresh license** button that calls it and reloads the status. Pull-only by design, per the discussion with Nikola: the instance always initiates; a license server that reaches into self-hosted deployments would contradict everything Cairn promises. Tests: forced check-in installs a re-signed same-id key (60→65 visible immediately); connectivity failure returns `ErrUnreachable` and provably leaves the installed license and state untouched; no-license returns `ErrNoLicense`. **#87 closed as no-defect** after code inspection: `SetKey` (manual `PUT /api/v1/license`) has no same-id or same-key short-circuit — it always verifies and installs. The observed "re-ingest didn't take" was the webhook async gap: the key was copied from the account page before Paddle's transaction completed, so the pre-change key was installed — correctly. The Refresh button removes the reason to hand-copy keys at all, and a companion cairn-site change makes the account page reload the key automatically after a seat change.
Cordy merged commit 2085784892 into main 2026-07-31 01:21:06 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
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#88
No description provided.