Skip to content

Expose StickyIndex resolved owner or validate the supplied Sequence #422

Description

@JoongWonSeo

Problem

StickyIndex.decode(data, sequence) documents sequence as “the Array or Text the sticky index belongs to”, but the supplied sequence is only retained as a transaction source. get_index() returns the offset resolved by Yrs from the sticky index's actual owner and does not check that Offset.branch is the supplied sequence.

That makes a foreign relative position silently retarget to the same numeric offset when decoded against a neighboring Text:

from pycrdt import Assoc, Doc, Map, StickyIndex, Text

doc = Doc()
root = doc.get("m", type=Map)
a = Text("abc")
b = Text("abc")
root["a"] = a
root["b"] = b

foreign = StickyIndex.new(b, 2, Assoc.AFTER).encode()
resolved = StickyIndex.decode(foreign, a)
assert resolved.get_index() == 2  # accepted, but the Yrs Offset.branch is b

Yrs already returns both pieces from StickyIndex::get_offset: Offset { branch, index, assoc }. pycrdt's Rust wrapper currently exposes only .index, discarding the branch. Yjs exposes the analogous absolute position's type, so cross-runtime code can validate exact shared-type ownership there but cannot do so through pycrdt.

Requested contract

Please expose a non-mutating way to resolve a sticky index against an exact Text/Array, returning None (or otherwise failing cleanly) when Offset.branch differs. For example:

StickyIndex.decode(data).resolve(sequence) -> int | None

or an owner identity on the resolved offset that can be compared with the supplied sequence. Keeping get_index() backward compatible is fine; the important part is that callers can inspect or enforce the resolved owner without parsing Yrs internals.

It would also be helpful for malformed/unresolvable positions to return a Python error/None rather than reaching the wrapper's current unwrap(), but exact owner resolution is the blocking need.

Observed with pycrdt 0.13.1; current main/0.14.4 appears to expose the same index-only wrapper.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions