Skip to content

feat(approvals): approver join table — exact pushdown for approver-filtered pagination#1782

Merged
xuyushun441-sys merged 1 commit into
mainfrom
feat/approvals-approver-join-table
Jun 12, 2026
Merged

feat(approvals): approver join table — exact pushdown for approver-filtered pagination#1782
xuyushun441-sys merged 1 commit into
mainfrom
feat/approvals-approver-join-table

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

Summary

The follow-up half of #1745 (server-side pagination landed in #1764). pending_approvers stayed a CSV column, so approver-filtered queries ("my pending") were still a post-filter over a bounded 500-row scan — correct for personal queues, wrong for org-wide approver queries past the window.

  • New sys_approval_approver object — one row per (pending request, approver identity: user id / email / role:* literal). Indexed on (approver, organization_id) and (request_id). The table only holds the live work queue: rows are cleared when a request leaves pending, so size tracks open approvals, not the append-only request history.
  • Service-side maintenance — every write path that touches pending_approvers (open / decide incl. unanimous partials / recall / send-back incl. auto-reject / reassign / SLA-escalate) mirrors the change into the index via a diff-based syncApproverIndex.
  • Full pushdownlistRequests / countRequests resolve approver filters to request ids through the index ($in on indexed equality replaces the per-row CSV scan), and status arrays now push down as $in. Every filter is engine-side, so limit/offset and totals are exact at any table size; the documented 500-row residual is gone.
  • BackfillrebuildApproverIndex() rebuilds the index from the CSV source of truth (drops orphans/stale/duplicate rows, inserts missing ones) and runs idempotently on kernel:ready, so rows written before the index existed become queryable after one boot.
  • pending_approvers stays the human-readable source of truth; sys_approval_request index comment updated accordingly.

No API contract change — IApprovalService.listRequests/countRequests signatures and the REST surface are untouched.

Tests

  • Index maintenance across all 8 write paths (open / decide / recall / unanimous partial / reassign / SLA-reassign)
  • Approver-filtered pagination correctness past the old 500-row scan window (30 matches buried under 510 newer rows)
  • Status-array $in pushdown
  • rebuildApproverIndex: legacy backfill, orphan + stale-entry cleanup, idempotence

90/90 package tests green, build green.

Closes #1745

🤖 Generated with Claude Code

…ltered pagination (#1745)

sys_approval_approver holds one row per (pending request, approver
identity); the service mirrors every pending_approvers change into it
and clears rows when a request leaves pending. listRequests /
countRequests resolve approver filters through the index and push
status arrays down as $in, so pages and totals are correct at any
table size — the 500-row bounded-scan residual is gone.
rebuildApproverIndex() backfills idempotently at plugin start.

Closes #1745

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 12, 2026 11:41am

Request Review

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Jun 12, 2026
@xuyushun441-sys
xuyushun441-sys merged commit f3c1735 into main Jun 12, 2026
12 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the feat/approvals-approver-join-table branch June 12, 2026 11:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf(approvals): server-side pagination + pushdown filtering for listRequests

2 participants