A private family media sharing platform where the server is explicitly untrusted. All user content is encrypted client-side before upload, and the server stores and routes data it cannot decrypt.
Technical Lead & Co-Founder, March 2025 to Present. Solo-built the entire technical stack.
133
Cloud Functions
1,494
Automated Tests
47+
Firestore Collections
8
Storage Buckets
Architecture
Flutter mobile client communicating over HTTPS with Firebase Cloud Functions v2 on GCP. Firestore for structured data, Cloud Storage for encrypted media. Clean architecture with BLoC state management, dependency injection via GetIt (76 registrations), and 13 feature modules.
Flutter Client (iOS/Android) | +-- BLoC (13 state managers) | +-- Repositories (11 abstract interfaces) | +-- Services (25+ API services) | +-- ApiClient (HTTP + auth interceptor) | |------- HTTPS -------| | Firebase Cloud Functions v2 (133 functions) +-- Auth middleware (Firebase Admin SDK) +-- Family access middleware +-- Business logic handlers | +-- Firestore (47+ collections) +-- Cloud Storage (8 buckets, signed URLs) +-- Firebase Auth (email/password, Google, Apple) +-- Cloud Scheduler + Cloud Tasks
Zero-Knowledge Encryption System
The core technical challenge: families need to share photos and videos privately, with the guarantee that even the server operator cannot access their content. This required designing a custom cryptographic system that handles multi-user access, key distribution, and member revocation without server-side plaintext access.
Threat Model
The server is explicitly untrusted for content access. It can validate family membership, serve encrypted blobs, execute queries against blind indexes, and rate-limit key operations. It cannot read content, derive keys, search plaintext, or impersonate users (private keys never leave the client).
Key Hierarchy
User Master Key (Argon2id from password)
|
+-- Family Epoch Keys (rotate on member removal)
| Wrapped per-member via X25519 ECDH
| Used to wrap: Post Keys, Profile Keys, Folder Keys
|
+-- Post Keys (unique per post, random AES-256)
Wrapped with Family Epoch Key
Encrypts: metadata + all media variantsThe Revocation Problem
The obvious approach (single shared key per family) breaks on member revocation. Removing a member would require re-encrypting every piece of media in the family vault. With per-family key hierarchies and individual user key wrapping, revocation only requires re-wrapping the family key for remaining members. This tripled the implementation complexity but made the system viable for real use.
Searchable Encryption
Posts are searchable by tag, type, and location without the server seeing plaintext. HMAC-SHA256 blind indexes are computed client-side and stored per-family context. The server matches on hash values during queries, never seeing the actual search terms.
Design Influences
Async key distribution from Signal (new members receive historical keys from an existing member, not the server). Envelope encryption from Proton (content encrypted with a random DEK, DEK wrapped with a KEK, multiple wrapped copies per access context). The multi-family key isolation and HMAC-based blind indexing are novel to Roots, as neither Signal nor Proton support these patterns.
MCP Servers
Two custom Model Context Protocol servers built to give Claude Code a single source of truth for the project's API contracts and product requirements.
API Documentation Server
Four tools: list/get API schemas, list/get endpoint definitions. Loads Swagger documentation from the backend and exposes it as structured tools. The AI agent queries real API specs during development instead of relying on its own assumptions.
Epics Management Server
Four tools plus two resources: list/search epics and user stories, browse the epic catalog by module, view requirement-to-story mappings. Parses markdown specification files and caches results in memory.
Why This Matters
Both servers follow a dual-mode pattern (HTTP standalone or stdio for MCP-hub integration). They give the AI agent a structured interface to the project's actual specifications, reducing drift between what the AI thinks the API does and what it actually does. This is the same class of tooling that powers agentic coding platforms at scale.
Infrastructure
Terraform manages three Firebase environments (dev/staging/prod) with modular IaC for Firebase services, Firestore, Storage, and Cloud Functions. State stored in GCS. GitHub Actions handles CI with test automation and Terraform plan/apply.
- Per-function service accounts with least-privilege IAM
- Storage lifecycle tiering (STANDARD to NEARLINE to COLDLINE)
- KMS encryption support (configurable, enabled in prod)
- Security scanning with Trivy and Checkov (weekly + PR scans)
- CI pipeline: analyze, unit tests (parallel by layer), integration tests, widget tests, E2E on iOS/Android simulators
Tech Stack
Frontend
Flutter, Dart, BLoC
Backend
Node.js, TypeScript, Cloud Functions v2
Database
Firestore, 47+ collections, 15+ compound indexes
Storage
Cloud Storage, 8 buckets, signed-URL delivery
Infrastructure
Terraform, GitHub Actions, Docker
Security
X25519 ECDH, AES-256-GCM, HMAC-SHA256, Argon2id
Auth
Firebase Auth (email, Google, Apple OAuth)
AI Tooling
Claude Code, custom MCP servers (2)