# compose-audit — Changelog

## v1.0.0 — 2026-06-25

Initial release. Third tool in the "productivity-boost" series queued
after the 2026-06-23 fleet review (queue: cmdb → notify → compose-audit
→ pkgaudit → shellrec → webfuzz → changefeed → signtree → backupcheck
→ tabletop → stegcrypt v1.1 audio → pwgen → burp-cli → sftui).

### Purpose

Every production cli.johlem.net deployment ends up with at least one
Dockerfile, one docker-compose stack, or one Kubernetes manifest set.
compose-audit walks them and flags hardening misses against the same
DORA / NIS2 / ISO/IEC 27001:2022 baseline the rest of the suite assumes,
so the consultant can hand the operator a single jfind-shaped backlog
of "fix this before going live" items.

### Subcommands

```
compose-audit audit       <path…> [--kind dockerfile|compose|k8s]
compose-audit dockerfile  <path…>
compose-audit compose     <path…>
compose-audit k8s         <path…>
compose-audit rules
```

All audit subcommands accept `-F human|json|jfind`, `-o <file>`, and
`--fail-on info|low|medium|high|critical`.

### Rule catalogue (32 rules)

- **Dockerfile** (6): `CA-DKR-001..006` — floating tag, no USER, ADD url,
  no HEALTHCHECK, curl-pipe-sh, secret material in ENV/ARG.
- **docker-compose** (13): `CA-CMP-001..013` — floating tag, `privileged`,
  `network_mode/pid/ipc: host`, root user, dangerous capabilities,
  `docker.sock` mount, host-root mount, secrets in env, no healthcheck,
  read-write rootfs, no resource limits.
- **Kubernetes** (13): `CA-K8S-001..013` — privileged, runAsRoot,
  hostNetwork/PID/IPC, allowPrivilegeEscalation, dangerous capabilities,
  floating tag, automountServiceAccountToken, missing probes, no
  resource limits, hostPath volumes, plain-env secrets.

Each rule carries a default severity, a one-line remediation, framework
controls (DORA Art. 9 + NIS2 Art. 21(2)(e) + ISO/IEC 27001:2022 A.8.9 by
default; A.8.2 for privilege escalation; A.8.24 + Art. 9(4)(c) for
secret material), and MITRE ATT&CK techniques (T1610 Deploy Container;
T1611 Escape to Host; T1552 / T1552.001 for secrets).

### jfind/v1 output

Category mapping:

| Category | Triggers |
|---|---|
| `policy-violation` | privileged, hostNetwork/PID/IPC, docker.sock mount, host-path mount, runAsRoot, allowPrivilegeEscalation |
| `data-exposure` | secret material in env (when severity ≥ High) |
| `misconfiguration` | everything else (default) |

The audit feeds straight into complymap (`compose-audit … -F jfind |
complymap map -`) and dossier (`… | dossier render --template
gap-assessment`).

### Exit codes

```
0  ok        — audit completed, no finding crossed --fail-on
2  usage     — clap parse error
3  runtime   — io, yaml parse, unknown manifest kind
4  policy    — a finding met or exceeded --fail-on
```

Exit 4 is new in the suite — borrowed for the "policy gate failed"
semantic so CI scripts can distinguish a clean run from a guard-rail
hit without grepping stdout.

### Build

- Library crate (`compose_audit`) + thin CLI binary.
- 35 unit + 15 integration tests = 50 tests, all green.
- Zero compiler warnings.
- Hand-rolled Dockerfile parser (line-by-line with continuation
  support); `serde_yaml` for the YAML side.
- Offline. No network access.
- Suite-standard exit codes + tagline footer.
- NixOS-only platform gate in `install.sh`.

### Suite interop

| Producer | Consumer | Use case |
|---|---|---|
| operator | compose-audit | scan a repo / chart |
| compose-audit | complymap | map findings → DORA / NIS2 controls |
| compose-audit | dossier | gap-assessment / pentest reports |
| compose-audit | notify | dispatch High+ findings to Slack/Teams |
| cmdb | compose-audit | (planned v1.1) read target paths from inventory |

### Deferred to v1.1

- `--diff <base>` — only report rules that *newly* fire compared to a
  baseline JSON.
- Helm chart support (currently treats `templates/*.yaml` as plain k8s
  YAML — works for most charts but doesn't expand `{{ … }}`).
- Custom rule packs via TOML config under `$XDG_CONFIG_HOME/cli-johlem/`.
- `--ignore CA-K8S-009` per-rule suppression flag (today: rebuild the
  rule list via `rules` + grep).
- Read targets from cmdb (`compose-audit audit --from-cmdb`).
