feat(extension): local verification via browser-client + auto-verify + http dev support#1
Merged
Merged
Conversation
Production HTMLTrust deployments use HTTPS by convention but the protocol itself is transport-agnostic. The local dev simulation harness and on-machine test pages run plain HTTP, so the extension currently can't verify them. Add "http://*/*" alongside the existing "https://*/*" pattern in chromium, firefox, and safari manifests with an explanatory comment field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…o-run on page load Replace server-mediated verification (deprecated /api/content/verify endpoint) with local SubtleCrypto verification using the shared @htmltrust/browser-client library, per spec §3.1. Verification now runs automatically on every page load with no popup interaction required. Changes: - Add @htmltrust/browser-client dependency (file: link to local reference impl). Pull @htmltrust/canonicalization in via the same file: pattern so the peer dep matches versions exactly. - Content script (content-scripts/index.ts): walks every <signed-section[signature]> on DOMContentLoaded, calls verifySignedSection (Layer 1) + evaluateTrustPolicy (Layer 2), injects inline trust badges next to each section. Visual style matches the e2e harness for screenshot consistency. Idempotent (skips sections that already have a badge sibling). Pages without signed-sections are a graceful no-op. - Background script (background/index.ts): popup's "Verify Content" command now runs verifySignedSection in the service worker context (HTML fragment passed via executeScript) instead of POSTing to the trust server. Best-effort author name lookup is preserved. - Content signing API client (core/api/content-signing-client.ts): verifyContent() is now a deprecated shim that returns a clear failure pointing callers at verifySignedSectionLocal(). The class also owns the resolver chain and exposes setTrustDirectories() so the directory list can be live-updated when settings change. - Pluggable keyid resolution: the resolver chain (defaultResolverChain → did:web → direct URL → trust directories) is built from extension settings and passed through to the lib in both the content script and background. Settings UI exposes a list of directory URLs (textarea, one per line); the legacy single-URL setting still works via getTrustDirectoryUrls() normalization. - Settings (core/common/types.ts, constants.ts, ui/options): add trustDirectoryUrls (list), personalTrustList, and trustedDomains. These feed evaluateTrustPolicy directly. The legacy trustDirectoryUrl scalar is preserved for back-compat with persisted settings. - Webpack config: IgnorePlugin for node:crypto so the canonicalization lib's Node-only code path doesn't break the browser bundle. Build: npm run build produces all three browser targets (chromium, firefox, safari) cleanly. typecheck (tsc --noEmit) passes. The Jest suite has zero test files and is missing jest-environment-jsdom; both are pre-existing P1 items in TODO-Cleanup.md and out of scope. Note on trust policy directorySubscriptions: passed empty for now, mirroring the e2e harness TODO. The lib's reputation URL shape (<dir>/keys/<keyid>/reputation) doesn't yet match the trust server's endpoint; will be wired once the server exposes the spec-compliant shape. Note on dependency path: package.json uses "file:../../htmltrust-browser-client" (two segments up) because this work happens in a git worktree at .worktrees/browser-ext/. From the main repo root the equivalent path is "file:../htmltrust-browser-client". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the four P0 browser-extension items from
TODO-Cleanup.md:/api/content/verifyendpoint withverifySignedSectionfrom@htmltrust/browser-client, which uses SubtleCrypto and runs entirely in the extension. The trust server is no longer contacted for verification.<signed-section[signature]>onDOMContentLoaded, verifies it locally, evaluates the trust policy, and injects inline trust badges next to each section. No popup interaction required. Pages without signed-sections are a graceful no-op.defaultResolverChainfrom the lib (did:web → direct URL → trust directories). The directory list is configurable in extension settings."http://*/*"alongside"https://*/*"in chromium, firefox, and safari manifests so the e2e simulation harness and local dev servers (which run plain HTTP) work. Production deployments are HTTPS by convention but the protocol is transport-agnostic; the comment fields in each manifest spell this out.Architecture
verifySignedSectionfrom@htmltrust/browser-client, called from both:verifyContent()(with the section's outerHTML, run in the service worker context).evaluateTrustPolicyfrom the lib. Inputs come from settings:personalTrustList,trustedDomains,directorySubscriptions(empty for now, matching the e2e harness TODO; the trust server doesn't yet expose the spec's<dir>/keys/<keyid>/reputationshape).defaultResolverChain({ directories })built from the user's configured trust-directory list.Settings changes (back-compat preserved)
trustDirectoryUrls: string[],personalTrustList: string[],trustedDomains: string[].trustDirectoryUrl: stringis preserved on read viagetTrustDirectoryUrls(settings)which normalizes to a list.Build / typecheck
npm run build(chromium + firefox + safari) compiles clean.npx tsc --noEmitpasses.IgnorePluginfornode:cryptoso the canonicalization lib's Node-only code path doesn't break browser bundles.jest-environment-jsdom. Out of scope (P1 in TODO-Cleanup.md).Deviations
"file:../htmltrust-browser-client"for the dep path. Because this work runs in a git worktree at.worktrees/browser-ext/, the actual relative path is"file:../../htmltrust-browser-client". If the PR is rebased back into the main repo's package.json (out of worktree), this should be normalized to../.Test plan
npm install && npm run build:chromiumproducesbuild/chromium/cleanly.build/chromium/as an unpacked extension in Chrome (chrome://extensions → Developer mode → Load unpacked).<signed-section signature="...">element. Confirm trust badges appear inline below the signed section without clicking the popup./api/content/verifyendpoint).http://page with a signed section. Confirm the extension can inspect it (host_permissions).https://page. Confirm the extension still works (no regression)./api/content/verifyare made during normal browsing.🤖 Generated with Claude Code