Siren

ProgramUnboundFromCollaboratorGroup

Fires when a program's collaborator group binding is cleared.

Last updated: June 3, 2026

ProgramUnboundFromCollaboratorGroup fires when an operator clears a program’s collaborator group binding. After this event, the program no longer has a group for cascade strategies to walk. Any cascade calc still configured on the program fails closed: it credits no one and raises no error, and it keeps doing so on every trigger until the program is bound to a group again. That silent zero-payout is the main reason to handle this event.

The event ID is program_unbound_from_collaborator_group, and its fully qualified class is Siren\Plus\Core\Groups\Events\ProgramUnboundFromCollaboratorGroup. It fires after the binding is cleared, from the program edit endpoint. To run code when it fires, register a handler with Siren’s event system. See listeners and the events introduction.

What does this event carry?

The event carries the program id and the group id that the program was previously bound to. That historical group id is included specifically so that audit listeners and external mirrors can describe what was removed, not just that something was removed.

use PHPNomad\Events\Interfaces\CanHandle;
use PHPNomad\Events\Interfaces\Event;
use Siren\Plus\Core\Groups\Events\ProgramUnboundFromCollaboratorGroup;

class HandleProgramUnbinding implements CanHandle
{
    public function handle(Event $event): void
    {
        if (!$event instanceof ProgramUnboundFromCollaboratorGroup) {
            return;
        }

        $programId = $event->getProgramId();
        $previousGroupId = $event->getGroupId();

        // Cascade calcs on this program now have no group to walk
    }
}

How does it fit?

The unbind event is only broadcast when there was a real prior binding to clear. Clearing an already-unbound program is a silent no-op so the activity feed doesn’t fill up with phantom events from idempotent edits. Re-binding to a different group produces an unbind for the old group id immediately followed by a ProgramBoundToCollaboratorGroup for the new one. Both fire synchronously in the same request, so the unbind precedes the bind.

This event tracks the deliberate unbind or rebind action, not the liveness of the binding. Deleting the bound group does not fire it: the binding row stays on the program, now pointing at a group that is gone, and a cascade bound to it fails closed. Deleting the program does not fire it either. So a system that mirrors which programs point at which groups must reconcile group and program deletions on its own rather than rely on this event alone.

ProgramBoundToCollaboratorGroup is the bind side, and DistributorBoundToCollaboratorGroup and DistributorUnboundFromCollaboratorGroup are the distributor-side pair. The collaborator group events reference lists the full family.