5.2 KiB
5.2 KiB
LexAI — Improvement Recommendations
Prioritized findings from a full read of the codebase (2026-07-13). Grouped by theme; each item notes rough effort (S/M/L) and why it matters.
🔒 Security & privacy
- Narrow host permissions (M). The manifest requests
<all_urls>host permission and injects the content script into every frame of every site — including banking, email, and internal apps. ConsideractiveTab+ on-demand injection, or a user-configurable allowlist. This is also the #1 thing that slows Chrome Web Store review. - The encryption is obfuscation, not protection (M).
encKeysits inchrome.storage.localright next toapiKeyEnc; anyone who can read storage can decrypt. Be honest in the UI ("stored locally, obscured") or derive the key from something not co-located (e.g.chrome.storage.sessionfor the key, WebCrypto, or a passphrase). At minimum, don't over-promise "encrypted" security to users. - Strip debug logging from production (S).
content.tslogs selection text and element values ([LexAI captureForButton],[LexAI Replace], etc.) to the page console — visible to the host page. Gate behind a__DEV__/import.meta.env.DEVflag.
🧹 Code quality & maintainability
- Collapse the duplicated provider layer (M). Each provider exists twice —
callOpenAI/callOpenAIWithPrompt, etc. — 8 near-identical functions. Refactor to onecallProvider(config, messages | systemPrompt, text)with a small per-provider adapter describing{ url, headers(config), body(model, system, text), extract(data) }. Cutsbackground.tsroughly in half and removes the "update both copies" trap noted in CLAUDE.md. - Extract shared UI/styling (M). The Catppuccin palette and button styles are re-declared
inline across content.ts, Options.tsx, Popup.tsx. Move colors/spacing into a shared
src/ui/theme.ts(and reusable style factories) so a palette change is one edit. - Remove dead dependencies (S).
zustandis installed but no store exists;tailwindcssautoprefixerare present but inactive. Either wire them up or drop them to shrink the install and remove confusion.
- Centralize provider/model config (S). The provider list, default models, and endpoints
live in both
Options.tsx(UI) andbackground.ts(calls). Put them in one shared module so the picker and the caller can't drift.
✅ Testing (biggest gap)
- Unit tests don't test real code (M).
tests/unit/background.test.tsonly exercises thechrome.storagemock — it never importsgetSystemPrompt,decryptApiKey, or the provider router. Extract those pure functions and test them directly (prompt normalization,fix→grammar, encrypt→decrypt round-trip, provider routing, error extraction). - Fix or quarantine the e2e tests (S).
tests/e2e/extension.test.tshard-codeschrome-extension://[EXTENSION_ID]/...— it cannot pass. Resolve the extension ID at runtime (read it from the service-worker target) or mark the suite.skipuntil fixed so CI green means something. - Add a content-script DOM test (L). The selection→snapshot→replace logic is the app's riskiest code and has zero coverage. A jsdom or Playwright test over textarea and contenteditable replace paths would catch regressions the current tests can't.
✨ Product / UX
- Make
max_tokensadaptive (S). It's hard-coded to1024everywhere; "Expand" on a long paragraph will truncate mid-sentence. Scale with input length or expose it in settings. - Add response streaming (L). Non-streaming means the user stares at "thinking…" for the full latency. Streaming tokens into the modal is the single biggest perceived-speed win.
- Accessibility (M). Toolbar/modal buttons lack
aria-labels, focus management, and keyboard navigation; the modal doesn't trap focus. Add roles/labels and Esc/Tab handling (Esc is partially handled already). - React error boundaries + graceful storage failures (S). Options/Popup call
createRoot(...).render()with no error boundary; a throw yields a blank page.
🚀 Build / release
- Pin the toolchain (S). Add an
.nvmrc/enginesfield for Node 22 to match CI, and apackage.jsonpackageManagerfield. Localnpm run *currently fails with nonode_modulesand no version guard. - Version bump is a two-file manual step (S).
versionmust be edited in bothpackage.jsonandwxt.config.ts. Add a script (or read one from the other) so a release can't ship mismatched versions — this has already caused churn in the git history. - CI clones instead of checking out (S). Both Gitea workflows
git clonethe repo into/tmprather than using the checked-out workspace, and disable TLS verification (http.sslVerify false). Worth revisiting for speed and security once the runner setup allows a normal checkout.
Suggested order
Quick wins first: 3, 6, 9, 11, 15, 16 (all S, mostly independent). Then the structural refactors 4, 5, 8, which make everything after them easier. Tackle 1/2 (permissions + key story) before any serious Chrome Web Store push. Save 10, 12, 13 for a focused Phase 2.