feat: v0.1.1 -- UX ship-blockers, hardening, and refactor
Summary
v0.1.1 patch addressing the four CRITICAL UX ship-blockers found after
v0.1.0 shipped, plus adjacent hardening (internal-CA support, restricted-
environment token file, tightened file modes) and a pre-existing CLI-setup
duplication between run and collect.
Every commit is a coherent unit; the branch is squash-ready but also bisect-friendly as-is.
Change groups
Ship-blocker fixes
fix: preserve health reports on partial collector runs--report.Generateruns even whencollector.Runreturns an error;errors.Joinpreserves the collector error forerrors.Iscallers.fix: flag unknown counts on partial runs-- "Active users on instance" and "MR authors in window" render(unknown)when their stage did not complete; newUNKNOWNzone value keeps partial-run reports from reading as "catastrophically unhealthy".fix: fast-fail preflight on unreachable GitLab instance-- new--preflight-timeout(default5s); probe also returns the instance version so the orchestrator skips a duplicate/api/v4/version.fix: Dockerfile bind-mount ergonomics-- both variants nowmkdir + chown /tach-databeforeUSER 1001, setWORKDIR, andCMD ["run", "--output", "/tach-data"]so baredocker runplus a bind-mount works on first run.VOLUMEdirective removed (anonymous- volume accumulation without a bind-mount is worse than the benefit).fix: tighten output file modes with Windows handling--0600oncollection.json,health-report.{txt,json},monthly.csv;--token-filepermission check gates onruntime.GOOS != "windows"since Windows synthesises mode bits.
Hardening
feat: support --ca-bundle and SSL_CERT_FILE-- PEM file appended to the system trust store for instances fronted by an internal CA.feat: support --token-file for restricted environments-- file-based PAT sourcing for hosts that forbid secrets in env vars; mutually exclusive withGITLAB_TOKEN; trim rule enforced; internal whitespace rejected; Unix permission check gated on0600-or-stricter.
Refactor
refactor: extract shared CLI setup for run and collect-- the flag block, env resolution, lockfile apply, and client construction collapse intocmd/tach/setup.go.--helpoutput is byte-identical before/after for each command; the two commands now diverge only in what they do with the resolved config (report render vs collect-only).
Cleanup
chore: remove unused checkpoint.json write path-- nothing read it.chore: drop residual context-leak wording in SECURITY.md and hero.svg.docs: changelog and gitlab-docs conformance-- newCHANGELOG.mdin Keep-a-Changelog format; vale sweep (British -> American English,via->through,filesystem->file system,usefulscrubbed).
Tests
test: bound CheckAdmin transport-error retry ladder-- drops a 34s test to sub-second by short-circuiting the retry with a bounded context.test: assert --token-file rejects every group-or-other bit-- table- driven truth table (0640/0620/0610/0604/0602/0601/0660/0606).
Not in scope
- Full e2e against a live GitLab instance (deferred; unit coverage is tight and prior audits cleared the silent-wrong-answer paths).
collection.jsonschema rework (compactmr_authors, derived pipeline/SAST/per-user-throughput fields). Tracked for v0.2.0 as a coordinated bump with the sibling consumer.
Test plan
-
go vet ./...clean -
go build ./...clean -
go test -count=1 ./...clean (full suite ~3s; collector package ~1s, down from ~36s before the CheckAdmin retry-bound) -
go run ./cmd/tach {run,collect,report,verify} --helpprints cleanly; flag lists match README - Four independent audits (simplify, adversarial context-leak, UX regression, vale) in two rounds against the diff -- zero blockers at the final sweep
- CI pipeline green
- Release pipeline produces clean artifacts (binaries + SLSA + cosign + container images)