license key install flimsy feeling as an admin operator #532

Closed
opened 2026-09-14 00:33:19 +00:00 by Cordy · 2 comments
Owner

— license key install needs to be a nicer flow, have some interaction, similar to the save bar popping up for a save, a bar can pop up as “Key installed.” this has been triggered when I replaced a key manually, and there was no real “action confirmed” interaction, so it felt “flimsy/incomplete” to me. Also, the Rows of the “license” table on that page seemed not to update all rows that would update on a Key replacement that would change information carried by that key. Just a double check on that last one.

— license key install needs to be a nicer flow, have some interaction, similar to the save bar popping up for a save, a bar can pop up as “Key installed.” this has been triggered when I replaced a key manually, and there was no real “action confirmed” interaction, so it felt “flimsy/incomplete” to me. Also, the Rows of the “license” table on that page seemed not to update all rows that would update on a Key replacement that would change information carried by that key. Just a double check on that last one.
Author
Owner

Traced both halves in the code.

Why it feels flimsy: the install handler ($("lic-install").onsubmit) does PUT /api/v1/license → clears the input → say(t("licInstalled"))refreshLic(). But say() only sets $("status").textContent — the little status line, nowhere near the dialog you're looking at, no colour, no motion. Success and "nothing happened" look nearly identical. The fix you're describing exists as a pattern already: the OCM allow-list save bar (#ocm-savebar, sticky bar with shadow). Plan: a confirmation band inside the licence dialog — "Key installed." with the licensed badge, appearing where the input was, auto-fading — plus the same treatment for key replacement ("Key replaced — plan X, expires Y"). Mockup-light; i18n ×4.

The stale-rows double check — you were right, at least partly:

  1. Found a concrete gap: remove (licrem-go) calls refreshLic(); admLicMeter(); but install calls only refreshLic() — the admin licence/seat meter elsewhere on the page is NOT refreshed after installing or replacing a key. If the new key changes seat count, that meter keeps showing the old one until a reload. That alone can explain "not all rows updated".
  2. The facts table itself (lic-facts) is fully rebuilt from a fresh GET /api/v1/license on every refreshLic(), so if a row there showed stale data, the server's PUT response must still be carrying old derived state — i.e. set validates and stores the key but some fields (label/org, expiry, seats) only refresh on the next check-in. Do you remember which rows were stale — the seat meter (case 1) or rows inside the facts table like plan/expiry (case 2)? If it was the facts table I'll chase the backend set path; if it was the meter, case 1 covers it.

Scope for the fix run: confirmation band (install + replace), admLicMeter() after install, and — depending on your answer — making set recompute all derived fields synchronously from the new key.

Traced both halves in the code. **Why it feels flimsy:** the install handler (`$("lic-install").onsubmit`) does PUT `/api/v1/license` → clears the input → `say(t("licInstalled"))` → `refreshLic()`. But `say()` only sets `$("status").textContent` — the little status line, nowhere near the dialog you're looking at, no colour, no motion. Success and "nothing happened" look nearly identical. The fix you're describing exists as a pattern already: the OCM allow-list save bar (`#ocm-savebar`, sticky bar with shadow). Plan: a confirmation band inside the licence dialog — "Key installed." with the licensed badge, appearing where the input was, auto-fading — plus the same treatment for key *replacement* ("Key replaced — plan X, expires Y"). Mockup-light; i18n ×4. **The stale-rows double check — you were right, at least partly:** 1. **Found a concrete gap:** remove (`licrem-go`) calls `refreshLic(); admLicMeter();` but install calls only `refreshLic()` — the admin licence/seat meter elsewhere on the page is NOT refreshed after installing or replacing a key. If the new key changes seat count, that meter keeps showing the old one until a reload. That alone can explain "not all rows updated". 2. The facts table itself (`lic-facts`) is fully rebuilt from a fresh `GET /api/v1/license` on every `refreshLic()`, so if a row there showed stale data, the *server's* PUT response must still be carrying old derived state — i.e. `set` validates and stores the key but some fields (label/org, expiry, seats) only refresh on the next check-in. Do you remember which rows were stale — the seat meter (case 1) or rows inside the facts table like plan/expiry (case 2)? If it was the facts table I'll chase the backend `set` path; if it was the meter, case 1 covers it. Scope for the fix run: confirmation band (install + replace), `admLicMeter()` after install, and — depending on your answer — making `set` recompute all derived fields synchronously from the new key.
Author
Owner

v0.6.192 shipped (PR #542), live on both dogfoods — closing.

  • Installing or replacing a key now shows a green confirmation band directly under the key field — "Key installed." / "Key replaced." — auto-hiding after 6 s, in the admin licence card and the dialog alike. i18n ×4. A failed install uses the error banner instead of the quiet status line.
  • The seat meter refreshes immediately after install (it was only refreshed on remove — one of the two stale-row causes).
  • The other cause, found and fixed with a witnessed-red test: replacing a key kept the OLD key's check-in plan label, and the plan row shows label before org — so it named the old plan until the next monthly check-in. SetKey now drops the label; the row shows the new key's org until the next check-in re-labels it.
  • Bonus symmetry: installing/replacing a key is now an audited admin action (license-install), matching key removal — and registered in the audit verb vocabulary, courtesy of the #433 guard test catching the omission.

Verify on your next key replacement: band appears, plan/seat rows all carry the new key's values immediately. If any row still lags after this, reopen with which row it was.

**v0.6.192 shipped (PR #542), live on both dogfoods — closing.** - Installing or replacing a key now shows a green confirmation band directly under the key field — "Key installed." / "Key replaced." — auto-hiding after 6 s, in the admin licence card and the dialog alike. i18n ×4. A failed install uses the error banner instead of the quiet status line. - The seat meter refreshes immediately after install (it was only refreshed on remove — one of the two stale-row causes). - The other cause, found and fixed with a witnessed-red test: replacing a key kept the OLD key's check-in plan label, and the plan row shows label before org — so it named the old plan until the next monthly check-in. `SetKey` now drops the label; the row shows the new key's org until the next check-in re-labels it. - Bonus symmetry: installing/replacing a key is now an audited admin action (`license-install`), matching key removal — and registered in the audit verb vocabulary, courtesy of the #433 guard test catching the omission. Verify on your next key replacement: band appears, plan/seat rows all carry the new key's values immediately. If any row still lags after this, reopen with which row it was.
Cordy closed this issue 2026-09-14 03:22:38 +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#532
No description provided.