docs(todos): mark shipped items + file shield polling follow-up

Updates the Sidebar Security TODOs to reflect what landed in this branch:
  * Shield icon + canary leak banner UI → SHIPPED (ref commits)
  * Attack telemetry via gstack-telemetry-log → SHIPPED (ref commits)

Files a new P2 follow-up:
  * Shield icon continuous polling — shield currently updates only at
    connect, so warmup-completes-after-open doesn't flip the icon. Known
    v1 limitation.

Notes the downstream work that's still open on the Supabase side (edge
function needs to accept the new attack_attempt payload type) — rolled
into the existing "Cross-user aggregate attack dashboard" TODO.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-04-19 19:21:37 +08:00
parent 59e0635eb5
commit c9a124d094
+35 -26
View File
@@ -223,41 +223,50 @@ defend the compiled-side ingress.
### ML Prompt Injection Classifier — v2 Follow-ups
#### Shield icon + canary leak banner UI (P0)
#### ~~Shield icon + canary leak banner UI (P0)~~ — SHIPPED
**What:** Render the security state in the sidepanel: shield icon (green/yellow/red) in the
header, and the approved canary leak banner when the agent emits `security_event` (variant A
mockup at `~/.gstack/projects/garrytan-gstack/designs/prompt-injection-canary-banner-20260419/variant-A.png`).
Banner landed in commits a9f702a7 (HTML+CSS, variant A mockup) + ffb064af
(JS wiring + security_event routing + a11y + Escape-to-dismiss). Shield
icon landed in 59e0635e with 3 states (protected/degraded/inactive),
custom SVG + mono SEC label per design review Pass 7, hover tooltip with
per-layer detail.
**Why:** The backend plumbing landed in v1 (`/health` returns security status; agent emits
security_event). Without the UI, the user never sees when the layer fires. Trust UX is
load-bearing here.
Known v1 limitation logged as follow-up: shield only updates at connect —
see "Shield icon continuous polling" above.
**Context:** Design spec in ceo-plan §"Design Review Additions 2026-04-19". Need to edit
`extension/sidepanel.html` + `sidepanel.js` + `sidepanel.css`. Respect DESIGN.md tokens
(amber #F59E0B primary, zinc neutrals, Satoshi/DM Sans/JetBrains Mono).
#### Shield icon continuous polling (P2)
**Effort:** M (human: ~1d / CC: ~2h)
**Priority:** P0
**Depends on:** v1 shipped on `garrytan/prompt-injection-guard`
**What:** Extend the sidepanel's `/sidebar-chat` polling loop to refresh the
`security` field so the shield icon reflects classifier warmup completion
in real-time. Currently the shield only updates at connection bootstrap —
if ML classifier warmup finishes 30s later (first run downloads 112MB), the
user has to reload the sidepanel to see the state flip from amber to green.
#### Attack telemetry via gstack-telemetry-log (P1)
**Why:** First-run UX. The shield is a trust signal — stale data undermines
it. User thinks "classifier never came up" when it actually warmed 45s ago.
**What:** Extend `~/.claude/skills/gstack/bin/gstack-telemetry-log` with an `attack_attempt`
event type. New flags: `--event-type attack_attempt --url-domain --payload-hash
--confidence --layer --verdict`. Existing `community`/`anonymous`/`off` tier gating
applies automatically.
**Context:** `server.ts`'s `/health` endpoint already returns `security: getStatus()`.
Two implementation options:
1. Add `security` to the `/sidebar-chat` response (piggyback on the 300ms poll)
2. Separate 10s poll of `/health` just for shield state
Option 1 is simpler (no new endpoint hits). Option 2 isolates concerns. Pick
after real-world usage tells us if 300ms is too fast or 10s is too slow.
**Why:** Local `~/.gstack/security/attempts.jsonl` is write-only. Piggybacking on existing
telemetry pipe (gstack-telemetry-log → community-pulse edge function → Supabase) means NO
new SDK, NO new auth, NO new migration. Closes the "attacks in the wild" feedback loop.
**Effort:** S (human: ~2h / CC: ~20min)
**Priority:** P2
**Depends on:** v1 shipped
**Context:** See ceo-plan §"E6 Telemetry Write Path — RESOLVED". Client POSTs the new
event type; community-pulse edge function stores in a generic `analytics_events.payload jsonb`
column. Typed `security_attempts` table + dashboard is a separate follow-up.
#### ~~Attack telemetry via gstack-telemetry-log (P1)~~ — SHIPPED
**Effort:** S (human: ~1d / CC: ~1h)
**Priority:** P1
Landed in commits 28ce883c (binary) + f68fa4a9 (security.ts wiring). The
telemetry binary now accepts `--event-type attack_attempt --url-domain
--payload-hash --confidence --layer --verdict`. `logAttempt()` spawns the
binary fire-and-forget. Existing tier gating carries the events.
Downstream follow-up still open: update the `community-pulse` Supabase edge
function to accept the new event type and store in a typed `security_attempts`
table. Dashboard read path is a separate TODO ("Cross-user aggregate attack
dashboard" below).
#### Full BrowseSafe-Bench at gate tier (P2)