← back to Website Analysis

runs/businessclaw-2026-05-05-2018/extension.html

162 lines

<!doctype html>
<html lang="en"><head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Chrome Extension — businessclaw.agentabrams.com</title>
<meta name="robots" content="noindex" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root{--ink:#f4f1ea;--ink-soft:rgba(244,241,234,.78);--ink-mute:rgba(244,241,234,.52);--bg:#0e0e10;--bg-elevated:#16161a;--bg-card:rgba(244,241,234,.04);--rule:rgba(244,241,234,.10);--gold:#d4a04a;--gold-soft:rgba(212,160,74,.14);--good:#8fb89a;--bad:#c9856e;--warn:#d9b577;--serif:"Cormorant Garamond",Georgia,serif;--sans:"Inter",system-ui,sans-serif;--mono:"JetBrains Mono",ui-monospace,Menlo,monospace}
*{box-sizing:border-box}
html,body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans)}
body::before{content:"";position:fixed;inset:0;background:radial-gradient(ellipse 80% 60% at 18% -10%,rgba(212,160,74,.06),transparent 60%);pointer-events:none;z-index:0}
.nav{position:sticky;top:0;background:rgba(14,14,16,.86);backdrop-filter:blur(8px);border-bottom:1px solid var(--rule);padding:14px 32px;display:flex;gap:20px;font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;z-index:9}
.nav a{color:var(--ink-mute);text-decoration:none}.nav a:hover,.nav .home{color:var(--gold)}
main{position:relative;z-index:1;max-width:1000px;margin:0 auto;padding:64px 32px 96px}
.eyebrow{font-family:var(--mono);font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--gold);margin-bottom:18px}
h1{font-family:var(--serif);font-weight:500;font-size:60px;line-height:1.05;letter-spacing:-.02em;margin:0 0 12px}
h1 em{font-style:italic;color:var(--gold)}
.lede{font-family:var(--serif);font-style:italic;font-size:20px;line-height:1.5;color:var(--ink);max-width:62ch;margin:0 0 36px}
h2{font-family:var(--serif);font-weight:500;font-size:30px;margin:48px 0 8px;border-top:1px solid var(--rule);padding-top:32px}
h2 em{font-style:italic;color:var(--gold)}
h3{font-family:var(--serif);font-weight:500;font-size:21px;margin:20px 0 6px}
p,li{font-size:15px;line-height:1.7;color:var(--ink-soft)}
ul{padding-left:22px}
pre{font-family:var(--mono);font-size:12px;background:#0a0a0c;border:1px solid var(--rule);border-radius:2px;padding:18px 22px;overflow-x:auto;line-height:1.65;color:var(--ink-soft)}
pre .k{color:var(--gold)}.s{color:var(--good)}.c{color:var(--ink-mute);font-style:italic}
code{font-family:var(--mono);font-size:12px;background:var(--bg-elevated);border:1px solid var(--rule);border-radius:2px;padding:2px 6px;color:var(--ink-soft)}
.callout{border-left:2px solid var(--gold);background:var(--gold-soft);padding:18px 22px;margin:18px 0}
.callout strong{font-family:var(--serif);font-weight:500;color:var(--ink)}
table{width:100%;border-collapse:collapse;font-size:13px;margin:18px 0}
th,td{padding:10px 12px;border-bottom:1px solid var(--rule);text-align:left;vertical-align:top}
th{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-mute);font-weight:500}
.tag{display:inline-block;font-family:var(--mono);font-size:9px;letter-spacing:.14em;padding:3px 7px;border-radius:2px}
.tag.good{background:rgba(143,184,154,.16);color:var(--good)}.tag.warn{background:rgba(217,181,119,.16);color:var(--warn)}.tag.bad{background:rgba(201,133,110,.16);color:var(--bad)}.tag.gold{background:var(--gold-soft);color:var(--gold)}
.struct{font-family:var(--mono);font-size:12px;background:#0a0a0c;border:1px solid var(--rule);border-radius:2px;padding:18px 22px;line-height:1.7;color:var(--ink-soft)}
.struct .dim{color:var(--ink-mute)}.struct .a{color:var(--gold)}
</style></head>
<body>
<nav class="nav">
  <a href="index.html" class="home">Commerce Claw — Audit Hub</a>
  <a href="report.html">Audit</a>
  <a href="peers.html">Peers</a>
  <a href="competitors.html">Competitors</a>
  <a href="mockups/index.html">Mockups</a>
  <a href="tools.html">Tools</a>
  <a href="hub.html">Info Hub</a>
  <a href="extension.html">Extension</a>
</nav>
<main>
  <div class="eyebrow">Chrome Extension · Section 07 of 07</div>
  <h1>Highlight, then <em>act.</em></h1>
  <p class="lede">A privacy-first MV3 Chrome extension that lets a Commerce Claw user highlight any text on any page — a customer name, an order number, an email — and run a connector action on it from a side panel. The companion piece to the chat surface inside the app.</p>

  <h2>What it does · in one paragraph</h2>
  <p>You're on a Yelp review page. You highlight the reviewer's name. The Commerce Claw extension icon glows. You click; a 320-px side panel slides in offering: <em>"Look up [name] in Stripe / HubSpot / Square — draft a reply — log to Notion."</em> You pick. The action runs through your existing Commerce Claw account, approval-gated like everywhere else. Nothing leaves your machine until you tap approve. The selection text never goes to any third-party LLM — only to <code>businessclaw.agentabrams.com</code> over HTTPS, with the same auth cookie you already have.</p>

  <h2>Privacy &amp; <em>permissions</em> posture</h2>
  <table>
    <thead><tr><th>What other "AI sidebar" extensions ask for</th><th>What Commerce Claw asks for</th></tr></thead>
    <tbody>
      <tr><td><code>&lt;all_urls&gt;</code> host permission</td><td><code>activeTab</code> only — granted per-click</td></tr>
      <tr><td>Auto-injected content script on every site</td><td>Content script lazy-loaded only when user clicks the action button</td></tr>
      <tr><td>"Read all your data on the websites you visit" warning</td><td>"See what's currently on the active tab when you click the extension" — the lightest possible warning</td></tr>
      <tr><td>Background telemetry to vendor analytics</td><td>Zero. No analytics in the extension itself.</td></tr>
      <tr><td>Selection text sent to OpenAI/Anthropic by extension</td><td>Selection sent only to <code>businessclaw.agentabrams.com</code> over fetch with credentials — same domain you'd already trust.</td></tr>
    </tbody>
  </table>

  <div class="callout"><strong>Marketing positioning.</strong> This is the privacy claim that wins the listing. Most "AI assistant" extensions in the Chrome Web Store have <code>&lt;all_urls&gt;</code> + auto-content-script. Commerce Claw's version asks for <em>nothing</em> until the user clicks. That's the screenshot for the store listing.</div>

  <h2>Manifest &amp; <em>file structure</em></h2>
  <div class="struct">
ext/<br>
├── <span class="a">manifest.json</span>          <span class="dim">// MV3, minimal permissions</span><br>
├── <span class="a">background.js</span>          <span class="dim">// service worker, ~80 lines</span><br>
├── <span class="a">sidepanel.html</span>         <span class="dim">// the 320px panel</span><br>
├── <span class="a">sidepanel.js</span>           <span class="dim">// fetches /api/extension/actions</span><br>
├── <span class="a">sidepanel.css</span>          <span class="dim">// gold/charcoal palette inline</span><br>
├── <span class="a">content.js</span>             <span class="dim">// only injected on click; reads selection</span><br>
├── icons/<br>
│   ├── <span class="a">16.png</span>  <span class="a">48.png</span>  <span class="a">128.png</span>   <span class="dim">// brand-gold C-dot logo</span><br>
└── <span class="a">README.md</span>              <span class="dim">// install + privacy notes</span>
  </div>

  <h2>manifest.json (v0.1)</h2>
<pre><span class="k">{
  "manifest_version"</span>: <span class="s">3</span>,
  <span class="k">"name"</span>: <span class="s">"Commerce Claw"</span>,
  <span class="k">"version"</span>: <span class="s">"0.1.0"</span>,
  <span class="k">"description"</span>: <span class="s">"Highlight any text on any page · run an action across Stripe, Shopify, Slack, and 53 more."</span>,
  <span class="k">"permissions"</span>: [<span class="s">"activeTab"</span>, <span class="s">"sidePanel"</span>, <span class="s">"storage"</span>],
  <span class="k">"host_permissions"</span>: [<span class="s">"https://businessclaw.agentabrams.com/*"</span>],
  <span class="k">"action"</span>: { <span class="k">"default_title"</span>: <span class="s">"Commerce Claw"</span>, <span class="k">"default_icon"</span>: { <span class="k">"16"</span>: <span class="s">"icons/16.png"</span> } },
  <span class="k">"background"</span>: { <span class="k">"service_worker"</span>: <span class="s">"background.js"</span> },
  <span class="k">"side_panel"</span>: { <span class="k">"default_path"</span>: <span class="s">"sidepanel.html"</span> },
  <span class="k">"icons"</span>: { <span class="k">"16"</span>: <span class="s">"icons/16.png"</span>, <span class="k">"48"</span>: <span class="s">"icons/48.png"</span>, <span class="k">"128"</span>: <span class="s">"icons/128.png"</span> },
  <span class="k">"content_security_policy"</span>: {
    <span class="k">"extension_pages"</span>: <span class="s">"script-src 'self'; object-src 'self'; connect-src 'self' https://businessclaw.agentabrams.com"</span>
  }
}</pre>

  <h2>Why this matters · five bullets</h2>
  <ul>
    <li><strong>Acquisition vector.</strong> Chrome Web Store is a discovery surface that doesn't depend on Commerce Claw's marketing-page SEO. A well-listed MV3 extension can pull 100–1,000 weekly installs without any homepage traffic.</li>
    <li><strong>Distribution moat.</strong> Once installed, the extension is a daily-touch surface. Bardeen rode this all the way to a Series A.</li>
    <li><strong>Trust artifact.</strong> A reviewable, open-source manifest with <em>activeTab only</em> is the easiest privacy proof a SaaS company can produce. Way more credible than a /security page.</li>
    <li><strong>Workflow completion.</strong> Today, "I'm on Yelp and want to draft a reply" requires 4 tab switches. With this, it's 2 clicks.</li>
    <li><strong>Owner-uploaded asset path.</strong> Per Steve's MEMORY, no stock images. The extension's icon is the existing gold C-dot — a 128×128 SVG → PNG export from the brand system already shipped.</li>
  </ul>

  <h2>The legal &amp; technical <em>memo</em></h2>

  <h3>1. Data flow</h3>
  <p>User clicks extension → content script reads <code>window.getSelection()</code> + page <code>document.title</code> + <code>location.href</code> → posted to <code>POST https://businessclaw.agentabrams.com/api/extension/plan</code> with credentials → server returns proposed actions → user picks one → <code>POST /api/extension/run</code> with explicit approval → server runs the connector, returns audit ID → side panel shows result. <strong>Selection text never reaches any third-party origin from within the extension.</strong> The LLM call happens server-side, on credentials encrypted with AES-256-GCM, exactly like the chat surface.</p>

  <h3>2. Host permissions justification (for Chrome Web Store review)</h3>
  <p><code>activeTab</code> only. Triggered by the user clicking the extension icon — Chrome's <em>highest-trust</em> permission tier. No <code>&lt;all_urls&gt;</code>. No <code>tabs</code> permission. No background polling of any site.</p>

  <h3>3. Retention</h3>
  <p>Selection text is sent over HTTPS, processed for a single LLM call, and the audit row is stored with the same retention policy as in-app chat. Selection text is <em>not</em> kept in the audit row by default — only the connector action that executed. Configurable per-tenant.</p>

  <h3>4. Mobile-friendliness</h3>
  <p>Chrome on Android does not support extensions. Mobile equivalent is the existing <code>/chat</code> PWA — installable from Safari/Chrome via "Add to Home Screen." The PWA shares the same <code>/api/extension/plan</code> endpoint behind the scenes, so feature-parity is essentially free.</p>

  <h3>5. Audit</h3>
  <p>Every action originating from the extension carries a <code>source: "chrome-extension"</code> label in the audit log. Filterable in the admin dashboard. Combined with the existing audit trail, this means every connector action triggered through the extension is provably traceable to: (a) which extension version, (b) which user session, (c) which page URL the action came from, (d) approval timestamp.</p>

  <h3>6. Threat model</h3>
  <table>
    <thead><tr><th>Threat</th><th>Mitigation</th></tr></thead>
    <tbody>
      <tr><td>Hostile webpage tries to trigger an action without user click</td><td>Content script only loaded after extension icon click. Page cannot inject a fake click programmatically due to <code>activeTab</code> trust gate.</td></tr>
      <tr><td>Token theft via XSS in extension page</td><td>CSP <code>script-src 'self'</code>. No inline scripts. Token stored in <code>chrome.storage.local</code>, not <code>localStorage</code>, so not reachable from page-context scripts.</td></tr>
      <tr><td>MITM between extension and businessclaw.agentabrams.com</td><td>HSTS-preload (already configured server-side) + CSP <code>connect-src</code> restricted to that one origin.</td></tr>
      <tr><td>Malicious npm dependency</td><td>v0.1 ships with zero npm dependencies. Vanilla JS, ~400 lines total. Package only when essential.</td></tr>
      <tr><td>Reviewer challenge on selection-text-sent-off-device</td><td>Privacy policy page documents the round-trip; selection sent only to first-party API. No third-party LLM endpoint.</td></tr>
    </tbody>
  </table>

  <h3>7. v0.1 acceptance criteria</h3>
  <ul>
    <li>Installs from <code>chrome://extensions</code> in unpacked mode without warnings.</li>
    <li>Click → side panel opens within 200ms.</li>
    <li>Side panel shows: selected text (truncated 200 chars), 3-action menu (Look up / Draft reply / Log to Notion), Approve/Reject buttons.</li>
    <li>"Approve" → action runs against the live Commerce Claw API, audit ID returned and displayed.</li>
    <li>No console errors. No <code>&lt;all_urls&gt;</code> warning at install.</li>
    <li>Bundle size &lt; 50 KB (icons included).</li>
  </ul>

  <h3>8. Roadmap (post-v0.1)</h3>
  <ul>
    <li><strong>v0.2</strong> · Right-click context menu integration (<code>contextMenus</code> permission, additive).</li>
    <li><strong>v0.3</strong> · Per-site profiles ("on Yelp, default to 'draft reply'") via <code>chrome.storage.sync</code>.</li>
    <li><strong>v0.4</strong> · Firefox + Safari ports. Same manifest with provider-specific tweaks.</li>
    <li><strong>v0.5</strong> · Recipe creation from extension: highlight → "save this as a recurring action" → recipe lands in dashboard.</li>
  </ul>

  <p style="font-family:var(--mono);font-size:11px;letter-spacing:.12em;color:var(--ink-mute);text-transform:uppercase;margin-top:48px">End · Chrome Extension · 7 of 7. Back to <a href="index.html" style="color:var(--gold)">Audit Hub</a></p>
</main>
</body></html>