One file or album quak cannot decrypt stops every refresh, so quak backup stores nothing #181

Open
opened 2026-10-14 01:31:46 +02:00 by clawbot · 1 comment
Collaborator

Problem

Client.filesSince and Client.collectionsSince (src/client.ts) decrypt every row of the server's answer with no guard. When one file's key, metadata or magic metadata, or one album's key or name, cannot be decrypted or parsed, the call throws, the library's refresh fails, and nothing is committed. lib.backup() waits for that refresh, so quak backup exits 1 before it stores anything, and it does so on every run until the server's copy changes. collections, files, get and the other read commands fail the same way.

The README promises the opposite: per-file errors are logged and the run continues. One bad record in a large account must not stop the backup of every other file.

Definition of done

  • A file whose key, metadata or magic metadata cannot be decrypted or parsed is left out of the refresh, and the rest of the account refreshes and commits as usual.
  • An album whose key, name or magic metadata cannot be decrypted is left out with its files, and the rest of the account refreshes as usual.
  • The library remembers each one it left out, in its cache, until a later refresh decrypts it or the server deletes it. This is needed because the next refresh asks only for changes, so it will not see the record again.
  • quak backup and lib.backup() back up every other file, record each left-out file in failures.json (its ID, and an error saying it could not be decrypted, with the reason), print one line for each left-out album naming its ID, and exit 1 while any remain. A run after the record decrypts, or is deleted, drops it and can exit 0.
  • The read commands answer from the records that did decrypt.
  • Tests, against a fake of the Ente HTTP API with real encryption (as test/client/usage.test.ts and test/client/enumeration.test.ts build one), cover: a file with a corrupt key, a file with metadata that is not JSON, an album with a corrupt key; the rest of the account backs up; the exit code; the record leaves failures.json once fixed or deleted.
  • README ("Backup layout" and "Session handling"/"Retries" as fits) says what happens to a record quak cannot decrypt.

Notes for the implementer

  • All network reads still happen before the store changes (see refreshOnce in src/library/index.ts).
  • Keep it plain: one list of left-out records in the store, written with the rest of metadata.json. No new terms in the README beyond plain sentences.
  • A file left out in one album but decrypted in another is not left out.

Model: opus-5-5

## Problem `Client.filesSince` and `Client.collectionsSince` (`src/client.ts`) decrypt every row of the server's answer with no guard. When one file's key, metadata or magic metadata, or one album's key or name, cannot be decrypted or parsed, the call throws, the library's refresh fails, and nothing is committed. `lib.backup()` waits for that refresh, so `quak backup` exits 1 before it stores anything, and it does so on every run until the server's copy changes. `collections`, `files`, `get` and the other read commands fail the same way. The README promises the opposite: per-file errors are logged and the run continues. One bad record in a large account must not stop the backup of every other file. ## Definition of done - A file whose key, metadata or magic metadata cannot be decrypted or parsed is left out of the refresh, and the rest of the account refreshes and commits as usual. - An album whose key, name or magic metadata cannot be decrypted is left out with its files, and the rest of the account refreshes as usual. - The library remembers each one it left out, in its cache, until a later refresh decrypts it or the server deletes it. This is needed because the next refresh asks only for changes, so it will not see the record again. - `quak backup` and `lib.backup()` back up every other file, record each left-out file in `failures.json` (its ID, and an error saying it could not be decrypted, with the reason), print one line for each left-out album naming its ID, and exit 1 while any remain. A run after the record decrypts, or is deleted, drops it and can exit 0. - The read commands answer from the records that did decrypt. - Tests, against a fake of the Ente HTTP API with real encryption (as `test/client/usage.test.ts` and `test/client/enumeration.test.ts` build one), cover: a file with a corrupt key, a file with metadata that is not JSON, an album with a corrupt key; the rest of the account backs up; the exit code; the record leaves `failures.json` once fixed or deleted. - README ("Backup layout" and "Session handling"/"Retries" as fits) says what happens to a record quak cannot decrypt. ## Notes for the implementer - All network reads still happen before the store changes (see `refreshOnce` in `src/library/index.ts`). - Keep it plain: one list of left-out records in the store, written with the rest of `metadata.json`. No new terms in the README beyond plain sentences. - A file left out in one album but decrypted in another is not left out. Model: opus-5-5
clawbot added this to the 1.0.0 milestone 2026-10-14 01:33:12 +02:00
Author
Collaborator

Built in #188: a refresh leaves out an album or file it cannot decrypt and the library keeps the list in its cache; quak backup stores every other file, records each such file in failures.json, prints a line per such album, and exits 1 until the record decrypts or is deleted.

Model: opus-5-5

Built in https://git.eeqj.de/sneak/quak/pulls/188: a refresh leaves out an album or file it cannot decrypt and the library keeps the list in its cache; `quak backup` stores every other file, records each such file in `failures.json`, prints a line per such album, and exits 1 until the record decrypts or is deleted. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/quak#181