Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-binview/.nornir/facett-binview.md

facett-binview — the shared binary-analysis pane

One-line pitch

One robot-testable egui Facet that renders a built artifact's size + hardening story — a per-crate/-symbol bloat treemap, checksec badges, a before→after diff waterfall, and a size sparkline — so dwarves/nornir mount ONE pane, not a per-app twin.

Why it exists (LAW #5 — DRY)

The nordisk binary-analysis subsystem (nornir) produces binary_facts (checksec: RELRO/PIE/NX/canary/stripped/…), section_sizes, symbol_sizes (per-crate/-symbol bloat) and artifact_diff (size/section/crate deltas + symbol added/removed/grown/ shrunk + ABI). Any surface that wants to show that story would otherwise grow its own bloat/checksec/diff render. This leaf owns the one pane body; the HOST supplies the rows through a seam.

Layering — WAREHOUSE-AGNOSTIC (the important constraint)

facett carries no nornir / warehouse / dwarves dependency. The pane is presentational + host-driven: the HOST implements the BinaryDataSeam trait (feeding rows from the warehouse tables), and BinaryPane only ever renders the rows the seam surfaces. This mirrors how the Release tab takes a ReleaseConvergence in and the auth pane takes a LoginState in — the pane never reaches for a backend.

Deps: facett-core (the Facet contract + the OKLCH colour space reused for the per-crate treemap hues — no twinned colour maths), egui, serde_json. Optional nornir-testmatrix behind the testmatrix feature only. A leaf beside facett-auth-ui / facett-releaseview.

The seam — BinaryDataSeam (HOST implements)

artifact_name()  -> String            the analysed binary's name
checksec()       -> Checksec          RELRO/PIE/NX/canary/stripped/fortify  (binary_facts)
crate_sizes()    -> Vec<CrateSize>    per-crate bloat aggregates            (symbol_sizes rollup)
symbol_sizes()   -> Vec<SymbolSize>   per-symbol leaves/detail              (symbol_sizes)   [default []]
diff()           -> Option<ArtifactDiff>  before→after size/section/symbol/ABI (artifact_diff) [default None]
size_history()   -> Vec<u64>          bytes across recent builds            [default []]
source()         -> &str              honest provenance banner              [default]

The pane — BinaryPane (facett_core::Facet)

title / ui / state_json / update_json. Caches a snapshot of the seam's rows (refresh() / update_json {"refresh":true} re-pulls). Renders four layers, each a pure egui-painter draw (wasm-clean, headless-snapshottable — no wgpu):

layer            what it paints
  ├─ checksec     one green(✓)/red(✗) chip per protection (Checksec::badges)
  ├─ sparkline    a polyline of size_history (skipped < 2 points)
  ├─ treemap      squarified rects sized by crate bytes, coloured by crate
  │               (biggest crate → biggest rect); a legend of real widgets under it
  └─ waterfall    [before] + one floating bar per section delta (grow=red↑/shrink=green↓)
                  + [after]; a summary line (+/− total, ABI verdict, symbol churn)

crate_treemap(area) -> Vec<CrateTile> is the exact layout the pane paints, exposed so the robot test asserts the painted layout as data. squarified_treemap(weights, area) is the self-contained geometry helper (no facett rect/layout helper existed to reuse); crate_color(name) derives a stable OKLCH hue per crate.

Robot test (kittest, red-when-broken) — matrix cell facett-binview/binary-pane

tests/robot.rs drives the REAL pane over StubBinaryData and asserts: the PIE ✓ and CANARY ✗ badges paint (checksec reflects the verdict); the treemap is non-blank (tiles cover >70% of the map) and nornir (biggest bytes) gets the biggest rect; the diff waterfall carries both a growth and a shrink section; the summary line paints; no crash. Red-when-broken: neutralizing any layer flips an assertion.

Host-side follow-up (NOT built here)

Wiring dwarves/nornir to implement BinaryDataSeam over the real warehouse (binary_facts / section_sizes / symbol_sizes / artifact_diff) is the host-side follow-up — the same one-way adapter shape as the release-engine → ReleaseConvergence feed.