A full-stack reference implementation of a "terms & conditions" guardian:
- Browser Extension (Manifest v3) scans web pages for fine print, checkbox clauses, and legalese, then alerts the user whenever risky language is found.
- Backend Service (Node.js + Express + Mistral LLM) receives snippets from the extension, asks Mistral for a structured risk assessment, and returns a risk level plus highlighted clauses.
extension/ # Chrome/Firefox-compatible extension bundle
manifest.json
background.js # Service worker orchestrating API calls + notifications
content-script.js # DOM scanner + heuristics
popup.* # Enhanced UI with filters/settings
server/ # Node/Express backend that talks to Mistral
src/index.ts
package.json
tsconfig.json
Dockerfile
docker-compose.yml # Docker stack for backend
- Node.js 20+
- npm 10+
- Mistral API key (create one at https://console.mistral.ai) – optional for local smoke tests, required for real scoring.
cd server
cp .env.example .env # create one; see below
npm install
npm run dev # starts on http://localhost:8787server/.env.example (create this file) should contain:
MISTRAL_API_KEY=sk-...
MISTRAL_MODEL=mistral-small-latest
PORT=8787
When the key is absent, the API returns a fallback medium-risk response so the extension keeps working.
- Build or run the backend so the extension can hit
http://localhost:8787/analyze. - Go to
chrome://extensions, toggle Developer mode, click Load unpacked, and select theextension/folder. - Pin the extension. Open the popup to refresh results.
- Visit a checkout page containing a terms & conditions checkbox or fine print. The content script detects it, sends it to the backend, and the background script triggers:
- A desktop notification whose color reflects the risk level.
- An audible alarm plus voice agent summary (SpeechSynthesis) announcing the risk + recommendation.
- A red highlight pulse around the detected snippet in-page.
- A stored entry visible inside the popup UI.
The extension reads the backend origin from chrome.storage.local.apiBaseUrl; use the popup console to tweak it if the backend lives elsewhere.
- Content script runs on every page, scanning
p,div,small,label, etc., with keyword + style heuristics (font size, opacity, italics) and special handling for checkbox labels. - Candidate snippets (≤1200 chars) are hashed to avoid duplicates, then dispatched to the background service worker.
- The service worker debounces repeats, calls
/analyze, stores the response inchrome.storage, and fires a notification + alarm message. It also instructs the content script to:- speak the assessment via the voice agent,
- visually highlight the matched DOM node for a few seconds so users can see the exact clause.
- The popup UI pulls the last 10 assessments and renders badges, clause bullet points, and timestamps.
- Validates requests with
zod. - Calls
https://api.mistral.ai/v1/chat/completionswith a JSON response format so the model emitsriskLevel,summary,clauses, andrecommendation. - Uses deterministic temperature 0 prompts to reduce hallucinations.
- Returns fallback JSON with
riskLevel: mediumwhen the Mistral call fails (network issues, missing key, etc.).
- Unit hooks: wrap
callMistralso you can inject a mock for unit tests. - Security: add an HMAC header or API key shared between extension and backend if you deploy publicly.
- False positives: consider hashing snippets per URL and storing them server-side to reduce duplicate billing.
- Inline UX: extend the content script to overlay risk info adjacent to the detected DOM node.
| Symptom | Fix |
|---|---|
| Popup shows "No detections yet" | Ensure the backend is running and the page actually contains T&C keywords; open DevTools console for content-script.js. |
| Notifications missing | Check Chrome notification permissions; service worker logs appear in chrome://extensions → background page. |
| Backend 502 / fallback responses | Verify MISTRAL_API_KEY is set and not rate-limited. |
| Type errors in backend | Run npm install to pull Express/CORS/Zod typings. |
Happy auditing!