Skip to content

Spec + fixtures: permission-scoped pagination — empty page with live cursor is legal; wire envelope example leaks total #141

Description

@cuibonobo

From docs/design-review-2026-08.md §A4. Documentation/fixture drift, not a code bug — ScopedStack.query()'s filtered-refill honors cursor semantics correctly.

Problem

  1. Empty page with a live cursor is legal and undocumented. The refill loop stops at maxFetched = limit * 10, so a low-visibility requester scanning a large stack can receive { records: [], cursor: "..." } — repeatedly — before results appear. "Empty page means done" is the near-universal client assumption, and nothing in §Sorting and pagination or the wire format warns against it. A server implementer or app author will ship the truncation bug the spec's own Core code treats one query() page as the complete result set (grants, attachment metadata, uploader checks) #50 rule exists to prevent.
  2. The wire format's response envelope example shows "total": 142 with no qualification, while the spec elsewhere requires permission-scoped queries to report total: null (cardinality leak, ScopedStack.query()'s deliberate behavior). A server implementer working from the envelope example will leak exactly what ScopedStack was designed not to.

Work items

  • §Sorting and pagination: one sentence — a page may be empty while cursor is non-null; cursor: null is the only end-of-results signal
  • Wire format response envelope: show total: null (or both variants, labeled with when each applies)
  • Conformance fixtures: scoped-query envelope asserts total: null; a fixture pinning empty-page-with-cursor as valid
  • Optional spec sentence: a server MAY cache grant/roster resolution within a single request (every scoped query currently cursor-walks _grant@1 and resolves group rosters per record — correct at intimates scale, and servers should be able to cache it without deviating from spec)

Cross-refs: #50 (pagination-as-exhaustive), #52 (fixtures), design-review-2026-08 §A4.

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