RIDING BYTES
← All insights

July 21, 2026 · 5 min read

End of the line: dispose and dispatch as optional workflows

SENAITE 2.x gets a Sample Dispose workflow and turns Sample Dispatch into a togglable one. Both share a new locking mechanism so downstream analyses can never be silently edited on an archived sample.

End of the line: dispose and dispatch as optional workflows

Most of the samples a lab handles pass through the same story: booked, received, tested, verified, published. What happens next was, until now, either invented per-lab or written down outside of SENAITE. Two recent PRs in senaite.core add proper endings.

A dispose workflow, opt-in

senaite.core#2970 introduces a real dispose transition and a disposed state. Turn on the Dispose workflow toggle in the setup (dispose_workflow_enabled, off by default) and every post-receipt state gets a Dispose action: sample_received, to_be_verified, to_be_preserved, verified, published, rejected, invalid, and even cancelled. So the sample that sat cancelled in the fridge for a year can still be recorded as disposed of, with actor, date, and reason.

The dispose_samples form asks for a comment, pre-filled with a sensible default. An alert viewlet on the sample view carries the disposal metadata forever. A guard blocks disposal while an analysis is still on a worksheet. Partition-primary rules apply: dispose a primary and its partitions follow; dispose the last partition and the primary auto-disposes.

A new permission, senaite.core: Transition: Dispose Sample, is granted to LabManager and Manager. An upgrade step registers the permission, state, and transition; nothing is user-visible until the toggle flips.

Dispatch, now optional and locking

senaite.core#2971 does the parallel move for the existing dispatch flow. The dispatch transition and the dispatched review-state tab are gated by Enable the Sample Dispatch workflow. For existing installs an upgrade step turns dispatch on so nothing breaks; new installs start it off.

More importantly, dispatching now locks the sample’s analyses. Before this PR, a dispatched sample was recognisable only through its review state; the JSON API could still write results on it because analysis edit permissions are governed by the analysis state, not the sample state. That gap is closed.

The reusable locking mechanism

The interesting part is what both features share. Instead of a one-off “dispatched analyses are locked” rule, the PR introduces a marker interface ILockingState and a new analysis state called locked. IDisposed and IDispatched both inherit from ILockingState. The analysis lock guard reads:

ILockingState.providedBy(sample)

That’s it. Any future sample state that wants the same behavior, say a hypothetical IStored in senaite.storage, just inherits ILockingState and gets analysis locking for free.

Locking is careful about what it touches. Analyses already in a terminal state (cancelled, rejected, retracted) are left alone, so disposing a cancelled sample never resurrects its analyses into locked and their is_active status stays truthful. The locked state has a single hidden, automatic unlock transition; its after_unlock event rolls each analysis back to the exact status it held before the lock. Restore a sample and the analyses come back with their original state intact, no bookkeeping in the caller.

What this means for a lab

Two immediate wins.

First, the end of a sample’s life is now first-class. If your retention policy says “hold for two years then dispose”, the disposal is a transition with an actor, a date, and a reason, on the sample itself. Auditors get one place to look.

Second, downstream integrations can trust a sample’s terminal state. Once dispatched or disposed, no adapter, no admin script, no JSON API call will silently mutate an analysis result. The locking is enforced in the workflow layer, above whatever code tries to write.

Both toggles ship off by default. If your lab does not need them, the day-to-day flow does not change. If it does, they slot in without touching custom code.

Bring this to your lab

Whether you are evaluating SENAITE, scaling it across sites, or wiring up instruments and monitoring, the team that wrote the platform is the team you talk to.

Start a conversation