Skip to content

fix: complete and harden the persistence/security cleanup#317

Merged
fjbarrett merged 3 commits into
mainfrom
fix/persistence-security-cleanup
Jul 10, 2026
Merged

fix: complete and harden the persistence/security cleanup#317
fjbarrett merged 3 commits into
mainfrom
fix/persistence-security-cleanup

Conversation

@fjbarrett

Copy link
Copy Markdown
Owner

Summary

Completes and hardens the in-flight persistence/security cleanup an earlier agent left uncommitted. Three commits:

Security — fix(security)

Offline reliability — fix(offline)

  • Replay no longer wedges on a permanently-rejected op (404/400/409/413) — it drops the dead op and keeps draining, still retrying transient failures and holding on 401.
  • Migrates un-replayed pending ops out of the legacy keep-offline IndexedDB into the per-owner DB before deleting it, instead of discarding queued offline edits.
  • Strictly monotonic pending-op stamps (a create can't replay after a same-millisecond update); a 401 refresh keeps cached notes on screen instead of blanking; create() upserts so a concurrent refresh can't drop the new note.
  • Adds a neutral, precached /offline fallback served on navigation failure (the personalized app shell is still never cached).

Cleanup — refactor

  • Removes the shelved client-side encryption feature (crypto/useEncryption/setup+unlock UI/enc route) across web and iOS. Notes stored as enc: ciphertext are no longer decrypted — accepted data loss (the feature carried no real data).
  • Replaces middleware.ts with proxy.ts (route protection + per-request CSP nonce), adds verified email/password sign-in with a resend flow, and reworks the notes API, sharing, and share tokens.

Test plan

🤖 Generated with Claude Code

fjbarrett and others added 3 commits July 9, 2026 18:07
…direct

Re-registering an existing-but-unverified email had begun overwriting its
password_hash, so an attacker who knows a victim's email could set the password
on the account the victim then activates by clicking the verification mail.
Restore the always-409 response for any existing email; the dedicated
/api/auth/resend route refreshes only the token, so re-verification still works
without a credential-rewrite path.

safeRedirect returned the resolved pathname without rechecking it, so
"/..//evil.com" normalized to the protocol-relative "//evil.com" and slipped
through as a same-origin path. Reject any result that isn't single-slash-rooted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ine page

replayPending left a permanently-rejected op (404/400/409/413) at the head of
the queue and broke out, wedging every later change behind it forever. It now
drops such ops and keeps draining, while still retrying transient failures and
holding on 401 until re-auth. The legacy "keep-offline" IndexedDB was deleted
outright, discarding un-replayed offline edits — migrate its pending ops into
the per-owner DB before removing it. Pending-op stamps are now strictly
monotonic so a create can't replay after an update queued in the same
millisecond; a 401 refresh keeps the cached notes on screen instead of blanking
to an empty guest list; and create() upserts so a concurrent refresh can't drop
the note the user just made.

The rewritten service worker cached no HTML and left offline navigations on the
browser's error page. Add a neutral, precached /offline fallback served on
navigation failure — the personalized app shell is still never cached.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Removes the shelved client-side encryption feature — the PBKDF2 passphrase
crypto, the useEncryption hook, the setup/unlock UI, the enc salt route — and
its handling across the web and iOS clients. Notes previously stored as "enc:"
ciphertext are no longer decrypted; that data loss is accepted, as the feature
never carried real data. Replaces middleware.ts with proxy.ts for route
protection and per-request CSP nonces, adds verified email/password sign-in with
a resend flow, and reworks the notes API, sharing, and share-token generation.

This is the in-flight cleanup an earlier agent left uncommitted. The security
and offline-reliability fixes layered on top of it are in the two preceding
commits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@fjbarrett
fjbarrett merged commit 8e195a1 into main Jul 10, 2026
3 checks passed
@fjbarrett
fjbarrett deleted the fix/persistence-security-cleanup branch July 10, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant