feat/select-all
needs attentionfaa43ee · incrementalPR #281reviewed 2026-07-09 01:11 UTC1H · 7M · 8L · 5I- Purpose
- Add Gmail-style select-all-matching bulk selection to the Contratos table so batch actions can target the entire filtered set beyond the 25-row page.
- Goal
- PR #281: feat(contratos): Gmail-style select-all-matching bulk selection
- Sub-goals
- SG-1: New GET /utility-contracts/keys endpoint + domain query (shares buildFullWhere with list)
- SG-2: Client-side materialized key set with epoch guard + selection lifecycle
- SG-3: BulkActionBar with persistent batch-result panel (grouped errors, narrow-to-failed, retry)
- SG-4: Fix pre-existing double-parse z.default() bug (serviceName schema) + regression test
- SG-5: Codify double-parse and select-all patterns in .claude/rules/
- What
- This commit (faa43eeb) adds documentation only — one bullet to api-patterns.md and one section to ui-patterns.md — codifying patterns discovered during implementation. The feature itself was in prior commits reviewed at af91420f.
- Why
- Persistent pattern capture so the double-parse z.default() hazard and Gmail-style selection architecture are available to future developers.
- Areas
- .claude/rules+39−0apps/platform/api+128−12apps/platform/BulkActionBar+706−98apps/platform/contratos+266−4apps/platform/messages+50−0domains/utility+147−1packages/api+101−2packages/analytics+11−0
- Blast
- 21 files, +1510/−118 across platform UI, API, domains, analytics, and .claude/rules. This commit is docs-only (+39/−0).
Findings · 21
correctness1
Double-parse scope 'internal routes' is ambiguous — applies to all ts-rest handlers with validateInput
.claude/rules/api-patterns.md
Readers interpret 'internal' as /api/internal/*. The hazard fires on any ts-rest handler that re-validates with validateInput after the contract parse.
security4
Keys endpoint docs omit role-floor requirement — any member can enumerate all RPU + address data
.claude/rules/ui-patterns.md
contractNumber (CFE RPU) and serviceName (address) are real-world sensitive identifiers returned up to 500/call. Doc must require the keys route carry the same role floor as the most-privileged action it feeds.
Cap bypass via sequential filtered calls
.claude/rules/ui-patterns.md
Cap is a UX rail, not a security ceiling. Doc should acknowledge or call out rate-limiting.
Sentinel-union fix may be misapplied to security-sensitive fields
.claude/rules/api-patterns.md
Add caveat for API keys/public IDs: prefer truly optional over present-but-empty sentinel.
Epoch guard has dual security property (confused-deputy prevention)
.claude/rules/ui-patterns.md
conventions4
PR reference format inconsistency — other bullets use 'PR-5 SG-N' not '#281'
.claude/rules/api-patterns.md
'imported by the schema' is misleading — CFE_BATCH_MAX_RECORDS is defined IN the schema file
.claude/rules/ui-patterns.md
'product-ux P10' is an opaque reference with no file path
.claude/rules/ui-patterns.md
Epoch guard not cross-referenced to Realtime list pages section
.claude/rules/ui-patterns.md
tests6
Epoch guard stale-response discard path has no unit test
apps/platform/src/app/[locale]/(dashboard)/bills/contratos/page.tsx:546
Filter-change-mid-flight → epoch-mismatch → discard is a key invariant with zero coverage. The 5 existing test files skip page orchestration logic.
Truncation-rejection path (total > keys.length → throw) is not tested
apps/platform/src/app/[locale]/(dashboard)/bills/contratos/page.tsx:552
BulkActionBar overCap test covers render-time matchingTotal > cap, not the runtime total > keys.length concurrent-write case.
Doc says 'abort' but implementation discards — terminology mismatch
.claude/rules/ui-patterns.md
Shared cap constant not verified by a cross-import test
packages/api/src/schemas/cfe-job.schemas.ts
Double-parse regression test exists and matches the prescribed pattern
packages/api/src/__tests__/schemas/cfe-job.schemas.test.ts
BulkActionBar batch-outcomes coverage is solid
apps/platform/src/app/[locale]/(dashboard)/bills/_components/__tests__/BulkActionBar.test.tsx
improvement6
api-patterns double-parse bullet: five actionable points in one run-on sentence
.claude/rules/api-patterns.md
Every adjacent Anti-Patterns bullet uses bold-lead + example + fix structure. Five points crammed into one sentence; split for scannability.
BAT-267 forward reference couples a stable rule doc to a point-in-time backlog ticket
.claude/rules/api-patterns.md
Replace with actionable instruction or drop — tracking tickets in rule files go stale.
selection-lifecycle 'or' clause reads as two alternatives, not bug-vs-guard
.claude/rules/ui-patterns.md
Second clause is the bug the guard prevents. Rephrase: '...discard it — otherwise a mid-flight filter change would silently resurrect a stale selection.'
Keys endpoint contract rules belong in api-patterns.md, not only ui-patterns.md
.claude/rules/ui-patterns.md
A developer writing a new keys endpoint looks in api-patterns.md first and misses count(*) OVER () vs separate count() correctness rule.
Row-meta REFRESH rule lacks test reference or observable symptom
.claude/rules/ui-patterns.md
Shared-caps bullet too abstract — naming CFE_BATCH_MAX_RECORDS gives a grep target
.claude/rules/ui-patterns.md