Skip to content

Use platform socket sessions in the minimal white-label example - #31

Closed
ozsay wants to merge 10 commits into
mainfrom
codex/white-label-builder-socket
Closed

ozsay wants to merge 10 commits into
mainfrom
codex/white-label-builder-socket

Conversation

@ozsay

@ozsay ozsay commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Replace periodic chat polling in examples/white-label-minimal with live builder updates over the Base44 platform socket, through the platform SDK (base44/javascript-sdk#286). The backend side is base44-dev/apper#26368 (socket sessions, merged) and base44-dev/apper#27220–#27222 (the declared public events and the white-label audience on /ws).

const { serverUrl, sessionToken } = await openBuilderSession(appId); // partner backend
const client = new Base44PlatformClient({ serverUrl, getSessionToken });
const builder = client.builder.init({ onError });
builder.subscribe(appId, { onSnapshot, onEvent, onError });
await builder.connect();
  • Credential. The browser holds only a socket session token. POST /api/base44/socket-session requires a signed-in user, the same origin and app ownership. It then opens a one-app session with a workspace key (POST /api/service/socket-sessions) and returns { serverUrl, sessionToken } with Cache-Control: no-store, private. The token lasts an hour, cannot write, and carries no Base44 identity. The service user's access token no longer reaches the browser.
  • Key. The key needs apps:watch. It is BASE44_WATCH_KEY, falling back to BASE44_SVC_KEY, following the existing BASE44_PROVISION_KEY pattern. A key missing the scope surfaces as a configuration error (503).
  • Ending. Switching apps, unmounting or closing the tab ends the Base44 session (closeBuilderSession, a keepalive request to DELETE /api/service/socket-sessions/{id}), freeing the key's live-session limit. The browser holds a handle: the session id signed with NEXTAUTH_SECRET for this user and app, so a user can end only their own sessions.
  • Connection. The SDK reuses the token across reconnects and asks the backend for a new session only after Base44 ends or rejects the current one.
  • State.
    • The first snapshot loads full history over HTTP.
    • A reconnect snapshot (status plus the last 50 messages) is merged by message id, with no HTTP read.
    • message.updated, message.removed, app.status_changed and image.resolved apply live.
    • The re-read signals (conversation.changed, files.changed, branch.deleted, repository.changed, pull_request.changed) and completed mutations reload over HTTP.
    • Tool widgets render the public tool shape (arguments, display, user_input, media results, approval); the server maps HTTP conversation reads into the same shape, and an approval shows the guard's reason when it has one.
  • Errors. Delivery stops with Reconnect live updates when another tab takes the session, access is revoked, or a handler fails. A missing socket snapshot only falls back to HTTP history.
  • All writes go through the partner backend.
  • The branch is rebased on main (the workspace stage layout and the builder "Ready" panel). The PR's own earlier commits are kept.
  • Pins @base44/sdk to npm:@base44-preview/sdk@0.8.52-pr.286.be667a9 (SDK PR head 78c6fd3).

Validation

  • npm run minimal:test: 46 tests passed (23 server and identity, 23 stream, conversation, question and tool-activity). They cover:
    • the session route's key, body and response;
    • ending a session, and rejecting a tampered handle, another app's handle or another user's handle without calling Base44;
    • the fallback to the mint key and the missing-scope error;
    • reconnect-snapshot merging;
    • the snapshot_unavailable fallback;
    • session_replaced;
    • message removal;
    • mapping HTTP tool calls to the public shape.
  • The example typechecks.
  • 26 Playwright browser tests pass, including one that checks a page hide ends the session, against the local fixture, using installed Chrome. The fixture socket speaks the new contract: /ws/socket.io/, the default namespace, {room, data} events with an app.snapshot on join, and it rejects a CONNECT without the session token.
    • The preview-card test now signals a finished build with app.status_changed: a conversation.changed rejoins for a snapshot, whose fixture status would overwrite the ready state.
  • ESLint on the changed files reports only existing findings: an <img> warning and three no-explicit-any errors in tests/build-stream.test.ts.
  • Dependency and lockfile review: only the @base44/sdk preview entry changes in package-lock.json.

Rollout prerequisites

  • The workspace needs the whitelabel-websockets and base44-for-platforms flags, plus a key with apps:watch granted to the apps.
  • Not yet verified against a deployed backend; the backend PRs are in review. Verification here uses fixture sockets.
  • Swap the SDK preview pin for a released version once #286 ships.

Intent (for reviewers & PR Autofix)

What this PR does

Use the platform SDK's builder module for minimal-example chat updates, authenticated by a partner-opened socket session, while keeping the existing HTTP mutations and the readable getting-started structure.

Key decisions & why

  • The browser gets a one-app, read-only session token, never the service user's access token. It is opened server-side behind the existing session, origin and ownership checks.
  • The first snapshot loads over HTTP, because the socket snapshot holds only the last 50 messages. Later snapshots merge without HTTP.
  • App metadata and full history keep their event-driven HTTP reads.

What NOT to touch

  • The SDK preview pin is intentional until its client entry point is released.
  • Do not restore periodic polling, and do not send the service user's access token or any workspace key to the browser.
  • Keep the app-ownership and same-origin checks on the session route and on the HTTP actions, and keep session handles signed and bound to the user and app.

Tradeoffs / follow-ups

  • Verify against the deployed backend before rollout.
  • A close lost to a crash or network drop still waits out the one-hour expiry.
  • This PR changes only the minimal example.

🤖 Generated with Claude Code

@netlify

netlify Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for sunny44-builder ready!

Name Link
🔨 Latest commit f5db6cd
🔍 Latest deploy log https://app.netlify.com/projects/sunny44-builder/deploys/6abd048610b2550008f843b6
😎 Deploy Preview https://deploy-preview-31--sunny44-builder.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for base44-platform-starter ready!

Name Link
🔨 Latest commit f5db6cd
🔍 Latest deploy log https://app.netlify.com/projects/base44-platform-starter/deploys/6abd04862ebf22000834802e
😎 Deploy Preview https://deploy-preview-31--base44-platform-starter.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ozsay
ozsay force-pushed the codex/white-label-builder-socket branch from 2d810d8 to ec485ac Compare September 17, 2026 10:32
ozsay and others added 5 commits September 29, 2026 13:18
The browser now gets a one-app, read-only socket session token from the
partner backend instead of the service user's access token. The backend
opens it with a workspace key holding apps:watch (BASE44_WATCH_KEY, or
BASE44_SVC_KEY when unset).

Aligns with the SDK's session contract: getSessionToken instead of
refreshToken, onSnapshot instead of onJoined and cursors. The first
snapshot loads full history over HTTP; reconnect snapshots merge by id.
Message removals apply live, and a missing socket snapshot no longer
stops delivery.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ozsay
ozsay force-pushed the codex/white-label-builder-socket branch from ac058fd to 9230b3c Compare September 29, 2026 10:25
@ozsay ozsay changed the title Use builder sockets in the minimal white-label example Use platform socket sessions in the minimal white-label example Sep 29, 2026
ozsay and others added 4 commits September 29, 2026 14:00
Switching apps, unmounting or closing the tab now ends the Base44 socket
session instead of leaving it to count against the key's live-session
limit for its full hour. The browser holds a handle signed for its user
and app, so it can end only its own sessions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The builder socket now sends named public events: apply message.updated,
message.removed, app.status_changed and image.resolved directly, and reload on
the re-read signals. Tool calls use the public shape (arguments, display,
user_input, media results, approval), and the server maps HTTP conversation
reads into it. Bumps the SDK preview to the matching platform-client build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A conversation.changed now rejoins for a snapshot, whose fixture status would
overwrite the ready state; a finished build arrives as a status event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Game assets and videos return a URL alone: a placeholder until image.resolved
replaces it, or the finished asset. The widget, the image resolver and the HTTP
mapping handle that shape. Bumps the SDK preview to the build with
selected_label and URL results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SDK now reports session_revoked when the partner or an admin ends the
session, so the chat says live updates are no longer available.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos added a commit that referenced this pull request Oct 4, 2026
…e-label example

Replace chat polling in examples/white-label-minimal with live builder
updates over the Base44 platform socket, through the Platform SDK
(@base44/platform). The partner backend opens a one-app socket session
with a workspace key; the browser holds only the session token.

Oz Sayag's work from #31, switched to the @base44/platform package.
package-lock.json is updated once @base44/platform is published.

Co-Authored-By: Oz Sayag <ozs@wix.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos added a commit that referenced this pull request Oct 4, 2026
Replace chat polling in examples/white-label-minimal with the Base44
platform socket, through the Platform SDK (@base44/platform). Kept
minimal on purpose:

- server: lib/base44/socket-session.ts opens a read-only session for one
  app with the workspace key, behind the existing sign-in and ownership
  checks (openBuilderSession action).
- browser: lib/chat/live-updates.ts subscribes; the snapshot replaces the
  chat, then message.updated / message.removed / app.status_changed.
- React: components/useBuilderSocket.ts, same interface as the polling
  hook it replaces, so the UI is unchanged.

Socket messages are converted to the shape the existing chat UI renders
(lib/chat/live-messages.ts). Production follow-ups (closing the session,
history beyond 50 messages, image placeholders) are listed in the README.

Based on Oz Sayag's work in #31. package-lock.json is updated once
@base44/platform is published.

Co-Authored-By: Oz Sayag <ozs@wix.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos added a commit that referenced this pull request Oct 4, 2026
Replace chat polling in examples/white-label-minimal with the Base44
platform socket, through the Platform SDK (@base44/platform). Kept
minimal on purpose:

- server: lib/base44/socket-session.ts opens a read-only session for one
  app with the workspace key, behind the existing sign-in and ownership
  checks (openBuilderSession action).
- browser: lib/chat/live-updates.ts subscribes; the snapshot replaces the
  chat, then message.updated / message.removed / app.status_changed.
- React: components/useBuilderSocket.ts, same interface as the polling
  hook it replaces, so the UI is unchanged.

Socket messages are converted to the shape the existing chat UI renders
(lib/chat/live-messages.ts). Production follow-ups (closing the session,
history beyond 50 messages, image placeholders) are listed in the README.

Based on Oz Sayag's work in #31.

Co-Authored-By: Oz Sayag <ozs@wix.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos added a commit that referenced this pull request Oct 4, 2026
Replace chat polling in examples/white-label-minimal with the Base44
platform socket, through the Platform SDK (@base44/platform). Kept
minimal on purpose:

- server: lib/base44/socket-session.ts opens a read-only session for one
  app with the workspace key, behind the existing sign-in and ownership
  checks (openBuilderSession action).
- browser: lib/chat/live-updates.ts subscribes; the snapshot replaces the
  chat, then message.updated / message.removed / app.status_changed.
- React: components/useBuilderSocket.ts, same interface as the polling
  hook it replaces, so the UI is unchanged.

Socket messages are converted to the shape the existing chat UI renders
(lib/chat/live-messages.ts). Production follow-ups (closing the session,
history beyond 50 messages, image placeholders) are listed in the README.

Based on Oz Sayag's work in #31.

Co-authored-by: Oz Sayag <ozs@wix.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos added a commit that referenced this pull request Oct 4, 2026
Replace chat polling in examples/white-label-minimal with the Base44
platform socket, through the Platform SDK (@base44/platform). Kept
minimal on purpose:

- server: lib/base44/socket-session.ts opens a read-only session for one
  app with the workspace key, behind the existing sign-in and ownership
  checks (openBuilderSession action).
- browser: lib/chat/live-updates.ts subscribes; the snapshot replaces the
  chat, then message.updated / message.removed / app.status_changed.
- React: components/useBuilderSocket.ts, same interface as the polling
  hook it replaces, so the UI is unchanged.

Socket messages are converted to the shape the existing chat UI renders
(lib/chat/live-messages.ts). Production follow-ups (closing the session,
history beyond 50 messages, image placeholders) are listed in the README.

Based on Oz Sayag's work in #31.

Co-Authored-By: Oz Sayag <ozs@wix.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amitbardos

Copy link
Copy Markdown
Contributor

Closing: Tiny Sunny's live updates now come from @base44/platform's useBase44Chat hook (#79), and the files this changes are no longer on main.

@amitbardos amitbardos closed this Oct 20, 2026
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.

2 participants