Skip to content

notes encrypt silently deletes a note's version history, then says it's still readable #82

Description

@cloudmanic

harbor notes encrypt deletes a note's version history without asking, then prints that the history is still readable.

What happens

Encrypting a note deletes every version snapshot that disagrees with the note's new state — the plaintext history is hard-deleted server-side, not tombstoned, and it is not recoverable. Decrypting does the same thing in reverse to the encrypted snapshots.

The CLI does neither of the two things a user needs here:

  1. It doesn't warn. The confirmation for this is client-side, and harbor notes encrypt doesn't have one. It runs, the history is gone, and the user finds out later — if ever. (notes decrypt already asks for a typed yes; notes encrypt asks for nothing.)

  2. It then tells the user the opposite of what just happened. cmd/notes_convert.go:605, printed after every run that seals something and carried in --help:

    • It does not clear the plaintext ALREADY ON THE SERVER. The note's earlier versions were snapshotted as plaintext and stay readable (harbor history list <id>). …

    That paragraph goes on to describe history coalescing as a rare exception "not to plan around." The exception is now the rule: every earlier version is deleted, every time.

So the message actively reassures someone that data still exists, moments after the CLI destroyed it. A user who encrypts a note because they want the old versions kept safe gets the exact opposite, silently.

Why it's wrong now

The copy predates the server change that made history and encryption state agree. Authoritative description: app.harbor.my/docs/encryption.md → "Changing encryption discards history", plus the code in internal/notes/. Short version:

  • Every snapshot of a note must agree with that note's is_encrypted. The write that changes the flag deletes every snapshot that disagrees.
  • Hard DELETE, not a tombstone. note_history doesn't sync and isn't indexed, so there is nothing to propagate and nothing to recover.
  • It is deliberate — sealing old snapshots instead would need a per-version crypto pass in all five clients, and the guarantee would only be as good as the weakest one.
  • The deletion is server-side; the confirmation is client-side. docs/encryption.md names harbor notes encrypt explicitly as a caller that "will discard history without asking," accepted as a known interim state — with the intended end state being that every client warns first.

⚠️ Don't verify this against the other clients

The same false sentence was copy-pasted into several repos. Three of them are not independent confirmation — they are the same stale claim:

Repo Status
app.harbor.my (web) ✅ Fixed — PR #1293
harbor-swift ✅ Fixed — PR #842
harbor-windows ❌ Still wrong — HarborCore/Ui/EncryptionDialogSpec.cs:63
harbor.my help docs ❌ Still wrong — encrypted-notes.md, encrypt-or-decrypt-a-single-note.md, developers/cli.md

docs/encryption.md and the server code are the source of truth. Note in particular that harbor.my/developers/cli.md:197 describes this CLI's caveat text — so fixing this issue makes that page wrong too, and it needs its own change.

What to do

  1. Warn before encrypting. notes encrypt should say plainly that the note's version history will be deleted and that it cannot be recovered, and require confirmation — same shape as notes decrypt's typed yes, with a --yes escape for scripts. Applies to the bulk --notebook form too, which can wipe the history of every note in a notebook in one command.
  2. Warn before decrypting too. notes decrypt already confirms, but for the wrong reason (publishing plaintext back). It also destroys the encrypted history and doesn't say so.
  3. Replace the false caveat in cmd/notes_convert.go — the post-run message and --help. State that earlier versions are deleted. Delete the history-coalescing paragraph; it described a rare exception to a rule that no longer exists.
  4. The attachment-bytes caveat in the same block is still true — keep it. The CLI genuinely does not re-encrypt attachment bytes.
  5. Check cmd/history.go and anywhere else that implies a note's history survives an encryption change.

Acceptance criteria

  • harbor notes encrypt refuses to run unattended without confirmation, and the prompt names the history deletion in plain words.
  • --yes (or equivalent) bypasses it for scripts.
  • The bulk --notebook form confirms once, and says how many notes' histories it will delete.
  • harbor notes decrypt's confirmation mentions the encrypted history being deleted, not only the plaintext downgrade.
  • No string in the CLI — output, --help, or long description — claims earlier versions stay readable or stay plaintext after encrypting.
  • A test pins the absence of that claim, so it can't come back the way it did here.
  • Verified against a real account: encrypt a note that has several versions, then harbor history list <id> and show they're gone.

Metadata

Metadata

Assignees

Labels

encryptionEnd-to-end encryption: keys, locking, sealing, and what encryption does and does not cover

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions