You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(security): measure the unscoped existence page cap instead of trusting it (#11518) (#11962)
`buildExistingByName`'s UNSCOPED page was capped at `limit: names.length`,
exact only while one row can exist per name. Since #8461 / ADR-0120 D1 the
identity tables are unique PER ORGANIZATION and ADR-0066 D1 encourages admins
to EXTEND the registry inside their own organization, so one name legitimately
carries a row per organization plus the platform's. The rows that fall off a
full page are the highest ids under #4363's `ORDER BY id ASC`, so whole names
vanish — and a vanished name reads as `absent`, which INSERTS.
No constant multiplier is correct (the bound is the organization count), so the
cap is now a measurement: the read asks for one row MORE than it will hold, and
a page carrying that extra row is a PREFIX of the answer. It joins the module's
existing "could not answer" causes and degrades to the per-item read — the
fallback already there for a driver without `$in` — with its own diagnostic.
⚠️ Behaviour change on two shipped seeders in the truncating case: from a
silent wrong answer to a loud slow one. Non-truncating installs are unchanged,
one read and no warning.
The SCOPED arm keeps #10103's `names.length * 2` — there the number is a proven
bound, not a budget — and gains the same probe, so a scoped page that overflows
it (an absent unique index) degrades loudly instead of truncating silently.
Claude-Session: https://claude.ai/code/session_01APWX2AwT3a4xDcjPCe8bk4
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments