Skip to content

Batch resolveUserAuthzGrants: 8 sequential round trips could be 2-3, with no caching and no staleness #10825

Description

@os-zhuang

Split out of #10757 (direction 4) by PM ruling on PR #10824.

resolveUserAuthzGrants (packages/core/src/security/resolve-authz-context.ts ~330–560) issues 8 sequential round trips — legs 6–13 of an authenticated data request:

6. sys_member {user_id}
7. sys_user_position
8. sys_member {organization_id} (fellow-org, limit 1000)
9. sys_user_permission_set
10. sys_position {name $in}
11. sys_position_permission_set
12. sys_permission_set {id $in}
13. sys_user {id} (ai_seat)

They could be 2–3. No caching, no invalidation contract, no staleness — every read stays live, so this is independent of #10757's tranche 2 (caching) and cannot drift from whatever invalidation design that lands.

Why this is likely the highest-leverage no-risk work left

cloud#1539 measured, causally by latency injection (R² = 0.9994), that an authenticated request is 23.4 sequential legs and that:

L, not N, is the multiplier. Batching is worth exactly as much as deleting.

So collapsing 8 legs into 2–3 removes ~5–6 of 23.4 — roughly a quarter of the whole request — without touching a single authorization semantic.

Against the measured prod model server_ms ≈ 33 + L × 36.6:

legsprod server time
today23.4~890 ms
after this card~18~690 ms

Not sufficient alone (cloud#1521's gate is ≤200 ms, and placement is the lever that clears it — cloud#1546 is testing that now), but it is the largest block available that carries no staleness risk whatsoever.

Why batching beats caching here, stated plainly

A batched read returns the same rows or fails loudly. A cache returns stale grants silently — a permission revoked at T still honoured until a TTL expires. On the authorization path that difference is the whole ballgame, which is why this is separable from tranche 2 and worth doing whether or not tranche 2 ever ships.

Constraints

Measuring the result

X-OS-Debug-Timing: json on an admin principal returns Server-Timing: db;dur=…;desc="N queries". That gives the query count directly, but the number that matters here is legs, not queries — report both, and say how you established the leg count (a batch that runs 3 queries in parallel is 1 leg; 3 sequential is 3).

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions