CMP v1 — Issue Bundle (Portal + Scanner + Drop-in)
This bundle captures 7 parallelizable tickets derived from UX_REQUIREMENTS.md. Each ticket lists scope, dependencies, and Definition of Done (DoD). Replace Owner with a specific engineer.
Global DoR (all tickets)
- API endpoints listed with method/signature and error codes
- UX wire or screenshot and acceptance criteria
- Perf and a11y notes captured
- Owner and estimate tagged
Global DoD (all tickets)
- Unit and E2E tests (happy + edge)
- Axe-core pass for impacted pages
- Docs updated (README/ops playbook)
- Metrics/alerts wired if applicable
CMP-001: Analytics — Cookies Tab v1
- Goal: Operator can see cookie activity and consent outcomes per site/time window.
- Summary: Implement Cookies analytics tab with filters, review queue, all-cookies table, and rollups (time buckets, GPC, region, consent states).
- Owner: TBD (Frontend)
- Labels: front-end, analytics, P1
- Enhancements:
- UX: AntD Tabs → "Overview | Cookies | Vendors"; stacked bar for accept vs reject; table includes CSV export.
- Dimensions/filters: time bucket (hour/day), GPC, region (EEA/non-EEA), consentState (accept/reject/partial), category (strict/functional/analytics/ads), search, min-confidence, unknown-only.
- Metrics: total sessions, prompt rate, accept/reject/partial %, GPC rate, pre-consent block rate, top-10 cookies by set count, top vendors.
- Header filters: range (7d/30d/custom), party, category, unknown-only, min confidence, search, refresh.
- Review queue (left): top 50 unknown/low-confidence; actions: Accept as Definition, Override (this site).
- All cookies (right): table with party, vendor, category, retention, flags, count, last seen; sorting by category then count.
- Empty states; toasts; optimistic updates.
- Out of Scope (v1.1): evidence drawer, bulk accept, virtualized rows.
- API dependencies:
- GET
/api/admin/analytics/sites/by-key/:siteKey/cookieswith filters (200; 404 unknown site; 400 invalid query). - GET
/api/admin/analytics/sites/by-key/:siteKey/cookies/rollup?from=&to=&bucket=hour|day&gpc=0|1®ion=eea|non-eea&state=accept|reject|partial&category=...- Returns:
{ buckets:[{t, sessions, promptRate, acceptPct, rejectPct, partialPct, gpcPct, preConsentBlockRate}], topCookies:[...], topVendors:[...] } - Errors: 404 unknown site; 400 invalid params.
- Returns:
- POST
/api/admin/cookies/definitions:batch(global accept). - POST
/api/admin/cookies/overrides(site override).
- GET
- A11y/RTL:
- Labeled controls; keyboard nav; visible focus; RTL when locale starts with
ar.
- Labeled controls; keyboard nav; visible focus; RTL when locale starts with
- Performance:
- Table render < 400ms P95 for 500 rows; 95th percentile rollup query < 800ms @ 10M events (hourly pre-aggregate recommended).
- Security:
- Never show cookie values; admin ops gated by
cmp.admintoken.
- Never show cookie values; admin ops gated by
- DoD:
- Filters apply server-side; review actions persist and refresh list; CSV export matches table state (if included).
- Unknown-only and min-confidence work as expected.
- No console errors; toasts on success/error; includes “Copy cURL” on error where possible.
- Axe: no critical violations; RTL validated.
- Docs updated in
docs/cmp/portal.md(Cookies tab section). - Data shape uses rollup view or job over
ConsentEvent(siteId, ts, gpc, state, categories); hourly buckets pre-aggregated for 30/90d windows.
CMP-002: Public Scanner Page v1
- Goal: Actionable, reproducible scans for any URL (GPC on/off) with artifacts.
- Summary: Run scans, display results, show artifacts, history with baselines and deltas.
- Owner: TBD (Frontend)
- Labels: front-end, scanner, P1
- Scope:
- Run: URL + toggles (GPC, Screenshot, Trace, Wait ms); disable button while running.
- Results: Pre vs Post cards (#cookies, #3P hosts); Violations card when non-essential detected pre-consent. Baseline vs current deltas: Δ tags for headers/cookies/3P.
- Artifacts: JSON download, screenshot preview, trace link; Copy cURL including flags and optional
--site-key. - History: rows with when/URL/new3P/newCookies; sparkline of last 10 scans; baseline marker; actions Re-run with same flags, View artifacts, Promote as baseline.
- Out of Scope (v1.1): Pin as baseline.
- API dependencies:
- POST
/scan(scanner service) and artifact fetch URLs (200 on success; 400 invalid URL; 500 scan failure). - GET
/health,/health/readyfor status. - GET
/v1/scans?topDomain=…&take=10(public) for sparkline inputs. - POST
/api/admin/scans/:id/baseline(promote) — 200 ok; 401/403 unauthorized; 404 unknown id.
- POST
- A11y/Perf:
- Focus management during run; skeletons/spinners.
- Route TTI < 1.5s P95.
- DoD:
- Re-scan action restores flags; permalink carries gpc/screenshot/trace.
- Δ computed client-side from
/v1/scans?topDomain=…; baseline stored per host (localStorage) with server fallback when available. - Artifacts downloadable; History persists across refresh; actions functional.
- Error states show inline message + toast with Copy cURL.
- Docs updated in
docs/cmp/public-scanner.md. - Sparkline visible for last 10 runs; neutral theme.
Subtasks (split & ship)
- Compute Δ vs last baseline (localStorage; fallback to
/v1/scans?baseline=1when API available). - Show Δ chips for headers/cookies/3P; add sparkline for last 10 new3p.
- “Promote baseline” button → POST
/api/admin/scans/:id/baseline.
CMP-003: Overrides Admin — Cookies CRUD + CSV
- Goal: Classify/override cookie → category/vendor; export/import at scale.
- Summary: Manage cookie overrides (site/global) with list, edit modal, bulk ops, and CSV import/export.
- Owner: TBD (Frontend)
- Labels: front-end, admin, P1
- Scope:
- Tables: domain → observed cookies (name, first/third-party, prevalence, firstSeen/lastSeen).
- List view: filters (site/global, name/domain, category), audit columns, edit/delete actions; confirm modal on destructive.
- Edit modal: category, vendor, purpose, retention, reason (audit); optimistic save.
- Bulk ops: select many → set category.
- CSV import with preview & conflict resolution; export (UTF-8; safe columns only).
- API dependencies:
- GET
/api/admin/cookies/overrides:list(200 paginated; 400 invalid query). - POST
/api/admin/cookies/overrides(201 create; 400 invalid; 409 duplicate). - PUT
/api/admin/cookies/overrides/:id(200 update; 404 missing). - DELETE
/api/admin/cookies/overrides/:id(204; 404 missing). - POST
/api/admin/cookies/overrides:import(202 accepted; returns job id; 400 invalid CSV). - GET
/api/admin/cookies/overrides:export?...(200 stream; 404 unknown site when scoped).
- GET
- A11y/Perf:
- Keyboard-accessible modal; labeled fields; validation messages.
- DoD:
- Schema enum for
category; server validates unknown vendors. - Overrides CRUD functional; audit
createdBy/updatedBycaptured; toasts on success. - Round-trip export→edit→import matches row counts.
- Docs updated in
docs/cmp/registry.md(overrides section).
- Schema enum for
CMP-004: Sites & Config UX — Panels and Actions
- Goal: Clear navigation, safe actions, copy-ready snippets.
- Summary: Enhance Sites and Config per spec (Localization & Policy, Vendors, Publish, Compliance Mode; Allowed Origins; Copy Snippet; Rotate Key).
- Owner: TBD (Frontend)
- Labels: front-end, config, P1
- Scope:
- Config panels: Localization & Policy (policy details per category), Vendors (suggest → add, CSV import), Publish (note + diff preview), Compliance Mode note/flag.
- Sites list: copy snippet (shows
data-site-keyanddata-cookie-domain, SRI if available), rotate key confirmation with immediate row update. - Allowed Origins table with add/remove; guard legacy domain; “Copy primary → domains”.
- IA/routes:
/sites,/sites/:key,/sites/:key/config,/scanner; 404 redirects to/sites. - Context: sticky header with env tag + tenant switcher (when claim present).
- API dependencies:
- Existing Sites/Config endpoints; CSV import for vendors if applicable.
- A11y/Perf:
- Forms with labeled inputs and inline errors; optimistic updates.
- DoD:
- Publish flow updates live version; diff shown when cheap.
- Copy snippet and rotate key actions work and update UI.
- Allowed origins CRUD with guard; toasts on success.
- Deep links work; perms enforced by JWT; alerts replaced by toasts.
- Docs updated in
docs/cmp/portal.md(Sites/Config sections).
Subtasks (split & ship)
- Add routes and navigation; SitesPage with AntD Table + Search + Pagination.
- Rotate key confirm + success toast; Copy snippet/verify with optional integrity.
CMP-005: Exports — Consents CSV/JSON/JSONL
- Goal: Operator can export large windows without memory spikes.
- Summary: Deliver consents export UI with formats and filters; server streams results.
- Owner: TBD (Full-stack)
- Labels: front-end, back-end, export, P1
- Scope:
- UI: format selector (CSV/JSON/JSONL); filters for date range, region, GPC.
- Backend: stream JSONL with back-pressure; CSV via streaming transformer; region/GPC filters.
- Security:
- Gate with
cmp.admin; include audit log of who/when downloaded.
- Gate with
- Performance:
- Streamed downloads; avoid timeouts for large date ranges; constant RSS at 10M rows JSONL; client pauses/resumes via HTTP.
- DoD:
- Export modal with progress indicator; link to artifact when ready.
- Exports download in all formats; filters applied correctly; file name includes siteKey + range + gpc flag.
- Sample validation of JSONL line count vs query window.
- Docs updated in
docs/cmp/portal.md(Export) and API docs if applicable.
CMP-006: Accessibility & RTL — WCAG 2.1 AA Pass
- Goal: Banner/Dialog/Portal pass axe-core + keyboard flows; RTL correct.
- Summary: Ensure portal and consent banner/dialog meet accessibility and RTL requirements.
- Owner: TBD (Frontend + QA)
- Labels: accessibility, qa, P1
- Scope:
- Banner/Dialog: role=dialog, aria-labelledby/aria-describedby, focus trap, Escape closes, equal prominence Accept/Reject.
- Focus mgmt: return focus to invoker; aria-live for toasts.
- Forms: labeled controls, keyboard navigation, visible focus; color contrast ≥ 4.5:1; check AntD theme tokens.
- RTL: dir="rtl" auto when
ui.strings.localestarts withar; verify components mirror.
- DoD:
- Axe: 0 critical/serious violations portal-wide and on banner/dialog.
- Keyboard E2E covers open→navigate→save→close; focus returns.
- Arabic copy reviewed; numerals legible; screenshots attached.
CMP-007: Telemetry & Performance Budgets
- Goal: SLOs and alarms that catch real regressions.
- Summary: Instrument key events and enforce performance budgets across routes.
- Owner: TBD (Full-stack)
- Labels: telemetry, performance, P2
- Scope:
- Budgets: p95
/v1/config< 250 ms, p99 < 600 ms; 429 ratio < 1%; dataset freshness < 48h; scanner 0 new pre-consent hosts. - Dashboards: Prometheus/Grafana panels; alerts for budget violations, dataset stale, scanner API not ready.
- Portal events: publish duration, override added, definition accepted, domain added, export download, scanner run.
- Scanner CI: pass/fail, artifact size, run time (emit to metrics). Optional RUM: portal TTI and route-to-first-paint.
- Budgets: p95
- DoD:
- Alerts fire in staging with injected faults; Grafana board linked in README.
- Metrics emitted to Prometheus/OTEL; dashboards/screenshots attached.
- Budget regressions flagged in CI or console warnings in dev.
Notes
- Cross-reference: see
docs/cmp/UX_REQUIREMENTS.mdfor full context and v1.1 backlog. - Consider adding labels:
good-first-issuefor small sub-tasks that spin out from these epics.
Milestone and Priority
- v1.0 (2–3 weeks):
- CMP-004 Sites & Config UX
- CMP-002 Public Scanner v1 (Δ + sparkline)
- CMP-003 Overrides Admin
- CMP-005 Exports
- CMP-001 Analytics (Cookies Tab)
- CMP-006 A11y & RTL (gates release)
- CMP-007 Telemetry & Budgets