Enforce public identity boundary for presence - #286
Merged
Conversation
commit: |
Deploying playhtml with
|
| Latest commit: |
4949208
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b06d38b0.playhtml.pages.dev |
| Branch Preview URL: | https://cx-fix-wikipedia-presence-li.playhtml.pages.dev |
spencerc99
marked this pull request as ready for review
July 8, 2026 05:19
spencerc99
commented
Jul 8, 2026
Owner
Author
Code reviewNo issues found. Checked for bugs and project-instruction compliance. |
Deploying we-were-online-website with
|
| Latest commit: |
33c8081
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://ff9286c5.we-were-online-website.pages.dev |
| Branch Preview URL: | https://cx-fix-wikipedia-presence-li.we-were-online-website.pages.dev |
spencerc99
commented
Jul 10, 2026
…ence-limit # Conflicts: # extension/src/__tests__/EventBuffer.test.ts # extension/src/__tests__/collectors.integration.test.ts # extension/src/__tests__/participant.test.ts # extension/src/entrypoints/background.ts # extension/src/storage/EventBuffer.ts # extension/src/storage/participant.ts
spencerc99
added a commit
that referenced
this pull request
Jul 25, 2026
Brings the branch up to date with #284 (users API), #329, and #327 (dead-code deletions). Key resolutions: - index.ts: kept the refcounted presence-transport registry; dropped the branch's copies of config vars deleted by #327 (config now derives from configuredOptions); element awareness identity now resolves through resolveMyIdentity()/usersAPI instead of cursorClient/generatePersistent. - Extension identity injection: usersAPI.adoptIdentity() (main) followed by elementAwarenessClient.refreshIdentity() (branch) so the element transport re-joins with the injected identity; listener installs unconditionally. - Restored MAX_PRESENCE_VALUE_BYTES to common/presence-protocol.ts: removed on main by #286 as unused, but this branch's element-awareness client bounds its channel payloads with it. - Element-awareness tests: kept the branch's transport-era suites, adapted handler access to the elementHandlers named export (main removed it from the public singleton). Verified: playhtml 417/417, common 16/16, react 50+1 integration all pass; tsc clean for packages; lint failures limited to pre-existing extension errors also present on main.
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.
Summary
{ public, privateKey }and keep discovered sites in separate profile storage.EventBufferno longer read the combined private storage record.PlayerIdentityprojection in@playhtml/common, with field allowlists, bounded strings, and bounded color palettes.Root cause
The extension stored public identity, private signing material, and browsing-derived profile fields in one flat
playerIdentityobject. Page-facing code could receive or load that full object before selecting public fields, producing oversized Wikipedia presence payloads and crossing the intended private/public boundary.The final transport audit also found that
join()andupdate()cached caller-owned values before validation. A rejected value could remain queued and throw again duringflushCurrentState(), while an accepted object could be mutated after validation.Security boundary
playerIdentity.publicis the only identity shape returned by identity/profile messages, DOM identity events, and presence.playerIdentity.privateKeyremains extension-local and is not returned by those APIs.Moving signing material from content-script-readable
browser.storage.localinto a background-owned non-extractable key store remains part of the signing design in #264. This PR fixes accidental data flow without redesigning signing.Presence limits
Shared presence validation now checks JSON serialization and known-channel schemas without imposing a generic byte threshold. PartyKit rejects raw messages above 1 MiB before parsing as an abuse safeguard.
Presence channels must survive Durable Object hibernation, so cumulative connection state is persisted through
connection.setState(). The server derives and validates candidate channels, attempts the real platform attachment write, and only then updates room state. A rejected attachment restores the prior accepted state and returns a presence error without broadcasting the candidate.Review
Final review covered the complete branch diff, current
origin/main, runtime-message and DOM boundaries, content-script storage access, persisted identity migration, presence join/update/reconnect paths, hibernation attachment atomicity, extension profile access, docs, release notes, and project instructions.An independent final review found the
EventBuffercontent-script storage read; that path was moved behindGET_PUBLIC_PLAYER_IDENTITYand re-reviewed with no remaining high-confidence findings.Validation
git diff --checkpassedbun run lintstill has the previously documented unrelated extension visualization, website shared, worker Cloudflare-global, and WXT manifest type errorsResidual risk: Cloudflare attachment rejection is covered by atomic persistence/rollback unit tests but was not forced in a live Durable Object runtime.