Skip to content

Commit 1ea9c69

Browse files
committed
Release v0.5.0
1 parent 4386681 commit 1ea9c69

1 file changed

Lines changed: 172 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,176 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.5.0] — 2026-04-21
11+
12+
### Added
13+
- Five new pipe-friendly sub-commands that replace the ad-hoc external
14+
tool chain (`sha256sum`, `shasum`, `xxd`, `base64`, `jq`, `date`)
15+
with built-ins that behave identically across macOS, Linux, BSD,
16+
WSL, and Git-Bash on Windows:
17+
- `truestamp hash` — SHA-2 / SHA-3 / BLAKE2 / MD5 / SHA-1 digests
18+
for files, stdin, URLs, or a picked file. Default output is
19+
byte-identical to GNU coreutils' `sha256sum` (including the
20+
standard `\`-escaping for filenames with newlines/backslashes).
21+
`--style bsd` matches `shasum --tag`; `--style bare` is
22+
digest-only. Legacy algorithms (MD5, SHA-1) emit a one-line
23+
stderr warning unless `--json` or `--silent` is set. Supports
24+
`--prefix 0xNN` (prepend a single domain-separation byte before
25+
hashing) and `--jcs` (apply RFC 8785 canonicalization first), so
26+
the Truestamp claims-hash intermediate is a one-liner:
27+
`truestamp hash --prefix 0x11 --jcs -a sha256 --style bare < claims.json`.
28+
- `truestamp encode` and `truestamp decode` — byte-encoding
29+
conversions among `hex`, `base64`, `base64url`, and `binary`,
30+
with strict cross-encoding-alphabet rejection. Both support
31+
text-to-text conversion via `--from`/`--to`.
32+
- `truestamp jcs` — apply RFC 8785 JSON Canonicalization to the
33+
input. Pipes directly into `truestamp hash` for hashing
34+
pipelines; `truestamp hash --jcs` is the shortcut.
35+
- `truestamp convert` — umbrella for domain-specific conversions:
36+
- `convert time` — parse and re-format timestamps across zones
37+
and Unix formats (auto / rfc3339 / unix-{s,ms,us,ns}, IANA
38+
zones, Go time layouts as `--format`).
39+
- `convert proof` — switch a proof bundle between JSON and CBOR
40+
wire formats. CBOR output uses RFC 8949 §4.2 core
41+
deterministic encoding and prepends the self-describing tag
42+
55799 so `truestamp verify` auto-detects the format.
43+
- `convert id` — extract the embedded millisecond timestamp
44+
from a ULID (item IDs) or UUIDv7 (block and entropy IDs).
45+
Auto-detects the type; supports `--to-zone` for display.
46+
- `convert keyid` — derive the 4-byte Truestamp `kid`
47+
fingerprint (`truncate4(SHA256(0x51 || pubkey))`) from an
48+
Ed25519 public key in hex, base64, or base64url.
49+
- `convert merkle` — decode a compact base64url Merkle proof
50+
(`ip` / `ep` fields) into a human-readable sibling list with
51+
position + hash per step.
52+
- `internal/inputsrc` — shared six-mode input resolver (positional,
53+
`--file [path]`, `--file` picker, `--url [url]`, `--url` prompt,
54+
stdin pipe). Used uniformly by `verify`, `create`, and every new
55+
sub-command. `pflag` `NoOptDefVal` sentinels are now readable
56+
`(pick)` / `(prompt)` strings so `--help` renders cleanly; `-`
57+
as a positional is accepted as the Unix-standard stdin alias.
58+
- `internal/encoding` — RFC 4648 hex/base64/base64url round-trip with
59+
tolerance for trailing whitespace and rejection of mismatched
60+
alphabets.
61+
- `internal/hashing` — 14-algorithm registry built on `crypto/{md5,
62+
sha1,sha256,sha512}` + `golang.org/x/crypto/{sha3,blake2b,blake2s}`,
63+
streaming `Compute`, and `sha256sum` / `shasum --tag` output
64+
formatters with proper filename escaping.
65+
- `ProofBundle.MarshalCBOR` on `internal/proof` — deterministic CBOR
66+
encoding (RFC 8949 §4.2) with the 0xd9d9f7 self-describing tag.
67+
Byte-valued fields (`pk`, `sig`, hashes, epoch/inclusion proofs)
68+
are re-encoded as CBOR major-type-2 byte strings per an explicit
69+
per-field policy; round-trips stabilize on the second pass.
70+
- `[hash]` and `[convert]` config sections in
71+
`~/.config/truestamp/config.toml`, plus matching env-var overrides
72+
(`TRUESTAMP_HASH_ALGORITHM`, `TRUESTAMP_HASH_ENCODING`,
73+
`TRUESTAMP_HASH_STYLE`, `TRUESTAMP_CONVERT_TIME_ZONE`).
74+
- Comprehensive test infrastructure:
75+
- **59 fuzz targets** (`FuzzXxx`) across 13 packages covering every
76+
parser that touches attacker-controlled bytes. Seed corpus lives
77+
in `f.Add()` calls; `go test` replays them on every run. Active
78+
mutation via `task fuzz-deep` (default 15s per target, 59
79+
targets, ~320M inputs per full pass).
80+
- **20+ benchmarks** (`BenchmarkXxx`) on hot paths: hashing across
81+
all 14 algorithms (SHA-256 ~2.9 GB/s, BLAKE2b ~1.1 GB/s on M3
82+
Max), encoding round-trip, proof parse / marshal (JSON + CBOR),
83+
Merkle decode + verify, domain-prefixed hashing.
84+
- **9 golden-output snapshot tests**`testdata/golden/` fixtures
85+
for `--help` output on root/verify/hash, `hash --list`, and JSON
86+
envelopes for `hash`, `encode`, and `convert {time,id,keyid}`.
87+
JSON is canonicalized before diffing so tests don't flake on
88+
Go's map-iteration order. Regenerate with
89+
`UPDATE_GOLDEN=1 go test ./cmd -run Golden`.
90+
- Coverage raised from 47.6% to 81.2% across 17 packages. Most
91+
packages are now >90%; the handful below that ceiling have
92+
structural reasons (interactive TTY, platform-specific Windows
93+
branches on a macOS/Linux runner, self-upgrade pipeline that
94+
needs a real release tarball + cosign binary).
95+
- New Taskfile entry points:
96+
- `task test-coverage-full` — covers CLI subprocess runs too by
97+
building the binary with `-cover -coverpkg=./...` and routing
98+
its `GOCOVERDIR` through a task-controlled directory (works
99+
around `go test -cover` clobbering `GOCOVERDIR` in the test
100+
process's environment).
101+
- `task test-race` — full suite under the race detector; currently
102+
zero-finding.
103+
- `task bench` / `task bench-compare` — benchmarks with `-benchmem`
104+
and a `-count=5` baseline suitable for `benchstat` comparison.
105+
- `task fuzz` / `task fuzz-deep` / `task fuzz-list`.
106+
- `task lint``go vet` + `gofmt -l` + `staticcheck` + `gosec`
107+
with documented exclusions for CLI-standard patterns
108+
(user-specified file paths, supported-with-warning legacy
109+
hashes, Unix-standard file permissions, hard-coded subprocess
110+
names).
111+
- `task vuln-check``govulncheck` against `go.mod` and stdlib.
112+
- `task precommit-full` — strict pre-release gate (fmt + lint +
113+
test-race + fuzz seeds + vuln-check + build-all, ~3-5 min).
114+
- `EXAMPLES.md` — new, ~800 lines. Per-sub-command tour with
115+
copy-pastable examples, ~15 pipeline recipes, `--json` + `jq`
116+
scripting patterns, CI conventions, and an offline/air-gapped
117+
usage section. Every example was exercised end-to-end against a
118+
live dev server to catch documentation drift. Linked prominently
119+
from the top of `README.md`.
120+
121+
### Changed
122+
- Go toolchain pinned to **1.26.2** in both `.tool-versions` and
123+
`go.mod` (previously `latest`, which resolved to 1.26.1). See
124+
Security below. All other entries in `.tool-versions` are now
125+
explicitly version-pinned rather than tracking `latest` to avoid
126+
silent drift.
127+
- `task precommit` slimmed to a **fast** hot-cache pass — `fmt` +
128+
`lint` + `test` + `build` (single-platform). ~2 s hot, ~8 s cold.
129+
Fuzz seed replay happens automatically as part of `task test` so
130+
no separate fuzz step is needed here. The comprehensive gate
131+
(race, active fuzz, vuln-check, cross-compile) lives in
132+
`precommit-full` and is intended for PR/release boundaries.
133+
- `cmd/verify.go` and `cmd/create.go` now consume the shared
134+
`internal/inputsrc` resolver; the old duplicated six-mode input
135+
logic in each command is gone.
136+
- `hash --style bare` now unconditionally omits the filename column
137+
(previously only did so when `--no-filename` was also passed,
138+
making `bare` accidentally byte-identical to `gnu` when a filename
139+
was available). The three styles now produce three distinct
140+
shapes:
141+
- `gnu``<hex> <filename>` (sha256sum-compatible)
142+
- `bsd``<ALGO> (<filename>) = <hex>` (shasum --tag)
143+
- `bare``<hex>` (digest only, always)
144+
- `internal/config.ConfigDir` and `internal/upgradecheck.cacheDir`
145+
split into `*_unix.go` / `*_windows.go` via build tags so each
146+
platform's branch is counted for coverage only on the platform
147+
where it can execute.
148+
- `ProofBundle.MarshalJSON` now writes `ts`, `pk`, `sig`, `s`, `b`,
149+
`ip`, `cx` in a stable map — with `encoding/json`'s alphabetical
150+
key ordering this yields a canonical JSON form suitable for
151+
round-trip comparisons against JCS.
152+
- `CONTRIBUTING.md` significantly expanded with a "When to run which
153+
task" table covering every Taskfile entry point, their durations,
154+
and recommended usage. The `Tests` section is now broken out by
155+
category (unit/integration, golden snapshots, fuzz, bench, race,
156+
coverage, lint, vuln-check) with guidance on what kind of test to
157+
add when.
158+
- `CLAUDE.md` updated with new package structure entries, the
159+
deterministic-CBOR policy, the shared inputsrc pattern, and a
160+
note on the 59-target fuzz coverage.
161+
162+
### Security
163+
- `golang.org/x/crypto` (already an indirect dependency) promoted to
164+
direct; used for SHA-3 and BLAKE2 implementations in
165+
`internal/hashing`. `task vuln-check` after the bump is clean.
166+
- Go toolchain bump to 1.26.2 eliminates **six standard-library
167+
vulnerabilities** flagged by `govulncheck` in 1.26.1: five in
168+
`crypto/x509` (various certificate-parsing issues reachable via
169+
`io.Copy` through our hash-streaming path, though not exploitable
170+
through the CLI's actual call graph) and one XSS-class bug in
171+
`html/template` (reachable from `fmt.Fprintln``template.Error`,
172+
again not exploitable from the CLI's call graph but eliminated on
173+
principle). `task vuln-check` now reports zero findings.
174+
175+
### Fixed
176+
- One real `staticcheck` finding addressed: an unused variable
177+
assignment in `cmd/coverage_extra_test.go` that the prior test
178+
suite never caught.
179+
10180
## [0.4.0] — 2026-04-17
11181

12182
### Added
@@ -303,7 +473,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
303473
v0.1.0 is the first release of a standalone Go codebase; the two share
304474
nothing beyond the repository name.
305475

306-
[Unreleased]: https://github.com/truestamp/truestamp-cli/compare/v0.4.0...HEAD
476+
[Unreleased]: https://github.com/truestamp/truestamp-cli/compare/v0.5.0...HEAD
477+
[0.5.0]: https://github.com/truestamp/truestamp-cli/releases/tag/v0.5.0
307478
[0.4.0]: https://github.com/truestamp/truestamp-cli/releases/tag/v0.4.0
308479
[0.3.3]: https://github.com/truestamp/truestamp-cli/releases/tag/v0.3.3
309480
[0.3.2]: https://github.com/truestamp/truestamp-cli/releases/tag/v0.3.2

0 commit comments

Comments
 (0)