Skip to content

feat(extension): onboarding consent screen for the opt-in - #1605

Merged
JOY (JOY) merged 3 commits into
devfrom
feat/extension-onboarding-consent
Nov 4, 2026
Merged

JOY (JOY) merged 3 commits into
devfrom
feat/extension-onboarding-consent

Conversation

@JOY

@JOY JOY (JOY) commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1603
Refs #1175

JOY decided on 2026-11-04 ("Cả hai, mặc định tắt"): ask for consent at install and keep the side-panel toggle. The default is off. This completes M1 of Docs/Proposals/2026-10-28-extension-data-source.md, together with #1602.

What is sent, the ingest API and the default are unchanged. Nothing is published.

What changes

  • Consent page (src/onboarding/): it opens once, on onInstalled with reason install, after the defaults are stored. Updates and reloads do not open it. The copy is short and comes in vi, en and cs:
    • what lookup sends, field by field;
    • what "Yes" adds: the same ten fields as the side panel, enforced by the pipeline test, plus the note that our servers may re-check the listing on the store;
    • "no account, name, email or cookies";
    • "off by default", and how to reach the side-panel toggle.
  • Choices. "No" has the primary style and the focus. "Yes" is a secondary button. Closing the page keeps the opt-in off.
    • The status line says what was saved, or that the save failed, and follows later changes made in the side panel.
    • aria-pressed marks the stored choice. Focus stays on the clicked button.
  • One setting. The page sends RATE_UPDATE_SETTINGS, which writes the same crowdContributeOptIn that the side-panel toggle uses. The toggle now follows storage.onChanged.
  • Sender check. isOnboardingSender accepts only this extension's exact consent page URL. A query, a hash, another extension or a web page is refused, and an unknown runtime id fails closed.
    • That sender may set the opt-in only. The server address is ignored for it.
    • isPrivilegedExtensionSender still refuses every tab sender, so content scripts cannot change settings.
    • The manifest has no web_accessible_resources, so no web page can frame or open the page.
  • Install defaults. Each missing default is written on its own, before the page opens. A quick choice is never overwritten, and a stored choice is kept.
  • Docs. The privacy policy (vi, en, cs) and CHROMEWEBSTORE.md name the consent page. RELEASE.md adds a test step and a changelog line.

Checks

  • pnpm test, tsc and pnpm build pass in apps/extension.
  • The built page was screenshotted with Playwright in light/desktop and dark/phone: no errors, "No" focused, no horizontal scroll.
  • Not run: an install of the real unpacked build in Chrome. The RELEASE.md step covers it before upload.

Review

Two fresh-context Claude reviews were run on 908152f.

  • Security and flow. The reviewer checked how Chrome sets MessageSender.url and tab, that tabs.create needs no tabs permission, and that the default stays off on every path.
  • Copy and UX. Checked against the Chrome Web Store consent expectations, contrast in both themes, and the vi, en and cs wording.

Neither review found anything blocking. Fixed in e6253de and 765c92d:

  • a narrow race where the first-install defaults could overwrite an early "Yes", which failed safe;
  • the consent sender getting full privileges;
  • the lookup line leaving out the URL and other fields;
  • the reused toggle text ("When on", no re-check note);
  • the vague pointer to the side panel;
  • lost keyboard focus, and a status that was not re-announced;
  • no mark on the stored choice;
  • the privacy policy and store doc not naming the page.

Codex not run.

🤖 Generated with Claude Code


📌 TL;DR

This PR introduces a one-time onboarding consent page that appears on first extension install, allowing users to opt-in to crowd-sourced product data collection. It updates the build pipeline, security guards, and localization files to support this new flow while ensuring the opt-in remains off by default and is only enabled via explicit user action.

🎯 Type of Change

  • 🚀 New feature
  • 🐛 Bugfix
  • 🧹 Refactor
  • ⚡ Performance
  • 📚 Documentation
  • ⚙️ CI / Configuration

🔍 Changes Walkthrough

File Summary of Changes
apps/extension/CHROMEWEBSTORE.md Updated privacy documentation to reflect the new install-time consent mechanism and clarify that closing the page keeps the opt-in off.
apps/extension/RELEASE.md Added release notes and checklist items for the new consent page behavior (#1603).
apps/extension/scripts/build.mjs Updated the build script to create the onboarding directory, bundle the onboarding.ts entry point, and copy onboarding.html to the dist folder.
apps/extension/src/_locales/*/messages.json Added new i18n keys (onboardingTitle, onboardingLookup, onboardingQuestion, etc.) for the consent page in Czech, English, and Vietnamese.
apps/extension/src/background/service-worker.ts Modified onInstalled listener to open the consent page on first install. Updated RATE_UPDATE_SETTINGS handler to accept messages from the onboarding page (restricted to opt-in only).
apps/extension/src/onboarding/onboarding.html New file. The static HTML structure for the consent page, including dark mode support and i18n placeholders.
apps/extension/src/onboarding/onboarding.ts New file. Logic to handle user choices on the consent page, send settings to the background script, and listen for storage changes to update UI state.
apps/extension/src/security-guards.ts Added ONBOARDING_PAGE_PATH constant and isOnboardingSender function to strictly validate messages from the consent page. Adjusted isPrivilegedExtensionSender to exclude tab-based senders.
apps/extension/src/sidepanel/sidepanel.ts Added a chrome.storage.onChanged listener to sync the side panel's opt-in checkbox with the setting if it is changed via the onboarding page.
apps/extension/src/test-extension-pipeline.ts Added unit tests for isOnboardingSender (validating URL and sender ID) and verified that the consent page text includes all required field labels.
apps/web/locales/*.json Updated the web app's privacy policy text to mention the new install-time consent option.

📊 Architectural Flow

sequenceDiagram
    participant User
    participant Chrome
    participant SW as Service Worker
    participant OB as Onboarding Page
    participant SP as Side Panel
    participant Storage as chrome.storage.local

    Note over User, Chrome: First Install
    User->>Chrome: Install Extension
    Chrome->>SW: onInstalled (reason: 'install')
    SW->>Storage: Set defaults (optIn: false)
    SW->>Chrome: Open Tab (onboarding.html)
    Chrome->>OB: Load Page
    OB->>User: Display Consent (Default: No)
    
    alt User clicks "Yes"
        User->>OB: Click "Yes"
        OB->>SW: RATE_UPDATE_SETTINGS (optIn: true)
        SW->>OB: Validate Sender (isOnboardingSender)
        SW->>Storage: Set optIn: true
        Storage-->>OB: onChanged Event
        OB->>User: Show "Saved: Contributing"
        Storage-->>SP: onChanged Event
        SP->>SP: Update Checkbox to Checked
    else User clicks "No" or Closes
        User->>OB: Click "No" / Close Tab
        Note over OB,Storage: Opt-in remains false (default)
    end
Loading

JOY (JOY) and others added 3 commits November 4, 2026 12:10
On a first install the extension opens a short consent page (vi, en,
cs): what the lookup sends, what the opt-in would add (the same field
list as the side panel), that nothing more is sent until the user says
yes, and that the side panel can change it. "No" has the focus and the
primary style; closing the page keeps the default, off.

The choice goes through RATE_UPDATE_SETTINGS to the same setting as the
side panel toggle, which now follows changes made elsewhere. The sender
guard accepts a tab sender only when it is this extension's consent page
URL, exactly; content scripts stay refused. Updates and reloads do not
open the page.

Refs #1603, #1175

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- isOnboardingSender accepts the exact consent page URL and lets it set
  the opt-in alone; isPrivilegedExtensionSender refuses tab senders again.
- onInstalled writes each missing default before opening the page, so a
  quick choice is never overwritten; a stored choice is kept.
- The page status follows the stored choice.

Refs #1603

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The consent page has its own opt-in text (onboardingOptInBody): the
  same fields as the side panel, tested, plus the server re-check and
  "no account, name, email or cookies". The lookup line lists every
  field lookup sends.
- "Off by default" and how to reach the side panel toggle replace the
  vague line; vi, en and cs say the same.
- Keyboard focus stays on the clicked button, the status is announced
  again on a repeat, and aria-pressed marks the stored choice.
- The privacy policy and CHROMEWEBSTORE.md name the consent page;
  RELEASE.md has a test step and changelog line for it.

Refs #1603

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@vercel

vercel Bot commented Nov 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
rate Ready Ready Preview Nov 4, 2026 5:24am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Nov 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 26 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: bc0d2c0b-91a7-409f-9603-84a941ff52a8
Commits

Reviewing files that changed from the base of the PR and between 8919776 and 765c92d.

Files selected for processing: 15
  • apps/extension/CHROMEWEBSTORE.md
  • apps/extension/RELEASE.md
  • apps/extension/scripts/build.mjs
  • apps/extension/src/_locales/cs/messages.json
  • apps/extension/src/_locales/en/messages.json
  • apps/extension/src/_locales/vi/messages.json
  • apps/extension/src/background/service-worker.ts
  • apps/extension/src/onboarding/onboarding.html
  • apps/extension/src/onboarding/onboarding.ts
  • apps/extension/src/security-guards.ts
  • apps/extension/src/sidepanel/sidepanel.ts
  • apps/extension/src/test-extension-pipeline.ts
  • apps/web/locales/cs.json
  • apps/web/locales/en.json
  • apps/web/locales/vi.json
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@github-actions github-actions Bot added area:frontend Frontend / Next.js / UI area:extension labels Nov 4, 2026
dos[bot]
dos Bot approved these changes Nov 4, 2026

@dos dos Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱️ Code Review completed (15 eligible files · 38,065 chars · 3 model call(s) · 2 PR unit(s))

Whole diff with bounded context at base 8919776 / head 765c92d.

✅ CLEAN_PASS: Complete diff reviewed

Context investigation was bounded to the explicitly requested snapshot paths.

@JOY
JOY (JOY) merged commit 47ff269 into dev Nov 4, 2026
20 checks passed
@JOY
JOY (JOY) deleted the feat/extension-onboarding-consent branch November 4, 2026 05:32

This branch was successfully deployed

1 active deployment
Preview — 765c92d5 Deployed Nov 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:extension area:frontend Frontend / Next.js / UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(extension): onboarding consent screen for the opt-in

1 participant