How a fix reaches production¶
Edition: Community and Enterprise
Every data fix in sealfix follows one path. Each step has one owner, and nothing moves forward until that step is done.
flowchart TB
subgraph Requester
A["Write the SQL template<br/>and submit the values"]
end
subgraph sealfix
B["Static checks<br/>on the template and values"]
C["Seal the values"]
D["Dry run on the target<br/>in a transaction that is rolled back"]
end
subgraph Reviewers
E["DBA reviewer approves the SQL"]
F["Business approver approves the change"]
end
subgraph Executor
G["Save the before-image<br/>run the statements<br/>compare with the dry run"]
end
A --> B --> C --> D --> E --> F --> G
B -- "a check fails" --> A
E -- "rejected" --> A
F -- "rejected" --> A
G -- "counts differ" --> X["Rolled back by itself<br/>nothing changed"]
G -- "counts match" --> Y["Committed"]
classDef ok fill:#E9EEF6,stroke:#23407A,color:#13202D
classDef bad fill:#F6E8EB,stroke:#7D1D2F,color:#13202D
class Y ok
class X bad
The template and the values¶
A request has two parts:
-
the template: the SQL with named parameters, which says what the change does;
-
the values: the data that says whom it is done to, one row per change. They are sealed on arrival and reach the database only as bind variables.
Checks before anyone looks¶
When the requester submits, sealfix checks the template and the values before anything is
stored. Only data-change statements (UPDATE, DELETE, INSERT) are allowed, an UPDATE or
DELETE needs a WHERE, a sensitive value written into the SQL is refused, and every table
must be on the target's allowlist. The full list is in Checks.
The dry run¶
The executor runs the fix on the target inside a transaction and rolls it back. The reviewers see what it would do: the rows per statement, a sample of the changed rows (with the values hidden), the query plans and every trigger it fires. A dry run that touches more rows than the request allows fails.
Approvals¶
Each environment says which approvals a fix needs. By default, production needs a DBA reviewer and a business approver, two different people, neither of them the requester. Non-production needs a DBA reviewer. See Approvals, risk and emergencies.
Every approval is bound to exactly what was approved: the template, the sealed values, the target, the row limit and the dry run's assessment. Change any of them and the approvals no longer count.
Execution¶
Only the requester starts the execution, and only the executor runs it, in one transaction:
- read and seal the rows the statements will change (the before-image);
- run the statements with the values bound;
- compare the row counts with the dry run, and with the request's row limit;
- commit if they match, roll back by itself if they do not.
The states¶
The state reference lists every state and transition.
stateDiagram-v2
direction LR
[*] --> draft
draft --> checking: submit
checking --> checks_failed: a check fails
checking --> dry_run_pending: checks pass
dry_run_pending --> dry_running
dry_running --> dry_run_failed
dry_running --> awaiting_review: dry run ok
awaiting_review --> awaiting_business: technical approval
awaiting_review --> approved: no business approval needed
awaiting_business --> approved: business approval
approved --> executing: execute
executing --> executed: committed
executing --> execution_failed: rolled back
executed --> rolled_back: a rollback ran
awaiting_review --> rejected
awaiting_business --> rejected