Conversation
A person's id now resolves to a name and face after they leave. The collab worker keeps a `people` table (schema v2, migrated from v1), upserts it on join and identity change, sends it in `welcome.people`, and announces new or changed profiles with a `people` message. The client store merges the directory with live participants. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Applets refer to a person by id (`id`, or `ids` for several) and the components resolve name, face, and presence themselves: `Person` (with `avatarOnly` and `showStatus`), `Facepile`, `Cursor`, `PresenceFrame`, `PresenceGutter`, and the `usePerson` hook. `PresenceFrame`, and with it `PresenceField` and `Selection`, hugs the single element it wraps and copies its corner radius. `SyncStatus` is gone; applets render `isSaving` and `error` from the shared-state hooks. Hooks and components now talk to a `CollabBackend` contract from context instead of the socket client. The workspace provides the live backend; `createFakeBackend` is an in-memory room behind the same store. `/dev/collab-kit` runs on it: every component with made-up people, then the connected components and the exported hooks against scripted participants. The registry Avatar gains an `xs` size and expresses its default size as a variant so applet-scoped CSS cannot override it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The people directory commit picked up an unrelated removal of `CollabCapability` from the working tree, while the code that stops using it is not committed yet. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 18937693f1
ℹ️ 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".
Remove persistent shared-state synchronization, expose connected peers and separate presence reads/publications, and resolve profiles through authoritative workspace directories supplied by Batiok. Built-in indicators publish only while active; disabled applets keep inert APIs. Validated with 1744 passing tests (4 platform skips), production build, lint, changed-file formatting, and typecheck excluding pre-existing invalid untracked sketch.tsx. Equivalent checks ran manually because the pre-commit hook formats the whole tree and would touch unrelated files.
Show only connected people in the workspace header. Export the full workspace directory hook with status filtering, clarify applet/page scoping, and support one presence wrapper around keyed list or form children. Verified 1754 tests, production build, two live browser sessions, filtered project typecheck, lint, and changed-file formatting. Ran checks manually instead of the whole-tree autoformat hook to preserve the existing invalid untracked sketch.tsx unchanged.
Forward --experimental-collab directly to child servers and initialize process configuration from parsed flags. Remove the environment toggle and service handling; keep init documentation installation separate from runtime opt-in. Verified 1755 tests, lint, changed-file formatting, and project typecheck with the pre-existing invalid sketch.tsx excluded. Ran checks manually to preserve that untracked file from the whole-tree formatting hook.
molefrog
commented
Sep 26, 2026
Return empty hooks and render nothing with one warning when an applet collab bridge is unavailable. Keep personal chat and view-builder creation from updating shared selection. Stop workspace presence, including pending connections, when the workspace is removed. Addresses PR #147 review findings. Verified 1774 tests, production client build, lint, formatting, and project typecheck excluding the pre-existing invalid sketch.tsx. Ran checks manually to avoid the whole-tree hook modifying that unrelated untracked file.
Integrate main's applet attachments and workspace navigation while retaining collaboration bridge access, presence lifecycle, and personal chat/tab selection. Adapt presence locations and regression fixtures to the new tab addresses. Validation: 1,865 tests passed, 4 skipped, 0 failed; production client build, typecheck, lint, and changed-file formatting passed. Typecheck and lint exclude the user's pre-existing untracked sketch.tsx parse error. The whole-tree auto-format hook is bypassed to preserve that file; equivalent checks ran manually. Generated dist output was removed after the build.
* Inherit collab identity from Cloudflare Access A deployment behind Cloudflare Access (Zero Trust) can set `cloudflareAccess` in config.json, or MOI_CLOUDFLARE_ACCESS_TEAM_DOMAIN and MOI_CLOUDFLARE_ACCESS_AUD, so every viewer inherits their Access identity instead of creating a dev profile. The server verifies the Access application token (Cf-Access-Jwt-Assertion, or the CF_Authorization cookie when a proxy drops the header): RS256 signature against the team's published keys, issuer, audience, and expiry. The profile takes id from `sub` and email from `email`; tokens carry no display name, so the name is the email's local part, and the color is a stable pick from the persona palette hashed from the id. GET /api/identity serves the verified profile and loads before the app mounts. The browser uses it over a saved dev profile, and an outer host still wins. Presence sockets verify the token on upgrade (401 without one) and pin every join and identity update to the verified profile, so one viewer cannot appear as another. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld6kvjMXg9eSvYsUJwo9NK * Leave the name out of Cloudflare Access profiles The base now allows users without names, with built-in labels falling back to the email. Access tokens carry no display name, so the inherited profile keeps only id, email, and the id-derived color instead of deriving a name from the email. The /dev/collab notice labels the profile with userDisplayName, which also fixes the typecheck against the optional name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld6kvjMXg9eSvYsUJwo9NK * Condense Cloudflare Access tests Fold the verifier rejections into one table, drop cases that repeat other coverage (concurrent fetches, clock drift, profile helpers), and merge the config, endpoint, socket pinning, and identity precedence checks into fewer tests. Coverage stays on signature, issuer, audience, expiry, key refresh throttling, header and cookie tokens, config parsing, socket pinning, and source precedence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld6kvjMXg9eSvYsUJwo9NK * Refuse mismatched Access identities and expire cached keys A presence socket verified by Cloudflare Access now joins only with the verified id. A different id, such as an outer host's own identity, is refused with identity_mismatch instead of being rewritten to the Access user, so peers never see a different person than the browser shows. Cached signing keys now expire after ten minutes, so a key Cloudflare stops publishing stops verifying tokens even when no new key id arrives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld6kvjMXg9eSvYsUJwo9NK * Verify Cloudflare Access tokens with jose Replace the hand-rolled JWT parsing, WebCrypto verification, and key cache with jose's jwtVerify and createRemoteJWKSet, the library Cloudflare's own verification examples use. Tokens must be RS256, name the team domain as issuer and one of the configured AUD tags, and carry an expiry, with 60 seconds of clock tolerance. jose caches the team's keys for ten minutes and refetches for an unknown key id after a 30 second cooldown. Failed key fetches are logged; bad tokens are not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld6kvjMXg9eSvYsUJwo9NK * Widen the Access token time margins in tests The not-yet-valid case set nbf 61 seconds past a timestamp taken at module load, one second outside the verifier's 60 second tolerance, so it failed whenever key generation in beforeAll took over a second, as on a slow CI runner. Expired and not-yet-valid tokens now sit ten minutes outside the tolerance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld6kvjMXg9eSvYsUJwo9NK --------- Co-authored-by: Claude <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds opt-in workspace presence through
moi/collab: connected peers, user lookup, cursors, focus, and selection. Batiok publishes one global account and workspace member lists atomically, so applets can resolve offline users and distinguish loading from an empty directory. Application-data synchronization is outside this PR.Enable presence with
moi start --experimental-collab; install applet guidance/types withmoi init --experimental-collab. One workspace engine/provider supplies all applets. Profiles require ID and color; name, email, and avatar are optional. Applets store user IDs and resolve current profiles through hooks and components.Architecture: collab RFC. Host integration: Batiok bridge. Applet authoring: collaboration guide.
Review focus
__proto__, remain ordinary IDs. Batiok owns authentication and access enforcement.Verification
bun test: 1,914 passed, 4 skipped, 0 failures. Typecheck, full lint (existing warnings), formatting, and registry validation pass. CLI dev-mode signal cleanup passed 50 repeated runs. Earlier two-browser checks covered grouped focus/selection, reorder/removal, ID changes, cursor anchors, profiles, directory loading, sign-out, and away/return behavior.