# Changelog

All notable changes to `mgf-secrets` are documented here. Format loosely follows
Keep a Changelog; versions follow SemVer.

## [Unreleased]

### Added
- **Phase 2 — encrypted store + value CLI + materialized cache.**
  - `mgf.secrets.store` — the age-encrypted store engine (dep: `pyrage`):
    `encrypt`/`decrypt` (public-key multi-recipient; either secret key decrypts),
    `store_put`/`store_get`, `manifest_load`/`manifest_verify`, the no-plaintext
    `plaintext_guard`, and `recipients.txt` parsing. Values are `bytes` in-process
    only — never logged, never in an exception, never on argv (AG-18). The encrypt
    path is deterministic-by-argument (the CLI stamps `encrypted_at`).
  - `mgf.secrets.resolve(id)` — the in-process value API for sibling tools (the
    AG-18-native replacement for `$(cat my_stuff/…)`); its docstring forbids logging.
  - `mgf.secrets.materialize` — key-free `plan` + `apply` that decrypt declared
    `local-file` surfaces into bare-value files at the exact registry paths,
    enforcing 0600 files / 0700 parent dirs, refusing `held` entries, **never
    deleting** anything (leftovers reported, not pruned) — the doc-form leak class dies.
  - CLI verbs (SPEC §4): `show --value` (refuses a TTY without `--tty-ok`, never
    `--json`), `add`/`set` (value via `--value-file PATH`, stdin `-`, or hidden
    prompt — never argv), `exec --with ID[:ENV] -- CMD` (env-injected child),
    `materialize --plan/--apply`, `export-offline` (founder-only bundle), `history`
    (git audit trail). Global `--store`/`--identity`; the P1 exit-code contract holds.
  - Extended suite: roundtrip property (both recipients), redaction over every value
    verb (canary absent everywhere but `show --value`/`exec`), argv/TTY guards,
    materialize idempotence + safety, manifest consistency, doc-form elimination,
    no-plaintext guard. Coverage stays above the 80% floor.
  - Internal: `mgf.secrets.resolve` (the `ALL_MANAGED` helper) renamed to
    `mgf.secrets.managed` so the public `resolve(id)` value API owns that name.
- **Phase 1 — registry + read-only doctor.**
  - `SECRETS.toml` schema, loader, and fail-closed validator (family-namespaced;
    duplicate ids across families and armed `held` entries are load errors).
  - Read-only doctor with checks C1–C8 (Woodpecker declared↔actual, consumed↔
    declared parity with `audit_secret_scopes.py`, unregistered-actual, held
    discipline, forge deploy-key coverage, local hygiene, host-file perms,
    policy), human table + `--json`.
  - Per-kind liveness probes (one handler per registered kind).
  - CLI `mgf-secrets` with `list` / `show` / `doctor` / `probe`, `--json`, and
    the exit-code contract (0 clean · 1 findings · 2 usage/credential/load error).
  - Test suite: schema fails-closed, ported scope-logic corpus, incident replays
    (CIR-02/33/34, expired JWT, unregistered-actor, doc-form), the AG-18 redaction
    property test, the no-ungoverned gate, and the kind-extension meta-test.
