页面 · Health Debug
Phase 3 — Chrome Extension (Manifest V3) Plan
Project: Health Debug (healthdebug.com) Phase: 3 of 6 (after Phase 1 ToGO backend + PostgreSQL + auth, and Phase 2 React web dashboard + theme/i18n engine) Status: Planning only — no implementation until UI design is finalized. Items dependent on the visual design are flagged PENDING DESIGN inline.
Purpose
This document plans the Health Debug Chrome Extension (Manifest V3): a lightweight browser-resident client that gives desk-bound professionals zero-friction protocol logging (+250ml water, clean caffeine), an Active Pomodoro Guard tied to the backend Kinetic Pomodoro Engine, a Contextual Trigger Scanner for highlighted text on any page, and always-visible protocol countdowns in the toolbar badge. Like every Health Debug client, the extension is a presentation and sensor-collection layer only: it never computes or hardcodes protocol business logic locally. All temporal and state logic lives in the central ToGO REST API, which is the Single Source of Truth (SSOT).
1. Constraints Inherited From the Core Spec (Non-Negotiable)
| # | Constraint | Consequence for the extension |
|---|---|---|
| 1 | The Protocol is Categorical, Not Quantitative | Trigger Scanner results are strictly categorical ("Safe" / "Trigger-bearing" per family). The extension never shows quantities, scores, percentages of risk, or any quantitative food deduction. |
| 2 | The App NEVER Invents Medical Certainty | Any AI-assisted output surfaced in the extension is behavioral-pattern only and must end with a "Consult your doctor" deferral. The extension never displays diagnosis, prescription, or drug-category guesses. |
| 3 | Clients never compute protocol logic | No countdown math, cooldown enforcement, cap enforcement, or window evaluation is implemented in extension code. The extension renders server state and submits user intents/sensor events. Local timers exist only to schedule re-fetching server state, never to derive protocol state. |
| 4 | AI BYOK, server-proxied | AI provider keys (OpenAI, Anthropic, Google, Apple Intelligence) are entered in the options page but submitted directly to the backend for encryption. Keys are never persisted in chrome.storage, never attached to client-side AI calls (there are none), and never echoed back by the API. |
| 5 | Strict color spec | Dark: #1A1A1A bg, #00FF33 neon green (active timers), #00CCFF cyan (active buttons), #FF3333 red (alerts), glowing effects. Light: #FFFFFF bg, #20A060 saturated teal, #0070A0 deep cyan blue, flat colors. No other accent colors introduced. |
| 6 | i18n | Full RTL support for Arabic including mirrored layout and progress bars; ICU Message Format; no string concatenation. |
2. MV3 Architecture Overview
2.1 Components
| Component | MV3 mechanism | Responsibility |
|---|---|---|
| Background service worker | background.service_worker | Polls ToGO for active countdowns/protocol state; updates badge text/icon; handles token refresh; owns chrome.alarms, chrome.contextMenus, chrome.notifications; relays messages between UI surfaces and the API client. |
| Popup | action.default_popup | Quick-glance panel: water, caffeine, pomodoro status, GERD timer + 1-click logging buttons. |
| Side Panel | Chrome Side Panel API (side_panel.default_path, chrome.sidePanel) | Mini-dashboard: Human Node diagram (PENDING DESIGN) + today's protocol timeline. |
| Options page | options_ui | Account linkage (TOGO auth), notification preferences, AI BYOK configuration proxy settings. |
| Context menu | chrome.contextMenus with contexts: ["selection"] | Entry point for the Contextual Trigger Scanner on highlighted text. |
| Content scripts | None. | The extension is content-script-free. The selection-based context menu does not require a content script: chrome.contextMenus.onClicked delivers info.selectionText to the service worker directly. |
2.2 Content-script-free rule
No content_scripts entry in the manifest and no chrome.scripting injection. Rationale: the extension never needs to read or modify page DOM; the only page interaction is the highlighted-text context menu, which MV3 supports natively. This also minimizes permission surface (no broad host access for page injection) and review friction on the Chrome Web Store.
Implication to accept explicitly: without content scripts, the Pomodoro Guard cannot draw overlays inside web pages. Break-time interception must use extension-owned surfaces (badge, notifications, popup/side panel, and optionally an extension-owned page/tab). See §5.
2.3 Planned directory tree (planning artifact, not code)
UI framework choice inside popup/sidepanel/options (e.g., reusing the Phase 2 React + TanStack setup vs. lighter-weight rendering) is an open decision — see §12. Reuse of the Phase 2 theme/i18n engine is the default assumption since Phase 2 ships first.
2.4 Manifest permission sketch (planning-level)
| Manifest key / permission | Why |
|---|---|
"manifest_version": 3 | Required. |
action (popup + badge) | Toolbar button, popup, badge text/icon. |
side_panel + "sidePanel" permission | Side panel mini-dashboard. |
options_ui | Options page. |
"storage" | Session token + display-only state cache in chrome.storage.local. |
"alarms" | Wake the service worker on a schedule to poll ToGO (MV3 workers are ephemeral). |
"contextMenus" | Trigger Scanner entry point on selections. |
"notifications" | Protocol alerts and Pomodoro Guard nudges (governed by notification prefs in options). |
"idle" | Candidate activity signal for the Pomodoro Guard (see §5.2 — decision open). |
host_permissions: [<ToGO API origin>] | Authenticated REST calls to the backend. Exact production origin (e.g., an API subdomain of healthdebug.com) is undefined at this time — to be fixed by the Phase 1 deployment plan. |
Nothing beyond this list. No tabs/webNavigation-style broad permissions unless the Pomodoro Guard activity-signal decision (§5.2) requires it, in which case the tradeoff must be revisited explicitly.
3. Backend Interaction Model (SSOT)
3.1 Principles
- Every surface renders the last snapshot returned by ToGO plus a "data as of" freshness marker. The extension may run a local ticking display between polls (e.g., counting down seconds from a server-provided deadline timestamp), but the deadline itself always comes from the server and is re-validated on every poll.
- All writes are intents ("user tapped +250ml at T"), never state assertions. The server applies protocol rules (250ml units, 5000ml cap, 30-second cooldown, 90-minute caffeine block, 4-hour GERD window, etc.) and returns the resulting state, including rejections.
- Rejections (e.g., water logged within the 30-second cooldown, caffeine during the block) are rendered exactly as the server reports them; the extension performs no pre-validation that duplicates protocol rules. At most it may disable a button based on server-declared state already in hand (display of server state, not local rule evaluation).
3.2 Consumed API surface (indicative — to be finalized against the Phase 1 API contract)
The paths below are placeholders to shape the client; the authoritative names/shapes come from the Phase 1 ToGO API plan.
| Purpose | Method + path (indicative) | Notes |
|---|---|---|
| Auth: session refresh | POST /auth/refresh | TOGO auth. Exact token model (lifetimes, refresh semantics) defined by Phase 1. |
| Protocol snapshot | GET /protocol/state | Single aggregate poll: active countdowns + statuses for Hydration, Caffeine Block, GERD Window, Medication Grace, Kinetic Pomodoro. One round trip per poll to keep the worker cheap. |
| Log water | POST /hydration/log | Intent for +250ml; server enforces unit, 5000ml cap, 30s cooldown. |
| Log clean caffeine | POST /caffeine/log | Server enforces the 90-minute post-wakeup block. |
| Trigger scan | POST /triggers/scan | Body: raw selected text + locale. Response: categorical verdicts per Trigger Family (Gout, IBS-GERD, Fatty Liver). See §6. |
| Pomodoro state/events | GET within snapshot; POST /pomodoro/events | Extension submits browser-activity sensor events during breaks (see §5.3); Kinetic Pomodoro Engine decides everything. |
| AI BYOK submission | POST /ai/keys (write-only) | Options page proxies key material straight to backend encryption; API must never return key material. |
| Notification prefs | GET/PUT /prefs/notifications | Preferences live server-side so all clients agree; extension caches for display only. |
Whether the snapshot poll is complemented by a push channel (e.g., SSE/WebSocket/Web Push) is a Phase 1 API question; this plan assumes polling only as the baseline, since that is what the brief specifies.
3.3 Polling design under MV3 worker lifetime
MV3 service workers are terminated when idle; long-lived setInterval polling is not viable. Plan:
chrome.alarmsperiodic alarm drives the poll loop. Chrome enforces a minimum alarm period (30 seconds in current Chrome; 1 minute on older versions) — the effective badge refresh cadence is bounded by this platform floor.- On each alarm: fetch
/protocol/state→ write snapshot tochrome.storage.local(display cache) → recompute badge text/icon from the snapshot → broadcast a message so any open popup/side panel re-renders. - Open popup/side panel surfaces may additionally fetch on open and render a per-second countdown display derived from server deadline timestamps, so the UI feels live even though the worker polls coarsely.
- On
chrome.runtime.onStartup/onInstalledand on network recovery: immediate poll. - Adaptive cadence (poll faster while a countdown is near expiry, slower when nothing is active) is a candidate optimization — parameters undefined, to be decided during implementation within the platform floor above.
4. One-Click Protocol Logging
4.1 Actions
| Action | Where | Behavior |
|---|---|---|
| +250ml water | Popup; side panel; (candidate: context-menu shortcut — open decision) | Sends hydration intent. Server enforces 250ml unit, 5000ml daily max, 30-second cooldown. On rejection, surface the server's reason verbatim (localized), e.g., cooldown active. |
| Clean caffeine | Popup; side panel | Sends caffeine intent. Server enforces the 90-minute post-wakeup Caffeine Block; a rejection during the block is rendered as an alert-state response, not silently swallowed. |
4.2 UX rules
- One tap = one intent. No local debouncing that masks the server's 30-second cooldown response — the cooldown is the server's rule to enforce and report.
- After any successful/failed log, the extension immediately re-fetches the protocol snapshot so badge and panels reflect the server's post-write truth.
- Button visual states (enabled/active per
#00CCFFcyan in dark,#0070A0in light; disabled/alert states) — exact component styling PENDING DESIGN. - During the GERD Window, the server's snapshot governs what the logging surfaces communicate (only water, chamomile, anise are allowed in that window). Whether the popup exposes chamomile/anise quick-log buttons in addition to water is an open product/design question — PENDING DESIGN and pending Phase 1 API confirmation.
5. Active Pomodoro Guard
5.1 Badge as state display
The toolbar badge continuously reflects the Kinetic Pomodoro Engine state from the server snapshot:
| Server state | Badge (proposed mapping) |
|---|---|
| Work interval running | Countdown text (badge text is limited to ~4 characters, e.g., minutes remaining); active-timer color per palette. |
| Break required / in progress, movement not yet detected | Break indicator; alert styling (#FF3333 family) while the user keeps browsing instead of moving. |
| Break satisfied (wearables confirmed movement away from screen) | Confirmation/reset indicator. |
| No session | Badge empty or neutral icon. |
Exact badge glyphs, text formats, and color-state assignments within the strict palette: PENDING DESIGN.
Critical rule: the extension never decides that a break was completed. The Kinetic Pomodoro Engine registers a break only when wearables detect physical movement away from the screen; the extension only mirrors that server-side determination.
5.2 Intercepting continuous browser activity during forced breaks
Requirement: while the server says "break in progress," continued browser activity should be intercepted. Because the extension is content-script-free, in-page overlays are off the table. Candidate mechanisms (decision open — see §12):
chrome.idlesignal: query/observe idle state; "active" during a break ⇒ the user is still at the keyboard. Coarse but permission-light.- Tab-activity events (tab switches/navigation as activity evidence): stronger signal, but requires broader permissions than the baseline set in §2.4 — permission tradeoff must be explicitly accepted if chosen.
- Interception surfaces:
chrome.notificationsnudge, forced badge alert state, auto-opening the side panel or an extension-owned break page/tab. Which combination (and how aggressive) is a product + design decision — PENDING DESIGN, also gated on the user's notification preferences from the options page.
The word "intercept" here means surface friction and record the violation — the spec does not define blocking/locking the browser, and this plan does not invent such a feature.
5.3 Extension as sensor
Detected browser activity during a server-declared break is reported to ToGO as a sensor event (POST /pomodoro/events, indicative). This keeps the extension in its architectural lane: it contributes evidence ("user was active in the browser at T"); the engine — which also has wearable movement data — draws all conclusions.
6. Contextual Trigger Scanner
6.1 Flow
- User highlights text on any page (e.g., an ingredient list on a recipe or food-delivery site) and right-clicks.
- Context menu item (registered with
contexts: ["selection"]) — label copy PENDING DESIGN/copywriting; must exist inenandar. chrome.contextMenus.onClickedfires in the service worker withinfo.selectionText. No content script involved; no page DOM is read beyond what Chrome hands over.- Service worker
POSTs the raw selection text to the ToGO trigger-check endpoint. - Backend checks it against the Trigger Families taxonomy: Gout, IBS-GERD, Fatty Liver.
- Result is rendered to the user (surface decision open: notification vs. side panel result view vs. both — PENDING DESIGN).
6.2 Result contract (categorical, per core opinion #1)
- Output is strictly categorical: for the recognized items, "Safe" or "Trigger-bearing," with the family/families implicated (Gout, IBS-GERD, Fatty Liver).
- No quantities, thresholds, portions, or risk scores. The scanner answers what something is, never how much is acceptable.
- Unrecognized/ambiguous text: the server's "unknown" outcome is shown as-is; the extension never guesses.
- Per core opinion #2: results are informational pattern/category lookups, not medical advice; the result surface carries the standard deferral ("Consult your doctor") wherever the shared UX copy dictates. Placement/wording PENDING DESIGN.
- Whether the categorization is a pure server-side taxonomy lookup or may involve the user's BYOK AI proxy for text extraction is a backend (Phase 1) decision; either way the extension only sees the categorical result.
7. Badge & Icon State Model
The badge/icon is the extension's always-on display of server state, recomputed after every poll:
| Server condition (from snapshot) | Toolbar treatment |
|---|---|
| GERD Window active and violated | Red bug icon (per spec), alert color #FF3333. |
| GERD Window active, compliant | GERD countdown indication — exact treatment PENDING DESIGN. |
| Pomodoro work/break | Per §5.1. |
| Caffeine Block active (first 90 min post-wakeup) | Block indicator — PENDING DESIGN. |
| Medication Grace window open (60-minute flexible log window) | Reminder indicator — PENDING DESIGN. |
| Multiple simultaneous states | Priority ordering for which state owns the badge is undefined in the spec — needs a product decision (proposed default: violations/alerts > active break > active countdowns > idle). |
| Signed out / stale data | Neutral/disconnected treatment — PENDING DESIGN. |
Icon asset set (including the red bug icon) at all required MV3 sizes: PENDING DESIGN.
Note: fertility Cycle Engine and Contraceptive Security states are part of the 8 backend engines but the brief does not assign them extension surfaces (badge, popup, or side panel). This plan deliberately leaves them out of the extension UI; if they should appear in the protocol timeline (§9.2), that is an open product question.
8. Auth & Session Management
- Identity: TOGO auth (Phase 1). Account linkage is initiated from the options page (§9.3). The concrete linkage flow (credentials vs. web-app-mediated authorization, e.g., signing in via the Phase 2 dashboard and handing a token to the extension) is a Phase 1/Phase 2 dependency — undefined here; must follow the TOGO auth contract.
- Storage: session token in
chrome.storage.local. Notes to carry into implementation:chrome.storage.localis not encrypted at rest; scope stored material to the minimum the TOGO auth model allows (short-lived access token + whatever refresh credential the contract defines). Never store AI provider keys (§9.3), never store anything the server can re-derive. - Background refresh: the service worker owns token refresh. On a 401/expiry signal from any API call (poll, log intent, scan), it performs the refresh flow, retries once, and only surfaces a sign-in prompt if refresh fails. Refresh must be single-flight (concurrent 401s from popup + poller must not trigger parallel refreshes) — an MV3-specific hazard worth naming now, since multiple surfaces share one worker.
- Signed-out behavior: badge cleared to the neutral state; popup/side panel render a sign-in call-to-action; poll alarm continues at a low cadence or is suspended until linkage (decision open).
- Sign-out / unlink: wipes
chrome.storage.local(token + display cache) entirely.
9. Key Views
All three surfaces share the Phase 2 theme engine tokens (strict palette, dark glow / light flat) and the i18n engine (ICU Message Format, full Arabic RTL mirroring — including progress/countdown bars, which must fill right-to-left in RTL). All layout, spacing, iconography, and component visuals are PENDING DESIGN unless stated otherwise.
9.1 Popup panel
Quick-glance + quick-act. Contents (per brief):
- Water: today's hydration state as reported by the server + the +250ml one-tap button.
- Caffeine: Caffeine Block status (blocked vs. clear, server countdown) + clean-caffeine log button.
- Pomodoro status: current Kinetic Pomodoro Engine state (work/break/satisfied) mirroring the badge.
- GERD timer: the 4-hour pre-sleep window countdown/state; alert styling on violation.
Active timers glow neon green #00FF33 in dark mode; active buttons #00CCFF (dark) / #0070A0 (light); alerts #FF3333. Layout and exact widget forms PENDING DESIGN.
9.2 Side panel mini-dashboard (Chrome Side Panel API)
- Human Node diagram — PENDING DESIGN. Referenced by the brief as the centerpiece visualization; its definition lives entirely in the design workstream. The plan reserves the top region of the side panel for it and treats it as a rendering of server-provided state (no local computation), but makes no assumption about its content or interactions.
- Today's protocol timeline: a chronological view of today's protocol events and windows (logs, blocks, windows opening/closing) as returned by the server. Which engines appear on the timeline beyond the four popup domains (e.g., Medication Grace) is an open product question (§12). Visual form PENDING DESIGN.
- Side panel opening behavior (on toolbar action click vs. only via menu) — decision open, coordinated with the popup's role.
9.3 Options page
- Account linkage: connect/disconnect the TOGO auth identity (§8).
- Notification preferences: which alerts (protocol alerts, Pomodoro Guard nudges, trigger-scan results) may use
chrome.notifications; stored server-side (§3.2) so preferences are consistent across all Health Debug clients, cached locally for display. - AI API key configuration (BYOK proxy settings): form for OpenAI / Anthropic / Google / Apple Intelligence keys and provider selection. Submission goes directly to the backend for encryption; the page must never write key material to any
chrome.storagearea, and the UI reflects only server-reported status ("a key is configured for provider X"), never the key itself. This is configuration of the server-side proxy, not of any client-side AI capability — the extension makes zero direct AI-provider calls.
10. Theming, i18n, Accessibility
- Palette: exactly the shared spec (§1 row 5). Dark mode uses glow effects; light mode is flat. Glow implementation technique in extension surfaces (small windows, GPU-cheap) is an implementation detail; visual intensity PENDING DESIGN.
- Theme source of truth: reuse Phase 2's theme engine tokens so web dashboard and extension cannot drift. Dark/light selection behavior (follow OS/browser vs. account-level preference) — decision open, should match whatever Phase 2 decides.
- i18n:
_locales-based catalogs generated from the shared ICU Message Format source used by Phase 2 (mechanism to be defined with Phase 2 — Chrome's nativemessages.jsonformat is not ICU, so the build step must bridge them). No string concatenation anywhere. Arabic:dir="rtl"on all three HTML surfaces, mirrored layout, mirrored progress/countdown bars. - Accessibility: keyboard operability of the one-tap actions and context-menu-equivalent flows; the red/green state signaling must have non-color redundancy (icon/text), since key states (alert vs. active timer) otherwise rely on hue alone. Specific a11y treatments PENDING DESIGN.
11. Security & Privacy Summary
- No AI provider keys on the client, ever (write-only submission to backend; server-side encryption; all AI calls proxied server-side).
- No content scripts, no page DOM access beyond
selectionTextexplicitly shared by the user via right-click. - Minimal permission set (§2.4); any expansion (notably for Pomodoro activity signals) requires an explicit tradeoff decision.
- Session token confined to
chrome.storage.local; full wipe on sign-out; single-flight background refresh. - Selected text sent to the trigger-scan endpoint is user-initiated per invocation; nothing is scanned passively.
- All requests to the ToGO origin over HTTPS with the session token; no third-party requests from the extension at all.
12. Open Decisions & PENDING DESIGN Register
Blocked on UI design (Figma / design workstream):
- Human Node diagram — entire definition (side panel centerpiece).
- Popup layout, widget forms, button states, glow intensity.
- Side panel protocol-timeline visual form.
- Badge glyph/text formats and color-state assignments; full icon asset set including the red bug icon.
- Trigger Scanner result surface (notification vs. side panel view) and result presentation, including "Consult your doctor" deferral placement/copy.
- Pomodoro Guard interception aggressiveness and surface combination (notification / auto-open side panel / break page).
- Context menu label copy (en + ar).
- Signed-out and stale-data visual treatments; a11y treatments.
Blocked on Phase 1 (backend/API contract):
- Final endpoint names/shapes for snapshot, logging intents, trigger scan, pomodoro events, BYOK submission, notification prefs (all paths in §3.2 are indicative).
- TOGO auth token model (lifetimes, refresh semantics) and the extension account-linkage flow.
- Production API origin for
host_permissions. - Whether trigger scanning uses pure taxonomy lookup or the BYOK AI proxy server-side.
- Poll-only vs. optional push channel for countdown updates.
Product decisions (not defined in spec — do not implement without a ruling):
- Badge priority ordering when multiple protocol states are simultaneously active.
- Whether GERD-window-permitted items beyond water (chamomile, anise) get quick-log buttons in the extension.
- Which engines appear on the side-panel timeline (e.g., Medication Grace; fertility/contraceptive engines are assumed out of extension scope per the brief).
- Pomodoro activity-signal mechanism (
chrome.idlevs. tab events) and the associated permission tradeoff. - Popup vs. side panel division of labor for the toolbar click; poll cadence tuning within the
chrome.alarmsplatform floor. - UI rendering stack for the three surfaces (default assumption: reuse Phase 2 React + TanStack + theme/i18n engine).
13. Phase 3 Milestones (Sequencing Within the Phase)
| # | Milestone | Exit criterion |
|---|---|---|
| 1 | Extension scaffold + manifest + CI packaging | Loads unpacked; empty surfaces render with theme tokens in both modes and both locales (RTL verified). |
| 2 | Auth + storage + background refresh | Account linked via TOGO auth; token survives worker restarts; refresh single-flight verified. |
| 3 | Poller + badge engine | Badge mirrors server snapshot across worker terminations; stale/signed-out handling. |
| 4 | 1-click logging (water, caffeine) | Intents round-trip; server rejections (cooldown, block) rendered verbatim; post-write re-fetch. |
| 5 | Popup panel | All four status domains live (water, caffeine, pomodoro, GERD) — gated on design delivery. |
| 6 | Pomodoro Guard | Badge work/break states + activity sensor events + chosen interception surfaces. |
| 7 | Trigger Scanner | Context-menu → scan → categorical result surface, en + ar. |
| 8 | Side panel | Timeline + Human Node diagram — gated on design delivery. |
| 9 | Options page | Linkage, notification prefs, BYOK write-only flow verified (no key material client-side). |
| 10 | Store readiness | Permission audit, privacy disclosures, listing assets (PENDING DESIGN), Chrome Web Store submission. |
End of Phase 3 plan. Predecessors: 04-* (Phase 1 backend), 05-* (Phase 2 web dashboard) planning documents govern every contract this document marks as indicative.