Tags: tijs/attic
Tags
fix(s3): pre-encode listObjects query values for SigV4 (beta.20) Beta.19's thumbnail-cleanup probe surfaced a long-latent signing bug: `attic backup` on a strict-canonicalization S3 endpoint failed with `SignatureDoesNotMatch` on the very first `listObjects` call. Root cause: `aws-signer-v4` (`signer.swift:211`) canonicalizes `url.query` raw — its own comment notes it "should really uriEncode all the query string values" but doesn't. Strict S3 servers canonicalize per AWS SigV4 spec, which requires query values to be URI-encoded. So the request URL went out with `prefix=thumbnails/`, the signer signed `prefix=thumbnails/`, the server canonicalized `prefix=thumbnails%2F`, and the two signatures diverged. `URLComponents.queryItems` did not save us: Foundation only encodes characters outside its built-in `urlQueryAllowed` set, which leaves `/`, `:`, `+`, `=` raw in query values — exactly the characters that matter for our prefixes (`thumbnails/`, `metadata/assets/`) and for PhotoKit cloud identifiers if they ever surface in a listing query. Fix: pre-encode each query value to RFC 3986 unreserved characters in `URLSessionS3Client.listObjects`, then assign via `percentEncodedQuery` directly. The wire form and the canonical form now match, so the signer-side bug becomes invisible without needing to fork the signer crate. Also explains why `attic rebuild`'s `metadata/assets/` listing has been quietly broken on strict endpoints — same code path. Same fix covers it. No behavior change for permissive S3 implementations that accepted the raw form. 262/262 tests still pass (mock S3 doesn't exercise real signing). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(release): wrap single-line function bodies in test mocks (beta.19) Beta.18 release CI failed at SwiftFormat: the `S3Providing` test doubles in `ThumbnailCleanupTests.swift` and `ThumbnailCleanupRunnerIntegrationTests.swift` had single-line empty function bodies that violate the project's `wrapFunctionBodies` rule. Re-ran `swiftformat .` to wrap them. No behavior change. 262/262 tests still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(release): split MigrationRunner.swift to satisfy file-length lint Beta.17 release CI failed at SwiftLint with `MigrationRunner.swift` at 746 lines (cap 600). Cleanup-phase additions pushed it past the budget. Factor the file along orthogonal seams that already exist in the code: - `MigrationReport` struct + `formatMigrationReport` + `formatMigrationReportJSON` move to `Migration/MigrationReport.swift`. - `CleanupConfirmation` enum, `MigrationRunnerError` enum, and the cleanup-phase orchestration body move to `Migration/ThumbnailCleanupPhase.swift` as `runThumbnailCleanupPhaseImpl(...)`. Runner's `runThumbnailCleanupPhase` shrinks to a one-line delegation. Behavior unchanged. All 262 tests still pass. Bumps version to 1.0.0-beta.18 to ship the fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore: bump version to 1.0.0-beta.17 Ships the thumbnail-cleanup migration step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: drop the viewer subcommand and all related code (beta.16) The web viewer was a fun side experiment but never core to attic's backup-and-verify use case. Maintaining it kept multiplying overhead: - Hummingbird dependency for an HTTP server pulling ~10 transitive packages - A separate JS frontend in `Sources/AtticCLI/Resources/viewer.html` with no type system, no test coverage, and a habit of breaking when the manifest's identifier format changed (cloud-uuid encoding bugs in beta.13–beta.15) - An SPM resource bundle that homebrew distribution couldn't ship alongside the binary without contortions Strip everything tied to the viewer: - Subcommand: `Sources/AtticCLI/ViewerCommand.swift`, `Sources/AtticCLI/ViewerServer.swift`, `Resources/viewer.html` - Backend support: `Sources/AtticCore/ViewerDataStore.swift`, `ThumbnailService.swift`, `ThumbnailCache.swift`, `ThumbnailProviding.swift`, `ImageThumbnailer.swift`, `VideoThumbnailer.swift` - Tests: `ViewerDataStoreTests.swift`, `ThumbnailTests.swift` - Package: drop Hummingbird dependency and the resources copy step - CLI: remove `ViewerCommand` from the subcommand list - Release workflow: revert the resource-bundle copy added in beta.15 - Docs: rewrite the design-context section to focus on backup/verify, drop the now-dead `viewer-unencoded-cloud-identifier-urls` learning, scrub the `ThumbnailCache` example from the percent-encoding learning Manifest data, S3 layout, and all backup/verify/refresh paths are unaffected. Restoring browsing later is possible by exporting metadata to a separate static-site generator that doesn't need to live inside the CLI binary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PreviousNext