Skip to content

Module Map

This is the developer’s first stop. It maps every Capsule workspace crate and module to the design doc(s) that govern its behavior, and to the validation tier (Unit / Smoke / E2E — see Validation Tiers) it ships with. The E2E test surface at the bottom is bounded: adding a test there means adding the test to the relevant doc’s Validation section and justifying why the cross-module surface is irreducible.

The mapping reflects the design intent. Some modules listed below are currently planned (annotated (planned)) rather than already implemented in the codebase — the doc structure already accounts for them so the boundary is set before code lands.

CratePurpose
capsule-coreShared logic across server and clients: cryptography, library layout, import pipeline, metadata, ML orchestration
capsule-sdkClient SDK: auto-generated OpenAPI client, upload protocol, per-platform hardware-key + peering glue
capsule-apiServer entry-point + routing
capsule-api-authAuthentication, sessions, OIDC, device directory
capsule-api-libraryGraphQL API for UI queries (assets, albums, search)
capsule-api-uploadTUS-like resumable upload protocol server
capsule-api-mediaMedia serving (ciphertext blobs, public shares)
capsule-api-syncgRPC sync API + federation
capsule-api-serviceHigher-level service layer over the entity model (album, asset, friendship, passkey, stack, user, quota)
capsule-api-entitySea-ORM entities (Postgres schema)
capsule-api-modelBusiness-logic models on top of entities
capsule-api-migrationSea-ORM migrations
capsule-api-environmentConfiguration, env vars, feature flags
capsule-api-testingShared test utilities (testcontainer setup, schema fixtures)
capsule-cliCommand-line client
capsule-mediaStandalone media utility crate
ModuleOwning design docValidation tier
crypto::primitives (planned)Cryptography — PrimitivesUnit (RFC vectors)
crypto::keys (planned)Cryptography — Keys, Device EnrollmentUnit + Smoke (hardware per-platform)
crypto::mls (planned)Cryptography — MLS, MLS ResilienceUnit + Smoke (protocol round-trip)
crypto::encryption (planned)Cryptography — EncryptionUnit (KAT, round-trip)
crypto::provenance (planned)Cryptography — ProvenanceUnit (exhaustive negative cases) + Smoke
crypto::verify_asset (planned)Cryptography — Write AuthorizationUnit (the single chokepoint; exhaustive)
backup (planned)Backup and RecoveryUnit + Smoke
library::{init,open,rebuild,lock,paths,scrub,trash}Filesystem — Client, Filesystem — MaintenanceUnit + Smoke
import::{scanner,planner,executor,plan,upload,group,progress,special}Import — PipelineUnit (planner determinism) + Smoke (executor)
metadata::{file,filter,types}MetadataUnit (filtering)
sidecar::*Metadata — Sidecar SchemaUnit (serde determinism)
exif::{extract,timezone}MetadataUnit
db::{driver,schema,rows}Filesystem — ClientUnit (SQLite ops)
domain::* (enums)Organization, Authorization, MetadataUnit (closed-enum rejection)
models::*Metadata, Import — PipelineUnit
ml (planned)AI/ML IntegrationsUnit + Smoke (inference parity per-platform)
sharing (planned)Share LinksUnit
ModuleOwning design docValidation tier
(auto-generated client)ClientsSmoke (re-generated; not unit-tested)
uploadImport — Upload ProtocolUnit + Smoke (client side)
peering (planned)PeeringUnit + Smoke per platform
hardware-keys (planned)Cryptography — Keys, Device EnrollmentSmoke per platform
ModuleOwning design docValidation tier
capsule-api (routing)Filesystem — ServerSmoke
capsule-api-auth::{oidc,session,claims,roles}Authentication, AuthorizationUnit + Smoke (testcontainer Postgres/Redis)
capsule-api-auth::devices (planned for enrollment)Device EnrollmentSmoke
capsule-api-library::schema::*Metadata, OrganizationSmoke (GraphQL)
capsule-api-library::loadersFilesystem — ServerUnit (DataLoader)
capsule-api-uploadImport — Upload ProtocolUnit + Smoke + 1 E2E
capsule-api-media::routesFilesystem — Server, ThumbnailsSmoke
capsule-api-media::shares (planned)Share LinksUnit + Smoke
capsule-api-sync (sync feed)Import — Download & SyncUnit + Smoke + 1 E2E
capsule-api-sync::federationFederationUnit + Smoke + 1 E2E
capsule-api-service::albumOrganizationUnit
capsule-api-service::assetAuthorization, OrganizationUnit + Smoke
capsule-api-service::quota (planned)QuotaUnit
capsule-api::moderation (planned)ModerationSmoke
capsule-api-entity::* (Sea-ORM)Filesystem — ServerUnit (Sea-ORM CRUD)
capsule-api-migrationVersioning (forward-only migrations)Smoke (migration run)
capsule-api-environment(configuration; no design owner)Unit
capsule-api-testing(test utilities; no design owner)n/a
CrateOwning design docValidation tier
capsule-cliClients (treats CLI as a client)Smoke
capsule-media(small utility crate; no specific design owner)Unit

Navigation from a design doc back to where the code lives.

Design docImplementing modules
Principles(meta — no specific code module)
Cryptography — Primitivescapsule-core::crypto::primitives (planned)
Cryptography — Keyscapsule-core::crypto::keys, capsule-sdk::hardware-keys (both planned)
Cryptography — MLScapsule-core::crypto::mls (planned, wraps OpenMLS)
Cryptography — Encryptioncapsule-core::crypto::encryption (planned)
Cryptography — Provenancecapsule-core::crypto::provenance + verify_asset chokepoint (planned)
Cryptography — Failure ModesCross-cutting: capsule-core::backup, capsule-core::library, capsule-core::crypto::*
MLS Resiliencecapsule-core::crypto::mls (extends main MLS module)
Device Enrollmentcapsule-core::crypto::keys, capsule-api-auth::devices
Authenticationcapsule-api-auth::{oidc,session,claims}
Authorizationcapsule-api-auth::roles, capsule-core::crypto::provenance (verify_asset)
Clientscapsule-sdk + per-platform native code
VersioningCross-cutting: capsule-api (header enforcement), capsule-core::crypto::mls (upgrade ceremony), capsule-api-migration
Backup and Recoverycapsule-core::backup (planned), capsule-api-auth (escrow surface)
Metadatacapsule-core::{metadata,sidecar,exif}, capsule-api-library::schema
Filesystem — Servercapsule-api, capsule-api-entity, blob store glue
Filesystem — Clientcapsule-core::{library,db}, per-platform native code
Filesystem — Maintenancecapsule-core::library::{scrub,rebuild,trash}, server-side scrub in capsule-api-upload
Import — Pipelinecapsule-core::import::*
Import — Upload Protocolcapsule-sdk::upload (client) + capsule-api-upload (server)
Import — Download & Synccapsule-sdk (client) + capsule-api-sync (server)
Federationcapsule-api-sync::federation
Peeringcapsule-sdk::peering (planned) + capsule-core::backup (artifact format)
Organizationcapsule-core::domain::stack_type, capsule-api-service::{album,stack}
AI/ML Integrationscapsule-core::ml (planned), model registry + per-platform inference runners
ThumbnailsClient-side gen in capsule-sdk + serving in capsule-api-media
Share Linkscapsule-core::sharing (planned), capsule-api-media::shares (planned)
Moderationcapsule-api::moderation (planned)
Quotacapsule-api-service::quota (planned)
Threat ModelEnforced across every validation chokepoint: capsule-core::crypto::verify_asset (client), capsule-api validators (server)
Threat Model — Scenarios(catalog; each row maps to the owner doc’s module)
Threat Model — Validationcapsule-api envelope checks (server-side), capsule-core::crypto::verify_asset (client-side)
Threat Model — Schema Rulescapsule-core::crypto decoders + capsule-api validators (closed-enum + Postel asymmetry)

The bounded global list of cross-module integration tests. Editing this list requires updating the relevant doc’s Validation section. Adding an E2E case past this list is a signal the design has unwanted coupling worth examining before adding the test.

Target count: ≤ 12 cases. Each one is named by what it proves — not “test X” but “X works through Y and Z.”

  1. Auth → Library query. Log in via OIDC → access-token → GraphQL query for own albums returns expected list. Covers capsule-api-auth::oidc + session × capsule-api-library::schema.
  2. Full import + upload + finalize. Local scan → plan → execute → upload session → finalize → blob present at blobs/{hash} + index row marked uploaded. Covers capsule-core::import × capsule-sdk::upload × capsule-api-upload × capsule-api-entity.
  3. Sync feed pickup. Upload from device A → device B’s /sync advances → device B fetches metadata blob and (per scope) the original. Covers capsule-api-sync × capsule-sdk download path × capsule-core::library write.
  4. Federation cross-server pull. Alice on home.tld shares to Bob on other.tld → capability token → Bob’s server pulls metadata + blobs → Bob’s client renders. Covers capsule-api-sync::federation (both sides) × capsule-api-auth (capability issue).
  5. LAN peering A→B. Two devices on the same LAN; mDNS discovery → TLS handshake → delta-scoped artifact → restore on receiver → byte-equal libraries. Covers capsule-sdk::peering × capsule-core::backup × capsule-core::library.
  6. Backup → restore on a fresh device. Export full backup → bootstrap new device via passphrase + escrow → import backup → assert every asset present and verifiable. Covers capsule-core::backup × capsule-core::crypto::keys × capsule-core::library.
  7. Full lifecycle. Create → metadata-update → trash → restore → re-delete → hard-purge after retention. Provenance chain advances through every transition; server refuses purge before retention_until. Covers capsule-api-auth::roles × capsule-core::crypto::provenance × server purge worker.
  8. Album upgrade ceremony. Multi-member album; admin initiates upgrade → quiesce → drain → tombstone → fork → queued writes replay. Includes one resume-from-crash mid-ceremony. Covers capsule-core::crypto::mls × capsule-api × client UI.
  9. Cross-version protocol gate. Client with protocol_version outside server’s range attempts upload; receives 426; UI surfaces actionable error. Covers capsule-api handshake × capsule-sdk error handling.
  10. Model regen after version bump. Bump canonical model version; assert stale embeddings excluded from queries; background regen produces fresh embeddings; queries return correct results post-regen. Covers capsule-core::ml × capsule-core::db vector index.
  11. Server crash mid-finalization. Inject crash between blob rename and Postgres transaction commit; restart; assert session moves to FailedProcessing cleanly, no orphaned blob, no zombie pending row. Covers capsule-api-upload × capsule-api-entity × capsule-api’s startup scrub.
  12. Cross-device enrollment. Existing device A authorizes new device B over a verified channel (enrollment code + 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. Covers capsule-api-auth::devices × capsule-core::crypto::keys × capsule-sdk::hardware-keys.
  • When implementing a module: find it in Module → Design Doc, open the owning doc, read the contracts and the validation tier expectations. The unit + smoke surface defined in that doc should be authorable without leaving the module.
  • When adding a feature: find the relevant design doc via the reverse lookup; confirm the feature fits within an existing module’s scope or warrants a new one. If new, add a row here.
  • When considering an E2E test: check this list first. If your proposed test isn’t here, either it’s an existing case in disguise (use that), or the design has cross-module coupling worth surfacing — discuss before adding.