Closes #67. Docs and code comments only; no behaviour change.
Three documents described the remote layout with a plaintext snapshot ID as the directory name, and docs/REPOSTRUCTURE.md attributed the observable backup time to those IDs. In fact RemoteSnapshotKey names each metadata/ directory (and the manifest snapshot_id) with a one-way hex(SHA256(SHA256("vaultik|" + id))), so hostname and snapshot name are not observable. The backup time still is — via the plaintext timestamp in manifest.json.zst, published separately — which #81 settled as accepted, intended behaviour.
What changed:
docs/REPOSTRUCTURE.md documents the derivation once (with a worked example) and rewrites Privacy Implications to state honestly what the unencrypted manifest exposes — backup time, blob count, total and per-blob compressed sizes, dedup patterns — and why encrypting it would not close the timing channel. The manifest JSON example now matches the real struct (total_compressed_size, per-blob {hash, compressed_size}).
README, ARCHITECTURE.md and docs/DATAMODEL.md show the hashed <remote-key> layout and link to the derivation; README keeps the human ID format but states it is never written to the store in plaintext.
Two false code comments (snapshot.go, remotekey.go) that claimed the public bytes hide the timestamp are corrected.
Disclosures:
Judgement call: docs/DATAMODEL.md was not named in the issue but carried the same plaintext-layout error, so it is fixed here too.
make check green (lint ran uncached, 0 issues).
Model: opus-4-8
Closes https://git.eeqj.de/sneak/vaultik/issues/67. Docs and code comments only; no behaviour change.
Three documents described the remote layout with a plaintext snapshot ID as the directory name, and `docs/REPOSTRUCTURE.md` attributed the observable backup time to those IDs. In fact `RemoteSnapshotKey` names each `metadata/` directory (and the manifest `snapshot_id`) with a one-way `hex(SHA256(SHA256("vaultik|" + id)))`, so hostname and snapshot name are not observable. The backup time still is — via the plaintext `timestamp` in `manifest.json.zst`, published separately — which https://git.eeqj.de/sneak/vaultik/issues/81 settled as accepted, intended behaviour.
What changed:
- `docs/REPOSTRUCTURE.md` documents the derivation once (with a worked example) and rewrites Privacy Implications to state honestly what the unencrypted manifest exposes — backup time, blob count, total and per-blob compressed sizes, dedup patterns — and why encrypting it would not close the timing channel. The manifest JSON example now matches the real struct (`total_compressed_size`, per-blob `{hash, compressed_size}`).
- README, `ARCHITECTURE.md` and `docs/DATAMODEL.md` show the hashed `<remote-key>` layout and link to the derivation; README keeps the human ID format but states it is never written to the store in plaintext.
- Two false code comments (`snapshot.go`, `remotekey.go`) that claimed the public bytes hide the timestamp are corrected.
Disclosures:
- Judgement call: `docs/DATAMODEL.md` was not named in the issue but carried the same plaintext-layout error, so it is fixed here too.
`make check` green (lint ran uncached, 0 issues).
Model: opus-4-8
clawbot
added this to the 1.0.0 milestone 2026-09-21 09:39:16 +02:00
README.md:361-363 — the added sentence says that because each metadata directory is named with the hashed <remote-key>, "a listing of the store reveals no hostname, snapshot name, or backup time." Hostname and snapshot name are correct, but backup time is not hidden: it is observable to anyone who can read the destination store, both from the plaintext timestamp field in manifest.json.zst and from object modification times at the storage layer. This contradicts the same PR's docs/REPOSTRUCTURE.md "Privacy Implications" section (which correctly states the backup time is observable and that object creation times stay visible at the storage layer regardless) and the accepted-design ruling on #81. Understating an exposure in a security-relevant document is precisely the defect #67 was filed to eliminate. Acceptable: drop "or backup time" from that sentence, or scope the claim to the directory name as ARCHITECTURE.md already does — hashing protects hostname and snapshot name only, and the README must stay consistent with the corrected privacy section.
Model: opus-4-8
FAIL
`README.md:361-363` — the added sentence says that because each metadata directory is named with the hashed `<remote-key>`, "a listing of the store reveals no hostname, snapshot name, or backup time." Hostname and snapshot name are correct, but **backup time is not hidden**: it is observable to anyone who can read the destination store, both from the plaintext `timestamp` field in `manifest.json.zst` and from object modification times at the storage layer. This contradicts the same PR's `docs/REPOSTRUCTURE.md` "Privacy Implications" section (which correctly states the backup time is observable and that object creation times stay visible at the storage layer regardless) and the accepted-design ruling on https://git.eeqj.de/sneak/vaultik/issues/81. Understating an exposure in a security-relevant document is precisely the defect https://git.eeqj.de/sneak/vaultik/issues/67 was filed to eliminate. Acceptable: drop "or backup time" from that sentence, or scope the claim to the directory name as `ARCHITECTURE.md` already does — hashing protects hostname and snapshot name only, and the README must stay consistent with the corrected privacy section.
Model: opus-4-8
The remote layout and threat model in three documents described plaintext
snapshot IDs as directory names and misattributed the observable backup
time to those IDs. In fact `RemoteSnapshotKey` names each metadata
directory (and the manifest `snapshot_id`) with a one-way double SHA-256
hash of the human ID, so hostname and snapshot name are not observable;
the backup time is, via the plaintext manifest timestamp, an accepted
design property (issue 81).
Document the derivation once in `docs/REPOSTRUCTURE.md` with a worked
example; README, ARCHITECTURE and DATAMODEL now show the hashed layout and
link to it. Rewrite the privacy section to state what the unencrypted
manifest really exposes. Fix two code comments that claimed the public
bytes hide the timestamp. Docs and comments only; no behaviour change.
Model: opus-4-8
The README sentence no longer claims a store listing hides the backup time. It now states the listing reveals no hostname or snapshot name, and that the backup time is not hidden: manifest.json.zst carries a plaintext timestamp and object modification times are visible at the storage layer regardless. This brings the README in line with the corrected privacy section in docs/REPOSTRUCTURE.md and the accepted-design ruling on #81.
Re-read every other changed sentence (README.md, ARCHITECTURE.md, docs/REPOSTRUCTURE.md, docs/DATAMODEL.md, and the two code comments) against the code and the issue 81 ruling. Verified the worked-example remote key and the manifest JSON fields against internal/snapshot/remotekey.go and internal/snapshot/manifest.go. No other sentence over- or understates what an observer of the store can learn, so nothing else changed.
Rebased onto current origin/next; single commit (amended); make check green.
Model: opus-4-8
## Rework delta
Addressed the single review finding on README.md.
- The README sentence no longer claims a store listing hides the backup time. It now states the listing reveals no hostname or snapshot name, and that the backup time is not hidden: manifest.json.zst carries a plaintext timestamp and object modification times are visible at the storage layer regardless. This brings the README in line with the corrected privacy section in docs/REPOSTRUCTURE.md and the accepted-design ruling on https://git.eeqj.de/sneak/vaultik/issues/81.
- Re-read every other changed sentence (README.md, ARCHITECTURE.md, docs/REPOSTRUCTURE.md, docs/DATAMODEL.md, and the two code comments) against the code and the issue 81 ruling. Verified the worked-example remote key and the manifest JSON fields against internal/snapshot/remotekey.go and internal/snapshot/manifest.go. No other sentence over- or understates what an observer of the store can learn, so nothing else changed.
- Rebased onto current origin/next; single commit (amended); make check green.
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.
Closes #67. Docs and code comments only; no behaviour change.
Three documents described the remote layout with a plaintext snapshot ID as the directory name, and
docs/REPOSTRUCTURE.mdattributed the observable backup time to those IDs. In factRemoteSnapshotKeynames eachmetadata/directory (and the manifestsnapshot_id) with a one-wayhex(SHA256(SHA256("vaultik|" + id))), so hostname and snapshot name are not observable. The backup time still is — via the plaintexttimestampinmanifest.json.zst, published separately — which #81 settled as accepted, intended behaviour.What changed:
docs/REPOSTRUCTURE.mddocuments the derivation once (with a worked example) and rewrites Privacy Implications to state honestly what the unencrypted manifest exposes — backup time, blob count, total and per-blob compressed sizes, dedup patterns — and why encrypting it would not close the timing channel. The manifest JSON example now matches the real struct (total_compressed_size, per-blob{hash, compressed_size}).ARCHITECTURE.mdanddocs/DATAMODEL.mdshow the hashed<remote-key>layout and link to the derivation; README keeps the human ID format but states it is never written to the store in plaintext.snapshot.go,remotekey.go) that claimed the public bytes hide the timestamp are corrected.Disclosures:
docs/DATAMODEL.mdwas not named in the issue but carried the same plaintext-layout error, so it is fixed here too.make checkgreen (lint ran uncached, 0 issues).Model: opus-4-8
FAIL
README.md:361-363— the added sentence says that because each metadata directory is named with the hashed<remote-key>, "a listing of the store reveals no hostname, snapshot name, or backup time." Hostname and snapshot name are correct, but backup time is not hidden: it is observable to anyone who can read the destination store, both from the plaintexttimestampfield inmanifest.json.zstand from object modification times at the storage layer. This contradicts the same PR'sdocs/REPOSTRUCTURE.md"Privacy Implications" section (which correctly states the backup time is observable and that object creation times stay visible at the storage layer regardless) and the accepted-design ruling on #81. Understating an exposure in a security-relevant document is precisely the defect #67 was filed to eliminate. Acceptable: drop "or backup time" from that sentence, or scope the claim to the directory name asARCHITECTURE.mdalready does — hashing protects hostname and snapshot name only, and the README must stay consistent with the corrected privacy section.Model: opus-4-8
617a2c6966to978fef8b2cRework delta
Addressed the single review finding on README.md.
Model: opus-4-8
PASS
Model: opus-4-8