Changelog

Auto-generated from CHANGELOG.md on every deploy. Format follows Keep a Changelog; Mailshade adheres to Semantic Versioning.

v0.1.0 — 2026-05-22

Initial pre-launch snapshot. Phase 0 + Phase 1 deliverables landed across phases phase0-w1, phase1-w1, phase1-w2, phase1-w3, phase1-w4. The version tag itself will be created by scripts/release.sh on first release.

Features

  • Landing site, infra, legal pages, and Hawk error masker (phase0-w1) — scripts/deploy.sh ships apps/webhook/ to auth.mailshade.org (Docker image build → load on VPS → docker compose), nginx configs for mailshade.org + auth.mailshade.org with certbot-managed TLS, privacy / terms / impressum pages, and a Hawk transport wrapper that strips PII (emails, hostnames, message subjects) before any error report leaves the extension.
  • WXT scaffold + Declarative Net Request + tracker database (phase1-w1) — Manifest V3 extension built with WXT (Chrome / Edge / Firefox channels), rules/pixels.json + rules/links.json DNR rules, IndexedDB-backed tracker store (Dexie) with BlockedRequest schema, popup + report React surfaces.
  • 6 mail-client adapters + popup + report dashboard (phase1-w2) — Per-client content scripts for Gmail / Outlook Web / Superhuman / Yahoo / ProtonMail / FastMail with sender extraction + pixel attribution, popup showing "today / 7d / 30d" counts, full report page with Recharts time-series + per-sender breakdown + CSV export.
  • Link unwrapper, onboarding, Polar webhook, licensing, options page (phase1-w3) — linkUnwrapper.ts with 35 tracker patterns + click-interceptor link-warning modal across all 5 hosts; 4-step onboarding flow with per-client chrome.permissions.request; apps/webhook/ Polar HMAC webhook receiver with file-locked founder counter (cap 1000 @ $19) at /polar/webhook and /polar/founder-quota; Polar /v1 license validate client + 7-day grace cache + feature gate (isPro / reportHistoryDays / topSendersLimit / sender + domain whitelists); 9-section options page (General / Clients / Blocking / Senders[Pro] / Domains[Pro] / Reports / Privacy / Upgrade / About).
  • i18n (10 locales), production landing polish, Playwright e2e, store assets, deploy gate (phase1-w4) — check-i18n.mjs enforces parity across en/ru/de/es/fr/it/ja/ko/pt-BR/zh-CN; site/ landing rewritten for production with Lighthouse CI gate (Perf ≥ 0.90, A11y ≥ 0.95) via scripts/check-lighthouse.mjs --url; Playwright e2e suite (14 specs — popup, report, link-warning, contextmenu-resolver, options-whitelist, onboarding, …); store-listing artefacts (5 PNG @ 1280×800 + marketing/store-listing.md + marketing/privacy-practices.md) gated by scripts/check-store-listing.mjs; live scripts/post-deploy-smoke.sh smoke runner with 11 PASS / 0 SKIP steps including live-URL Lighthouse check.

Fixes

  • ESLint v9 flat config now covers scripts/**/*.{mjs,js} with Node globals (root cause: --ext is a no-op under flat config). pnpm lint restored to exit 0.
  • tests/e2e/contextmenu-resolver.spec.ts de-flaked: fresh launchPersistentContext per test + iterative chrome.tabs.query + probe loop replacing the single-tab race. --repeat-each=3 and 3 consecutive full-suite runs all 14/14 green.
  • linkInterceptor.onOpenDirectly now emits chrome.runtime.sendMessage({type:'toast:show', variant:'link-opened-directly', payload:{originalHost, unwrappedHost}}) after navigating; producer side wired so the toast asserted in the Playwright spec has a real source.

Build

  • WXT auto-syncs manifest.version from package.json (verified pnpm build.output/chrome-mv3/manifest.json .version equals package.json .version).
  • vite.esbuild.charset = 'ascii' in wxt.config.ts to keep the Dexie "￿" range sentinel out of the bundle (Chromium's IsStringUTF8 rejects non-character code points even when bytes are valid UTF-8).

CI

  • .github/workflows/ci.yml runs lint + typecheck + unit + e2e + build + store-assets gate + landing Lighthouse on every PR. Tag-triggered release pipeline (this version) lives in .github/workflows/release.yml.