gg

Overview

The devices are Google Pixels wiped and flashed with GrapheneOS - no Google services, no telemetry, full verified boot. Stock Android wasn't an option.

The app encrypts everything at rest with SQLCipher, locks behind a PIN with brute-force protection, and syncs only over local WiFi. Inventory fields (GPS coordinates, photos) are gated behind a separate password that doubles as user tiering - only users with the password can access inventory on both mobile and dashboard. These fields get their own encryption layer, so even a database extraction yields nothing without the second key.

The web dashboard decrypts and visualizes synced backup data - period-aware summaries, category breakdowns, debt tracking - all with client-side decryption via the Web Crypto API. Sync is WiFi-only with silent failures by design - if the server is unreachable, the app continues without interruption.

Tech Stack

Mobile Client

  • Kotlin + Jetpack Compose
  • Room + SQLCipher

Web Dashboard

  • Flask
  • React + TypeScript

Security

  • PBKDF2-HMAC-SHA256 (100k iterations)
  • AES-256-GCM encryption
  • Android Keystore master key
  • Web Crypto API (client-side)

Platform

  • Google Pixel + GrapheneOS
  • No Google Play Services dependency
  • WiFi-only sync (no cellular)
  • Self-hosted sync server

Encryption Architecture

Three independent encryption layers, each with its own key material:

Layer 1: Database (SQLCipher)
  - Full database encryption at rest
  - Key derived from PIN via Android Keystore
  - Transparent to application code

Layer 2: Backup Files
  - Format: [salt:16][iv:12][ciphertext + GCM tag]
  - PBKDF2-HMAC-SHA256, 100k iterations, 256-bit key
  - Used for export/import and WiFi sync

Layer 3: Inventory Secure Fields
  - Separate password doubles as access control (user tiering)
  - Format: Base64([salt:16][iv:12][ciphertext + GCM tag])
  - GPS coords + photos encrypted per-field
  - Decrypted client-side on dashboard via Web Crypto API