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
{{ message }}
Repository navigation
[finding] The share-link eligibility pin passes with the declared-field binder fully ablated — the surface it claims to cover has no real coverage #9085
Found while measuring #8489 (the plugin-sharing declared-field binder swap). Out of that card's scope — filed separately, unassigned, for triage. Measured, not inferred.
The gap
packages/plugins/plugin-sharing/src/share-link-eligibility.test.ts carries a case named for the exact behaviour the binder exists to produce:
"a DECLARED field the row left empty is judged, not faulted"
That case passes identically with bindDeclaredFields fully ablated. Measured: record.owner_id == null on row a_ok reaches RECORD_NOT_ELIGIBLE both with the binder and with the binder removed.
The reason is in the fixtures, not the assertion: every seeded row carries owner_id, so the row never exercises the declared-and-absent path. The binder is never the thing under test, and the case name asserts a property the test cannot observe.
Why it matters
assertEligiblefails closed — an unevaluable predicate raises ELIGIBILITY_UNEVALUABLE and refuses to mint the link. So this is not a live hole today; the cost is that the one pin standing over a security-relevant gate's materialisation behaviour cannot fail, and would not notice the binder being deleted, changed, or diverging further.
⭐ This is the same failure shape as the card that surfaced it: something written down as covering a contract, reconciled against nothing that would notice if it stopped.
#8489 is now needs-user-decision (adopting the canonical helper changes eligibility verdicts on one measured input class, in both directions). Whichever option is ruled there, its implementation has to rewrite this pin anyway — the dev's own note is that a discriminating pin needs a row where the declared field is genuinely absent, plus the !has(record.x) case.
So the cheapest sequencing is probably to fold this into #8489's eventual fix rather than land it standalone: both touch packages/plugins/plugin-sharing, and a standalone fix here would collide with that card and would have to guess which semantics to pin. Recording it as its own card so it is not lost if #8489 stays parked in the decision box — ⛔ not because it wants a separate dispatch.
Reproduction
Ablate bindDeclaredFields at share-link-service.ts:274 (pass record straight through) and run the suite. The named case stays green.
Finding triage (first-touch grading): pm:on-hold (seat-graded, 2026-08-16, triage seat), type Task. Not queued — the card's own analysis is right that a standalone fix would collide with #8489 and would have to guess which eligibility semantics to pin while that ruling is open. Not closed — a security-relevant gate whose only pin cannot fail is a real coverage hole, just not one that is live (the gate fails closed today, measured).
Named restart condition (single, observable): the #8489 ruling lands. Its implementation must rewrite this pin anyway (a row with the declared field genuinely absent, plus the !has(record.x) case), so this card folds into that dispatch as an in-scope deliverable rather than a separate PR. Trigger files for the lane's pre-dispatch check: packages/plugins/plugin-sharing/src/share-link-eligibility.test.ts, packages/plugins/plugin-sharing/src/share-link-service.ts. Cross-reference left on #8489.
If #8489 somehow closes without touching the binder, this re-opens for independent grading instead.
Triage: this comment is from the triage seat (scheduled run) — no claim.
Unlock/hold scan: the named restart condition — the #8489 ruling — fired 13:05Z today (maintainer accepted the recommendations; #8489 is back in the identity queue). Per this card's own hold terms, the discriminating pin rewrite must ride #8489's implementation rather than land independently, so the honest state is pm:on-hold → pm:blocked on #8489: this card is not independently dispatchable, and the unlock scan will re-check it when #8489's PR merges. Expected disposition at that point: verify the rewritten pin actually fails under binder ablation on the merged ref, then close this card as absorbed (or requeue the residual if the dispatch did not carry it).
A pointer has been left on #8489 so the dispatching seat folds this in.
Triage: this comment comes from the triage seat Routine; not a claim.
✅ Closed as absorbed by #8489 — the named restart condition fired and the deliverable landed
PM dispatch seat, session session_01Y26DJEHSBhhAQ6wwfsHNza. This card said explicitly it was "⛔ not because it wants a separate dispatch" — it wanted folding into #8489's fix. That is what happened.
#8489 landed as PR #9278 → fab693bee on main. The 2026-08-16 ruling made this pin's rewrite an in-scope, same-PR deliverable, and I verified the rewrite rather than taking the merge as proof.
Verified, not assumed
The complaint here was that the pin could not fail — it passed identically with bindDeclaredFields fully ablated, because every seeded row carried owner_id, so the declared-and-absent path was never exercised.
share-link-eligibility.test.ts on main now carries, in its own words:
:314 — "reached RECORD_NOT_ELIGIBLEidentically with the binder fully ablated" — the old defect recorded in the file, so the next reader learns why the shape is what it is
:330 — "The two cases fail in OPPOSITE directions under ablation"
:476 — "the ablation's control group"
:400 — the !(name in record) case, named and pinned
⭐ That is the discriminating structure the ruling asked for, and it went further than required: it keeps an explicit control group, so the ablation's failure is evidence rather than coincidence. A pin whose two halves move in opposite directions under ablation cannot silently stop testing anything.
Canonical helper adopted: import { materializeDeclaredFields } from '@objectstack/objectql/core' (share-link-service.ts:34), called at :276 as materializeDeclaredFields({ ...record }, schema?.fields) — the spread preserving non-mutation, exactly as Option A specified.
The local mirror is gone — function bindDeclaredFields no longer exists anywhere in packages/plugins/plugin-sharing/src/. Verified as an anti-control, not inferred from the diff.
⛔ Closing completed rather than not_planned: the work was done, just not in a PR of this card's own. pm:blocked cleared in the same stroke.
Activity
os-project-manager commentedon Aug 16, 2026
Finding triage (first-touch grading):
pm:on-hold(seat-graded, 2026-08-16, triage seat), type Task. Not queued — the card's own analysis is right that a standalone fix would collide with #8489 and would have to guess which eligibility semantics to pin while that ruling is open. Not closed — a security-relevant gate whose only pin cannot fail is a real coverage hole, just not one that is live (the gate fails closed today, measured).Named restart condition (single, observable): the #8489 ruling lands. Its implementation must rewrite this pin anyway (a row with the declared field genuinely absent, plus the
!has(record.x)case), so this card folds into that dispatch as an in-scope deliverable rather than a separate PR. Trigger files for the lane's pre-dispatch check:packages/plugins/plugin-sharing/src/share-link-eligibility.test.ts,packages/plugins/plugin-sharing/src/share-link-service.ts. Cross-reference left on #8489.If #8489 somehow closes without touching the binder, this re-opens for independent grading instead.
Triage: this comment is from the triage seat (scheduled run) — no claim.
Generated by Claude Code
os-project-manager commentedon Aug 16, 2026
Blocked-by: #8489
Unlock/hold scan: the named restart condition — the #8489 ruling — fired 13:05Z today (maintainer accepted the recommendations; #8489 is back in the identity queue). Per this card's own hold terms, the discriminating pin rewrite must ride #8489's implementation rather than land independently, so the honest state is
pm:on-hold→pm:blockedon #8489: this card is not independently dispatchable, and the unlock scan will re-check it when #8489's PR merges. Expected disposition at that point: verify the rewritten pin actually fails under binder ablation on the merged ref, then close this card as absorbed (or requeue the residual if the dispatch did not carry it).A pointer has been left on #8489 so the dispatching seat folds this in.
Triage: this comment comes from the triage seat Routine; not a claim.
Generated by Claude Code
fix(sharing): eligibility binds declared fields through the canonical…
os-project-manager commentedon Aug 17, 2026
✅ Closed as absorbed by #8489 — the named restart condition fired and the deliverable landed
PM dispatch seat, session
session_01Y26DJEHSBhhAQ6wwfsHNza. This card said explicitly it was "⛔ not because it wants a separate dispatch" — it wanted folding into #8489's fix. That is what happened.#8489 landed as PR #9278 →
fab693beeonmain. The 2026-08-16 ruling made this pin's rewrite an in-scope, same-PR deliverable, and I verified the rewrite rather than taking the merge as proof.Verified, not assumed
The complaint here was that the pin could not fail — it passed identically with
bindDeclaredFieldsfully ablated, because every seeded row carriedowner_id, so the declared-and-absent path was never exercised.share-link-eligibility.test.tsonmainnow carries, in its own words::314— "reachedRECORD_NOT_ELIGIBLEidentically with the binder fully ablated" — the old defect recorded in the file, so the next reader learns why the shape is what it is:330— "The two cases fail in OPPOSITE directions under ablation":476— "the ablation's control group":400— the!(name in record)case, named and pinned⭐ That is the discriminating structure the ruling asked for, and it went further than required: it keeps an explicit control group, so the ablation's failure is evidence rather than coincidence. A pin whose two halves move in opposite directions under ablation cannot silently stop testing anything.
The rest of #8489, for the record
import { materializeDeclaredFields } from '@objectstack/objectql/core'(share-link-service.ts:34), called at:276asmaterializeDeclaredFields({ ...record }, schema?.fields)— the spread preserving non-mutation, exactly as Option A specified.function bindDeclaredFieldsno longer exists anywhere inpackages/plugins/plugin-sharing/src/. Verified as an anti-control, not inferred from the diff.⛔ Closing
completedrather thannot_planned: the work was done, just not in a PR of this card's own.pm:blockedcleared in the same stroke.Generated by Claude Code
fix(sharing): eligibility binds declared fields through the canonical…