# Workflow * branch (from `main`) * do the work in Next Step * move Next Step to the top of Completed Steps * move the top item of Future Steps into Next Step * commit (`TODO.md` changes in the same commit as the work) * merge to `main` if the branch is not protected, otherwise open a PR * push # Status pre-1.0. No git tags. TODO.md carries open 1.0 security blockers. Work in flight on branch secure-enclave-unlocker (clean tree as of 2026-07-06). # Next Step Bring the repo into policy compliance in one commit: - Add fmt-check and hooks targets to the Makefile (test/lint/fmt/check/ docker already exist). - Add REPO_POLICIES.md and .editorconfig. - Add .gitea/workflows/check.yml running make check. - Verify Dockerfile base images are pinned by sha256. # Completed Steps - 2026-10-04: What a command killed part-way left under a `.tmp-` name (https://git.eeqj.de/sneak/secret/issues/75), the temporary directories of `secret.TempDirFor` and the temporary files of `secret.WriteFileAtomic`, encrypted keys included, is deleted by the next command that takes the state directory lock. Before, it stayed until deleted by hand. A command writes `finished` into the lock file just before it releases the lock; the next one to take the lock searches only when it does not find that, so after a command that finished nothing is searched, however many secrets and versions there are. The search looks in the state directory, each vault, each secret and each version, the only directories those helpers make them in. A command that only reads takes no lock and deletes nothing. A failure to delete is warned about and the command goes on. An unlocker directory with no metadata file was already removed by `secret unlocker remove` given its directory name; a test now shows it. - 2026-10-04: `secret rm`, `secret version rm`, `secret vault remove` and `secret unlocker remove` ask `[y/N]` before removing anything (https://git.eeqj.de/sneak/secret/issues/39), naming what they remove: the secret, its vault and its version count; the version, secret and vault; the vault and its secret count; the unlocker, its vault and whether it is the last, and for the last the vault's secret count and that the vault then opens only with its mnemonic. Only `y` or `yes` goes ahead. Without `--force`, a command whose stdin is not a terminal fails at once. `--force` (now also on `rm` and `version rm`) removes without asking; it replaces the old refusals to remove a vault with secrets or the last unlocker of one without `--force`, which the question now covers. The checks run, and the question is asked, before the state directory lock is taken; under the lock the checks run again, and if they would ask a different question, nothing is removed. `secret rm` fails when it cannot count the versions. - 2026-10-04: A crash while an unlocker is being replaced no longer leaves a current unlocker that cannot open the vault (https://git.eeqj.de/sneak/secret/issues/71). Every new unlocker gets a directory of its own, named with the time to the nanosecond: `passphrase-