# The board

2026-08-11

Phase 3 of the issue tracker. The model, the screens and the admin exist; this
is the first view that is not a list.

## 🚨 The decision everything else follows from: a drag is a transition

Dragging a card from one column to another looks like setting a field. It is
not. It is a **status change**, and every rule the workflow enforces has to
apply to it — the same rules that were enforced on the issue page, by the same
code, refusing the same moves.

The lazy version writes the new status straight onto the row. That version:

- lets a bug go from Open to In review in one gesture, which the workflow
  spends its whole existence forbidding
- closes an issue with no resolution recorded, so "why did we stop" is blank on
  exactly the issues somebody dragged rather than clicked
- ignores group restrictions, because there is no button to hide
- writes no history, so the one action people take fifty times a day is the one
  action that leaves no trace

So the board calls `Workflow::apply()` like everything else. **If no transition
exists between the two statuses, the drop is refused and the card goes back.**

That has a visible consequence worth stating plainly: **a board can have
columns you cannot drag between.** That is not a bug to be designed around — it
is the workflow being true. The board's job is to show it early: a column the
card cannot reach is dimmed while dragging, so the refusal happens before the
drop rather than after.

The same argument that removed `/triage` in phase 2. A second door into the
same state is not a convenience, it is the rules being optional.

## Columns come from the workflow, until somebody says otherwise

A board with no configuration is a board people use. So by default the columns
**are** the workflow's statuses, in the workflow's own order, and a site that
never opens the board settings still gets something correct.

Configuration is for the case the default gets wrong: several statuses that
belong under one heading. *Confirmed* and *Open* are both waiting; a team that
wants one **To do** column should have it. So a column may hold more than one
status, and dropping into it moves the card to the column's **first** status
that the workflow can actually reach from where the card is.

🚨 **Only stored when customised.** A board row that duplicates the workflow is
a copy that goes stale the moment somebody adds a status — the board would
quietly stop showing issues in it, with nothing to say why. No row means "ask
the workflow", which cannot drift.

## WIP limits warn, they do not block

A column over its limit is coloured, and the number says so. It does not refuse
the drop.

The reason is what a WIP limit is *for*: it is a signal to a team about their
own habits, not a permission. Blocking the drop means the work still happened
and the board now disagrees with reality — and the person's next move is to
turn the limit off, which loses the signal permanently. A limit people can
exceed and see is one they keep.

## What decides the order within a column

`board_rank`, the decimal column added in phase 1. Dropping a card between two
others sets its rank to the midpoint of theirs: one `UPDATE`, no renumbering.

🚨 **Cards with no rank sort last, by key.** Every issue filed before the board
existed has a null rank, and sorting nulls first would greet a team with their
entire backlog in front of the work they had just ordered by hand.

## Swimlanes

By epic, by assignee, or none. None is the default, because a swimlane is only
useful once a board has enough cards to need dividing and an empty board split
four ways looks broken.

## What this phase does not do

- **Sprints and a backlog.** That is phase 4; a Kanban board has no sprint.
- **Card editing in place.** A card is a link to the issue.
- **Cross-project boards.** A board belongs to a project. The filter language
  that would make a board over several projects meaningful is phase 5, and
  building the board on a filter it cannot express yet would mean building it
  twice.

## Not matched, deliberately

- **Card layouts.** Jira lets an administrator choose which fields appear on a
  card. Convoro shows key, title, type, priority, assignee and labels, decided
  once. The configurability costs more in confusion than it returns — the same
  call the phase 1 note made about screen schemes.
- **Board-level permissions.** Who may see a board is who may see its project.
  A second permission model over the same issues is two answers to one question.
