# complymap — Changelog

## v1.0.0 — 2026-06-22

Initial release. Phase 2 of the cli.johlem.net consulting layer
(jfind → complymap → dossier → inciclass → roigen → tiberscope).

- Library crate (`complymap`) + CLI binary (`complymap`).
- Four subcommands:
  - `complymap map <bundle> --framework dora,nis2,iso27001,cssf -o mapped.json`
    enriches each finding's `controls[]` with matches from the
    requested frameworks. Emits `jfind-bundle/v1` (when input has
    bundle / engagement metadata) or NDJSON `jfind/v1` (otherwise).
  - `complymap gap <bundle> --framework dora --entity credit-institution`
    builds a per-control coverage matrix
    (covered / partial / gap / unknown) joined to the findings that
    landed on each control. Emits a `complymap-gap/v1` JSON document
    or a human table.
  - `complymap delta <bundle> --baseline iso27001 --target dora`
    lists controls in `target` not transitively covered by `baseline`
    via the crosswalk. Items DORA demands that ISO alone does not
    satisfy are marked `dora_specific: true` with a free-text reason
    from the crosswalk's `dora_specific[]` block.
  - `complymap coverage <bundle> --framework dora --format json|human`
    flat per-framework rollup (covered % / partial % / gap %).
- Vendored framework data (embedded via `include_str!`):
  - **DORA** — 13 articles incl. RTS 2024/1774 Art.11 (ICT security),
    RTS 2024/1772 (incident classification), RTS 2025/301 / ITS 2025/302
    (incident reporting), RTS 2024/1773 + ITS 2024/2956 (third-party
    + RoI), batch-2 TLPT RTS.
  - **NIS2** — 11 articles incl. Art. 21(2)(a)-(j) measures and Art. 23
    reporting obligations.
  - **ISO/IEC 27001:2022** — 12 Annex A controls covering the categories
    the five retrofitted finding-producers emit (asset inventory,
    crypto, privileged access, malware, vulnerability, monitoring,
    networks, suppliers, incident management).
  - **CSSF Luxembourg circulars** — 13 control points across 20/750
    (ICT & security risk management) and 22/806 (outsourcing) — the
    Luxembourg differentiator.
  - **Crosswalk** — 10 cross-framework equivalences + a
    `dora_specific[]` block flagging 5 DORA-only items
    (Art. 18 classification thresholds, Art. 19 reporting deadlines,
    Art. 24 TLPT, Art. 30 contractual clauses, Art. 31 Register of
    Information).
- **Mapping engine**: category match + MITRE technique match +
  keyword substring match. Deterministic, explainable, and
  unit-test-pinned. Multiple matches merge into a sorted, deduped
  `controls[]` for each finding.
- **Status calculation**: a control is `gap` if any High/Critical
  finding touches it; `partial` if Medium; `covered` if only Info/Low;
  `unknown` if no finding touches it.
- Reads `jfind/v1` finding, `jfind-bundle/v1`, JSON array, or NDJSON
  stream — same content-sniffing logic used elsewhere in the suite.
- Suite-wide exit codes per `SUITE_STANDARDS.md` §1:
  0 ok / 1 gap present / 2 usage / 3 runtime / parse.
- Mandatory tagline footer on every `--help`:
  `[ complymap ] ─ an independent project by johlem.net`.
- `--full` extended help (suite convention).
- 12 unit tests (data load, engine matching, gap report severity
  rollup) + 11 integration tests (CLI behaviour, NDJSON input,
  DORA-specific delta acceptance gate). Zero compiler warnings.

### Acceptance gate (Phase 2)

Given a sample bundle, `complymap delta --baseline iso27001
--target dora` lists exactly the DORA-specific items
(Art. 18 classification thresholds, Art. 19 reporting, Art. 24 TLPT,
Art. 30 clauses, Art. 31 RoI) as remaining with
`dora_specific: true`. Verified end-to-end against a fixture
bundle in the integration tests.

### Deferred for v1.1+

- `dossier` integration — `complymap-gap/v1` is already
  jfind-compatible, but the dossier "Gap Assessment" template recipe
  is not yet written.
- DORA proportionality (entity-type-driven control subsetting).
  `--entity credit-institution` is accepted and recorded in metadata
  in v1.0 but does not gate which controls apply.
- Match-score banding (strong / medium / weak). Engine collects the
  data but the surface currently only emits the boolean
  match/no-match.
- TIBER-EU scope hooks (depends on `tiberscope` — phase 4).
