Skip to content

fix(web): stop boot from consuming the /share route's claim params - #452

Merged
crs48 merged 2 commits into
mainfrom
fix/share-claim-boot-param-strip
Jul 10, 2026
Merged

fix(web): stop boot from consuming the /share route's claim params#452
crs48 merged 2 commits into
mainfrom
fix/share-claim-boot-param-strip

Conversation

@crs48

@crs48 crs48 commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Opening a share link in the web app died with 'Missing link, handle, or payload in share link': the boot resolver (resolveHubSessionFromLocation) consumed ?hub= as a hub-pin request and scrubbed payload/handle — before the router ever mounted. Share links carry link+hub+#s= as the /share route's claim input, so the route parsed an already-stripped URL. Worse, the issuing hub got persisted as the user's pinned hub. Present since the cross-surface claim flow landed (masked when the Electron deep link won the race); surfaced while validating the hub.xnet.fyi recovery today.

  • Boot now leaves the /share route's URL untouched (path- and hash-routed forms); the ?hub= pin and stray payload/handle scrub still apply on all other routes.
  • The share route's own sanitizer kept a bare #s= secret fragment on path-routed deployments while discarding the search — now it drops it (that's the one thing it exists to remove).
  • resolveHubSessionFromLocation extracted to boot/hub-session.ts (unit-testable without the SQLite worker graph) + tests for all four cases.

Verified in a real browser against the production hub: an interstitial-shaped URL now claims and navigates to the shared doc; address bar ends clean at /share.

🤖 Generated with Claude Code

xNet Test added 2 commits July 10, 2026 12:02
The boot resolver treated ?hub= as a hub-pin request and scrubbed stray
payload/handle params — but it runs before the router mounts, and share
links carry link+hub (+#s= secret) as the /share route's claim INPUT. Boot
stripped them first, so every web-fallback claim died with 'Missing link,
handle, or payload in share link' (and the issuing hub got persisted as
the user's pinned hub). Present since the flow landed; masked until now
because the Electron deep link usually won the race.

- boot: leave the /share route's URL untouched (path- and hash-routed);
  keep the ?hub= pin and payload/handle scrub on all other routes
- share route sanitizer: drop a bare #s= fragment instead of keeping it —
  it retained the secret in the address bar on path-routed deployments
  while discarding the search params
- extract resolveHubSessionFromLocation into boot/hub-session.ts so it's
  unit-testable without the SQLite worker import graph

Verified in-browser against hub.xnet.fyi: interstitial-shaped URL now
claims and lands on the shared doc.

Signed-off-by: xNet Test <test@xnet.dev>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 temporarily deployed to pr-452 July 10, 2026 19:02 — with GitHub Actions Inactive
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Preview removed for PR #452.

github-actions Bot added a commit that referenced this pull request Jul 10, 2026
github-actions Bot added a commit that referenced this pull request Jul 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🖼️ UI changes in this PR

Warning

1 changed UI file(s) map to no capture target.
Only the home shell was captured, so the surface you changed is not shown
here. Add a routes[] entry — or a flows[] entry + runner if the UI is
behind a tab/inspector/modal/seed data — in scripts/visuals/manifests.json
(scripts/visuals/README.md → Tuning).

Unmapped files
  • apps/web/src/routes/share.tsx

CI run

@crs48
crs48 merged commit 850de51 into main Jul 10, 2026
15 checks passed
@crs48
crs48 deleted the fix/share-claim-boot-param-strip branch July 10, 2026 19:45
github-actions Bot added a commit that referenced this pull request Jul 10, 2026
crs48 added a commit that referenced this pull request Jul 10, 2026
Extends URL share-links to two more node kinds, reusing the exact
pipeline pages/databases already use (and that #448/#452 hardened this
week).

## Channels
- Hub accepts `docType: 'channel'` (`SHARE_DOC_TYPES`).
- Share entry points: a **Share button in the channel header**
(`ChannelView`) and a **Share action in the ChatsPanel** channel
context-menu/kebab.
- A claimed channel routes to `/channel/$channelId` (both `docRouteFor`
and the `/share` web-fallback map).
- **Authorization:** `ChatMessage@` is added to the comment-schema
allowlist, so a **comment-role** channel share means "can post messages,
can't edit the channel" — `write` still required to edit the channel
node itself. `Channel@` is deliberately *not* in the allowlist.

## Workspaces
- Per-row **Share button in the workspace (bench) switcher**, alongside
the pre-existing `Workspace: Share…` command. Preset workspaces aren't
shareable (guarded by `isPresetWorkspaceId`).
- `EditorHeader` maps `channel` tabs to the `channel` docType too, so a
focused channel shows Share in the editor chrome.

## Verification
- **Channel flow verified end-to-end in a real browser** against a live
hub: created a channel → **Share → New link** minted a hub link → a
second identity claimed it via the API (200, `docType: channel`, role
granted) → the in-browser `/share` claim routed to
`/channel/$channelId`.
- Hub tests assert **all eight** `ShareDocType`s round-trip
create→claim, and that a comment grantee may post `ChatMessage` but not
`Channel`/arbitrary schemas.
- Web unit tests cover `docRouteFor('channel')`; typecheck + lint clean
across hub and web.
- The workspace-switcher Share button reuses the identical
`ShareDialog`/`setShareFor` path the existing `workspace.share` command
already ships (typecheck-verified).

Also fixes a stale source-guard test that still pointed at
`use-boot-sequence.ts` after #452 moved the URL-stripping logic to
`boot/hub-session.ts`.

No publishable package changed (hub + apps/web are private) → no
changeset; changelog fragment included.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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