feat: version gating, client-id declarations, and PUD-only update suppression - #28
Draft
petergaultney wants to merge 1 commit into
Draft
Conversation
…pression Three behavioral additions, all backward compatible: 1. allowed_client_versions (relay.toml [server] field): when non-empty, doc websocket connections must report one of the listed plugin versions via the `v` query param. Server tokens are exempt. Denial warns are throttled to one per user per 30 minutes. 2. cid query param + relayClientIds awareness field: a plugin can pre-declare the Yjs client ids it mints (e.g. a merge working copy), binding them to its reported version at connect time. Also registers declared ids in PUD at upgrade, so the authenticated user is bound before any update can mis-attribute them. 3. Server-only update suppression: updates authored entirely by the server's own 53-bit client ids (PUD registration writes) skip the normal event callback path, suppressing the webhook dispatch that would otherwise fire for internal bookkeeping. Supporting infrastructure: - client_versions.rs: per-client-id version tracking with declared (owner-minted) and inferred (first-introduction) trust levels - edit_author.rs: client-id extraction from updates, is_server_only_update - AwarenessEntryFacts struct on DocConnection for typed awareness parsing - PUD registration made public so the cid upgrade path can call it - doc_id on DocConnection, so its log lines can name the doc
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
Adds three server-side capabilities for self-hosters managing a fleet of Relay plugin installations:
Plugin version gating (
allowed_client_versions): doc websocket connections from user-claimed tokens must report a version in the configured allowlist, or get 403. Server tokens are exempt. Empty list (default) disables gating. Denial warns are throttled to one log line per user per 30 minutes.Client-id declarations (
cidquery param +relayClientIdsawareness field): plugins can declare which Yjs client ids they mint edits under (e.g. a merge-recovery working copy uses a separate local doc with its own client id). The server records these in PUD at websocket upgrade and tracks their plugin version via awareness payloads. This enables accurate version attribution even for edits that arrive through intermediary docs.PUD-only update suppression: updates authored entirely by the server's own 53-bit client ids (PermanentUserData registration writes) now skip webhook dispatch. These are internal bookkeeping, not human-produced content changes, and firing webhooks for them creates unnecessary git-sync churn.
Details
Version gating
A new
allowed_client_versionsfield on[server]in relay.toml. When non-empty, thevquery param on websocket upgrade is checked against it. Clients too old to report a version are blocked. The gate is enforced on both the deprecated and full-path websocket upgrade handlers.Client-id declarations
The
cidquery param accepts a comma-separated list of Yjs client ids. At websocket upgrade, each declared id gets:vparam)usersmap)The
relayClientIdsawareness payload field is also consumed: when a client broadcasts additional ids it mints edits under, those are recorded with the same declared version.Version tracking infrastructure
client_versions.rsimplements a two-tier trust model:cidparam orrelayVersionawareness payload. Overwrites previous values.~prefix.Updates never bind versions (the deliverer is not the minter). Non-first awareness entries are tracked as "seen" but never inferred from.
PUD suppression
is_server_only_updatechecks whether all client ids in an update are >= 2^32 (server-authored). These updates still get dispatched as event envelopes (so sync protocol events fire), but skip the webhook path.Relationship to the other open PRs
Independent - this branches straight off
mainand contains only behavior changes. No log-level changes here; those are all in #26.#26 and this PR both touch the
Received awareness update with more than one clientline - #26 changes its level, this one adds adoc_idfield. Whichever merges second takes a one-line textual conflict; there is no semantic disagreement.Test plan
vparam are rejected whenallowed_client_versionsis non-emptycidparam registers PUD entries at upgradeallowed_client_versions(default) disables gatingcargo testincrates/)