Foundation unit for the cache/API design (#36). This
is the first piece; everything later needs it, so it lands first.
Goal
Carry three fields that arrive on the wire but are dropped at decryption, so the
metadata cache, the plain records, and the download/integrity code can see them:
info.fileSize and info.thumbSize (bytes on the wire), and
isDeleted (the tombstone flag).
Current state (grounded)
RawEnteFile already declares info?: { fileSize?; thumbSize? } and isDeleted? (src/model/types.ts), but decryptFile (src/model/decrypt.ts)
copies neither into the returned EnteFile.
EnteFile.file/EnteFile.thumbnail are FileBlob { decryptionHeader; size? }
— size exists on the type but is never populated.
Scope (extend existing; no new modules)
In decryptFile, set file.size = raw.info?.fileSize and thumbnail.size = raw.info?.thumbSize (leave undefined when the server
omits them — do not coerce to 0).
Surface the tombstone on the decrypted record. Add isDeleted?: boolean to EnteFile and set it from raw.isDeleted. decryptFile currently assumes a
live row; a tombstone row may lack the fields needed to decrypt
(encryptedKey, metadata). So: when raw.isDeleted is true, return a
minimal EnteFile carrying id, collectionID, updationTime, and isDeleted: true, without attempting decryption. Confirm the exact tombstone
shape against the test fixtures before deciding which fields are safe to read.
Do not change any caller behaviour in this unit. Client.listFiles today
filters isDeleted before calling decryptFile, so it never passes a
tombstone in; that path is unchanged here and is reworked in the enumeration
unit.
Definition of done
decryptFile populates file.size, thumbnail.size, and isDeleted.
A live-file fixture yields the sizes; a tombstone fixture yields { id, collectionID, updationTime, isDeleted: true } and does not throw.
New/extended tests in test/model/decrypt.test.ts cover both cases,
including the size-absent case (stays undefined).
make check green. No behaviour change for existing callers.
Dispatch notes for the implementer: TDD (red test first). No scripted edits —
read and hand-edit; format only via make fmt. Do not ask interactive
questions; decide from this brief and the fixtures. Land the squash commit
subject ending (closes #<this issue>). Every commit message, PR body, and
comment ends with Model: opus-4-8.
Model: opus-4-8
Foundation unit for the cache/API design (https://git.eeqj.de/sneak/quak/issues/36). This
is the first piece; everything later needs it, so it lands first.
## Goal
Carry three fields that arrive on the wire but are dropped at decryption, so the
metadata cache, the plain records, and the download/integrity code can see them:
- `info.fileSize` and `info.thumbSize` (bytes on the wire), and
- `isDeleted` (the tombstone flag).
## Current state (grounded)
- `RawEnteFile` already declares `info?: { fileSize?; thumbSize? }` and
`isDeleted?` (`src/model/types.ts`), but `decryptFile` (`src/model/decrypt.ts`)
copies neither into the returned `EnteFile`.
- `EnteFile.file`/`EnteFile.thumbnail` are `FileBlob { decryptionHeader; size? }`
— `size` exists on the type but is never populated.
## Scope (extend existing; no new modules)
- In `decryptFile`, set `file.size = raw.info?.fileSize` and
`thumbnail.size = raw.info?.thumbSize` (leave `undefined` when the server
omits them — do not coerce to 0).
- Surface the tombstone on the decrypted record. Add `isDeleted?: boolean` to
`EnteFile` and set it from `raw.isDeleted`. `decryptFile` currently assumes a
live row; a tombstone row may lack the fields needed to decrypt
(`encryptedKey`, `metadata`). So: when `raw.isDeleted` is true, return a
minimal `EnteFile` carrying `id`, `collectionID`, `updationTime`, and
`isDeleted: true`, without attempting decryption. Confirm the exact tombstone
shape against the test fixtures before deciding which fields are safe to read.
- Do not change any caller behaviour in this unit. `Client.listFiles` today
filters `isDeleted` before calling `decryptFile`, so it never passes a
tombstone in; that path is unchanged here and is reworked in the enumeration
unit.
## Definition of done
- `decryptFile` populates `file.size`, `thumbnail.size`, and `isDeleted`.
- A live-file fixture yields the sizes; a tombstone fixture yields
`{ id, collectionID, updationTime, isDeleted: true }` and does not throw.
- New/extended tests in `test/model/decrypt.test.ts` cover both cases,
including the size-absent case (stays `undefined`).
- `make check` green. No behaviour change for existing callers.
## Grounding
Files: `src/model/types.ts`, `src/model/decrypt.ts`, `test/model/decrypt.test.ts`.
Dispatch notes for the implementer: TDD (red test first). No scripted edits —
read and hand-edit; format only via `make fmt`. Do not ask interactive
questions; decide from this brief and the fixtures. Land the squash commit
subject ending ` (closes #<this issue>)`. Every commit message, PR body, and
comment ends with `Model: opus-4-8`.
Model: opus-4-8
decryptFile now carries file.size/thumbnail.size from the server's info
(left undefined when omitted), and returns a minimal tombstone for a deleted
file without decrypting.
One design call worth your eye: rather than making EnteFile's structural
fields optional (which breaks every consumer under strict tsc), a tombstone is a
distinct EnteFileTombstone type and decryptFile returns EnteFile | EnteFileTombstone. Details and disclosures are in the PR body.
Model: opus-4-8
Implemented in [PR #55](https://git.eeqj.de/sneak/quak/pulls/55).
`decryptFile` now carries `file.size`/`thumbnail.size` from the server's `info`
(left `undefined` when omitted), and returns a minimal tombstone for a deleted
file without decrypting.
One design call worth your eye: rather than making `EnteFile`'s structural
fields optional (which breaks every consumer under strict tsc), a tombstone is a
distinct `EnteFileTombstone` type and `decryptFile` returns
`EnteFile | EnteFileTombstone`. Details and disclosures are in the PR body.
Model: opus-4-8
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Foundation unit for the cache/API design (#36). This
is the first piece; everything later needs it, so it lands first.
Goal
Carry three fields that arrive on the wire but are dropped at decryption, so the
metadata cache, the plain records, and the download/integrity code can see them:
info.fileSizeandinfo.thumbSize(bytes on the wire), andisDeleted(the tombstone flag).Current state (grounded)
RawEnteFilealready declaresinfo?: { fileSize?; thumbSize? }andisDeleted?(src/model/types.ts), butdecryptFile(src/model/decrypt.ts)copies neither into the returned
EnteFile.EnteFile.file/EnteFile.thumbnailareFileBlob { decryptionHeader; size? }—
sizeexists on the type but is never populated.Scope (extend existing; no new modules)
decryptFile, setfile.size = raw.info?.fileSizeandthumbnail.size = raw.info?.thumbSize(leaveundefinedwhen the serveromits them — do not coerce to 0).
isDeleted?: booleantoEnteFileand set it fromraw.isDeleted.decryptFilecurrently assumes alive row; a tombstone row may lack the fields needed to decrypt
(
encryptedKey,metadata). So: whenraw.isDeletedis true, return aminimal
EnteFilecarryingid,collectionID,updationTime, andisDeleted: true, without attempting decryption. Confirm the exact tombstoneshape against the test fixtures before deciding which fields are safe to read.
Client.listFilestodayfilters
isDeletedbefore callingdecryptFile, so it never passes atombstone in; that path is unchanged here and is reworked in the enumeration
unit.
Definition of done
decryptFilepopulatesfile.size,thumbnail.size, andisDeleted.{ id, collectionID, updationTime, isDeleted: true }and does not throw.test/model/decrypt.test.tscover both cases,including the size-absent case (stays
undefined).make checkgreen. No behaviour change for existing callers.Grounding
Files:
src/model/types.ts,src/model/decrypt.ts,test/model/decrypt.test.ts.Dispatch notes for the implementer: TDD (red test first). No scripted edits —
read and hand-edit; format only via
make fmt. Do not ask interactivequestions; decide from this brief and the fixtures. Land the squash commit
subject ending
(closes #<this issue>). Every commit message, PR body, andcomment ends with
Model: opus-4-8.Model: opus-4-8
clawbot referenced this issue2026-09-22 10:55:32 +02:00
Implemented in PR #55.
decryptFilenow carriesfile.size/thumbnail.sizefrom the server'sinfo(left
undefinedwhen omitted), and returns a minimal tombstone for a deletedfile without decrypting.
One design call worth your eye: rather than making
EnteFile's structuralfields optional (which breaks every consumer under strict tsc), a tombstone is a
distinct
EnteFileTombstonetype anddecryptFilereturnsEnteFile | EnteFileTombstone. Details and disclosures are in the PR body.Model: opus-4-8