Found while triaging the parameterless-catch read seams for #12753 (see PR #12851 for the full 11-site triage). Filed unassigned, and ⛔ with no domain:* — that is triage's single-producer field, per the convention recorded on #8901.
⛔ Not repaired in #12851: that PR's scope is a gate-header record, and this is a source fix in another package.
The seam
packages/objectql/src/lifecycle/lifecycle-service.ts, loadGovernance():
if(typeofengine.find==='function'&&declared.length>0){try{constorgs=awaitengine.find('sys_organization',{limit: TENANT_SCAN_LIMIT,context: { ...SYSTEM_CTX}});for(constorgoforgs??[]){ ... snapshot.tenantOverrides.set(objectName,list);}}catch{// No sys_organization (single-tenant kernel) - tenant overrides n/a.}}returnsnapshot;Why it is wrong
Same #4728 shape as the seam this is filed beside: the comment names one benign cause, the catch swallows every cause. But the consequence here is heavier than an invisible row, because the value being computed governs deletion.
snapshot.tenantOverrides is the ADR-0057 §3.2 per-tenant retention/expiry window set. On any failure of the sys_organization read — connection loss, permission refusal, a driver fault — the map is returned empty, and the sweep that consumes it cannot tell "this deployment has no tenant overrides" from "the read that would have found them did not happen". Every tenant then falls back to the global retention window, which is the wrong window in both directions: a tenant configured to keep rows LONGER has them expired early, and one configured to keep them shorter keeps them.
The failure is not reported anywhere: loadGovernance returns a GovernanceSnapshot with no field saying the tenant pass was incomplete, and the catch logs nothing.
The fix
}catch(error){if(!isMissingTableError(error))throwerror;// packages/metadata/src/errors.ts}— or, if the sweep must stay fail-open on every branch, one logger.error naming the consequence, which is what the read-seam rule asks for at a seam that genuinely cannot discriminate. What must not stay is an empty override map that is indistinguishable from a configured one.
Measurement context
1 of 11 read seams with a parameterless catch on origin/main @ 6f0fec3d0, and 1 of only 2 of those 11 graded genuinely wrong. Related but distinct: #8906 (closed) covered checkGovernance in the same file — a different method, a different probe. Not covered by #8901's cohort, #8896 or #8895.
Generated by Claude Code
Found while triaging the parameterless-catch read seams for #12753 (see PR #12851 for the full 11-site triage). Filed unassigned, and ⛔ with no
domain:*— that is triage's single-producer field, per the convention recorded on #8901.⛔ Not repaired in #12851: that PR's scope is a gate-header record, and this is a source fix in another package.
The seam
packages/objectql/src/lifecycle/lifecycle-service.ts,loadGovernance():Why it is wrong
Same #4728 shape as the seam this is filed beside: the comment names one benign cause, the
catchswallows every cause. But the consequence here is heavier than an invisible row, because the value being computed governs deletion.snapshot.tenantOverridesis the ADR-0057 §3.2 per-tenant retention/expiry window set. On any failure of thesys_organizationread — connection loss, permission refusal, a driver fault — the map is returned empty, and the sweep that consumes it cannot tell "this deployment has no tenant overrides" from "the read that would have found them did not happen". Every tenant then falls back to the global retention window, which is the wrong window in both directions: a tenant configured to keep rows LONGER has them expired early, and one configured to keep them shorter keeps them.The failure is not reported anywhere:
loadGovernancereturns aGovernanceSnapshotwith no field saying the tenant pass was incomplete, and the catch logs nothing.The fix
— or, if the sweep must stay fail-open on every branch, one
logger.errornaming the consequence, which is what the read-seam rule asks for at a seam that genuinely cannot discriminate. What must not stay is an empty override map that is indistinguishable from a configured one.Measurement context
1 of 11 read seams with a parameterless
catchonorigin/main@6f0fec3d0, and 1 of only 2 of those 11 graded genuinely wrong. Related but distinct: #8906 (closed) coveredcheckGovernancein the same file — a different method, a different probe. Not covered by #8901's cohort, #8896 or #8895.Generated by Claude Code