Architecture Overview

Vauchi is a privacy-focused contact card system. Users exchange contact cards in person via QR code (with NFC and Bluetooth as additional transport options). After exchange, cards update automatically — when you change your phone number, everyone who has your card sees the change.

System Architecture

┌─────────────────────────────────────────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────────────────┐
│                                         CLIENTS                                         │ │                        RELAY SERVER                          │
│                                                                                         │ │           • Store-and-forward encrypted messages             │
│                                                                                         │ │            • No access to plaintext (oblivious)              │
│ ┌───────────────────────────┐     ┌─────────┐     ┌─────────┐     ┌──────┐     ┌──────┐ │ │ ┌───────────•─Rate limiting,─quotas,┐GDPR purge────────────┐ │
│ │                           │     │         │     │         │     │      │     │      │ │ │ │              │     │              │     │                │ │
│ │                           │     │         │     │         │     │      │     │      │ │ │ │              │     │              │     │                │ │
│ │            iOS            │     │ Android │     │ Desktop │     │ CLI  │     │ TUI  │ │ │ │ Blob Storage │     │ Device Sync  │     │ Recovery Store │ │
│ │          SwiftUI          │     │ Compose │     │  Native │     │ Rust │     │ Rust │ │ │ │ (encrypted)  │     │ (per-device) │     │  (90-day TTL)  │ │
│ │                           │     │         │     │         │     │      │     │      │ │ │ │              │     │              │     │                │ │
│ └─────────────┬─────────────┘     └────┬────┘     └────┬────┘     └───┬──┘     └───┬──┘ │ │ └──────────────┘     └──────────────┘     └────────────────┘ │
│               │                        │               │              │            │    │ │                                                              │
│               │                        │               │              │            │    │ └──────────────────────────────────────────────────────────────┘
│               ├────────────────────────┴───────────────┴──────────────┴────────────┘    │                                                                 
│               │                                                                         │                                                                 
│               ▼                                                                         │                                                                 
│ ┌───────────────────────────┐                                                           │                                                                 
│ │                           │                                                           │                                                                 
│ │        vauchi-core        │                                                           │                                                                 
│ │          (UniFFI)         │                                                           │                                                                 
│ │ Crypto, storage, protocol │                                                           │                                                                 
│ │                           │                                                           │                                                                 
│ └─────────────┬─────────────┘                                                           │                                                                 
│               │                                                                         │                                                                 
└────────OHTTP─encrypted──────────────────────────────────────────────────────────────────┘                                                                 
                │                                                                                                                                           
                │                                                                                                                                           
                ▼                                                                                                                                           
  ┌───────────────────────────┐                                                                                                                             
  │                           │                                                                                                                             
  │                           │                                                                                                                             
  │       OHTTP Gateway       │                                                                                                                             
  │     (strips client IP)    │                                                                                                                             
  │                           │                                                                                                                             
  └─────────────┬─────────────┘                                                                                                                             
                │                                                                                                                                           
         WebSocket (TLS)                                                                                                                                    
                │                                                                                                                                           
                │                                                                                                                                           
                ▼                                                                                                                                           
  ┌───────────────────────────┐                                                                                                                             
  │                           │                                                                                                                             
  │           Relay           │                                                                                                                             
  │                           │                                                                                                                             
  └───────────────────────────┘                                                                                                                             

Note: All remote client↔relay traffic flows through an OHTTP gateway per ADR-037 — the relay never sees client IP addresses, and the gateway never sees request content. Sequence diagrams below omit the gateway hop for protocol clarity.

Core Components

vauchi-core

The Rust core library provides all cryptographic and protocol functionality:

ModulePurposeKey Files
crypto/Encryption, signing, KDFencryption.rs, signing.rs
exchange/Contact exchange protocolsession.rs, qr.rs, x3dh.rs
sync/Update propagationdevice_sync.rs, delta.rs
recovery/Social recoverymod.rs
storage/Local encrypted databasecontacts.rs, identity.rs
network/Relay communicationconnection.rs, protocol.rs
ui/Core-driven UI (vauchi-app)screen.rs, component.rs
i18nInternationalization (vauchi-app)i18n.rs

vauchi-protocol

Shared protocol message types used by both vauchi-core and the relay:

  • Serde-only crate (no crypto, no I/O)
  • Defines MessageEnvelope, MessagePayload, and all variant structs
  • Provides framing helpers (encode_message/decode_message)
  • Ensures wire format consistency between clients and relay

Relay Server

Rust server for message routing (depends on vauchi-protocol for shared types):

  • WebSocket-based store-and-forward
  • TLS required in production
  • No user accounts — just encrypted blobs
  • Background cleanup tasks (hourly)

Client Applications

PlatformStackBinding
iOSSwiftUIvauchi-platform-swift (SPM)
AndroidKotlin/ComposeMaven AAR from core CI
Linux (GTK)GTK4 (gtk4-rs)Direct Rust linkage
Linux (Qt)Qt6 (Widgets)cbindgen C FFI
macOSSwiftUIUniFFI (shared with iOS)
WindowsWinUI3 (C# .NET 8)C ABI (vauchi-cabi)
CLIRustDirect library use
TUIRust (ratatui)Direct library use

Core-Driven UI

Core defines what to show; frontends only decide how to render natively. New workflows are pure Rust — zero frontend code unless a new component type is needed.

┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐           
│                                                                                                                                                  Core (Rust)                                                                                                                                                   │ │                                       Frontend (per platform)                                       │           
│                                                                                                                                                                                                                                                                                                                │ │                                                                                                     │           
│                                                                                                                                                                                                                                                                                                                │ │                                                                                                     │           
│ ┌────────────────────────────────────────────┐     ┌───────────────────────────────────────────┐     ┌───────────────────────────────────────────────┐     ┌────────────────────────────────────────┐                                                          ┌─────────────────────────────────────────────┐ │ │ ┌───────────────────────────────────────────────────────────┐     ┌───────────────────────────────┐ │   ┌──────┐
│ │                                            │     │                                           │     │                                               │     │                                        │                                                          │                                             │ │ │ │                                                           │     │                               │ │   │      │
│ │            WorkflowEngine trait            │     │                                           │     │                                               │     │                                        │                                                          │                                             │ │ │ │    "Component Library (one native widget per Component)   │     │         ScreenRenderer        │ │   │      │
│ │      • current_screen() → ScreenModel      │     │ ScreenModel { screen_id, title, subtitle, │     │ Component { TextInput, ToggleList, FieldList, │     │ UserAction { TextChanged, ItemToggled, │                                                          │   ActionResult { UpdateScreen, NavigateTo,  │ │ │ │ TextInput → TextField / OutlinedTextField / <input> │     │  Maps ScreenModel → native UI │ │   │ Core │
│ │ • handle_action(UserAction) → ActionResult │     │      components, actions, progress }      │     │  CardPreview, InfoPanel, Text, Divider, ... } │     │          ActionPressed, ... }          │                                                          │ ValidationError, Complete, ShowToast, ... } │ │ │ │         ToggleList → Toggle list / Checkboxes / [x        │     │ Sends UserAction back to core │ │   │      │
│ │                                            │     │                                           │     │                                               │     │                                        │                                                          │                                             │ │ │ │                                                           │     │                               │ │   │      │
│ └────────────────────────────────────────────┘     └───────────────────────────────────────────┘     └───────────────────────────────────────────────┘     └────────────────────────────────────────┘                                                          └─────────────────────────────────────────────┘ │ │ └───────────────────────────────────────────────────────────┘     └───────────────────────────────┘ │   └───┬──┘
│                                                                                                                                                                                                                                                                                                                │ │                                                                                                     │       │   
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────────────────────────────────────────┘       │   
                                                                                                                                                                                                                                                                                                                                                                                                                                 │   
                                                                                                                                                                                                                                                                                                                                                                                                                                 │   
                                                                                                                                                                                                                                                                                                                                                                                                                                 │   
  ┌────────────────────────────────────────────┐                                                                                                                                                                                                                                                                                                                                                                                 │   
  │                                            │                                                                                                                                                                                                                                                                                                                                                                                 │   
  │                  Frontend                  │◄─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────ScreenModel─(JSON─or─direct)───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘   
  │                                            │                                                                                                                                                                           UserAction (JSON or direct)                                                                                                                                                                               
  └────────────────────────────────────────────┘                                                                                                                                                                                                                                                                                                                                                                                     

Each frontend implements a component library (one native component per Component variant) and a ScreenRenderer that maps ScreenModel to native UI. The component library is built once and reused across all workflows.

ComponentLinux GTK4Linux Qt (Widgets)macOS/iOS (SwiftUI)Android (Compose)Windows (WinUI3)TUI (Ratatui)CLI
TextInputgtk::EntryTextFieldTextFieldOutlinedTextFieldTextBoxInput widgetstdin prompt
ToggleListgtk::CheckButtonCheckBoxList + ToggleLazyColumn + CheckboxToggleSwitch[x]/[ ] listnumbered choice
FieldListgtk::ListBoxListViewList + chipsLazyColumn + chipsListViewTable rowsformatted output
CardPreviewgtk::FrameFrameCard viewCard composableBorderBox rendertext output
InfoPanelgtk::BoxColumnLayoutVStackColumnStackPanelBlockprintln sections

Transport: Rust clients (CLI, TUI, Desktop) call WorkflowEngine directly. Mobile clients (iOS, Android) use JSON over UniFFI.

Adding workflows: Implement a new WorkflowEngine in core. All frontends render it automatically via the existing component library — no frontend changes needed.

Adding component types: Define a new Component variant in core, then implement the corresponding native widget in each frontend's component library. This is rare — the vocabulary stabilizes quickly.

Data Flow

1. Contact Exchange (In-Person)

 ┌───────┐                         ┌─────┐   
 │ Alice │                         │ Bob │   
 └───┬───┘                         └──┬──┘   
     │                                │      
     │  Display QR (identity + key)   │      
     │────────────────────────────────▶      
     │                                │      
     │   Scan QR, verify proximity    │      
     ◀────────────────────────────────│      
     │                                │      
     │      X3DH key agreement        │      
     │────────────────────────────────▶      
     │                                │      
     │   Exchange encrypted cards     │      
     ◀────────────────────────────────│      
     │                                │      
   ┌──────────────────────────────────┐      
   │ Both now have each other's cards │      
   └──────────────────────────────────┘      
     │                                │      
 ┌───┴───┐                         ┌──┴──┐   
 │ Alice │                         │ Bob │   
 └───────┘                         └─────┘   

2. Card Updates (Remote via Relay)

┌──────────────────────────────────────────┐
│                                          │
│        Alice updates phone number        │
│                                          │
└─────────────────────┬────────────────────┘
                      │                     
                      │                     
                      │                     
                      │                     
                      ▼                     
┌──────────────────────────────────────────┐
│                                          │
│                                          │
│          Encrypt delta with CEK          │
│ (per-contact shared key, Double Ratchet) │
│                                          │
└─────────────────────┬────────────────────┘
                      │                     
                      │                     
                      │                     
                      │                     
                      ▼                     
┌──────────────────────────────────────────┐
│                                          │
│                                          │
│              Send to relay               │
│               (WebSocket)                │
│                                          │
└─────────────────────┬────────────────────┘
                      │                     
                      │                     
                      │                     
                      │                     
                      ▼                     
┌──────────────────────────────────────────┐
│                                          │
│                                          │
│       Relay stores encrypted blob        │
│        (indexed by recipient_id)         │
│                                          │
└─────────────────────┬────────────────────┘
                      │                     
                      │                     
                      │                     
                      │                     
                      ▼                     
┌──────────────────────────────────────────┐
│                                          │
│                                          │
│               Bob connects               │
│       (receives pending messages)        │
│                                          │
└─────────────────────┬────────────────────┘
                      │                     
                      │                     
                      │                     
                      │                     
                      ▼                     
┌──────────────────────────────────────────┐
│                                          │
│                                          │
│              Decrypt delta               │
│      (update Alice's card locally)       │
│                                          │
└──────────────────────────────────────────┘

3. Multi-Device Sync

All devices under one identity share the same master seed. Device-specific keys are derived via HKDF:

┌─────────────┐     ┌───────────────────────┐
│             │     │                       │
│             │     │                       │
│ Master Seed ├────►│     Device 1 keys     │
│             │     │ (HKDF + device_index) │
│             │     │                       │
└──────┬──────┘     └───────────────────────┘
       │                                     
       │                                     
       │                                     
       │                                     
       │                                     
       │            ┌───────────────────────┐
       │            │                       │
       │            │                       │
       ├───────────►│     Device 2 keys     │
       │            │ (HKDF + device_index) │
       │            │                       │
       │            └───────────────────────┘
       │                                     
       │                                     
       │                                     
       │                                     
       │                                     
       │            ┌───────────────────────┐
       │            │                       │
       │            │                       │
       └───────────►│     Device 3 keys     │
                    │ (HKDF + device_index) │
                    │                       │
                    └───────────────────────┘

Device linking uses QR code scan with time-limited token.

4. Recovery (Social Vouching)

When all devices are lost:

  1. Create new identity
  2. Generate recovery claim (old_pk → new_pk)
  3. Meet contacts in person, collect signed vouchers
  4. When threshold (3) met, upload proof to relay
  5. Other contacts discover proof, verify via mutual contacts
  6. Accept/reject identity transition

Security Model

End-to-End Encryption

  • All card data encrypted with XChaCha20-Poly1305
  • Per-contact keys derived via X3DH + Double Ratchet
  • Forward secrecy: each message uses unique key
  • Relay sees only encrypted blobs

Key Hierarchy

┌───────────────────────────────────────────┐                                                                     
│                                           │                                                                     
│                                           │                                                                     
│                Master Seed                │                                                                     
│ (256-bit, generated at identity creation) │                                                                     
│                                           │                                                                     
└───────────────────────────────────────────┘                                                                     
                      │                                                                                           
                      │                                                                                           
                      ├─────────────────────────────────────────┬──────────────────────────────────┐              
                      │                                         │                                  │              
                      ▼                                         ▼                                  ▼              
┌───────────────────────────────────────────┐     ┌───────────────────────────┐     ┌────────────────────────────┐
│                                           │     │                           │     │                            │
│                                           │     │                           │     │                            │
│            Identity Signing Key           │     │        Exchange Key       │     │ SMK (Shredding Master Key) │
│            (Ed25519, raw seed)            │     │   (X25519, HKDF derived)  │     │       (HKDF derived)       │
│                                           │     │                           │     │                            │
└───────────────────────────────────────────┘     └───────────────────────────┘     └────────────────────────────┘
                                                                                                   │              
                                                                                                   │              
                      ┌─────────────────────────────────────────┬──────────────────────────────────┤              
                      │                                         │                                  │              
                      ▼                                         ▼                                  ▼              
┌───────────────────────────────────────────┐     ┌───────────────────────────┐     ┌────────────────────────────┐
│                                           │     │                           │     │                            │
│                                           │     │                           │     │                            │
│                    SEK                    │     │            FKEK           │     │      Per-Contact CEK       │
│          (Storage Encryption Key)         │     │ (File Key Encryption Key) │     │      (random 256-bit)      │
│                                           │     │                           │     │                            │
└───────────────────────────────────────────┘     └───────────────────────────┘     └────────────────────────────┘

Physical Verification

Contact exchange requires in-person presence:

  • QR + ultrasonic audio verification (18-20 kHz) — implemented on iOS, planned for Android
  • NFC Active tap (planned — centimeters range)
  • BLE with RSSI proximity check (planned — GATT transport)

Repository Structure

vauchi/                    ← Orchestrator repo
├── core/                  ← vauchi-core + vauchi-platform + vauchi-protocol
├── relay/                 ← WebSocket relay server (uses vauchi-protocol)
├── linux-gtk/             ← GTK4 Linux desktop app
├── linux-qt/              ← Qt6 (Widgets) Linux desktop app
├── macos/                 ← macOS native app (SwiftUI)
├── windows/               ← Windows native app (WinUI3)
├── ios/                   ← SwiftUI app
├── android/               ← Kotlin/Compose app
├── cli/                   ← Command-line interface
├── tui/                   ← Terminal UI
├── features/              ← Gherkin specs
├── locales/               ← i18n JSON files
├── ohttp-relay/           ← OHTTP relay proxy
├── themes/                ← Design tokens
├── e2e/                   ← End-to-end tests
└── docs/                  ← Documentation