Shared Rust Core

Concept

The monorepo contains two Rust crates with a strict public/private boundary:

  • core (public) — client-safe logic that ships everywhere: models, validation, scoring, sync, protobuf. This code compiles to WASM and native libraries, so anything in it can be decompiled.
  • server (private) — server-only logic that never leaves the server: auth, authorization, billing, admin operations, database queries. Imports core.
┌──────────────────────────────────────────────────────────────┐
│                         Monorepo                             │
│                                                              │
│  libs/                                                       │
│  ┌────────────────────────────────────────────────────────┐  │
│  │              core (public Rust crate)                  │  │
│  │                                                        │  │
│  │   Data models, validation, scoring rules,              │  │
│  │   serialization (protobuf), offline queue,             │  │
│  │   sync protocol                                        │  │
│  └──────┬──────────┬───────────┬───────────┬─────────┬────┘  │
│         │          │           │           │         │       │
│  apps/  │          │           │           │         │       │
│  ┌──────┴──────┐ ┌─┴────────┐ ┌┴───────┐  ┌┴───────┐┌┴──────┐│
│  │ server      │ │dashboard │ │ pwa    │  │ iOS    ││Android││
│  │ (private)   │ │ (Dioxus) │ │(Dioxus)│  │SwiftUI ││Jetpack││
│  │             │ │          │ │        │  │        ││Compose││
│  │ Axum + auth │ │ core     │ │ core   │  │ core   ││ core  ││
│  │ billing, DB │ │ only     │ │ only   │  │ only   ││ only  ││
│  └─────────────┘ └──────────┘ └────────┘  └────────┘└───────┘│
└──────────────────────────────────────────────────────────────┘

What Lives in Core (Public — Ships to Clients)

  • Data models (Score, Drill, Event, Roster, User, etc.)
  • Validation rules (field-level, format checks)
  • Scoring calculations
  • Protobuf serialization/deserialization
  • Offline queue management
  • Sync protocol logic

What Lives in Server (Private — Never Leaves Server)

  • Authentication and authorization
  • Subscription and billing logic
  • Admin-only operations
  • Database layer (queries, migrations)
  • API route handlers (Axum)
  • Any proprietary business rules

The server crate depends on core (it needs the same models and validation), but never the reverse. Clients only ever see core.

How Core Is Consumed

Server (Rust direct)

The server crate imports core and adds private logic:

use rangedaypro_core::{validate_score, calculate_score, Score};
 
// Core logic — same as what clients run
let result = validate_score(&score);
let total = calculate_score(&score);
 
// Server-only logic — never shipped to clients
let authorized = check_permissions(&user, &event);
let subscription = validate_subscription(&org);

Dashboard + PWA (Rust direct → WASM)

Both Dioxus apps import core only (they are separate apps, deployed independently):

use rangedaypro_core::{validate_score, calculate_score, Score};
 
let result = validate_score(&score);
let total = calculate_score(&score);

iOS (UniFFI → Swift)

UniFFI generates typed Swift bindings from core:

let result = validateScore(score: score)
let total = calculateScore(score: score)

Android (UniFFI → Kotlin)

UniFFI generates typed Kotlin bindings from core:

val result = validateScore(score)
val total = calculateScore(score)

Why This Matters

  • Security boundary — server-only logic (auth, billing, admin ops) never ships to clients. It cannot be decompiled from WASM or native binaries.
  • One source of truth — a struct defined once in core runs on the server, in the browser (WASM), and on iOS and Android (native). They cannot drift apart.
  • Type safety across all platforms — UniFFI generates fully typed bindings. Changes to core surface as compile errors in Swift and Kotlin.
  • No thin-client compromise — mobile apps run validation and scoring locally via core. Offline use has full logic, not just data capture.
  • Native performance everywhere — Rust compiles to native code for server, iOS, and Android. WASM for the browser. No interpreter, no bridge overhead.
  • Framework independence — core knows nothing about UI. Swapping SwiftUI, Jetpack Compose, or Dioxus requires zero changes to business logic.