Skip to content

feat(browser): Browser-8 — per-site trust relax for login-gated SPAs (x.com)#139

Merged
th3-br41n merged 2 commits into
mainfrom
feat/browser-per-site-relax
Jul 11, 2026
Merged

feat(browser): Browser-8 — per-site trust relax for login-gated SPAs (x.com)#139
th3-br41n merged 2 commits into
mainfrom
feat/browser-per-site-relax

Conversation

@th3-br41n

Copy link
Copy Markdown
Contributor

The problem

Login-gated SPAs (x.com and similar) are unusable in the in-app Browser: the strict privacy default — third-party-cookie block + tracker blocklist — breaks their SSO and scripts (flow/viewer.json 403, ERR_BLOCKED_BY_CLIENT). There was no per-site escape hatch (site-permissions only does device perms).

The approach (as decided)

Keep the strict default; add a per-site opt-in TRUST ("compatibility mode"). Trusting an origin relaxes the blocklist + third-party-cookie strip only for pages whose first party is that origin. Never softens the global default — it's opt-in, per site.

Slice 1 — core (store + runtime + enforcement)

  • site-trust.tsSiteTrustStore (mirrors site-permissions): strict by default, sync isTrusted(origin) for the webRequest glue, only trusted:true rows persist (untrust deletes). Per-vault web-site-trust.json.
  • web-privacy-runtime.ts — a third vault-scoped store; load + persist + re-key on vault switch, fail-closed strict with no vault.
  • web-view-factory.ts — a trustedFirstParty(details) check keyed on the tab's top-level origin (never the request URL); a trusted first party skips the blocklist cancel and the 3p-cookie strip. isTrustedOrigin wired from the runtime.

Slice 2 — management UI

  • web-privacy:site-trust:{list,set,revoke} privileged IPC (set canonicalizes + validates the origin) + preload webPrivacy.trust.*.
  • Settings → Privacy → Trusted sites: add-origin form (x.comhttps://x.com, inline invalid hint) + trusted list with per-origin remove. Shared <Button>; input shares the control height.

Verification

117 web tests green (22 new: store parse/CRUD + runtime load/persist/re-key), typecheck (packages) + full lint (biome/reactivity/control-faces/css-tokens/i18n) clean.

Follow-up (not in this PR)

An in-browser "Trust this site" affordance in the Browser chrome (one click when a site is failing) — app-side UI, best verified with a running shell. Settings management here already makes the feature fully usable; repro-pinning x.com under a real shell confirms the cookie-block was the decisive restriction.

🤖 Generated with Claude Code

th3-br41n and others added 2 commits July 11, 2026 20:31
…e + enforcement)

Login-gated SPAs (x.com etc.) are unusable in the Browser app: the strict
default (third-party-cookie block + tracker blocklist) breaks their SSO +
scripts. Fix per the decided approach — keep the strict default, add a per-site
opt-in TRUST ("compatibility mode") that relaxes both for pages whose FIRST
PARTY is the trusted origin. Never softens the global default.

- `site-trust.ts` — `SiteTrustStore` (mirrors `site-permissions`): strict by
  default, `isTrusted(origin)` sync for the webRequest glue, only `trusted:true`
  rows persist (untrust deletes). Per-vault `web-site-trust.json`.
- `web-privacy-runtime.ts` — a third vault-scoped store alongside permissions +
  egress; `trust.isTrusted/set/revokeOrigin/list`, load + persist + re-key on
  vault switch (fail-closed strict with no vault).
- `web-view-factory.ts` — a `trustedFirstParty(details)` check keyed on the
  tab's top-level origin (never the request URL); a trusted first party skips
  the blocklist cancel AND the 3p-cookie strip. `isTrustedOrigin` dep wired from
  the runtime in `main/index.ts`.

17 tests (store parse/CRUD + runtime load/persist/re-key). typecheck + lint green.
Remaining (Slice 2): IPC handlers + Settings → Privacy trusted-sites management.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Slice 2: the management surface over the Browser-8 trust store.

- `web-privacy-handlers.ts` — `web-privacy:site-trust:{list,set,revoke}` privileged
  IPC (dashboard-bound, never the broker). `set` canonicalizes + validates the
  origin via `webOriginOf` (bare host / non-http(s) → no-op), so only a real web
  origin is ever stored.
- preload — `webPrivacy.trust.{list,set,revoke}`.
- `browser-privacy-panel.tsx` — a "Trusted sites" group: an add-origin form
  (`x.com` → `https://x.com`, inline invalid hint) + the trusted list with a
  per-origin remove, between site-permissions and egress. Uses the shared
  `<Button>`; input shares `--control-height-sm` with it. + en.json strings.

typecheck + full lint (biome/reactivity/control-faces/css-tokens/i18n) green.
@th3-br41n th3-br41n merged commit 84ec66a into main Jul 11, 2026
2 of 3 checks passed
@th3-br41n th3-br41n deleted the feat/browser-per-site-relax branch July 11, 2026 20:07
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.

1 participant