Daeseon Yoo
Back to project
·UX retro·3 min·Review needed

Trust comes from 'feeling, control, relationship,' not an encryption explainer — and multitenancy

A discussion and decision on how to handle 'I'm scared my data is stored outside' in a sensitive product. Where E2EE fits, prioritizing felt trust, implementing export/delete-everything, and proving multitenancy isolation.

AI version

This product handles a person's weakest moment + the voice and face of someone they love. So "where does my data go?" is the product's life or death. The decisions that came out of the discussion:

1. The real fix for "external storage scares me" is E2EE — but conditionally

It still goes up to the server, but encrypted on the user's device, so the server only sees ciphertext ("even we can't see it"). Matches the pendant metaphor exactly. However, the honest trade-offs:

  • Lost key = permanently unrecoverable → fatal for an app you open in a crisis (§15) → passkey/recovery-code backup is mandatory.
  • Since the server can't see the content, §12 audio transcoding, thumbnails, and push body previews are impossible.
  • Contributors (no account) need a hybrid scheme that encrypts with the owner's public key. → Decision: not implementing it now. Treat it as a differentiator/roadmap item. (When implemented, if lib/storage is changed to store only ciphertext, the routes stay the same.)

2. For the average user, trust is built by "feeling," not by "understanding"

Key insight: 99% don't read the privacy policy or E2EE. So trying to remove anxiety by explaining the encryption is aiming in the wrong direction. The levers that work:

  • Don't talk defensively — leading with "It's safe!" actually triggers anxiety. Lead with value (the pendant) and keep safety quiet.
  • Relationship carries trust — since the contribution link comes from someone they love, trust comes from the relationship, not the brand. (Already built into the product.)
  • Minimize what you ask for — no real name, phone, contacts, or location → "if there's nothing to give, there's nothing to fear."
  • Visible control — easy export/delete is the core of the sense of control.

3. So here's what was actually implemented (53e25d5)

  • Export: GET /api/exportmanifest.json + media files as a pure Node ZIP (lib/zip.ts, store method). Verification: a valid zip containing voice m4a + photo png.
  • Delete everything: DELETE /api/account → real media deletion + user deletion (FK cascade) + session cleanup. Verification: after deletion the box returns 401, and re-logging in with the same email gives an empty box (0).
  • One quiet line of reassurance + contextual permission prompts (mic only when recording).
  • Stance on monetization: ads and data sales are forbidden for this product (they destroy trust). → a separate monetization entry.

4. Multitenancy — is "a million people each owning their own" possible (proof)

The data model is one box per person, fully isolated per user. Verified in practice:

A(demo) box != B(새 사용자) box
B의 새 보관함: 항목 0
B 쿠키로 A의 사진 → 404
쿠키 없이 → 401
A 본인 → 200

→ "each owning their own" is the design default. The number of users is not a constraint. But the precondition for true ownership = a real login (Kakao, done) + swapping in production parts (real Postgres, R2, shared rate-limit, push queue). This is a local parts problem, not a code-structure one — see stack-decisions.

One line

Ask for little, let the relationship carry the trust, and make control visible — these three dissolve most of the anxiety. E2EE is the "insurance + bragging right" laid on top of that, not the conversion lever for the average user.

Review needed

No human review on this entry yet.