Summary
S3 / Backblaze object keys that contain / (i.e. essentially every real folder-style key, and the bucket separator itself for the path-style amazon-s3 ops) are percent-encoded to %2F by the shared declarative-REST path interpolation, so the request addresses the wrong (non-existent) object. The SigV4 signature is correct (it signs url.pathname verbatim for S3), so AWS accepts the signature and returns NoSuchKey/404 — the resource path is what's wrong, not the auth.
Surfaced while implementing SigV4 (#113 / #118). Pre-existing, but newly load-bearing: before #118 these adapters used Bearer auth and never authenticated, so the path mangling was moot.
Evidence
executeRestRequest builds the path via interpolate(request.path, inv.args) (src/connectors/adapters/declarative-rest.ts).
interpolate runs encodeURIComponent(String(value)) on each substituted value, turning / → %2F.
amazon-s3 path-style ops carry bucket+key as a single {key}/{destinationKey} segment (files.read path /{key}, etc.). backblaze keeps {bucket} as its own segment but still mangles intra-key slashes.
Repro
amazonS3Connector.executeRead({ capabilityName: 'files.read', args: { key: 'mybucket/folder/file.txt' }, ... })
// → GET https://s3.<region>.amazonaws.com/mybucket%2Ffolder%2Ffile.txt (wrong object)
Suggested fix
Render path placeholders with a slash-preserving encoder (encode each segment but leave / intact), distinct from query/header interpolation which should keep encoding /. Because the S3 canonicalUri signs url.pathname verbatim, switching to literal / keeps signing consistent with what's sent. This touches shared declarative-REST path rendering (350+ adapters), so it needs a careful per-path-param policy (raw vs encoded) rather than a blanket change.
Refs #113, #118.
Summary
S3 / Backblaze object keys that contain
/(i.e. essentially every real folder-style key, and the bucket separator itself for the path-styleamazon-s3ops) are percent-encoded to%2Fby the shared declarative-REST path interpolation, so the request addresses the wrong (non-existent) object. The SigV4 signature is correct (it signsurl.pathnameverbatim for S3), so AWS accepts the signature and returnsNoSuchKey/404 — the resource path is what's wrong, not the auth.Surfaced while implementing SigV4 (#113 / #118). Pre-existing, but newly load-bearing: before #118 these adapters used Bearer auth and never authenticated, so the path mangling was moot.
Evidence
executeRestRequestbuilds the path viainterpolate(request.path, inv.args)(src/connectors/adapters/declarative-rest.ts).interpolaterunsencodeURIComponent(String(value))on each substituted value, turning/→%2F.amazon-s3path-style ops carry bucket+key as a single{key}/{destinationKey}segment (files.readpath/{key}, etc.).backblazekeeps{bucket}as its own segment but still mangles intra-key slashes.Repro
Suggested fix
Render path placeholders with a slash-preserving encoder (encode each segment but leave
/intact), distinct from query/header interpolation which should keep encoding/. Because the S3canonicalUrisignsurl.pathnameverbatim, switching to literal/keeps signing consistent with what's sent. This touches shared declarative-REST path rendering (350+ adapters), so it needs a careful per-path-param policy (raw vs encoded) rather than a blanket change.Refs #113, #118.