# Changelog
All notable changes to Firebreak are documented here. The format is based on
[Keep a Changelog](https://keepachangelog.com/), and the project follows
semantic versioning.
## [0.1.0]
Initial public release.
Firebreak builds two graphs from an Elixir/OTP project — the declared supervision
tree and the actual process-to-process coupling — and reports where coupling
crosses a supervision boundary the tree treats as "contained": a synchronous call
from one branch into another, which a restart turns into `:noproc`/`:timeout` for
the caller. No app boot, no LLM, CI-friendly.
### Analysis
- **Two-graph model.** The supervision *forest* is read the way OTP reads it — by
calling each supervisor's `init/1` (child specs are runtime data; `init/1`
returns them without starting anything) — with static AST parsing as the fallback
for code it can't load. The *coupling graph* is always static: it resolves
`GenServer.call`/`cast`, `:gen_server`/`:gen_statem`, registered names,
`Registry`, `:global`, `Process.whereis`, `:ets`, `Phoenix.PubSub`, and `:pg` to
the owning module, following wrapper functions transitively.
- **Synchronous vs async weighting.** Only a synchronous crossing makes a caller
block on `:noproc`, so severities are gated on it — async-only coupling rates lower.
- **Confidence.** Findings are tagged `exact` (read via `init/1`) or `best-effort`
(static), so you know which is which.
### Checks
- **Coupling / correctness:** `cross_tree_coupling`, `crash_cascade` (failure
simulation over the restart closure), `cyclic_coupling`, `boot_order_cycle` (an
in-`init/1` synchronous cycle means an unbootable tree), `missing_trap_exit`,
`boot_order_dependency`, `start_link_in_callback`.
- **Blast radius / structural:** `one_for_all_blast_radius`,
`supervisor_subtree_blast`, `dynamic_supervisor_restart_blast`,
`orphaned_stateful_process`, `dynamic_supervisor_registry_race`,
`lookup_or_create_race`, `unhandled_port_exit`,
`shutdown_exceeds_intensity_window`, `default_restart_intensity`.
### Runtime observation (`--observe`)
Attach to a live node over distributed Erlang and fold its real shape into the
analysis: live `DynamicSupervisor` children join the forest, registered names are
recovered, `runtime_fanout` reports supervisors running more children than the
source models, and `runtime_mailbox_backlog` flags a deep mailbox on a
synchronously-called process. Reads use standard-library `:rpc` only — the target
needs nothing installed.
### Output formats (`mix firebreak --format`)
`text` (default; leads with primary findings, collapses advisories), `json`,
`dot`, `mermaid`, `github` (PR annotations), `html`, `model` (the supervision-model
IR), `score` (a structural risk score + per-supervisor ranking), `failure` (a
Mermaid diagram of the cross-tree failure modes), and `overlay` (static crossings
annotated with a live node's observed state; needs `--observe`).
### The model IR and its backends
`mix firebreak --format model` emits a **versioned, documented contract**
([`notes/model-ir-contract.md`](notes/model-ir-contract.md)) — every other artifact
is a pure function of it:
- **`mix firebreak.spec`** — a TLA+ lifecycle spec per supervisor (restart-intensity
budget + escalation, and the cross-tree caller's permanent `:noproc`), runnable
with TLC. `--lang quint` emits the same model as Quint.
- **`mix firebreak.lockstep`** — a lockstep regression-test scaffold per
synchronous crossing.
- **`Firebreak.WhatIf`** — simulate a refactor (`move/3`, `set_strategy/3`) and diff
the crossings before touching code.
- **`Firebreak.RiskScore`**, **`Firebreak.FailureViz`**, **`Firebreak.RuntimeOverlay`**
— a risk score, a failure-mode diagram, and a live overlay, all from the IR.
### CI integration
- `--fail-on <severity>` gate; `--min-severity` filter.
- `--write-baseline` / `--baseline` to gate only on *new* findings; a
`.firebreak.exs` allowlist for accepted findings.
- `--write-expected` / `--expect` topology conformance: snapshot the intended tree
and report `topology_drift` (strategy flips, dropped children, intensity changes).
- A composite GitHub Action (`action.yml`).
### Implementation
Pure Elixir, zero runtime dependencies (hand-rolled JSON encoder; `ex_doc` is
dev-only).