central-worker-4 abd21f73f2 #5002: the rescue stamp is spent once the appointee uses it
VERIFY #5008 attacked the state #5002's own tests never built: not the rescue
that goes wrong and is undone within the minute, but the one that WORKS. A
group that was orphaned, was rescued, and is now being run by the person the
rescue appointed — with `recovered_by` still sitting on that person's row,
because the only thing that cleared it was the appointee re-saving their own
row, a write nobody makes.

So arm 3 of requireRemoveAccess() stayed open on the sole working manager of a
group that is plainly somebody else's business, which is the line the method's
own docblock says the stamp is narrow enough not to cross: strip the manager,
then "rescue" the group that press just orphaned, and a site admin who never
ran the desk manages it with the manager who staffed it gone. Two presses.

settleRescueStamp() clears the stamp on the actor's own row the moment they
ACT as the manager the rescue made them — staff the group, rename it, archive
it, give it a project or an email connection, remove a row: anything this file
lets a manager do to their own group. It is called from the three gates, not
from each action, because the gates are where "this write was authorised by
the actor's OWN manager row" is already decided, and a read of the page never
comes through them. The undo therefore lasts exactly as long as the mistake it
is for: until somebody takes the appointment up.

removableAgentIds follows without a change — it reads `recovered_by`, so the
button disappears with the gate.

  green: test_a_successful_rescue_does_not_leave_the_rescuer_able_to_take_the_group_over
         test_a_stamp_earned_on_one_group_is_not_a_claim_on_another
         all 17 of OrphanRecoveryIsReversibleTest, 215 Feature/Ticketing,
         3917 tests/Unit

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-21 06:58:49 -07:00
2026-04-08 14:12:03 -07:00
Description
Ticketing snap-in for dashboard-shell
Readme 756 KiB
Languages
PHP 100%