Update and uninstall

What a second install of the same document does, why most kinds of brick block on a change, and why removing a blueprint never takes your data.

This is the part of blueprints that surprises people, so it gets its own page. Two sentences carry most of it: an update is just another install, and an uninstall deletes nothing.

#An update is an install

There is no update button and no update endpoint. You install the newer document exactly as you installed the first one — plan it, read it, consent to it, run it — and the plan finds the previous run's ledger rows on its own, from the blueprint id the document declares.

What changes is only the verdicts you get back. Bricks the document did not touch come back NOOP; the ones it changed come back UPDATE; anything you edited by hand since is DRIFT or CONFLICT and keeps your version unless you ask for a reset; anything the new document dropped is an ORPHAN, offered for removal and never removed for you. Install one explains each verdict.

Two installs of the same document are not always an update, though. Every blueprint has one parameter that namespaces everything it creates, and its value is fixed for the life of an install: planning with a different value is not an update but a fork — a second, separate copy beside the first.

#Twelve of fifteen kinds block on a real change

Only three kinds of brick can be re-applied over something that already exists: a collection (the schema is patched), a flow (it is re-imported in place) and grants (the blueprint's own partition of the permissions table is revoked and re-appended). For the other twelve — row scopes, roles, seeded rows, scripts, pages, attachments, renderers, saved views, navigation entries, webhooks, search indexes and containers — there is no way to apply a changed brick over a live resource.

So a document that changes one of those gets BLOCKED on that brick, and the plan is not installable until you deal with it. That is the deliberate answer. The alternatives are a create that collides with the existing resource and fails halfway through the install, or a delete-and-recreate that takes your data with it.

BLOCKED only applies to a change you made to the document. Drift on one of those kinds — you edited the live resource, the document did not change — is not blocked: it defaults to changing nothing, so the install still runs and only the offer to reset it is withdrawn.

What to do about one:

  • Make the change in the product yourself, and edit the document to match what you made. The next plan compares the two, finds no difference, and stops calling it a change.
  • Or name a new resource in the document — a new brick, creating something the project does not have yet. That one is created, and the resource it replaces is presented as an orphan for you to remove.

#Rolling back is allowed, and says so

Installing an older version of a document over a newer one is legal. It raises a warning naming both versions, never a refusal: a rollback to a known-good version is a legitimate thing to do, and refusing it would only teach authors to edit the version number to get past it — which loses the one signal there is.

The warning is about the document as a whole rather than any one brick, and it is compared against the highest version among the rows the project currently carries, because a partial run can leave rows from two versions side by side.

Silence is not an answer. No warning does not mean this is not a rollback. Three cases are quiet: the versions are equal or newer, which is the point; the stored version is a string that cannot be ordered against yours, in which case the comparison answers "unknown" rather than guessing; or the plan found no baseline to compare against at all, which happens when the install it would have compared against could not be identified. Resolve that and plan again if you need the answer.

#What supersede means

When an update settles, the older run is superseded twice over: per resource, as each brick takes over the resource its predecessor held, and then per run, once the older run owns no current resource at all. A run that still owns something — a brick your update skipped, a grant you left unticked — keeps its status, because it is still the answer to "what put this here". The superseded rows are kept rather than deleted, so what an earlier version applied stays readable.

#Uninstalling detaches; it does not delete

Nothing is deleted unless you tick it. The collections, every row written into them since, the flow documents, the pages, the saved views, the navigation entries and the roles all stay exactly as they are. What changes is ownership: the ledger records that the blueprint no longer owns them.

This is not a caveat, it is the design. By the time you remove a blueprint, the data in the tables it created is yours and was mostly written by people who never knew a blueprint made the table.

Three kinds are offered for revocation instead, and the question they answer is not "could this be deleted" but "does it still act once the blueprint is gone?"

Kind The call Why it is offered
grants DELETE /api/v1/roles/:id/permissions/grants?blueprintKey= A permission the blueprint handed out is a door it opened, not your data.
webhook DELETE /api/v1/webhooks/:id It is not your data either — it is a URL, the record events that fire it, and an HMAC secret — and it keeps POSTing every record change to a third party after the blueprint is gone.
flow, when it was installed active PATCH /api/v1/automate/flows/:id/status with {"status":"inactive"} The flow is yours and stays; only the activation the blueprint applied comes off, which stops its schedule, its record triggers and its public webhook URL. It keeps its published version, so switching it back on is one click.

Like the grant that added it, each is applied only if you tick it — leaving a webhook running after the blueprint that configured it is a legitimate choice, and it is yours to make. A flow the ledger recorded as a draft carries no offer at all, because there is nothing to stop.

Row scopes are not among the three, and the difference is worth holding onto: a scope that confines people to their own rows stays applied when the blueprint leaves. Both land in the same permissions table, and the uninstall follows the brick kind, not the table the write landed in.

An uninstall does not need the original installer — requiring them would mean a blueprint installed by somebody who has since left could never be removed. It does need system/blueprints:install. A run that is still in progress is refused; anything else is safe to re-run.

#Reinstalling afterwards

Plan the same document again after an uninstall and every brick comes back ADOPT: the resources are there, they match, and no install claims them any more. Accepting adopts them without writing to a single one — the ledger simply learns who owns them again — and the plan after that is NOOP throughout.

The wire shapes for all of this, including what an uninstall returns before you confirm it, are on Reference.