← The specification

Rollback

Rendered from spec at76d46f3 (2026-10-25) · its source · Edit this page

Status: Accepted · Audience: Operator · Area: E — Maintenance


Purpose

Undo a recent change quickly, without a full restore.

E3 recovers from disasters. Rollback handles the far more common case: something was changed a few minutes ago and it made things worse. A preset was adjusted, a service updated, a remediation applied, a data root moved.

Requiring a full restore for a small regret is heavy enough that operators don’t bother — they live with the regression, or they poke at it manually until the state is something nobody designed. Making undo cheap is what makes the system feel safe to touch.

Behaviour

Changes are journaled

Every change lemonfiber makes is recorded: what changed, from what to what, when, and why. That journal is what makes targeted undo possible, and it doubles as an answer to “what happened to my stack?”

Rollback is per-change, not global

The operator reverts the thing they regret, not everything since a point in time. Rolling back an update should not also revert an unrelated preset change made afterwards.

What can and cannot be rolled back is stated plainly

Change Rollback
Configuration values Yes — restore prior values
Quality preset Yes
Service version, no migration Yes — repin and restart
Service version, migration occurred No — requires restore from backup
Applied remediation Yes, where it recorded prior state
Data root move Partially — path re-pointed; moved data is not moved back automatically
Seed operations Yes — prior values restored
A secret Only while the secret store’s one previous value still matches the fingerprints journalled; otherwise replaced at the terminal (ARCH-R276)
Uninstall No

The migration row is the important one. Offering an action that cannot succeed is worse than stating the limitation: the operator would attempt it, fail, and have lost time in a moment of stress.

The distinction is explained, not just enforced

When rollback is unavailable because a database migrated, lemonfiber says why and points at the backup taken automatically before that update (E1-R4) — which is precisely the situation that backup exists for.

Rollback is itself journaled

A rollback is a change, and can be rolled back. Undoing an undo must be possible; operators overshoot.

History is browsable

What changed, when, by which operation. Answers “why is this different from last week?” without archaeology.

On the companion

Rollback reaches the companion twice: as the act (N6) and as the record it leaves (N11).

The table above is the load-bearing part of the act. Two of its rows are partial, and the data root move is the clearest: the path is re-pointed, and the data does not come back with it. N6-R6 requires a reversal to name what it could not reverse and why, and to lead with that rather than append it — an operator who believes a thing was undone and finds half of it still there has been told something false. The migration row is the other one. Where rollback is unavailable and a restore is what remains, N6-R10 forbids offering either as though it were the other: they put back different things, and this is the worst possible moment to be unclear about which.

What this feature journals is what N11 renders. A browsable history has an end, and N11-R1 requires that end stated, because a list that simply stops is indistinguishable on a small screen from nothing having happened. Since a rollback is itself a change, every entry can carry how it would be reversed; N11-R2 requires that carried, and requires an entry that cannot be reversed to say so rather than omit the field — an absent field reads as a question nobody answered, not as a no. N11-R3 requires an entry to show how many changes accompanied it, because per-change rollback only means something if the operator can see what the change was part of, and N11-R4 requires a recorded reason shown where there is one.

Two failures of rendering are named rather than left to judgement. N11-R5 forbids presenting this record as a log, which is the line N2 already draws, and N11-R10 requires changes written at the same instant ordered deterministically rather than shown as one having preceded the other. An empty record and a record that could not be read remain different answers (N11-R9).

States

Per journaled change:

State Meaning
applied In effect
reversible Can be rolled back automatically
irreversible Cannot; reason stated
partially-reversible Some aspects revert; others stated
rolled-back Reverted
superseded A later change replaced it; rolling back needs care

Edge cases

Situation Behaviour
Later change depends on the one being rolled back Detect and report the dependency; require explicit confirmation or refuse.
Value changed manually since Treat as drift (C9) — don’t silently overwrite the operator’s later edit.
Rollback target no longer valid A prior image tag pulled from the registry can’t be restored; report rather than fail obscurely.
Rollback of a data root move Re-point configuration; state clearly that data itself is not moved back.
Journal unavailable or corrupt Report that rollback is unavailable and direct to restore.
Very old change Journal is bounded; state the horizon.
Rollback fails partway Report the exact resulting state. Never leave it ambiguous.
Rollback of a change made by another tool Not journaled, so not rollable. Report as unmanaged.
Service running during rollback Stop, revert, restart; state what will be interrupted.
Rollback would reintroduce a known problem Note it, and proceed if confirmed — the operator may have a reason.
Multiple changes in one operation Roll back as a unit, since they were applied as one.

Acceptance criteria

ID Requirement
E4-R1 Every change lemonfiber makes MUST be journaled with prior value, new value, timestamp and originating operation, a secret’s values by their fingerprints (ARCH-R276).
E4-R2 Rollback MUST operate on individual changes, not only on points in time.
E4-R3 Each journaled change MUST be classified as reversible, irreversible, or partially reversible.
E4-R4 Rollback MUST NOT be offered where it cannot succeed.
E4-R5 Where rollback is unavailable due to a database migration, lemonfiber MUST state the reason and point at the pre-update backup.
E4-R6 A rollback MUST itself be journaled and MUST be rollable.
E4-R7 Rolling back a change with dependent later changes MUST detect the dependency and require confirmation or refuse.
E4-R8 A value manually changed since MUST be treated as drift and MUST NOT be silently overwritten.
E4-R9 Rolling back a data root move MUST state that data is not moved back.
E4-R10 An unavailable rollback target MUST be reported explicitly.
E4-R11 Journal history MUST be browsable, showing what changed and when.
E4-R12 A partially failed rollback MUST report the exact resulting state.
E4-R13 Journal retention MUST be bounded and the horizon MUST be stated.
E4-R14 Changes applied as one operation MUST roll back as one unit.