Skip to content

feat(web): cloud-tasks browser host#3447

Open
gantoine wants to merge 8 commits into
mainfrom
posthog-code/web-host
Open

feat(web): cloud-tasks browser host#3447
gantoine wants to merge 8 commits into
mainfrom
posthog-code/web-host

Conversation

@gantoine

Copy link
Copy Markdown
Member

Summary

Brings up apps/web as a cloud-tasks-only browser host for PostHog Code — the same @posthog/ui shell and @posthog/core services as the desktop app, running in a plain browser tab over web platform adapters (no Electron, no local workspace-server). An authenticated user can reach the cloud task list, create a cloud task, stream the SSE chat, review diffs, attach files, run /skill commands, and use Channels/Canvas — entirely client-side.

Also a portability smoke test for the layered architecture: @posthog/core and @posthog/ui run unchanged; everything web-specific lives in the apps/web composition root.

What's here

  • Auth — browser PKCE OAuth (popup → /callback → BroadcastChannel relay), refresh token encrypted at rest with a non-extractable Web Crypto key in IndexedDB.
  • Cloud tasks — real AuthService / CloudTaskService (host-agnostic core) over an in-process host-router slice via tRPC unstable_localLink; SSE chat, diffs, log history, sidebar.
  • Canvas / Channels — the four canvas routers over the host-agnostic canvas services (PostHog desktop_file_system API).
  • Attachments (drag/paste/picker), /skill commands (fflate bundler), posthog-js analytics/error-tracking/flags, browser notifications, per-device stores (localStorage).
  • Build — vendor + route code-splitting (TanStack Router autoCodeSplitting).
  • Tests — a hermetic Playwright happy-path e2e (boot → onboarding → sign-in → /callback), wired into CI alongside the desktop suite; mprocs procs for local dev.

⚠️ Depends on (merge first)

This is the additive web-host layer split out of #3353. It builds on three small enabling PRs and is red until they land, then a rebase turns it green:

  1. refactor(auth): make the token cipher async #3444refactor(auth): make the token cipher async
  2. feat(platform): host capabilities seam + boot-time binding guard #3446feat(platform): host capabilities seam + boot-time binding guard
  3. refactor(shared): move the SKILL.md serializer into @posthog/shared #3445refactor(shared): move the SKILL.md serializer into @posthog/shared

Verified locally: with all three applied on top of current main, @posthog/web and apps/code typecheck clean and the web e2e passes. The standalone red is exclusively unresolved symbols from those three (async cipher, @posthog/platform/host-capabilities + @posthog/di/hostCapabilities + REQUIRED_HOST_CAPABILITIES, serializeSkillMarkdown).

Notes

apps/web is a new app; nothing in main imports it, so its blast radius on the desktop host is nil. The shared-package/desktop changes that do carry risk were peeled into the three enabler PRs above.


Created with PostHog Code

Bring up apps/web as a cloud-tasks-only browser host: the same @posthog/ui
shell and @posthog/core services as desktop, over web platform adapters
(WebCrypto refresh-token cipher, popup PKCE OAuth, localStorage per-device
stores, in-browser host-router slice via unstable_localLink, posthog-js
analytics/flags, fflate skill bundler, @pierre/diffs worker). Vendor + route
code-splitting, a hermetic Playwright happy-path e2e, and mprocs procs.

Depends on (merge first): async token cipher, host-capabilities seam, and
the shared SKILL.md serializer. Red until those land; rebase then.

Generated-By: PostHog Code
Task-Id: 77d13a30-444d-4045-9d80-5e2a9f2e68ae
@trunk-io

trunk-io Bot commented Jul 14, 2026

Copy link
Copy Markdown

⏳ Waiting to start tests on this pull request - details.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 243dc09.

@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "feat(web): cloud-tasks browser host" | Re-trigger Greptile

Comment thread apps/web/src/web-oauth-flow.ts
@gantoine
gantoine marked this pull request as draft July 14, 2026 20:18
gantoine added 4 commits July 15, 2026 14:28
Resolve conflicts in apps/web/vite.config.ts (keep web-host refactor,
carry over main's git alias into posthogSrcAliases) and mprocs.yaml
(adopt main's layer-grouping model, slot in the new web/web-playwright/
desktop-playwright procs).

Generated-By: PostHog Code
Task-Id: d5bcaf27-c54b-45d5-920d-cc4f65c9e9fb
The popup used a fixed window name ("posthog-code-oauth"), so a second
tab starting sign-in before the first finished could reuse and navigate
away the first tab's popup. The first flow's callback then never fired,
and the shared BroadcastChannel only carried the second flow's state, so
the first tab waited until the five-minute timeout.

Name each popup uniquely per flow (suffixing the per-flow OAuth state) so
concurrent sign-ins open independent windows. State-based callback
routing over the shared channel already delivers each callback to its own
flow.

Generated-By: PostHog Code
Task-Id: d5bcaf27-c54b-45d5-920d-cc4f65c9e9fb
CI's `pnpm install --frozen-lockfile` failed on this branch: the merge of
main left pnpm-lock.yaml inconsistent with apps/web/package.json.

- apps/web recorded zod specifier `^4.4.3`, but main's override
  (`zod@^4.0.0: 4.4.3`) pins it to `4.4.3`; align it like apps/code and
  packages/ui already do.
- Restore the missing webpack@5.105.0(esbuild@0.27.2) and
  terser-webpack-plugin@5.3.16 snapshot entries (pulled in by apps/web's
  @tanstack/router-plugin) that the merge dropped, which otherwise broke
  the lockfile with ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY.

Surgical edits only, so no unrelated transitive version drift.

Generated-By: PostHog Code
Task-Id: d5bcaf27-c54b-45d5-920d-cc4f65c9e9fb
Resolve conflict in apps/web/src/web-container.ts: keep the web-host
container bindings and fold in main's taskThreadCoreModule (import +
container.load, grouped with canvasCoreModule). Also drop the web LLM
gateway host's invalidatePlanCacheUrl binding and its now-removed
getGatewayInvalidatePlanCacheUrl import, matching main's trimmed
LlmGatewayEndpoints interface (mirrors apps/code's binding).

Generated-By: PostHog Code
Task-Id: d5bcaf27-c54b-45d5-920d-cc4f65c9e9fb
@gantoine
gantoine marked this pull request as ready for review July 17, 2026 15:31
container
.bind(AUTH_TOKEN_OVERRIDE)
.toConstantValue(
(import.meta.env.VITE_POSTHOG_ACCESS_TOKEN_OVERRIDE as

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Development access token can be bundled in production

Vite replaces this value with a string literal in the client bundle. An attacker can extract and use the static access token from deployed assets whenever the override is accidentally configured during a production build; gate this binding on import.meta.env.DEV or fail production builds when the variable is set.

@veria-ai

veria-ai Bot commented Jul 17, 2026

Copy link
Copy Markdown

PR overview

This pull request adds a web-facing cloud-tasks browser host, with changes in the web container code to support the new runtime/browser-host behavior.

One security issue remains open after one prior issue was addressed. The remaining concern is that a development access token override can be compiled into the client bundle if it is accidentally configured during a production build, allowing extraction from deployed assets. Because exploitation depends on that production misconfiguration being present, the current whole-PR risk is moderate but conditional.

Open issues (1)

Fixed/addressed: 1 · PR risk: 4/10

@posthog

posthog Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Visual changes approved by @gantoine — baseline updated in acb47d2.

View this run in PostHog

7 changed.

7 updated
Run: 01703e08-05db-400a-b7d3-dd7ba8b8e6be

Co-authored-by: gantoine <3247106+gantoine@users.noreply.github.com>
@gantoine gantoine added the reviewhog ($$$) Reviews pull requests before humans do label Jul 20, 2026

@jonathanlab jonathanlab left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really good: I noticed we're using a mix of local storage and indexed DB, I think it would make sense to choose 1 source of truth for handling browser storage instead of having this split across 2 mechanisms.

I think it would also be good if we updated our AGENT.md or relevant agent instructions with pointers on how to build for web.

Comment thread apps/web/src/web-archive-store.ts
# Conflicts:
#	apps/code/snapshots.yml
#	apps/web/package.json
#	apps/web/src/web-container.ts
#	apps/web/src/web-trpc.ts
#	pnpm-lock.yaml
Comment thread apps/web/src/main.tsx
@gantoine

Copy link
Copy Markdown
Member Author

/trunk merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewhog ($$$) Reviews pull requests before humans do

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants