<!-- nornir:class: design -->
# OCI bind mounts — the mount-aware container path (kills the `podman -v` twin)
> **Why.** Skidbladnir's `msi.rs` (WiX v4 under Wine) and `pack.rs` shell out to
> `Command::new("podman") … -v host:ctr …` — a zero-shell-charter violation and a
> second container engine (dup-audit P1). They need **bind mounts** to pass the WXS
> in and the `.msi` out. draupnir owns the ONE OCI engine, but its create path had
> no bind support. This adds it **additively**, so those twins can route through
> `ContainerBoot::run_to_completion_with_binds` instead of a podman subprocess.
## The seam (all additive — `BootSpec` untouched)
The shared `BootSpec` has no `Default`, so a new field would break every struct
literal across nornir/korp/dwarves. Instead binds ride the **create path** as an
explicit `&[String]` (`host:container[:opts]`, `-v` semantics), threaded through
new `*_with_binds` twins; the bind-free entries **delegate** to them, so every
existing caller is byte-for-byte unchanged.
| bind-free (unchanged) | mount-aware (new) | note |
|---|---|---|
| `Engine::create_body` | `Engine::create_body_with_binds` | pure body builder; empty binds ⇒ identical body (`HostConfig.binds` stays `None`) |
| `Engine::create_and_start` | `Engine::create_and_start_with_binds` | create+start with `HostConfig.binds` |
| `Boot::boot` | `ContainerBoot::boot_with_binds` | mount-aware boot |
| `ContainerBoot::run_to_completion` | `ContainerBoot::run_to_completion_with_binds` | the seam Skidbladnir consumes |
The run-to-completion **loop** (drain→poll→final-drain→stop) is factored into one
`drive_to_completion(backend, &machine, opts)` that both paths share — single-source,
no duplicated driver. `binds` empty ⇒ every path equals its bind-free original.
```
Skidbladnir msi.rs / pack.rs draupnir (ONE OCI engine, bollard)
┌───────────────────────────┐ ┌──────────────────────────────────┐
│ run_to_completion_with_binds(spec, opts, │ boot_with_binds → create_and_start│
│ ["/in:/work/in:ro", │ ───────────▶ │ _with_binds → create_body_with_ │
│ "/out:/work/out"]) │ │ binds → HostConfig.binds = -v │
└───────────────────────────┘ │ drive_to_completion (shared loop) │
(replaces Command::new("podman") -v …) └──────────────────────────────────┘
```
## Status
- draupnir: **landed** — builds default (no bollard) + `--features backend-oci`; test
`create_body_with_binds_attaches_host_mounts_and_stays_parity_when_empty` green.
- Skidbladnir consumption (route `msi.rs`/`pack.rs` off `podman` onto
`run_to_completion_with_binds`) = the **next task** (this unblocks it).