# REPORT — keyproxy v0 finish (commit + push of the self-killed turn) Date: 2026-08-28 21:30 Repo: https://git.knownelement.com/ukrrs/mopac-keyproxy (branch `main`, pushed through `47343d5`) Task: verify the keyproxy-v0 working tree left uncommitted by the previous turn (it self-SIGTERM'd via a broad pkill before committing), re-test in the Docker builder, commit in logical chunks, push, report. ## What shipped (v0, per the TASK spec) - **Two shapes, one resolver**: `keyproxy serve` (localhost HTTP resolve hop) + `keyproxy get REF` (exec-style CLI, bare value, no newline). - **Endpoints** (`internal/server/server.go`): - `POST /v1/resolve` — bearer-token auth (constant-time compare, bootstrapped at startup from the file backend), body `{"ref":"mpk-"}` → `{"value":"..."}`. - `GET /healthz` — unauthenticated liveness. - Status codes: 200 / 401 / 400 (malformed body or non-`mpk-` ref, never echoed) / 404 / 405 / 413 (4 KiB cap) / 500 (recovered panic, detail suppressed) / 501 (stub backends) / 502. Failure bodies carry ref + backend + fixed reason enum only. - **Backends** (`internal/backend/`, one `Backend` interface): - `file` — 0600 KEY=VALUE env files, parsed in pure Go (never sourced), `~` expansion, permission mask enforced before read (default 0600, stricter passes, looser refused). - `env` — process-environment indirection (source IS the var name). - `bitwarden`, `vault` — **explicit not-implemented stubs** returning 501 `not_implemented` behind the same interface; phase-3 drop-ins. - **Config** (`internal/config/`): strict stdlib-only TOML subset parser; unknown keys and backend-specific misconfigurations fail loudly at startup; `keyproxy.toml.example` tracked, real `keyproxy.toml` gitignored (holds the ref MAP — locations only, never material). - **Redaction, no persistence, no admin UI**: memory-only material; every log line naming a ref masks it `=***`; auth failures log remote address only; parse errors carry line numbers, never contents; panic values discarded. Enforced by tests + smoke log scan. - **Build discipline**: all dev in Docker via digest-pinned `golang:1.26-bookworm` (`golang@sha256:e8c859f5...e5514`); `dev.sh build|vet|test|check|smoke`, `make` is a thin front door. Host runs no Go toolchain. ## Verification (re-run this turn, all in the Docker builder) - `./dev.sh check` (= build + vet + test): PASS — `ok internal/backend`, `ok internal/config`, `ok internal/server`, `go vet` clean, binary built. - `./dev.sh smoke` (end-to-end, containerized): **10/10 PASS** — healthz; 401 no-token; 401 wrong-token; 200 file resolve; 200 env resolve; 404 unknown ref; 400 invalid ref without echo; 501 bitwarden stub; 501 vault stub; 405 GET resolve. Server log verified redacted: no material strings, refs masked `ref=mpk-smoke=***`. Smoke container torn down by exact name (`docker rm -f keyproxy-smoke`); no pkill used this turn. ## Commits pushed to origin/main Previous turn left everything uncommitted. Committed in 5 logical chunks (hashes post-rebase, see note below): | Commit | Content | |---|---| | `b43bc55` | backend interface + file/env backends + bitwarden/vault stubs + env-file parser, with tests | | `7bec2a1` | config loader + stdlib TOML subset parser, with tests | | `82861b6` | HTTP resolve hop (auth, redaction, reason enums), with tests | | `24a57c1` | CLI (`serve`, `get`, `help`; exit codes 0/1/2) | | `47343d5` | dev.sh/Makefile Docker tooling, smoke/, keyproxy.toml.example, .gitignore, README | Note: first push was rejected — origin/main had been re-seeded (`6c88e65` + `325a36c`), an unrelated history whose README/LICENSE are byte-identical to our never-pushed local seed. Resolved by rebasing the 5 implementation commits onto `325a36c` (dropping the redundant local seed; resulting tree verified identical to the pre-rebase tree). Push: `325a36c..47343d5 main -> main`, working tree clean. ## How to start it See README "Quickstart" (repo root, verified verbatim on 2026-08-28): `./dev.sh check` → create 0600 env files + `cp keyproxy.toml.example keyproxy.toml` → `./bin/keyproxy serve` (binds 127.0.0.1:8082) → `POST /v1/resolve` with bearer token, or `./bin/keyproxy get mpk-example`. ## Left for phase 3 - `bitwarden` backend: replace stub with Bitwarden Secrets Manager REST (machine accounts, stdlib-first — official SDK license is AGPL-incompatible). - `vault` backend: replace stub with HashiCorp Vault KV v2 + AppRole (official Go api pkg, MPL-2.0, vendored). - Optional: short-TTL memory cache (per README "Today vs planned"). Both stubs already fail loudly (501 `not_implemented`) naming ref + backend; connectors slot into the single `backend.Backend` interface and `newRegistry()` in `cmd/keyproxy/main.go`. ## Hygiene - No broad pkill this turn; the only process handling was `docker rm -f keyproxy-smoke` (exact container name) in the smoke script's cleanup trap. - Nothing seeded beyond the repo; real `keyproxy.toml`, `*.env`, `bin/`, `.smoke/` all gitignored; working tree clean after push.