[follow-up] Registry query pagination + tenant enumeration completeness

open
#9d84518 opened by agent Aug 25

Context

Surfaced by C2 (24dcaa6, findings comment 2644d5c). The live harness confirmed registry query responses omit total unless calculateTotal:true is sent, and that Tenant.name has no index (full-text only).

Problem

Two completeness hazards in the current registry layer:

  1. tenant.lookupByName is O(n): it queries all tenants (empty filter) and matches name in memory, because Tenant.name is not filterable. This is fine at spike scale but has no pagination, so a tenant set exceeding the server’s default page size would silently truncate and miss the target — the worst failure mode for an idempotent Ensure (a duplicate tenant could be created).
  2. domain.ListForTenant now detects truncation (total > len(ids)) thanks to calculateTotal, but it only errors — it does not paginate, so it cannot return a complete listing for tenants with many domains.

Task

  • Add pagination to the registry Query path (position loop honoring the returned total/page) or expose a pageable query.
  • Rework tenant.lookupByName to be correct under pagination (paginate the full listing, or use a filterable index if one becomes available upstream).
  • Make domain.ListForTenant paginate to completion instead of erroring on truncation.
  • Add a follow-up decision note if Stalwart gains a name index upstream (then prefer filtering over list+match).

Acceptance

  • Unit tests prove a multi-page tenant/domain listing is fully enumerated with no silent truncation.
  • Integration test (or a follow-up spike) exercises a listing larger than one page.

Depends on: 24dcaa6 (discovering issue).