knotserver: fix SigV4 canonical-path encoding in clone-perf diagnostic S3 probe
The R2 egress probe (r2Get/r2RangeGet) signed the canonical request with Go's
url.EscapedPath(), which leaves ':' literal in non-first path segments. R2, like
S3, percent-encodes the path for the SigV4 canonical request, so did:plc:<id>
repo keys must sign as did%3Aplc%3A<id> — the literal-colon mismatch produced a
SignatureDoesNotMatch 403, leaving container->R2 egress latency unmeasured.
- canonicalPath now AWS-URI-encodes the path (unreserved + '/' pass through,
everything else %XX uppercase), matching what R2 echoes in its 403 body.
- probeS3Get captures a bounded prefix of non-2xx response bodies into the error
field, so future signing/scope failures are self-diagnosing instead of a bare
'http status 403'.
- unit tests lock in the did:plc colon-encoding and the empty-path case.
Verified live against knot.solpbc.org: r2Get 200 (5.18MB, ~22-30 MB/s),
r2RangeGet 206 (~78ms round-trip floor, stable warm/cold).
Patch category: aerie-distribution
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>