* fix(browser): restore the Chrome-shaped browser identity (STA-7147) #18749 replaced every browser partition's Chrome-shaped UA with Electron's stock one, so since v1.4.198 the embedded browser announces itself on every non-Google host as: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Orca/1.4.198 Chrome/150.0.7871.224 Electron/43.4.1 Safari/537.36 No browser sends that. Sites that re-check the identity holding a session reject it: users report being signed out of x.com, LinkedIn and "most websites," and at least one was signed out of LinkedIn in their own Chrome and met LinkedIn's "suspicious activity" SMS check -- server-side revocation, which reaches beyond our app. The repo already documented the mechanism in browser-google-auth-ua.ts: copied-in cookies "sent under a UA that doesn't match a real first-party browser get flagged by anti-fraud." That is why the Google auth-host switch exists; #18749 kept it for accounts.google.com and handed every other host an Electron identity. Restore the pre-#18749 session identity: strip the Electron and app tokens, and rewrite sec-ch-ua to match. Nothing in the cookie-import write path changed -- it never did; cookies were always written correctly and servers were refusing them. Deliberately KEPT from #18749, all independent of the UA: - anti-detection.ts stays deleted. Its premises were measured false on Electron 43 and its overrides are themselves published bot signatures. - No Runtime.enable into cross-origin iframes (the documented Cloudflare CDP tell). - No unconditional CDP debugger attach on every browsing guest. Known tradeoff, measured: this re-opens #13822. On the unmerged predecessor branch brennan/sta-3905-cloudflare-ua, commit 9f0a4772fe recorded the stock UA clearing dash.cloudflare.com 5/5 while every rewritten variant failed 12/12, and noted that adding client hints does not rescue it. So Cloudflare-gated sites will show verification failures again until a coherent-identity fix lands. That is a bounded, in-app annoyance; session revocation damages users' real accounts. A CDP Emulation.setUserAgentOverride with full userAgentMetadata -- which drives navigator.userAgentData as well as the headers, and was never tested -- is the candidate that could satisfy both, and is being measured separately. Tests: the real-Electron wire-identity test now asserts the stripped identity on ordinary hosts and Firefox on Google auth hosts. Ablation-verified: neutering cleanElectronUserAgent turns it red on the Electron-token assertion. Its fixture also gained an app name -- without one the raw UA carried no app token, so the Orca/x.y.z half of the cleaner was never exercised. * fix(browser): finish the identity revert in the files CI caught browser-session-registry.persistence.test.ts still asserted #18749's behaviour ("keeps the stock UA", "keeps the engine UA"), so the shipped code and its test disagreed. Caught by CI shard 4/8, not locally: I reverted four test files and went to typecheck without re-running the browser suite. Also restores the accurate wording that #18749 generalised away, now that the behaviour it described is back: - browser-google-auth-ua.ts: names the Electron/Chrome-shaped UA again as what anti-fraud flags, which is the reason the auth-host switch exists at all. - docs/browser/profiles.mdx: documents the cleaned Chrome UA default and the --no-ua-spoof escape hatch, which is real again. - tests/tools/google-signin-ua-probe.cjs: comments name the live handler. Deliberately left at #18749's version, because those changes stay correct with anti-detection.ts deleted: - browser-manager-viewport.ts: its comment no longer cites the retired addScriptToEvaluateOnNewDocument injection. - browser-webauthn-profile-delete.test.ts: its added webRequest mock is REQUIRED by the restored setupClientHintsOverride, so reverting it would break the test. * fix(browser): keep restored UA hints browser-owned --------- Co-authored-by: Merge Sim <sim@local>
@orca/docs
This package contains the product documentation and public media intended to ship alongside Orca's source code.
Open-source product documentation for Orca, served at /docs (same URL shape as https://www.onorca.dev/docs).
This package is a self-contained Next.js app. It is intentionally not a root monorepo workspace member, so installing Electron app dependencies does not pull Next/fumadocs.
Local development
cd docs/site
pnpm --ignore-workspace install
pnpm --ignore-workspace dev
Open http://localhost:3004/docs.
Production build
cd docs/site
pnpm --ignore-workspace install
pnpm --ignore-workspace build
pnpm --ignore-workspace start
pnpm start serves the production build on port 3004. Paths:
| Path | Purpose |
|---|---|
/ |
Redirects to /docs |
/docs |
Docs index |
/docs/... |
Nested doc pages from content/docs |
/docs/api/search |
Fumadocs search index |
/docs/og/... |
Per-page Open Graph image route |
Layout
content/docs/— MDX pages +meta.jsonnavigationpublic/docs/— docs-only media, logo, and favicon (GIFs, posters, screenshots)src/app/docs/— fumadocs routes, OG imagessrc/components/— docs-scoped chrome (header/footer/search), not marketing site
Updating content
Treat the documentation tree as a deliberate publication boundary. Before importing source material, review the diff for internal references, credentials, third-party media rights, and feature/version claims, then copy only approved pages and assets. Keep the app shell and deployment configuration in this repository so a docs-only pull request can be reviewed and built independently.
Same-domain routing
The docs app is a separate Vercel project (the docs zone) and keeps the
public /docs URL namespace. The marketing site remains the default zone for
www.onorca.dev; configure its Next/Vercel proxy with these beforeFiles
rewrites, replacing DOCS_ORIGIN with the docs project's production URL:
return {
beforeFiles: [
{
source: '/docs',
destination: `${DOCS_ORIGIN}/docs`
},
{
source: '/docs/:path*',
destination: `${DOCS_ORIGIN}/docs/:path*`
},
{
source: '/docs-static/:path*',
destination: `${DOCS_ORIGIN}/docs-static/:path*`
}
]
}
/docs-static is the docs zone's assetPrefix; it prevents _next asset
collisions with the marketing zone. Keep the rewrites in the default zone and
use ordinary <a> links when navigating between zones. Do not add
basePath: '/docs' to this app: its route tree and Fumadocs baseUrl already
include /docs, so doing so would publish /docs/docs/... URLs. If a future
deployment needs basePath, first move the route tree to an unprefixed
src/app/[[...slug]] shape and update every generated/link URL together.
Deploy (Vercel)
- Create a Vercel project with Root Directory unset (
.). The workflow invokes Vercel fromdocs/site, so that directory is already the deployment root; setting it again would resolvedocs/site/docs/site. Leave automatic Git deployments disabled so this workflow remains the only deployment path. - Framework preset: Next.js. Use
pnpm --ignore-workspace install --frozen-lockfilefor install andpnpm --ignore-workspace buildfor build; this package has its own lockfile beside the root workspace. - Set GitHub Actions secrets (required by the production deploy job):
VERCEL_TOKENVERCEL_ORG_IDVERCEL_PROJECT_ID(docs project, not the marketing site)
- Protect the
docs-productionGitHub environment with required reviewers and custom deployment branch policies formainandv*tags. The release-cut dispatch runs frommain; the direct published-release fallback runs from a stable tag, while the workflow still authorizes only exact stable tags. - Prepare the three rewrites above in the
www.onorca.devmarketing project, but leave them disabled until the docs deployment is verified. A Vercel custom domain cannot delegate only/docsby itself; the default zone must proxy both page/API/media requests and/docs-staticassets. Keep the marketing project's old docs routes available for rollback during the transition; putting the proxy rules inbeforeFilesensures they win once enabled. - Deploy a stable desktop tag that contains
docs/site, verify the docs origin, then enable the marketing rewrites. Tags cut before this package was added cannot bootstrap the docs project because production intentionally checks out the tag's exact commit. Remove the old marketing docs routes in a follow-up after the proxy is stable.
.github/workflows/docs.yml runs credential-free checks for every pull request.
It intentionally does not deploy PR previews: a PR-controlled build must not
receive Vercel credentials. A maintainer can add a separate trusted preview
workflow later. Production deploys only from an authorized stable desktop release: an exact
vX.Y.Z tag, a published non-prerelease release, and the
github-actions[bot] release author. Manual dispatch must run from the default
branch and name an existing release that meets the same checks. Mobile,
prerelease, draft, and human-authored releases are skipped. Fork pull requests
remain build-only because GitHub does not expose deployment secrets to fork
jobs.
Versioning
versioning.config.ts keeps the current unversioned /docs URLs stable while
reserving content/versions/<id> for future snapshots. Versioned routes are not
live yet; when they are needed, add the corresponding loader/routes and a
version entry. The release workflow can then deploy them without a trigger
change.
Isolation from the desktop app
- Own
package.json+pnpm-lock.yamlunderdocs/site/ - Not listed in the root
pnpm-workspace.yaml; install withpnpm --ignore-workspace - Engineering notes remain in repo-root
docs/— do not confuse with this package