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
[finding] plugin-security: three find() seams still report an un-happened read as [] — the invention half of #15598's DROP shape, left in place by that card's fence #15840
Filed unassigned and ungraded by the os-dev seat working #15598 (PR #15838, branch claude/issue-15598-plugin-security-dead-limbs, session session_01XpTx2tbq3pZRYAdoGt6E6Y). domain:*, type and priority are triage's.
What was found
#15598 asked for two things: remove six dead { records } limbs, and repair the seventh block (security-plugin.ts's sys_permission_set loader), which was inventing an empty answer for a read that did not happen. That repair landed: the read fault now propagates and an unreadable page refuses, so an outage is no longer reported as "this principal has no permission sets".
While driving the other six seams, the same invention was measured in three of them — smaller, but the same shape:
non-array answers []; the catch answers [] silently
Each maps "the read did not answer" onto the same value as "there is nothing there". That is the read-seam invention rule in AGENTS.md — a storage read in a try, a path out returning an invented empty, never discriminating on the error's type — and it is exactly the direction #15092 named as the opposite of a dead limb.
The consequence differs per site and needs reading, not sweeping. The seventh block was repairable with confidence because its consumer already declared the handling — PermissionEvaluator.resolvePermissionSets catches a throwing loader, stays fail-closed, and reports it ([security][observability] resolvePermissionSets swallows dbLoader failures silently — custom permission sets vanish with no log #2565). These three have no such declared consumer contract, so what "gap" means at each one is an open question: normalizeManagedByVocab returning a count it cannot attest, claimSeedOwnership deciding whether an unreadable page should stop the pass, reconcileOrgAdminGrant deciding whether an unreadable membership read should skip or refuse.
⛔ Not a request to widen any gate — #15094 ruled against that (precision 0.446 / 0.857, measured), and PR #15838 changed no gate's population.
⛔ Not a claim that any of the three is currently causing a user-visible failure. The engine was driven and resolves a bare array at all three seams today (PR #15838's table), so the non-array arm is not reached; the catch arms are the reachable half.
⛔ Not blocked on anything, and nothing is blocked on it.
Dedup
One targeted search_issues (REST is 403 for this seat and gh is absent, so the deterministic listing route was unavailable), with the control satisfied in the same call: the query returned #15598 and #15597, both known must-hits, so the empty result for this finding is a reading and not a false zero. Ten results total; the nearest neighbour (#12515, the two human-user predicates disagreeing on non-object rows) is closed and a different subject.
Refs
#15598 (the card this was found from) · PR #15838 (the repair that fenced it out) · #15092 (gap-vs-drop, the direction) · #15094 (the census, and the ruling against one rule for all instances) · #14843 / #14460 · #2565 (the declared-consumer contract that made the seventh block's repair decidable)
Filed unassigned and ungraded by the
os-devseat working #15598 (PR #15838, branchclaude/issue-15598-plugin-security-dead-limbs, sessionsession_01XpTx2tbq3pZRYAdoGt6E6Y).domain:*, type and priority are triage's.What was found
#15598 asked for two things: remove six dead
{ records }limbs, and repair the seventh block (security-plugin.ts'ssys_permission_setloader), which was inventing an empty answer for a read that did not happen. That repair landed: the read fault now propagates and an unreadable page refuses, so an outage is no longer reported as "this principal has no permission sets".While driving the other six seams, the same invention was measured in three of them — smaller, but the same shape:
packages/plugins/plugin-security/src/auto-org-admin-grant.ts:151(tryFind)[]; thecatchanswers[]atdebugpackages/plugins/plugin-security/src/claim-seed-ownership.ts:177(idsFrom)[], with no report at allpackages/plugins/plugin-security/src/normalize-managed-by.ts:53(tryFind)[]; thecatchanswers[]silentlyEach maps "the read did not answer" onto the same value as "there is nothing there". That is the read-seam invention rule in AGENTS.md — a storage read in a
try, a path out returning an invented empty, never discriminating on the error's type — and it is exactly the direction #15092 named as the opposite of a dead limb.Why it was NOT fixed in PR #15838
Deliberate, and stated in that PR's body. Three reasons:
[]into one that gaps or refuses is a behaviour change with its own blast radius. PR fix(plugin-security): retire seven dead{ records }find-result limbs, and stop the permission-set loader inventing an empty page #15838 keeps each of the six blocks' existing disposition for a non-array exactly as it was, precisely so the diff carries no unreviewed behaviour.PermissionEvaluator.resolvePermissionSetscatches a throwing loader, stays fail-closed, and reports it ([security][observability] resolvePermissionSets swallows dbLoader failures silently — custom permission sets vanish with no log #2565). These three have no such declared consumer contract, so what "gap" means at each one is an open question:normalizeManagedByVocabreturning a count it cannot attest,claimSeedOwnershipdeciding whether an unreadable page should stop the pass,reconcileOrgAdminGrantdeciding whether an unreadable membership read should skip or refuse.{ records }-normalizer gate's population is app-showcase page modules, but all three instances found so far are outside it — #14460's stated evidence threshold is now met #15094's triage says to treat "N instances" as evidence the class is real, never as evidence one rule fits them all — and plugin-security: 7{ records }union-normalizer blocks onfind()results — dead limbs, one of them also #15092's DROP shape (security-plugin.ts:1292) #15598's own triage says a uniform sweep would have got its seventh block backwards.What this is not
⛔ Not a request to widen any gate — #15094 ruled against that (precision 0.446 / 0.857, measured), and PR #15838 changed no gate's population.
⛔ Not a claim that any of the three is currently causing a user-visible failure. The engine was driven and resolves a bare array at all three seams today (PR #15838's table), so the non-array arm is not reached; the
catcharms are the reachable half.⛔ Not blocked on anything, and nothing is blocked on it.
Dedup
One targeted
search_issues(REST is 403 for this seat andghis absent, so the deterministic listing route was unavailable), with the control satisfied in the same call: the query returned #15598 and #15597, both known must-hits, so the empty result for this finding is a reading and not a false zero. Ten results total; the nearest neighbour (#12515, the two human-user predicates disagreeing on non-object rows) is closed and a different subject.Refs
#15598 (the card this was found from) · PR #15838 (the repair that fenced it out) · #15092 (gap-vs-drop, the direction) · #15094 (the census, and the ruling against one rule for all instances) · #14843 / #14460 · #2565 (the declared-consumer contract that made the seventh block's repair decidable)