Skip to content

cloud/C8: LicenseSettings panel#224

Closed
blueberrycongee wants to merge 2 commits intoloop/cloud-C4from
loop/cloud-C8
Closed

cloud/C8: LicenseSettings panel#224
blueberrycongee wants to merge 2 commits intoloop/cloud-C4from
loop/cloud-C8

Conversation

@blueberrycongee
Copy link
Copy Markdown
Owner

What

Standalone settings panel for entering, viewing, and removing the Lumina Cloud license. Reads useLicenseStore directly — explicitly no dependency on AISettingsModal.tsx per the C8 spec, since that file is currently locked behind WIP.

Stacked on #220 (C4) because the panel binds to useLicenseStore. Stack chain: #217 (C1) → #218 (C2) → #220 (C4) → this PR.

Behavior by status

  • idle: heading, helper copy, textarea, Verify button (disabled while empty or loading).
  • loading: button label flips to "Verifying…", status line with role="status" mirrors it.
  • invalid: role="alert" line — "Could not verify this license. Check the token and try again." The local verify path doesn't surface a granular reason; the online verify in §2.1 does, but that's C5/C9 territory.
  • valid: <dl> with email / SKU / expiry / feature badges + a Remove license button. Click opens an inline role="alertdialog" confirmation — Remove calls clearLicense; Cancel just dismisses.

Tailwind for styling. Dark-mode classes throughout.

expires_at: null → "Lifetime"; non-null gets formatted as YYYY-MM-DD.

Acceptance criteria

  • Paste license → calls useLicenseStore.setLicense → shows status (Verifying / Valid / Invalid + reason).
  • Valid: shows email, SKU, expiry, features as quiet badges.
  • "Remove license" button → confirmation → clearLicense.
  • No dependency on AISettingsModal.tsx — verified by grep; only imports are useLicenseStore, LicensePayload type, and React.
  • Tests cover the three status states (idle, valid, invalid). (plus loading via the disabled-button assertion in idle, and explicit Remove + Cancel flows.)
  • Component renders without throwing in jsdom.

How I tested

  • npm run typecheck: pass.
  • npm test -- --run src/components/settings/LicenseSettings.test.tsx: 7/7 pass.
  • Tests use vi.hoisted to mock verifyLicense / saveLicense / removeLicense / loadLicense from @/services/luminaCloud and exercise the store from the component side.

Touched files outside src/services/luminaCloud/

  • New: src/components/settings/LicenseSettings.tsx + test — both inside the PRD §3 allow-list.
  • cloud/TASKS.md — marked C8 [x] and appended Done-log entry.

Notes for Lead

  • Inline alertdialog instead of window.confirm. Keeps it test-friendly and matches the rest of the app's component-level confirmation patterns.
  • "Could not verify" copy is generic on purpose — the local Ed25519 path can't tell the user why (signature bad? malformed? wrong key?) without leaking implementation detail. The online verify in CONTRACT.md §2.1 returns a reason; if you want richer feedback later, hook §2.1 into the failure path.
  • Mounted by C10 (Account tab). Until C10 lands, this component is unreachable in the app shell — that's fine; tests prove it works in isolation.

blueberrycongee and others added 2 commits April 28, 2026 13:07
Standalone settings panel for entering / viewing / removing the
Lumina Cloud license. Reads useLicenseStore directly; no dependency
on AISettingsModal. Tailwind styled.

States:
- idle: heading, helper text, textarea, Verify button (disabled
  while empty or while status is 'loading').
- loading: Verify button label flips to "Verifying…", status line
  with role="status" mirrors it.
- invalid: role="alert" line — "Could not verify this license."
- valid: dl with email / SKU / expiry / feature badges, plus a
  "Remove license" button that opens an inline alertdialog
  confirmation before calling clearLicense.

Tests cover the three status states + idle entry-form rendering
+ the confirmation flow (Remove and Cancel paths) + ISO date
formatting for non-lifetime expiries. 7 tests, all pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@blueberrycongee
Copy link
Copy Markdown
Owner Author

Closing — re-issued cleanly by integrator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant