Appearance
Workflow Rules
Allowed moves
Implement HasKanbanTransitions on the status enum:
php
enum TaskStatus: string implements HasColor, HasIcon, HasKanbanTransitions, HasLabel
{
public function getTransitions(): array
{
return match ($this) {
self::Backlog => [self::Todo],
self::Todo => [self::Backlog, self::InProgress],
self::InProgress => [self::Todo, self::Review],
self::Review => [self::InProgress, self::Done],
self::Done => [self::Review],
};
}
}Or define them on the board:
php
->transitions(['todo' => [TaskStatus::InProgress]])Columns you don't list accept anything. Refused moves are flagged while you drag, before you drop:

WIP limits
php
->wipLimits(['in_progress' => 3])The header shows 3 / 3, amber at the limit and red above it. Limits warn by default, like Jira. Refuse moves into a full column:
php
->wipLimits(['in_progress' => 3], enforce: true)
// or
->enforceWipLimits()Your own rules
php
->validateUsing(fn (Task $record, TaskStatus $to, ?Member $lane): ?string => ...)Return a message to refuse a move.
Hooks
php
->afterMove(fn (Task $record, TaskStatus $from, TaskStatus $to) => ...)Runs after a move is saved, for notifications or activity logs.
Permissions
With a policy on the model, update controls dragging and editing, create controls adding, and delete the delete action. Locked cards show a lock and can't be picked up.
Every rule runs on the server for drags, keyboard moves, inline adds and both modals.