82 lines
5.2 KiB
Markdown
82 lines
5.2 KiB
Markdown
# 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
|
|
|
|
1. **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. Consider `activeTab` + on-demand injection, or a user-configurable
|
|
allowlist. This is also the #1 thing that slows Chrome Web Store review.
|
|
2. **The encryption is obfuscation, not protection (M).** `encKey` sits in
|
|
`chrome.storage.local` right next to `apiKeyEnc`; 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.session` for the key, WebCrypto, or a passphrase). At
|
|
minimum, don't over-promise "encrypted" security to users.
|
|
3. **Strip debug logging from production (S).** `content.ts` logs 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.DEV` flag.
|
|
|
|
## 🧹 Code quality & maintainability
|
|
|
|
4. **Collapse the duplicated provider layer (M).** Each provider exists twice —
|
|
`callOpenAI`/`callOpenAIWithPrompt`, etc. — 8 near-identical functions. Refactor to one
|
|
`callProvider(config, messages | systemPrompt, text)` with a small per-provider adapter
|
|
describing `{ url, headers(config), body(model, system, text), extract(data) }`. Cuts
|
|
`background.ts` roughly in half and removes the "update both copies" trap noted in CLAUDE.md.
|
|
5. **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.
|
|
6. **Remove dead dependencies (S).** `zustand` is installed but no store exists; `tailwindcss`
|
|
+ `autoprefixer` are present but inactive. Either wire them up or drop them to shrink the
|
|
install and remove confusion.
|
|
7. **Centralize provider/model config (S).** The provider list, default models, and endpoints
|
|
live in both `Options.tsx` (UI) and `background.ts` (calls). Put them in one shared module
|
|
so the picker and the caller can't drift.
|
|
|
|
## ✅ Testing (biggest gap)
|
|
|
|
8. **Unit tests don't test real code (M).** `tests/unit/background.test.ts` only exercises the
|
|
`chrome.storage` mock — it never imports `getSystemPrompt`, `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).
|
|
9. **Fix or quarantine the e2e tests (S).** `tests/e2e/extension.test.ts` hard-codes
|
|
`chrome-extension://[EXTENSION_ID]/...` — it cannot pass. Resolve the extension ID at
|
|
runtime (read it from the service-worker target) or mark the suite `.skip` until fixed so
|
|
CI green means something.
|
|
10. **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
|
|
|
|
11. **Make `max_tokens` adaptive (S).** It's hard-coded to `1024` everywhere; "Expand" on a
|
|
long paragraph will truncate mid-sentence. Scale with input length or expose it in settings.
|
|
12. **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.
|
|
13. **Accessibility (M).** Toolbar/modal buttons lack `aria-label`s, focus management, and
|
|
keyboard navigation; the modal doesn't trap focus. Add roles/labels and Esc/Tab handling
|
|
(Esc is partially handled already).
|
|
14. **React error boundaries + graceful storage failures (S).** Options/Popup call
|
|
`createRoot(...).render()` with no error boundary; a throw yields a blank page.
|
|
|
|
## 🚀 Build / release
|
|
|
|
15. **Pin the toolchain (S).** Add an `.nvmrc`/`engines` field for Node 22 to match CI, and a
|
|
`package.json` `packageManager` field. Local `npm run *` currently fails with no
|
|
`node_modules` and no version guard.
|
|
16. **Version bump is a two-file manual step (S).** `version` must be edited in both
|
|
`package.json` and `wxt.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.
|
|
17. **CI clones instead of checking out (S).** Both Gitea workflows `git clone` the repo into
|
|
`/tmp` rather 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.
|