proto/server: one list contract — `List`, `ListSchedules`, `GetTimeline` and `GetCatalog` page four different ways, none declares an order, and only one takes a filter
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 9
- Forks
- 0
- Avg merge
- 3h 3m
- Merged PRs (30d)
- 509
Description
Observed behavior
At eb8172f:
| RPC | Page shape | More? | Order | Filter |
|---|---|---|---|---|
List (service.proto:688-748) |
page_size, opaque page_token |
next_page_token |
none declared | CEL over a vocabulary documented in the field comment |
ListSchedules (schedule.proto:265-279) |
none | truncated bool |
"whatever order the cluster returned them" | none |
GetTimeline (service.proto:1130-1201) |
max_entries, after_event_id |
truncated bool |
event order | none |
GetCatalog (service.proto:1300) |
none | none | none | none |
grep -rn order_by proto/ returns nothing. A page walk without a declared sort key cannot promise a stable boundary, which is the hazard next_page_token's own comment spends a paragraph on. The filter vocabulary is prose in one field's comment (service.proto:713-747), so an agent building a filter parses a docstring; the schedule list has no filter, so flow schedule list cannot narrow at all. A client library implements three cursor loops and three "is there more" predicates for one service.
The CLI already pays: flow list --all walks pages, flow schedule list reads one truncated page, and the MCP tools inherit each shape verbatim.
Desired outcome
One contract, stated once and applied to every list-shaped RPC:
page_size(bounded, server-clamped) and an opaquepage_token,next_page_tokenempty at the end, on every list.order_bywith a closed set of keys per resource and a default that is stable (start_time desc, workflow_idfor runs), declared in the request message's comment and enforced.filteras CEL on every list, with the bound names published as a machine-readable declaration (GetCatalogalready carries the CEL environment for expressions; the filter vocabularies belong beside it) so an editor and an agent read the same list the server compiles against.truncatedretired in favor of the token, since a truncated page with no cursor cannot be resumed.
Acceptance criteria
ListSchedulesRequestandGetTimelineRequesttake the same paging fieldsListRequestdoes;flow schedule list --filter 'state == "paused"'works.- A test walks each list under a page size of 1 and asserts every item appears exactly once, in the declared order, on a fixture of at least three items.
- The filter vocabularies are served by one RPC and
docs/reference/renders them from it.
Constraints and dependencies
List's in-process tenant filtering and its scan bounds (#1384) are unchanged by this; ordering must be the visibility store's order or the contract says pages are ordered within the scanned window only.GetTimeline's cursor (#1119, #1135 in the proto comments) becomes the page token.- Additive fields;
truncatedis deprecated before removal per #722.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with service.proto sections 688-748, 1130-1201, and 1300, then compare schedule.proto lines 265-279 with ListRequest. Trace flow list --all and flow schedule list to understand their current pagination behavior. Done means every list passes the page-size-1 uniqueness and ordering checks, schedule filtering works, and one RPC supplies vocabularies rendered by docs/reference/.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend-api-design, cli, documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100