feat(datastore): List guard extraction, zero cursor id part 1/4 (S09 Enforcement plan: 18/20)
Part 1 of 4 of the S09 enforcement plan — Step 18: Candidate repository enumeration.
The step is split into 4 stacked MRs to keep each within the review size limit (≈800 ideal). Each part targets the previous one (part 1 → main); review and merge bottom-up.
Stacked MRs (review/merge bottom-up)
- feat(datastore): List guard extraction, zero cu... (!2143 - merged) • David Fernandez • 19.4
👈 - feat(datastore): repository key enumeration par... (!2144 - merged) • David Fernandez • 19.4
- test(datastore): enumeration integration suite ... (!2145 - merged) • David Fernandez • 19.4
- feat(datastore): fetch rows by id set with a ba... (!2146 - merged) • David Fernandez • 19.4
This part (~203 reviewable LoC at ddfffa14)
Groundwork shared with List: extracts ListRepositoriesParams.validate() (the guard chain) and repositoryListClauses (the WHERE predicate and ORDER BY assembly) out of List/listRepositoriesStmt, so the candidate-key enumeration part 2 adds can share them. One behavior addition rides with the extraction: a cursor whose ID is the zero UUID is now rejected (errRepositoryCursorZeroID) — under the non-name sorts a zero id in the row-value bound would silently re-serve (ascending) or skip (descending) the whole tie group at the cursor's key. The rendered SQL of List is unchanged (its EXPLAIN pins still pass).
References
No e2e scenario is added or affected: datastore-only reads with no route change; no catalog covers the management API, and the listing filter's behavior is pinned by Step 19's handler tests (plan Testing Strategy).
Related to #860 (closed)