Security Implementation Plan

Threat model and security hardening plan for Reaktor services and workbench operations.

Direction

Use Cisco MLS++ (mlspp) as the only end-to-end encryption protocol engine. Every secure conversation is an MLS group: direct chats, group chats, member changes, new devices, and key rotation all map to MLS group operations.

Expose

  • createDirectConversation(peerUserId)
  • createGroupConversation(memberUserIds)
  • encryptMessage(conversationId, plaintext)
  • processIncoming(envelope)
  • addMembers(conversationId, users)
  • removeMembers(conversationId, users)

Do Not Expose

  • Raw MLS state or private tree material
  • Raw private keys, group secrets, or nonces
  • Low-level crypto toolkit APIs
  • Server-side decryption paths
  • Signal provider abstractions

Current Repository Shape

Keep the module aligned with the rest of Reaktor: Gradle/KMP lives in the normal src/*Main layout, native code lives under cpp/, TypeScript lives under ts/, and generated Kotlin externals are produced through Karakum into ts/import.

reaktor-security/
  cpp/
    external/mlspp/
    external/json/
    external/googletest/
    rsec-mls-core/
    rsec-mls-capi/
    tests/native/
  src/
    commonMain/
    androidMain/
    iosMain/
    jsMain/
    jvmMain/
  ts/
    export/
    import/
    package.json
    karakum.config.json
  README.md
  THIRD_PARTY_LOCK.md

Hard Blocker

Durable MLS state snapshots are the first serious implementation blocker. The engine must prove that a process can create a group, persist encrypted state, restart, reload state, process the next message, and send the next message deterministically.

RsecMlsStateSnapshotV1 must cover:
  cipher suite
  group id and epoch
  public and private tree state
  transcript hash
  extensions
  epoch secrets and message ratchet state
  own leaf index
  identity private key references
  external and resumption PSKs
  pending proposals and cached update

Preferred path: keep a small audited patch against vendored MLS++ that adds State::export_snapshot() and State::import_snapshot(). That is easier to review than reconstructing state through derived-class access to protected internals.

Execution Phases

P0 - Native Core and Build Hygiene

Pin MLS++, keep CMake deterministic, keep tests under cpp/tests, maintain the stable C ABI, and keep Gradle sync green across Reaktor, BestBuds, and Manna.

P1 - Durable State and Credentials

Implement encrypted MLS state snapshots, canonical device credentials, signature verification, and key-package private-material storage.

P2 - Conversation Operations

Ship direct conversations, group conversations, incoming queue processing, member add/remove, device add/remove, and epoch conflict recovery.

P3 - Platform Secret Boxes

Implement Android Keystore, Darwin Keychain, Windows DPAPI, Linux Secret Service, and WebCrypto/IndexedDB sealing paths behind one PlatformSecretBox contract.

P4 - Server Backends

Implement identical protocol behavior for Spring Boot/Postgres and Cloudflare Worker/D1/Durable Objects. Servers store and order ciphertext, credentials, key packages, welcomes, and commit metadata only.

P5 - Web, WASM, and React Native

Compile the C++ core to WASM for web, expose a TypeScript wrapper, and add a React Native JSI adapter that avoids passing long-term secrets through JavaScript.

P6 - Hardening and Release

Complete fuzzing, malformed envelope tests, replay tests, credential expiry tests, license allowlist checks, SBOM generation, and state migration tests.

Task Backlog

TaskStatusScopeAcceptance Signal
RSEC-001
Repository skeleton
DoneUse Reaktor KMP layout, cpp/, and ts/. Consolidate planning in root plan.html.Build graph is obvious, public APIs are MLS-only, no module-local docs/schema drift.
RSEC-002
Vendor and build MLS++
ActivePin Cisco MLS++, nlohmann/json, and GoogleTest. Keep lock and license notes in THIRD_PARTY_LOCK.md.Host native tests and Gradle native def generation pass from a clean checkout.
RSEC-003
Native C ABI
ActiveExpose engine lifecycle, key packages, group creation, join, encrypt, decrypt, and buffer ownership through rsec.h.C tests cover create/destroy, invalid input, buffer free, and direct conversation round trip.
RSEC-004
MLS state snapshot
NextAdd versioned encrypted snapshot export/import around MLS++ state.Create, persist, restart, reload, decrypt, send, add/remove all pass deterministically.
RSEC-005
Device credential encoding
PlannedCanonical binary DeviceCredentialV1, auth signature verification, expiry, tenant/app scoping.Identical credentials produce identical bytes; tampering and wrong tenant/app fail.
RSEC-006
Key package generation
PlannedGenerate, seal private material, upload public bytes, track local claimed packages.MLS++ parses packages; reused local package is rejected; low inventory is visible.
RSEC-007
Direct conversation
ActiveFetch peer devices/packages, create MLS group, emit welcomes, persist state, exchange messages.Alice and Bob both decrypt after restart; server never sees plaintext.
RSEC-008
Group conversation
PlannedClaim packages for all active devices and create initial group state/welcomes.Three users with multiple devices can all join and decrypt.
RSEC-009
Incoming queue
PlannedProcess handshakes before application messages, queue missing epochs, dedupe replay.Out-of-order messages decrypt after missing commits arrive; replay does not advance state twice.
RSEC-010
Members and devices
PlannedAdd/remove members, add/remove own device, and verify membership policy proofs.Removed devices cannot decrypt future messages; stale or wrong-conversation proofs fail.
RSEC-011
Android package
PlannedKotlin facade, JNI binding, Android Keystore secret box, native library packaging.Instrumented tests cover register, key packages, create, persist/reload, encrypt/decrypt.
RSEC-012
iOS/macOS package
ActiveKotlin/Native cinterop, Darwin Keychain secret box, KMP framework output.Simulator/device/macOS paths pass and default to this-device-only secret records.
RSEC-013
Desktop package
PlannedJVM facade, native loader, DPAPI, Keychain, Secret Service, explicit Linux passphrase fallback.Local state survives restart and fails under wrong user or missing secret store.
RSEC-014
Web/WASM package
PlannedWASM build, TypeScript wrapper, WebCrypto plus IndexedDB secret storage.Browser creates device, joins group, encrypts/decrypts, reloads state, rejects insecure context.
RSEC-015
React Native JSI
PlannedC++ JSI adapter and high-level TypeScript facade.React Native app can encrypt/decrypt without JS receiving group state or private key material.
RSEC-016
Spring server
PlannedSpring Boot, Postgres, migrations, OpenAPI, transactional key-package claims and commit appends.Commit conflicts are handled; all server writes are transactional; no plaintext path exists.
RSEC-017
Cloudflare server
PlannedWorker service, D1 registry/key packages/welcomes, Durable Object per conversation for ordering.Conflicting commits return a typed conflict; Durable Object serializes appends.
RSEC-018
Attachments
PlannedChunked local encryption and MLS-protected content-key delivery.Object stores see ciphertext only; wrong conversation cannot decrypt attachment metadata.
RSEC-019
Verification primitives
PlannedDevice fingerprint, safety number/QR payload, verification state store.Changed device key warns; verification state is tenant/app/user/device scoped.
RSEC-020
Hardening
PlannedNative, KMP, Android, iOS, desktop, WASM, server, fuzz, replay, migration, license, and SBOM tests.Malformed envelopes, stale proofs, expired credentials, reused packages, crashes, and conflicts are covered.

Server Protocol Surface

Spring Boot/Postgres and Cloudflare Worker/D1/Durable Objects should implement the same client-visible protocol. The client SDK should not care which backend is deployed.

POST /security/devices/register
POST /security/key-packages
POST /security/key-packages/claim
POST /security/conversations
POST /security/conversations/{id}/messages
GET  /security/conversations/{id}/messages
GET  /security/welcomes
POST /security/welcomes/{id}/consume

All server-side authorization decisions that affect membership must produce client-verifiable policy proofs. Clients must reject server-added devices or members without valid Reaktor-auth-signed credentials and membership proofs.

P0 Completion Bar

  • MLS++ native core is pinned and documented in THIRD_PARTY_LOCK.md.
  • C ABI owns stable buffer/result/error behavior and does not leak C++ exceptions.
  • Kotlin common and TypeScript APIs expose conversation operations only.
  • Karakum generates Kotlin externals from reaktor-security/ts.
  • Host C++ tests live under cpp/tests/native and pass through CTest.
  • Gradle sync succeeds when reaktor is consumed from BestBuds and Manna composite builds.

Do Not Implement

  • No Signal provider.
  • No low-level crypto API for app developers.
  • No raw key export API.
  • No server-side decrypt API.
  • No plaintext search.
  • No metadata privacy claims beyond what the implementation actually provides.
  • No silent plaintext fallback on Linux or Web.
  • No unpinned MLS++ dependency.
  • No JSON signatures for security-critical credentials or policy proofs.
  • Auth Architecture - Use before changing reaktor-auth or request authorization boundaries.
  • Reaktor Secrets - Use before moving, rotating, distributing, caching, or materializing secrets.
  • DevOps - Use before changing the build/deploy/ops pipeline, the Kotlin platform model, deployment partitioning, gated deploy operations, or the reaktorDesktop Deploy pane; pairs with reaktor-cloud-pane (operator view) and secrets-management.
  • Control Plane - Use when exposing Reaktor safely to humans and agents.
  • Shadow Dev - Use before building production-like test and replay environments.
  • Gemini DevOps Agent - Use before handing DevOps execution from Codex or Claude to Antigravity CLI, adding agent-run recipes, or wiring build/test/deploy operations into reaktorDesktop.

References

  1. Cisco MLS++
  2. RFC 9420 - Messaging Layer Security
  3. Emscripten
  4. Android Keystore
  5. Apple Keychain Services
  6. Windows DPAPI CryptProtectData
  7. Freedesktop Secret Service API
  8. Web Crypto API
  9. Cloudflare D1
  10. Cloudflare Durable Objects