feat: attributed-content endpoint for per-span doc authorship - #30
Draft
petergaultney wants to merge 1 commit into
Draft
feat: attributed-content endpoint for per-span doc authorship#30petergaultney wants to merge 1 commit into
petergaultney wants to merge 1 commit into
Conversation
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 a
GET /d/:doc_id/attributed-contentendpoint that returns the current visible text content of a document, split into spans by authoring client, with clients resolved to users via the PermanentUserData "users" map.This enables downstream consumers (e.g. a git-sync server) to produce per-author commits from collaborative documents.
Auth
The endpoint requires server auth (
Y_SWEET_AUTHBearer token) - the same auth used by/check_storeand other admin endpoints. This is intentionally more restrictive than doc-token auth since the endpoint exposes content and authorship information that is appropriate for server-to-server use, not end-user access.API
Response:
{ "doc_id": "abc123", "root": "contents", "spans": [ {"text": "hello", "client_id": 42, "user": "alice"}, {"text": " world", "client_id": 99, "user": "bob"} ] }The
rootquery param defaults to"contents"(the standard text root for Relay documents). Returns 404 if the doc has no text root by that name.Implementation
The attribution walk runs on a cloned doc (not the live one) to avoid mutating shared state. It uses
diff_rangebetween the current snapshot and an empty snapshot, which surfaces every visible item with its originating client ID. Adjacent characters from the same client are merged into a single span.A
catch_unwindguard handles a known yrs 0.26 panic infind_pivotwhen splitting at the current snapshot while a client's stream is a single one-unit block - in that case the full content is returned as one unattributed span.That panic is a divide-by-zero in
find_index(block_store.rs), which I filed upstream as y-crdt/y-crdt#645; it was closed in favor of #647, which fixes part of the same problem. Neither is in a crates.io release, so on our own deployment we pin a fork carrying the fix on top of thedtkav/y-crdtrevision this repo already uses:petergaultney/y-crdtrev4996719(branchthds/0.26.0-patched).The
catch_unwindin this PR is deliberately the whole remedy here - it degrades to one unattributed span rather than requiring a patched yrs, so this PR needs no dependency change. If you would rather take the yrs pin instead and drop the guard, that works too, but it means carrying a fork of yrs.Relationship to the other open PRs
Independent of the logging/behavior split (#26, #23, #24) - no overlapping hunks, any merge order works.
Companion PR: No-Instructions/relay-git-sync#6 consumes this endpoint to produce per-author commits. That PR degrades gracefully when the endpoint is absent or returns 401/404, so it does not have to merge after this one.
Test plan