CelinQ Insights · No. 14

Undo for the whole repository: recovering from a bad edit

A confident way back when something goes wrong across the shared model.

A NILUS perspective on collaborative modelling for Sparx Enterprise Architect

Every architect who has worked in a shared repository for any length of time carries a particular memory, and it usually involves a quiet moment of dread. Something has gone wrong across the model. Perhaps a script that was supposed to tidy up a handful of stereotypes ran against the wrong package and rewrote hundreds of elements. Perhaps a bulk operation deleted a set of relationships that turned out to matter. Perhaps a well-meaning colleague restructured a domain over a weekend in a way that made sense to them and broke three diagrams that other people depended on. Whatever the cause, the shape is always the same: the model is now in a state it should not be in, the damage is spread across many parts, and the question hanging in the air is the one nobody wants to answer — can we get back, and how much are we going to lose getting there?

The reason that question is so frightening is that, in a great many working setups, the honest answer is a shrug. The individual undo inside a modelling tool covers your own recent actions in your own session, and it evaporates the moment you close the tool or someone else touches the model. It was never designed to reach across a whole repository or across the work of several people. So when the damage is broad, undo is useless, and the fallback is a backup — last night's copy of the database, if you are lucky, or last week's if you are not. Restoring that backup means throwing away everything anyone has done since it was taken, which turns a localised mistake into an organisation-wide loss. The choice on offer is grim: live with the broken model, or roll the entire world back and sacrifice every good change that happened to share a timeframe with the bad one.

Why ordinary undo does not scale to a shared model

It is worth understanding precisely why the familiar tools fail here, because the failure is not laziness on anyone's part; it is a structural mismatch. Undo inside an editing session is a stack of your recent actions, held in memory, private to you, and short-lived. It knows nothing about what other people did, it does not persist across sessions, and it certainly does not span the repository as a whole. That is entirely appropriate for what it was built to do, which is to let you take back the last few things you typed. It was never meant to be a safety net for the shared model, and pressing it into that role is like trying to reverse a building's construction by asking the last bricklayer to undo their morning.

The database backup sits at the opposite extreme, and it fails for the opposite reason. A backup is a snapshot of everything at a single instant, and its granularity is the entire repository. You cannot use it to reverse one bad change while keeping the good changes that came after, because it does not know the difference between them; it only knows the state of the whole thing at the moment it was taken. Restoring it is a blunt instrument, and using a blunt instrument on a delicate problem does exactly the damage you would expect. Between the too-small scope of session undo and the too-large scope of a full restore, there is a vast middle ground where almost every real recovery problem actually lives, and traditional setups leave that middle ground unserved.

The consequence is a culture of fear around the shared model, and that fear has costs of its own. People become reluctant to run useful bulk operations because the blast radius of a mistake is unbounded and irreversible. Cleanups that would improve the model get deferred indefinitely. Structural improvements that carry any risk get talked about and never done. The absence of a confident way back does not just hurt on the rare day something breaks; it makes the model rigid every other day, because everyone is quietly protecting themselves against a mistake they cannot undo.

History as a first-class part of the model

CelinQ approaches recovery from a completely different foundation, and the foundation is history. As architects work in their local repositories and their saved changes flow through to the shared workspace, the platform maintains a complete, ordered revision history of the model. This is not an occasional snapshot taken overnight and not a log written for auditors and then ignored. It is a continuous, sequenced record of the model as it evolved, and it is a first-class part of how the platform works rather than an afterthought bolted on for compliance.

Because the history is ordered and complete, the current state of the model is never a mystery and never simply the accumulated residue of whoever happened to save last. It is the sum of a knowable sequence of changes, each recorded in order. That single property is what makes genuine recovery possible, because it means you can talk about the model at any point along that sequence, not just the state it happens to be in right now. The bad edit did not arrive from nowhere; it entered the history at a particular point, and everything before that point is still there, described exactly, waiting to be reasoned about.

The shift is from asking "do we have a backup from before this went wrong?" to asking "what changed, when, and which of those changes do we want to keep?" The first question has a yes-or-no answer and usually the answer is disappointing. The second question is one you can actually work with.

This matters because most bad edits are not mysteries about what the model should look like. They are usually perfectly clear in hindsight: a specific operation touched a specific set of things at a specific time, and it should not have. What has been missing is not the knowledge of what went wrong but the ability to act on that knowledge surgically — to reverse the harmful change without disturbing the healthy ones around it. A complete ordered history is the raw material that makes surgical recovery possible, because it lets you see the model as a progression rather than a single opaque present state.

Recovery at the granularity of facts, not files

The other half of the story is granularity, and here the merge engine at the centre of the platform, CelinQ Fusion, does the heavy lifting. Fusion works at the level of individual model facts — the specific properties, relationships, and attributes that make up the model — rather than at the level of whole files or whole packages. This fine granularity is what elevates the revision history from a passive record into something you can genuinely recover from, because it means changes can be reasoned about and combined precisely rather than in coarse, all-or-nothing lumps.

Consider the earlier scenario of a script that ran against the wrong package. In a file-or-snapshot world, the damage and everything intermingled with it are welded together, and separating them by hand is the tedious, error-prone job that makes people reach for a full restore out of exhaustion. When change is recorded at the level of individual facts, the situation is different in kind. The harmful edits are describable as a specific set of changes to specific facts, distinct from the legitimate work that happened around them. Reversing the harm becomes a matter of restoring the affected facts to their prior recorded state, while the unrelated good work — the changes other people made to other parts of the model during the same window — remains untouched because it was never part of the same set of facts in the first place.

This is the difference between rolling back the world and correcting a mistake. The full-restore approach cannot tell the bad change apart from the good ones that share its timeframe, so it takes everything back together and calls the collateral damage the price of recovery. Fact-level history and a deterministic merge engine let you take back only what actually went wrong. The rest of the model, and the rest of everyone's work, carries on as though the correction were simply the next ordinary change in the sequence — which, in an important sense, it is.

Because Fusion is deterministic and reproducible, a recovery does not introduce fresh uncertainty. Folding a corrected state back into the shared model follows the same rules as any other change, and those rules never resolve a genuine disagreement by silently picking a winner. If reversing a bad edit turns out to collide with legitimate later work — someone built something new on top of the very thing you are trying to restore — the engine does not paper over the tension. It isolates that collision explicitly and puts it in front of a person, because a conflict between recovering an old state and preserving new work is exactly the kind of decision a human with context should make, not something an engine should guess at.

A safety net is only worth anything if you trust it enough to attempt the things that might need it. The point of confident recovery is not the rare rescue; it is the everyday courage to improve the model at all.

Deletions and the danger of things quietly coming back

Recovery involving deletions is where careless systems do their most insidious damage, and it deserves particular attention. Imagine that the bad edit you want to reverse included, among other things, the deletion of some elements — and that in the meantime a colleague has deliberately created new elements in the same area. A crude rollback that simply reinstates an earlier state risks resurrecting things that were correctly removed elsewhere, or clobbering the new work, and doing either of those silently is precisely how a recovery turns into a second incident.

CelinQ carries deletions as explicit tombstones rather than treating a deleted element as a mere gap to be filled by whatever was there before. Because a deletion is a recorded fact in its own right, the platform can reason about it during recovery just as it reasons about any other change. When you reverse an edit, the engine is not blindly stamping an old picture over the present; it is reconciling recorded facts, and it can see the difference between an element that should return and one whose removal must stand. Where an intended restoration genuinely conflicts with an intended deletion or with new work, that tension is surfaced explicitly rather than resolved by accident. Nothing that a person deliberately decided is silently reversed as a side effect of someone else's recovery.

This is the same principle that governs everything else in the platform, applied to the frightening case. The engine never resolves a real disagreement by timing or by luck. It merges what can be merged without ambiguity, and it isolates what cannot, so that the small number of genuine conflicts get a human decision. Recovery does not get an exemption from that discipline; if anything, it is where the discipline matters most, because a recovery is exactly the moment when the temptation to just make the problem go away is strongest and most dangerous.

Recovery is a governed act, not a panic button

It would be a mistake to present all of this as a magic button that any user can press to rewind the shared model on a whim, and skeptical architects would be right to distrust such a thing. Reaching back into the shared model to reverse changes is a consequential action, and the platform treats it as one. Roles determine who can do what — Viewer, Editor, Administrator, Owner — and the ability to perform a broad recovery belongs with those who hold responsibility for the model as a whole, not with everyone who can edit an element. The change review and governance capabilities mean that significant actions are visible and accountable rather than happening in the dark. Recovery, in other words, sits inside the same framework of stewardship that governs the rest of the shared workspace.

This governance is not friction for its own sake. It is what makes the capability safe to have at all. A recovery mechanism that anyone could trigger without oversight would be a new hazard rather than a safety net, and the fear it removed on one side it would reintroduce on the other. By placing recovery within clear roles and within a reviewable record of changes, the platform makes it something an organisation can rely on precisely because it is not an unaccountable free-for-all. The people who can reach back are the people whose job it is to, and their actions are as visible in the history as everyone else's.

And because the whole arrangement runs on infrastructure the organisation operates itself — the shared workspace on the organisation's own server, storage in SQLite or PostgreSQL as the deployment requires, encrypted transport with certificate pinning and token-based authentication — recovery never means reaching out to some external service and hoping it kept a copy of your model. The history that makes recovery possible lives where the rest of the organisation's architecture lives: under its own control, within its own boundary, answerable to its own governance. The confidence that you can get back is grounded in infrastructure you actually own, not in a promise from somewhere you cannot see.

A worked example, and why the history is what saves you

It helps to walk a concrete case all the way through, because the abstract description of fact-level history can sound like a claim that has to be taken on faith. Suppose a nightly maintenance routine is meant to normalise the naming of a set of interfaces in one subsystem, and through a bad parameter it instead rewrites the names of interfaces across three subsystems, including two that a colleague spent the previous day carefully documenting. The damage is discovered mid-morning. By then, several architects have already been working for a couple of hours on entirely unrelated parts of the model, and their work has flowed into the shared workspace and intermingled, in time, with the fallout from the routine. This is the exact configuration that makes a full restore so painful: the bad change and a morning of good changes now share a window, and a snapshot cannot tell them apart.

Because the platform holds a complete ordered history recorded at the level of individual facts, the bad change is not an undifferentiated smear across the model. It is a describable set of edits to a describable set of interface names, entered at a known point in the sequence. Reversing it means restoring those specific facts to the state they held before the routine ran, and nothing about that operation needs to touch the morning's unrelated work, because that work concerned other facts entirely. The colleague's careful documentation from the previous day is likewise recoverable to its prior state fact by fact, rather than being sacrificed because it happened to sit near the damage in time. What would have been an agonising choice between two bad extremes becomes a targeted correction that leaves the rest of the model exactly as its authors left it.

The history is what makes this more than a hopeful story. Without an ordered record, you would be reconstructing the prior state from memory and guesswork, which is precisely the fragile, error-prone work that drives exhausted teams toward the blunt instrument of a full restore in the first place. With the record in place, the prior state is not remembered; it is known, described exactly, and available to be reasoned about. The recovery is an inspection followed by a deliberate correction, not an act of archaeology. And because the correction itself flows through the same engine as any other change, it too is recorded in the history — visible, ordered, and accountable — so that the act of recovering does not become a mysterious discontinuity in the model's story but simply the next well-understood step in it.

What confident recovery changes about how people work

The most important effect of a real way back is not felt on the day of the disaster. It is felt on every ordinary day, in the form of a willingness to improve the model that fear had previously suppressed. When people know that a bad bulk edit can be reversed precisely, without sacrificing everyone else's work and without a full restore, they stop treating the shared model as something too fragile to touch. The cleanups that had been deferred get done. The structural improvements that carried a little risk get attempted. The useful script that operates across many elements gets run, because if it goes wrong the way back is surgical rather than catastrophic. A confident recovery capability does not just rescue the model on bad days; it keeps the model alive and improving on all the others.

There is a temptation, writing about this, to promise that mistakes no longer matter, and that would be dishonest. Mistakes still matter. A bad edit across a shared model is still a serious event, it still demands attention, and reversing it still calls for judgement about what to keep and what to unwind. What changes is that the event is now recoverable in proportion to its actual scope, rather than forcing a choice between two bad extremes. You are no longer stuck choosing between living with damage and detonating everyone's recent work to undo it. You have the thing that was always missing from the middle: the ability to reverse what went wrong while keeping what went right.

That is what "undo for the whole repository" really means. Not a literal reversal of time, and not a single keystroke that magics the model back to yesterday, but a foundation — a complete ordered history and a merge engine that reasons at the level of individual facts — that together make it possible to correct a broad mistake with the same precision you would want for a small one. The dread that hangs in the air when something goes wrong across the shared model comes from not knowing whether there is a way back. When there is a confident, governed, precise way back, that dread has somewhere to go, and the architects who live in the model can get on with the work of making it better instead of quietly guarding it against a mistake they were never able to undo.

None of this is a promise that recovery will always be effortless or that every incident will resolve into a single tidy correction. Some situations are genuinely tangled, and unwinding them still calls for careful thought about what the model ought to look like. But there is a large and important distance between a problem that is hard because it requires judgement and a problem that is hopeless because the tools cannot express the distinction you need. Traditional setups left too many recovery problems in the second category, hopeless not for want of understanding but for want of any instrument fine enough to act on that understanding. A complete ordered history and a fact-level merge engine move those problems back into the first category, where they belong — hard, sometimes, but never hopeless, and always answerable to the judgement of the people responsible for the model.