# 27. Browser Extension — Move to browser-ext/ and Update API Client meta: id: shieldai-unified-restructure-27 feature: shieldai-unified-restructure priority: P1 depends_on: [shieldai-unified-restructure-23] tags: [extension, browser, api, migration] objective: - Move the browser extension from `packages/extension/` to `browser-ext/`, update its build configuration, and rewrite the API client to communicate with the unified monolith's tRPC endpoints instead of the legacy Fastify API. deliverables: - `browser-ext/` directory with all extension code: - `src/background/index.ts` — Service worker (MV3) - `src/content/index.ts` — Content script for phishing detection - `src/popup/popup.html` + `popup.ts` — Extension popup UI - `src/options/options.html` + `options.ts` — Options page - `src/lib/api-client.ts` — Updated API client - `src/lib/phishing-detector.ts` — Phishing detection logic (preserved) - `src/lib/cache.ts` — Request caching (preserved) - `src/lib/settings.ts` — Extension settings (preserved) - `src/types/index.ts` — TypeScript types - `public/manifest.json` — Manifest V3 - `public/icons/` — Extension icons - `vite.config.ts` — Build config - `package.json` — Dependencies - Updated `browser-ext/src/lib/api-client.ts`: - Communicates with `https://api.shieldai.com/api/trpc` (or local dev URL) - Uses tRPC HTTP batch link for efficient requests - Authenticates with API key (`x-api-key` header) or JWT - Endpoints: - `spamshield.checkNumber` — check phone number reputation - `spamshield.classifySMS` — classify SMS text - `extension.getAuthStatus` — check if user is linked - `extension.linkDevice` — link extension to user account - Error handling with retry logic - Updated `browser-ext/package.json`: - Dependencies: `@trpc/client`, `superjson` (for serialization) - Build scripts for Chrome/Firefox - Updated manifest: - Permissions: `activeTab`, `storage`, `declarativeNetRequest`, `notifications` - Host permissions: `https://api.shieldai.com/*`, `https://*.shieldai.com/*` steps: 1. Create `browser-ext/` directory at project root. 2. Move all files from `packages/extension/` to `browser-ext/`: - `git mv packages/extension/src browser-ext/src` - `git mv packages/extension/public browser-ext/public` - `git mv packages/extension/vite.config.ts browser-ext/` - `git mv packages/extension/package.json browser-ext/` - Copy tests: `cp -r packages/extension/tests browser-ext/` 3. Update `browser-ext/package.json`: - Change name to `@shieldai/browser-ext` - Update dependencies: add `@trpc/client`, remove legacy API client deps - Update build scripts 4. Update `browser-ext/src/lib/api-client.ts`: - Remove old Fastify REST client code - Create tRPC proxy client: ```ts import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'; import type { AppRouter } from '../../../web/src/server/api/root'; export const api = createTRPCProxyClient({ links: [httpBatchLink({ url: API_URL, headers: { 'x-api-key': API_KEY } })], }); ``` - Note: Type import from web/ may need a shared types package or copy types. For now, use a generated type file. 5. Update background script: - On install: call `api.extension.linkDevice` with extension ID - On SMS received (if API available): call `api.spamshield.classifySMS` - On call received: call `api.spamshield.checkNumber` - Cache results using existing `cache.ts` 6. Update popup UI: - Show auth status (linked/unlinked) - Show recent spam detections - Quick actions: "Check number", "Report spam" - Use ShieldAI theme colors (import theme tokens or hardcode for now) 7. Update content script: - Preserve phishing detection logic - Report detected phishing to `api.extension.reportPhishing` 8. Update options page: - Settings for API key, notification preferences - Link/unlink account flow 9. Update build config: - `vite.config.ts` should output to `dist/` with correct manifest - Add scripts for `build:chrome` and `build:firefox` if needed 10. Test extension: - Load unpacked extension in Chrome - Verify popup renders - Test API calls against local dev server steps: - Unit: API client creates correct tRPC requests - Unit: Background script caches API responses - Integration: Extension popup successfully calls `spamshield.checkNumber` - E2E: Install extension, link device, verify API key auth works acceptance_criteria: - [ ] Extension code lives in `browser-ext/` and builds successfully - [ ] API client uses tRPC instead of legacy REST endpoints - [ ] Background script handles install, SMS, and call events - [ ] Popup UI shows auth status and recent detections - [ ] Content script preserves phishing detection and reports to tRPC - [ ] Options page allows API key configuration and account linking - [ ] Extension works with both local dev and production API URLs - [ ] All existing tests pass after migration validation: - `cd browser-ext && pnpm build` completes without errors - Load `browser-ext/dist/` as unpacked extension in Chrome - Open popup and verify UI renders - Test API call by entering a phone number → verify tRPC request in Network tab - Run `cd browser-ext && pnpm test` for extension tests notes: - Reference legacy: `packages/extension/src/` - The extension cannot directly import from `web/` due to build isolation. Options for tRPC types: 1. Generate a standalone type file from the web app's router and copy it to `browser-ext/src/types/trpc.ts` 2. Create a shared `@shieldai/types` package (but we're unifying, so avoid new packages) 3. Use `any` for the router type in extension (not recommended) Recommended: Option 1 — generate types as part of web build. - The extension's popup UI is currently plain HTML/TS. Consider using a lightweight framework (e.g., SolidJS for popup) for consistency with the web app, but this is optional. - For Manifest V3, service workers have limited lifetime. Ensure API calls complete before worker sleeps. - The `declarativeNetRequest` API can block requests at the network level without a persistent background script. Consider using it for known phishing domains.