Spec 16 web frontend and deploy leg#98
Conversation
There was a problem hiding this comment.
Pull request overview
Adds the missing Spec 16 “web frontend + deploy” leg by introducing a browser-first transport layer for Matrix calls (HTTP + WebSocket), updating upload/media/avatar flows to work in both Tauri and browser builds, and wiring in build/CI support for web previews.
Changes:
- Add
matrixTransportto route Matrix commands/events to either Tauri IPC or companion-server HTTP/WS. - Make media/avatar URLs and file upload inputs work in web builds (browser
File) while preserving Tauri behavior. - Add web build script/env typing plus a Cloudflare Pages preview workflow; extend
/api/auth/meresponse for restore support.
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vite-env.d.ts | Adds typed Vite env vars for selecting build target and API base. |
| src/lib/platform.ts | Adds isWebBuild() to detect browser builds/config. |
| src/lib/mediaUrl.ts | Introduces a helper to normalize media URLs across Tauri file paths vs web/API URLs. |
| src/lib/matrixTransport.ts | New transport adapter: maps Matrix commands to HTTP routes and listens to WS events in web builds. |
| src/lib/matrixTransport.test.ts | Adds focused tests for route mapping, HTTP errors, uploads, and WS event dispatch. |
| src/lib/matrix.ts | Switches core Matrix wrapper to use the new transport; broadens upload params to `string |
| src/features/settings/useProfile.ts | Uses new media URL helper; allows avatar mutation with File. |
| src/features/settings/AccountPanel.tsx | Adds web file input path for avatar uploads while keeping Tauri dialog flow. |
| src/features/rooms/roomDisplay.ts | Uses toLoadableMediaUrl instead of direct convertFileSrc. |
| src/features/rooms/media/useMediaSource.ts | Uses toLoadableMediaUrl for resolved media paths/URLs. |
| src/features/rooms/ChatShell.tsx | Adds web file input support for attachments; updates drag/drop/paste handling to accept File. |
| src/features/room-info/useRoomAdminActions.ts | Allows room avatar mutation with `string |
| src/features/room-info/RoomSettingsForm.tsx | Adds web file input for room avatar uploads while keeping Tauri dialog flow. |
| package.json | Adds build:web script to build browser-targeted bundle. |
| crates/charm-web-server/src/routes.rs | Extends /api/auth/me to include device_id; improves cross-signing bootstrap error mapping. |
| .github/workflows/web-preview.yml | Adds Cloudflare Pages preview deploy workflow with secret-gated skipping + PR comment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sentry Snapshot Testing
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
src/lib/matrix.ts:323
sendAttachmentnow accepts aFilein web builds, but the parameter namefilePathsuggests it is always a filesystem path. Renaming the local parameter makes the dual (path vsFile) contract clearer without changing the public API surface.
export function sendAttachment(
roomId: string,
filePath: string | File,
txnId: string,
caption?: string,
): Promise<void> {
return invoke("send_attachment", { roomId, filePath, txnId, caption });
}
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4a815ae75f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ca5894aa7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| marker="<!-- charm-web-preview -->" | ||
| body="${marker} | ||
| Web preview: ${PREVIEW_URL} | ||
|
|
||
| Built with \`VITE_CHARM_BUILD_TARGET=web\` and a same-origin \`/api/*\` Pages proxy so Strict session cookies work in authenticated preview flows." |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3af4aed443
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| */api) api_target="${api_base}/:splat" ;; | ||
| *) api_target="${api_base}/api/:splat" ;; | ||
| esac | ||
| printf '/api/* %s 200\n' "$api_target" > dist/_redirects |
There was a problem hiding this comment.
Use a supported Pages API proxy
Here api_target is an absolute http(s) companion URL and this writes it into _redirects as a 200 rewrite, but Cloudflare's Pages _redirects proxying docs say “Proxying will only support relative URLs on your site. You cannot proxy external domains.” (https://developers.cloudflare.com/pages/configuration/redirects/#proxying). Because the web bundle is built with an empty VITE_CHARM_WEB_API_BASE_URL, preview login/session/media calls all stay on the Pages host; this rule will not forward them to the companion API, so authenticated previews fail unless this is implemented with a Pages Function/Worker or another supported same-origin proxy.
Useful? React with 👍 / 👎.
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | ||
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | ||
| CLOUDFLARE_PAGES_PROJECT: ${{ secrets.CLOUDFLARE_PAGES_PROJECT }} | ||
| CHARM_WEB_API_BASE_URL: ${{ secrets.CHARM_WEB_API_BASE_URL }} |
There was a problem hiding this comment.
Keep preview secrets out of PR build steps
For same-repository PR branches where these environment secrets are available, exporting the Cloudflare credentials at job scope means the later pnpm install and pnpm build:web steps run PR-controlled package/build scripts with CLOUDFLARE_API_TOKEN in their environment. A malicious PR can exfiltrate the Pages deploy token before deployment; keep these secrets out of the build/install job and inject them only in a trusted deploy step or separate job that does not execute PR-controlled code.
Useful? React with 👍 / 👎.
| CLOUDFLARE_PAGES_PROJECT: ${{ secrets.CLOUDFLARE_PAGES_PROJECT }} | ||
| CHARM_WEB_API_BASE_URL: ${{ secrets.CHARM_WEB_API_BASE_URL }} | ||
| steps: | ||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
There was a problem hiding this comment.
Disable checkout credential persistence
This checkout uses the default persist-credentials: true; the actions/checkout v4 README states that the auth token is persisted in local git config so later scripts can run authenticated git commands. In this PR workflow the later pnpm install/pnpm build:web steps execute PR-controlled code while the job token has issues: write, so a malicious same-repository PR can recover and misuse that token before the comment step. Set persist-credentials: false here and pass GH_TOKEN only to the step that calls gh.
Useful? React with 👍 / 👎.
Description
Adds the remaining Spec 16 web frontend/deploy leg on top of the companion web server work from #55.
This PR adds a browser transport for Matrix calls, routes web builds through HTTP and WebSocket endpoints instead of Tauri IPC, supports browser
Fileuploads for chat and avatar flows, and makes media/avatar URLs load correctly in both Tauri and web builds. It also adds abuild:webscript, web env typing,/api/auth/medevice restore support, and a Cloudflare Pages preview workflow that skips cleanly when preview deploy secrets are not configured.Related to #55
Type of change
Checklist:
pnpm lint,pnpm fmt:check,pnpm typecheck,pnpm test:coverage,pnpm knip, andpnpm buildall pass locallyAdditional validation:
pnpm build:webcargo test -p charm-web-server --libgit diff --checkAI disclosure:
The generated code adds the web transport adapter, browser upload/media handling, the preview deploy workflow, and focused tests for the transport mapping, HTTP error handling, restore behavior, uploads, and WebSocket event dispatch.