Skip to content

Module Map

Draft

This map answers one question: for a given piece of code, which design doc owns its contract and what tier validates it. It says nothing about whether a surface is built — that is the slice tracker’s job, and keeping the answer in one place is what stops this map going stale. To learn whether something exists today, find its slice: rg 'S-C16' SLICES.md.

CrateOwnership
capsule-coreCryptography (including the MLS album authority), canonical CBOR, validation, CRDTs, sidecars, backup, lifecycle, client filesystem, local SQLite and vector index, import scan/plan/execute, culling, LQIP, share and drop crypto, aggregated federation views, ML orchestration
capsule-serverThe Kynos REST/OpenAPI application — see Server Modules
capsule-sdkThe Spargen-generated REST client plus the orchestration over it Capsule owns: auth and session refresh, the resumable upload state machine, sync, recovery, protocol-version negotiation, LAN peering
capsule-wireThe response taxonomy shared by server and SDK. Framework-free by construction: serde is its only dependency, so neither side’s transport choices reach the other
capsule-wasmThe browser sealing surface capsule-web loads — share-link open and guest-drop sealing over capsule-core with default features off. Built by mise run build-wasm; never committed
capsule-i18n + xtask::i18nCanonical ICU catalogs, runtime localization, generated platform catalogs
capsule-core-ffiUniFFI bindings for native Swift and Kotlin consumers, on one UniFFI version across both surfaces
capsule-core-swift, capsule-core-kotlinPer-platform harnesses that link the compiled core over those bindings, and the HardwareSigner implementations (Secure Enclave, StrongBox)
capsule-cli + its entity/migration cratesLocal CLI behavior and its SQLite persistence; network commands ride the SDK
capsule-webThe browser client: the guest-drop and share-link viewer surfaces, over capsule-wasm
capsule-swift, capsule-androidThe native applications
capsule-visionModel-evaluation notebooks; no shipped source

GraphQL and gRPC are retired transports and no compatibility surface will be restored (ADR-0001). Review-only sources live under legacy-review/: they are not Cargo packages and have no validation status until rewritten against their owning contracts.

ModuleOwning designValidation
crypto::{primitives,keys,encryption,provenance,verify_asset}Cryptography and AuthorizationUnit vectors, negative cases, smoke
crypto::authorityKeys — Write Authority InterfaceUnit; epoch-ledger round trip
crypto::authority::openmls_authorityMLS and MLS ResilienceUnit and smoke; protocol round trip
cborMetadataCanonical-byte vectors; cross-language conformance
validationValidationPure invariant unit tests
backupBackup and RecoveryUnit and smoke
lifecycleOrganization and ProvenanceUnit and smoke; signed write path
library::{init,open,rebuild,scrub,cache,lock,paths,receipts,auth_gate}Client Filesystem and MaintenanceUnit and smoke
library::{space,storage_verify}Import Pipeline and Storage VerificationUnit boundary and release-gate tests
import::{scan,scanner,planner,group,special,scope,default_album,importers,streaming,upload,executor,progress}Import PipelineUnit; the executor’s media half waits on capsule-core::media
drop, sharingWeb Upload and Share LinksUnit and KAT; sealing round trips cross-language against capsule-wasm
cullingOrganization — CullingUnit; filtered views and reject sweep
federationFederationUnit; aggregated album view over authority fixtures
ml::{registry,orchestrator,regen,runner}AIUnit determinism; the real inference runner is post-v1
cohortAuthenticationUnit determinism
metadata, sidecarMetadataUnit determinism and round trips
dbClient FilesystemUnit SQLite operations; vector index over sqlite-vec
domain, modelsOrganization, MetadataClosed-enum and model unit tests

OpenMLS and the inference engines are implementation dependencies; Capsule retains the application protocols, schemas, provenance, and policy. Peering is the SDK’s, not the core’s — it is a transport between two clients, and the artifact it moves is the backup container.

capsule-server is one Kynos REST/OpenAPI application composed from cohesive internal modules, not separate public transports or microservices. Route modules under routes/ carry the HTTP surface; the modules below carry the behavior behind it.

ModuleContract ownerRequired validation
auth, enrollment, directoryAuthentication and Device EnrollmentUnit plus Postgres/Valkey adapter parity
uploadUpload ProtocolState-machine property tests, adapter parity, smoke and E2E
blob, serveServer FilesystemSharded-layout round-trip and full-store enumeration, range, corruption, crash, quarantine tests
verify, attestationStorage VerificationReceipt chain continuity, nonce echo, verdict-over-the-same-read tests
gc, scrubFilesystem — MaintenanceRefcount mark-and-sweep, retention purge, read-only integrity scrub
syncDownload and SyncCursor, monotonicity, pagination and range-resume tests
albumAuthorization and VersioningLifecycle-write authorization, chain advance, upgrade ceremony
shareShare LinksCapability and expiry tests
drop, escrowWeb Upload and Backup and RecoveryDrop-session validation, adoption, escrow store/replace
federationFederationCapability, compartmentalization and pull-path tests
quota, moderationQuota and ModerationUnit plus policy smoke tests
storeServer Filesystem — Required ServicesOne conformance suite every adapter runs, which is what lets the in-memory double be trusted
problem, limits, bodyAPI Surfaces — Rejection MappingCoded-problem bodies, body-size limits, header census on every route

The server owns its content-addressed blob implementation behind a Capsule-defined backend trait. The E2EE-aware resumable protocol also stays in Capsule. Authentication state and upload state use separate typed ports; no generic CAS, transfer, or TTL library is introduced.

BoundaryDecision
REST clientSpargen-generated Rust from a checked-in OpenAPI 3.2 document
SDK workflowsCapsule-owned authentication, upload, sync, recovery, and protocol-version orchestration
Workspace verbs over FFIThe capsule_sdk UniFFI namespace exposes the workspace surface apps need — enroll/open (including a hardware-signer constructor), albums, seal and import, verify, sync-apply, master-key escrow, and device-directory publish. Orchestration and shape only: each verb is one call into capsule-core, which keeps every cryptographic step, and the capsule_core namespace never shares a binary with it
MediaRawshift performs detection, decode/encode, metadata normalization, derivatives, previews, and video work, consumed through capsule-core::media
LQIPCapsule imports Chromahash 0.7.1 directly; Rawshift has no Chromahash responsibility
Import commitCapsule applies privacy policy, creates sidecars/provenance, encrypts, signs, and commits normalized media results
AlertsAlert classes and trigger predicates live in capsule-core::notify so every platform evaluates one decision function; scheduling and presentation are native per client. See Notifications

These are the intended complexity boundaries. A dependency is not added to an active manifest until the named acceptance gaps are verified with contract fixtures or a minimal spike.

LibraryScope Capsule delegatesAcceptance gaps Capsule must verify
KynosHTTP runtime, REST routing, middleware composition, OpenAPI 3.1 and 3.2 emission, limits, shutdown, observabilityStreaming request/response bodies, cancellation and backpressure; deterministic schema output; custom protocol/error headers on every response; middleware ordering; test harnesses without live infrastructure
SpargenRust client generation from the checked-in Kynos OpenAPI contractOpenAPI 3.1 and 3.2 compatibility; streaming upload/range download; opaque binary bodies; stable error-code mapping; auth and protocol headers; supported Rust targets; deterministic generation and version-compatibility checks
RawshiftMedia detection, decoding/encoding, metadata normalization, derivatives, previews, and video processingRequired format/codec matrix; bounded memory and concurrency; cancellation/progress; malformed-input isolation; deterministic orientation/color/HDR behavior; normalized metadata provenance; mobile/desktop targets; no Chromahash API
Chromahash 0.7.1LQIP encode/decode only, imported directly by CapsuleDeterministic output; wide-gamut/HDR fixtures; decoder fallback behavior; supported FFI targets. The pin and the retired ThumbHash decision are Dependencies
OpenMLSMLS protocol and cryptographic state transitionsRequired cipher suites and credential model; deterministic persistence/restore; external signer integration; epoch/exporter behavior; cross-platform size/performance; Capsule-owned album policy and provenance stay outside it
PostgreSQL driver/ORMDurable server index and default implementations of the two typed state portsTransactions needed for finalization, row locking, migration strategy, cancellation, typed error mapping, tracing, and adapter conformance. Select the narrowest mature stack after Kynos integration is proven
redis-rsRequired Valkey adapters for AuthStateStore and UploadSessionStoreAtomic compare/update and expiry primitives required by each port; cluster behavior; cancellation/timeouts; tracing; behavioural parity with the PostgreSQL and in-memory adapters under one conformance suite — parity is what lets the in-memory double be trusted in tests, not a claim that Valkey is substitutable
RustCrypto, ciborium, rusqlite, sqlite-vec, UniFFI, wasm-bindgenExisting crypto primitives, canonical serialization, local catalog and vector index, native bindings, and the browser boundaryContinue vectors, canonical-byte tests, migration tests, and binding smoke tests; these libraries do not own Capsule protocols or schemas

Explicit non-dependencies: no generic CAS crate, object_store, resumable-transfer library, generic TTL/CAS library, GraphQL/gRPC stack, or in-repository media codec stack. Reconsider extraction only after a product-neutral interface has two real consumers and removes more audit surface than it adds.

The E2E surface is bounded: adding a test here means adding it to the relevant doc’s Validation section and justifying why the cross-module surface is irreducible. Each case must remain backed primarily by unit and adapter-contract tests. Cases are numbered so that code can name the case it covers (rg "E2E case N"), and slices in the repo-root SLICES.md reference these numbers.

  1. Auth → sync → client-side library query. Sign in → access token → the sync feed returns the account’s album entries → the client applies them and a local library.sqlite query lists the expected albums (rich queries are client-side per API Surfaces).
  2. Full import + upload + finalize. Local scan → plan → execute → upload session → finalize → blob present at its content address and the index row marked uploaded.
  3. Sync feed pickup. Upload from device A → device B’s feed advances → device B fetches the metadata blob and, per scope, the original.
  4. Federation cross-server pull. Alice on home.tld shares to Bob on other.tld → capability token → Bob’s server pulls metadata and blobs → Bob’s client renders.
  5. LAN peering A→B. Two devices on one LAN; discovery → TLS handshake → delta-scoped artifact → restore on the receiver → byte-equal libraries.
  6. Backup → restore on a fresh device. Export a full backup → bootstrap a new device via passphrase and escrow → import the backup → assert every asset present and verifiable.
  7. Full lifecycle. Create → metadata update → trash → restore → re-delete → hard purge after retention. The provenance chain advances through every transition and the server refuses purge before retention_until.
  8. Album upgrade ceremony. Multi-member album; an admin initiates the upgrade → quiesce → drain → tombstone → fork → queued writes replay. Includes one resume-from-crash mid-ceremony.
  9. Cross-version protocol gate. A client whose protocol_version falls outside the server’s range attempts an upload, receives 426, and the UI surfaces an actionable error.
  10. Model regen after version bump. Bump the canonical model version; assert stale embeddings are excluded from queries; background regen produces fresh embeddings; queries return correct results afterwards. Entirely within capsule-core::ml and the capsule-core::db vector index, so it is unaffected by the server rebuild.
  11. Server crash mid-finalization. Inject a crash between the blob rename and the Postgres transaction commit; restart; assert the session moves to FailedProcessing cleanly, with no orphaned blob and no zombie pending row.
  12. Cross-device enrollment. Device A authorizes new device B over a verified channel (enrollment code plus safety-code check) → B generates hardware keys → A cross-signs B into the device directory → B joins each album’s MLS group → B’s library matches A’s. Includes one MITM-on-relay abort.
  13. Web drop → adopt. A browser/WASM client seals a drop to an upload link → the provisioning user’s native client decapsulates, rewraps the key under the album AMK, and adopts it in place → the asset appears in the library and verify_asset-accepts on a second device. The only case exercising the web/WASM client and the wrapped-key path.