# layout — design
> **Class:** `design` · **Function axis:** `f5` (AIRGAP5). States only the shape we ship.
## The prepared directory layout
`pub struct Layout { data_dir, log_dir, software_dir, version }` (`layout.rs:18`). Software is
partitioned by a date-stamped version so upgrades are generations, not in-place overwrites:
```text
<software_dir>/<version>/<product>/… ← this generation's files
<software_dir>/current → <version> ← atomic symlink to the active generation
<data_dir>/<product>/… ← persistent data (survives updates)
<log_dir>/<product>/… ← logs (survive updates)
```
`Layout::dated(data_dir, log_dir, software_dir)` (`layout.rs:34`) stamps `version` with today's
`YYYYMMDD`. Path builders: `version_dir` (`layout.rs:48`), `product_software(name)`
(`layout.rs:53`), `product_data(name)` (`layout.rs:58`), `product_log(name)` (`layout.rs:64`),
`current_link` (`layout.rs:70`).
## Provisioning
- `prepare()` (`layout.rs:79`) — idempotently creates `data`, `log`, and `software/<version>`
roots; does **not** touch `current`.
- `prepare_product(name) -> (software, data, log)` (`layout.rs:96`) — `prepare()` then the three
per-product dirs; idempotent, **never clobbers** an existing `data/<name>` or `log/<name>`.
## Atomic upgrade swap
`activate()` (`layout.rs:115`, unix) writes a temp symlink `.current.tmp` pointing at the version,
then `rename(2)`s it onto `current` — a single atomic op on the same filesystem. The symlink
targets the **relative** version name, so the whole tree is relocatable (`layout.rs:121`). On
non-unix it writes a `CURRENT` marker file (`layout.rs:129`).
`active_version() -> Option<String>` (`layout.rs:139`) resolves what `current` points at.
`current_product_path(software_dir, product)` (`layout.rs:153`) resolves a product path *through*
`current`, so a running service always follows the active generation.
## Rollback
There is no separate `rollback()` — a swap never deletes the previous generation, so rollback is
re-`activate()`ing an older `Layout` (the old version dir is retained, asserted at `layout.rs:247`).
## Contract (inject-assert tests)
`prepare_product_creates_software_data_and_log_dirs` (`layout.rs:193`),
`atomic_symlink_swap_on_upgrade` (`layout.rs:222`),
`dated_version_is_yyyymmdd_and_paths_compose` (`layout.rs:258`),
`reactivate_same_version_is_idempotent` (`layout.rs:295`).