Zero-Knowledge by Design:
Architecture Notes for miLife

I have journals from a decade ago sitting in apps I no longer trust, on servers I did not agree to at the time. That bothered me enough to start building a different kind of archive — one where the data stays on the device, encrypted before it is ever saved, and where I am the only one with the key. This is what I have designed so far and why the decisions are what they are.

The Problem With Trusting Convenience

Most people have their personal memories scattered across a handful of apps and services that were never designed to hold memories — photo storage apps, note-taking tools, social platforms, voice memos. None of them talk to each other. Most of them hold your data on their servers. A few of them have been breached or acquired or simply shut down, taking data with them.

This is not a paranoid framing. It is what happens when you store personal information inside products whose primary interest is the product, not the archive. Convenience trades against control. The more convenient the storage, the more of your data lives somewhere you cannot fully audit.

I am not interested in building another convenient app with a premium subscription tier where "enhanced privacy" costs extra. I am interested in building an archive where the design assumption — from the very first decision — is that no one except you should ever be able to read it. That constraint changes everything.

Why Existing Tools Do Not Solve This

Before I started building, I spent time looking at what already exists. The landscape is better than it was five years ago, but the fundamental problem remains:

ToolPrivacy modelThe problem
Apple Journal Device + iCloud iCloud backup decrypts on Apple's servers unless you enable Advanced Data Protection manually — most users never do
Day One End-to-end optional E2E encryption is a paid feature. Free tier syncs through Day One's servers. The default is not zero-knowledge.
Notion Server-side Your notes are a database row in Notion's infrastructure. Encrypted at rest in their systems, not yours.
Standard Notes E2E encrypted Genuinely zero-knowledge. Good model. But structured around notes, not a life archive with a navigable hierarchy.
Physical notebook Offline Not searchable. Not backed up. Not cross-device. Not recoverable if lost.

Standard Notes comes closest to the right privacy model. The gap is structure. A flat list of encrypted notes is not a life archive. It is an encrypted inbox that eventually becomes unsearchable.

Lives & Moments: Why Structure Matters

The core design decision in miLife is that your archive is not a journal. A journal implies chronological entries. Life does not work chronologically — it works in contexts.

You have a life as a professional. A life as a parent, partner, friend. A life as someone with specific health concerns, hobbies, long-term projects. Those contexts exist in parallel, not in sequence. When you want to find something from five years ago, you rarely remember the date. You remember the context — which part of your life it belonged to.

Moments belong to Lives. A Moment is a discrete entry: an event, a thought, a photo, a voice note. Every Moment is assigned to one or more Lives. The archive is navigable by context, not just by time. Searching your professional Life for entries about a specific collaborator finds everything relevant regardless of when it was recorded.

// Why this is hard to retrofit

Most journal and note-taking apps start with a flat structure and add organisation later as tags or folders. That works for notes. It does not work for a life archive where you need to ask questions like "what were my thoughts about this health issue across the last three years?" The hierarchy has to be a first-class concept from the beginning, not a workaround bolted on after the fact.

Why Local-First

Local-first means the canonical copy of your data lives on your device, not on a server. Sync, if it exists, is a replication of that local truth — not the other way around.

The reason I chose this model is not primarily technical. It is about ownership. When your data lives on a server, your access to it is contingent on a company's continued operation, continued pricing, continued terms of service, and continued security record. Four things, any one of which can change without your consent.

A file on your device that you encrypted with your own key is yours unconditionally. You can back it up yourself, using whatever backup strategy you trust. You can move it. You can keep it indefinitely. No subscription required to access your own history.

// The honest version

Local-first is a harder technical problem than cloud-first. You have to solve sync, conflict resolution, and backup without a server to act as the single source of truth. I am not pretending these problems are easy. I am saying they are worth solving rather than trading them away for convenience.

Encryption Choices

Key Derivation: Argon2id

The archive is unlocked with a passphrase. That passphrase is never stored anywhere. It is used to derive the encryption key using Argon2id — the winner of the Password Hashing Competition and the current OWASP recommendation for password-based key derivation.

Why Argon2id over bcrypt or PBKDF2? I covered this in detail in the previous post on key derivation. The short version: Argon2id is memory-hard and time-hard simultaneously, which means it is expensive to attack both on GPUs and on custom ASIC hardware. PBKDF2 is only time-hard — a fast GPU attack is significantly cheaper. For a life archive that may hold decades of personal data, the resistance to hardware attacks matters more than compatibility.

The parameters are tuned to the OWASP recommended minimums — enough memory and iteration cost to be genuinely expensive to attack at scale, while remaining fast enough that unlock feels immediate on a normal phone. The key output is 256 bits, matching the AES-256 cipher used for content encryption.

Content Encryption: AES-256-GCM

Each Moment is encrypted individually using AES-256-GCM. GCM (Galois/Counter Mode) provides both confidentiality and authentication — the cipher produces an authentication tag that detects any modification to the ciphertext. You cannot tamper with an encrypted Moment without the decryption failing, loudly.

The 256-bit key derived from Argon2id is what encrypts each Moment. Each Moment gets a unique nonce generated from a cryptographically secure random source. The nonce is stored with the ciphertext — it does not need to be secret. Reusing a nonce with the same key would be catastrophic (it breaks GCM's security guarantees), so a fresh nonce is generated for every single encryption operation without exception.

This is the same approach used in LockedPages — consistency across the platform means the same audited decisions, not a different choice made under different time pressure.

// On disclosing the algorithm

Some people ask whether publishing the encryption details is a security risk. It is not. This is Kerckhoffs's principle: a cryptographic system should be secure even if everything about it except the key is public knowledge. AES-256-GCM and Argon2id are public standards. The security comes from the key, which never leaves your device. Keeping the algorithm secret would not add security — it would just make the system harder to audit.

The Trade-offs I Have Not Resolved

I want to be honest about what is unsolved rather than present this as a complete system. It is not.

Cross-device sync. The architecture I am designing supports sync by treating the archive as an encrypted blob that can be replicated without being decrypted by any intermediary. You sync the ciphertext — not the plaintext. A sync provider (self-hosted or a trusted third party) handles replication without seeing your data. But I have not built this yet. The sync protocol for handling conflicts between two devices that both wrote while offline is a genuinely hard problem.

Backup UX. Local-first puts the backup responsibility on the user. Most users will not set up a backup strategy without being guided through it explicitly. The app needs to make backup frictionless — probably via OS-native encrypted backup mechanisms — without creating a path where the backup bypasses the encryption. I have not solved the UX for this yet.

Search on encrypted content. Full-text search across encrypted Moments requires either decrypting everything in memory first, or building a client-side search index. Both approaches have trade-offs around performance and memory on older devices. I am leaning toward an in-memory decrypted index rebuilt on each unlock — simple, correct, and the performance cost is paid once per session rather than on every search. But this is not tested yet.

// What I will not compromise on

There are decisions I will not walk back regardless of how hard they make things: no server-side decryption, no account required to use the app, no analytics on what you record or how often. These are constraints that come from the design premise, not features that get dropped when they become inconvenient to implement.

Where This Is Now

miLife is in the architecture phase. The philosophy is defined. The data model is being designed. The encryption approach is determined — the same cryptographic choices proven in LockedPages, applied to a different storage problem.

Android is the first platform. Not because I have a strong preference, but because the development tools and distribution options fit better with what an independent developer building a privacy-focused app can actually ship and maintain.

I am not publishing a timeline. The decisions I described above need to be made correctly before anything is released. A life archive that loses data, that has a subtle encryption bug, or that handles sync conflicts by silently discarding entries would be worse than not building it. There is no acceptable MVP that cuts corners on data integrity.

What I can say is that the constraints are clear: local-first, zero-knowledge, no accounts, encrypted at rest, navigable by context. Everything that gets built must satisfy all five. If a feature cannot meet that bar, it does not ship.