Skip to content

World-class hardening: enforce type-checking, clear CVEs, tighten permissions, polish editor#2

Merged
DCCA merged 8 commits into
mainfrom
claude/exciting-mccarthy-l225ql
Jun 20, 2026
Merged

World-class hardening: enforce type-checking, clear CVEs, tighten permissions, polish editor#2
DCCA merged 8 commits into
mainfrom
claude/exciting-mccarthy-l225ql

Conversation

@DCCA

@DCCA DCCA commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Summary

A full review-driven hardening sweep across four workstreams. Every commit is verified against the new gates (typecheck + lint + format + tests + build), and the final state passes npm ci with 0 vulnerabilities.

See .docs/done/2026-06-20-world-class-hardening/ for the full proposal/spec/design/tasks/completion-summary.

1 · Dependency security

  • Upgraded Vite 5→8, Vitest 2→4, @vitejs/plugin-react 4→6, TypeScript→5.9; refreshed @types/chrome; added @types/node.
  • npm audit: 10 advisories (1 critical, 3 high, 5 moderate, 1 low) → 0.

2 · Foundational hardening

  • Type-checking was silently broken and unenforced (tsc failed; CI only ran test+build via esbuild). Restored it and fixed the failing cases.
  • Added ESLint (flat config) + Prettier. CI now gates on typecheck, lint, format:check, test, build, and npm audit --audit-level=high; Node bumped to 22; added .nvmrc + engines.
  • Fixed a real bug: editor arrow-heads rendered in the page's default text color instead of the arrow color.
  • Hardened download(); extracted pure helpers to src/lib/feedback.ts. Tests 17 → 26 (LLM prompt, box-handle geometry, binary base64 round-trip).

3 · Permission tightening

  • Removed the unused web_accessible_resources block (exposed assets/* to every site — a fingerprinting vector with no functional use).
  • Documented every permission's rationale and the local-only data posture in SECURITY.md + README.md.

4 · Polish & features

  • Real extension icons (16/32/48/128) via a reproducible, dependency-free generator.
  • Editor keyboard shortcuts (Esc deselect / Delete remove).
  • "Saved Shares" panel (list / open / delete).
  • Doc cleanup: fixed stale CONTRIBUTING reference, archived completed change folders, synced TODOs.

Verification

  • npm run check (typecheck + lint + test + build) and npm run format:check pass.
  • 26/26 tests; npm ci clean; 0 audit advisories.

Deferred (cannot run in CI)

  • Manual in-browser QA of capture/annotate/share flows.
  • host_permissions: <all_urls> and static content-script registration kept by design (general screenshot tool needs broad capture access); on-demand-only injection tracked in next-improvements.md.
  • Editor integration-style tests (coverage is unit-level on pure logic).

🤖 Generated with Claude Code

https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W


Generated by Claude Code

claude added 8 commits June 20, 2026 15:46
Upgrade Vite 5→8, Vitest 2→4, @vitejs/plugin-react 4→6, TypeScript to
5.9, and refresh @types/chrome; add @types/node. Clean reinstall resolves
all 10 prior advisories (1 critical, 3 high, 5 moderate, 1 low) to zero.

Tests (17/17) and build verified on the new toolchain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
Type-checking was silently broken (tsc failed; CI only ran test+build via
esbuild, which skips type-checking). Restore it and enforce quality gates:

- tsconfig: add node types, stricter flags, skipLibCheck; tsc --noEmit
  now passes (fixed illegal `chrome`-as-type casts in the storage test).
- ESLint flat config (typescript-eslint + react-hooks) + Prettier; convert
  empty shadcn interfaces to type aliases to satisfy lint.
- Apply a one-time Prettier pass to source and top-level docs.
- CI now runs typecheck, lint, format:check, test, build, and
  `npm audit --audit-level=high`; bump CI Node to 22, add .nvmrc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
…ck helpers

- Editor arrow-head markers filled with currentColor but the line never
  set color, so heads rendered in the page's default text color instead of
  the arrow color. Set color on the line so the head matches.
- download() now mirrors the other export actions: capture-required guard,
  try/catch, and success/error status messaging.
- Extract buildExternalLlmPrompt and annotationSummary into src/lib/feedback.ts
  (pure, now unit tested).
- Add tests for the LLM prompt builder, box-handle geometry/cursors, and a
  binary base64 round-trip through local-share storage (17 → 26 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
The manifest exposed assets/* to <all_urls> via web_accessible_resources,
but nothing loads those from a foreign origin: the content script injects no
extension resources into pages, and the editor/viewer load their assets as
same-origin extension pages. Removing the block eliminates an
extension-fingerprinting vector with no functional impact (verified the dist
manifest and build).

Also document the rationale for every remaining permission (and the
local-only data posture) in SECURITY.md, and add a Permissions & Privacy
section plus the new dev-command scripts to the README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
The extension shipped with no icon (default puzzle piece). Add a camera
mark in the app's emerald theme at 16/32/48/128 and wire it into the
manifest (icons + action.default_icon).

Icons are generated by scripts/generate-icons.mjs (pure Node + zlib, no
image deps) so they are reproducible in CI via `npm run gen:icons`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
- Esc clears the current selection and any in-progress draw/drag/resize;
  Delete/Backspace removes the selected annotation (ignored while typing in
  a field so comment editing is unaffected). Surface the hints in the help text.
- Add a 'Saved Shares' panel that lists persisted local shares (page, time,
  size) with open/delete actions, backed by the existing listLocalShares /
  deleteLocalShare APIs. Refreshes on mount and after creating a share.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
… changes

- CONTRIBUTING referenced a non-existent .docs/doing/current-task.md; replace
  with the FIREHOSE per-change folder workflow and the new quality gates.
- Sync next-improvements and the dated priority TODO with what the hardening
  sweep resolved (deps, permissions docs, tests) and what remains (manual QA,
  editor integration tests).
- Archive completed change folders to .docs/done/: box-resize,
  firehose-compliance-alignment, and world-class-hardening (each with a
  completion summary).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
- engines.node: align floor with Vite 8's supported range
  (^20.19.0 || >=22.12.0) so Node 21/23 don't satisfy engines while
  Vite 8 rejects them.
- design.md: correct the permissions note to reflect that
  web_accessible_resources was removed entirely (not narrowed); extension
  pages load their own assets as same-origin resources.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJ5c2e5VcKVhugy7TAzi4W
@DCCA DCCA merged commit 1b2ca76 into main Jun 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants