From 891d561aaa6bcc700d9e4b73d7eea8a4daebe67c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Wed, 9 Sep 2026 12:20:31 +0200 Subject: [PATCH] Fix AMO submission requirements: data collection permissions, innerHTML lint, source README - Declare data_collection_permissions in browser_specific_settings.gecko (Firefox 140+/AMO validation requirement) to reflect wallet address, auth signature, and trading-identity data sent to the backend. - Replace innerHTML assignments in blur-disable.ts and toast.ts with DOM construction (createElementNS/createElement) to clear the AMO linter's unsafe-innerHTML warning on content.js. - Add build instructions to README.md for AMO's source code submission requirement, triggered by WXT/Vite's bundling and minification. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01HoMzqFw3d93hG6c9xB4thU --- README.md | 44 ++++++++++++++++++- .../interventions/blur-disable.ts | 31 +++++++++++-- src/notifications/toast.ts | 31 +++++++++---- wxt.config.ts | 11 +++++ 4 files changed, 103 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ab578dc..1a6fe1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,42 @@ -# copilot -Your blockchain powered Agent to help with your trading emotions +# Osias — copilot + +Your blockchain-powered trading companion. This is the open-source browser extension +frontend (Apache License 2.0). See [`CLAUDE.md`](CLAUDE.md) for full architecture and +protocol documentation. + +## Build instructions + +Built with [WXT](https://wxt.dev) (Vite-based). To reproduce the exact `.output/firefox-mv3` +bundle submitted to addons.mozilla.org from source: + +**Environment** +- Node.js 22.x (built and tested on 22.11.0) +- npm 11.x (built and tested on 11.14.1) + +**Steps** +```sh +npm install # also runs `wxt prepare` via postinstall +npm run build:firefox +``` + +Output is written to `.output/firefox-mv3/`. To produce the uploaded `.zip` directly: + +```sh +npm run zip:firefox +``` + +Output zip is written to `.output/`. + +No build secrets, environment variables, or private dependencies are required — everything +needed to build is in this repository and on the public npm registry, pinned via +`package-lock.json`. + +## Development + +- `npm run dev:firefox` — dev build + watch targeting Firefox/Zen, auto-opens a temporary + profile with the extension loaded. +- `npm run compile` — `tsc --noEmit` type-check only. + +## License + +Apache License 2.0 — see [`LICENSE`](LICENSE). diff --git a/src/content-scripts/interventions/blur-disable.ts b/src/content-scripts/interventions/blur-disable.ts index aa80a90..d174daf 100644 --- a/src/content-scripts/interventions/blur-disable.ts +++ b/src/content-scripts/interventions/blur-disable.ts @@ -17,8 +17,33 @@ const locked = new WeakMap(); // reason toast is surfaced on `click` once the gesture completes. const INTERCEPTED_EVENT_TYPES = ['pointerdown', 'mousedown', 'mouseup', 'click'] as const; -const LOCK_ICON_SVG = - ''; +const SVG_NS = 'http://www.w3.org/2000/svg'; + +function createLockIcon(): SVGSVGElement { + const svg = document.createElementNS(SVG_NS, 'svg'); + svg.setAttribute('viewBox', '0 0 24 24'); + svg.setAttribute('width', '16'); + svg.setAttribute('height', '16'); + svg.setAttribute('fill', 'none'); + svg.setAttribute('stroke', 'currentColor'); + svg.setAttribute('stroke-width', '2'); + svg.setAttribute('stroke-linecap', 'round'); + svg.setAttribute('stroke-linejoin', 'round'); + + const rect = document.createElementNS(SVG_NS, 'rect'); + rect.setAttribute('x', '4'); + rect.setAttribute('y', '10'); + rect.setAttribute('width', '16'); + rect.setAttribute('height', '10'); + rect.setAttribute('rx', '2'); + svg.appendChild(rect); + + const path = document.createElementNS(SVG_NS, 'path'); + path.setAttribute('d', 'M8 10V7a4 4 0 0 1 8 0v3'); + svg.appendChild(path); + + return svg; +} // `backdrop-filter` (not `filter`) is deliberate: `filter` on the container // would recomposite the container's entire subtree — including the lock @@ -80,7 +105,7 @@ export const blurDisable: Intervention = { const overlay = document.createElement('div'); overlay.dataset.osiasOverlay = 'true'; overlay.style.cssText = OVERLAY_STYLE; - overlay.innerHTML = LOCK_ICON_SVG; + overlay.appendChild(createLockIcon()); const onOverlayEvent = (event: Event) => { event.preventDefault(); diff --git a/src/notifications/toast.ts b/src/notifications/toast.ts index 1e0d313..e6d0fe4 100644 --- a/src/notifications/toast.ts +++ b/src/notifications/toast.ts @@ -54,22 +54,35 @@ function ensureToast(): HTMLElement { el = document.createElement('div'); el.id = TOAST_ID; - el.innerHTML = ` -
🔒
-
-
Osias: buying locked
-
-
View details
-
- `; + + const icon = document.createElement('div'); + icon.className = 'osias-toast-icon'; + icon.textContent = '🔒'; + + const body = document.createElement('div'); + body.className = 'osias-toast-body'; + + const title = document.createElement('div'); + title.className = 'osias-toast-title'; + title.textContent = 'Osias: buying locked'; + + const reasonEl = document.createElement('div'); + reasonEl.className = 'osias-toast-reason'; + + const action = document.createElement('div'); + action.className = 'osias-toast-action'; + action.textContent = 'View details'; // No manual close button — the toast only goes away on its own (auto-hide // timer below) or when the lock state actually changes; clicking it never // unlocks anything. - el.querySelector('.osias-toast-action')?.addEventListener('click', () => { + action.addEventListener('click', () => { const message: OsiasMessage = { type: 'osias:open-popup' }; browser.runtime.sendMessage(message).catch(() => undefined); }); + body.append(title, reasonEl, action); + el.append(icon, body); + document.body.appendChild(el); return el; } diff --git a/wxt.config.ts b/wxt.config.ts index cb86627..19ecfaa 100644 --- a/wxt.config.ts +++ b/wxt.config.ts @@ -17,6 +17,17 @@ export default defineConfig({ gecko: { // Placeholder id for local/dev builds; replace before publishing to AMO. id: 'osias-extension@osias.trade', + // Firefox-required data collection disclosure (Firefox 140+ / AMO + // validation). Reflects what the extension actually transmits to the + // backend: wallet address + signature during Phantom sign-in + // (authenticationInfo, personallyIdentifyingInfo), and the wallet + // identity that ties the account to on-chain trading activity + // (financialAndPaymentInfo). See copilot/CLAUDE.md's "Backend + // connection" and "Wallet auth" sections. + data_collection_permissions: { + required: ['authenticationInfo', 'personallyIdentifyingInfo', 'financialAndPaymentInfo'], + optional: [], + }, }, }, },