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.
Crate Roster
Section titled “Crate Roster”| Crate | Purpose |
|---|---|
capsule-core | Shared logic across server and clients: cryptography, library layout, import pipeline, metadata, ML orchestration |
capsule-sdk | Client SDK: auto-generated OpenAPI client, upload protocol, per-platform hardware-key + peering glue |
capsule-api | Server entry-point + routing |
capsule-api-auth | Authentication, sessions, OIDC, device directory |
capsule-api-library | GraphQL API for UI queries (assets, albums, search) |
capsule-api-upload | TUS-like resumable upload protocol server |
capsule-api-media | Media serving (ciphertext blobs, public shares) |
capsule-api-sync | gRPC sync API + federation |
capsule-api-service | Higher-level service layer over the entity model (album, asset, friendship, passkey, stack, user, quota) |
capsule-api-entity | Sea-ORM entities (Postgres schema) |
capsule-api-model | Business-logic models on top of entities |
capsule-api-migration | Sea-ORM migrations |
capsule-api-environment | Configuration, env vars, feature flags |
capsule-api-testing | Shared test utilities (testcontainer setup, schema fixtures) |
capsule-cli | Command-line client |
capsule-media | Standalone media utility crate |
Module → Design Doc
Section titled “Module → Design Doc”capsule-core
Section titled “capsule-core”| Module | Owning design doc | Validation tier |
|---|---|---|
crypto::primitives (planned) | Cryptography — Primitives | Unit (RFC vectors) |
crypto::keys (planned) | Cryptography — Keys, Device Enrollment | Unit + Smoke (hardware per-platform) |
crypto::mls (planned) | Cryptography — MLS, MLS Resilience | Unit + Smoke (protocol round-trip) |
crypto::encryption (planned) | Cryptography — Encryption | Unit (KAT, round-trip) |
crypto::provenance (planned) | Cryptography — Provenance | Unit (exhaustive negative cases) + Smoke |
crypto::verify_asset (planned) | Cryptography — Write Authorization | Unit (the single chokepoint; exhaustive) |
backup (planned) | Backup and Recovery | Unit + Smoke |
library::{init,open,rebuild,lock,paths,scrub,trash} | Filesystem — Client, Filesystem — Maintenance | Unit + Smoke |
import::{scanner,planner,executor,plan,upload,group,progress,special} | Import — Pipeline | Unit (planner determinism) + Smoke (executor) |
metadata::{file,filter,types} | Metadata | Unit (filtering) |
sidecar::* | Metadata — Sidecar Schema | Unit (serde determinism) |
exif::{extract,timezone} | Metadata | Unit |
db::{driver,schema,rows} | Filesystem — Client | Unit (SQLite ops) |
domain::* (enums) | Organization, Authorization, Metadata | Unit (closed-enum rejection) |
models::* | Metadata, Import — Pipeline | Unit |
ml (planned) | AI/ML Integrations | Unit + Smoke (inference parity per-platform) |
sharing (planned) | Share Links | Unit |
capsule-sdk
Section titled “capsule-sdk”| Module | Owning design doc | Validation tier |
|---|---|---|
| (auto-generated client) | Clients | Smoke (re-generated; not unit-tested) |
upload | Import — Upload Protocol | Unit + Smoke (client side) |
peering (planned) | Peering | Unit + Smoke per platform |
hardware-keys (planned) | Cryptography — Keys, Device Enrollment | Smoke per platform |
capsule-api (root + sub-crates)
Section titled “capsule-api (root + sub-crates)”| Module | Owning design doc | Validation tier |
|---|---|---|
capsule-api (routing) | Filesystem — Server | Smoke |
capsule-api-auth::{oidc,session,claims,roles} | Authentication, Authorization | Unit + Smoke (testcontainer Postgres/Redis) |
capsule-api-auth::devices (planned for enrollment) | Device Enrollment | Smoke |
capsule-api-library::schema::* | Metadata, Organization | Smoke (GraphQL) |
capsule-api-library::loaders | Filesystem — Server | Unit (DataLoader) |
capsule-api-upload | Import — Upload Protocol | Unit + Smoke + 1 E2E |
capsule-api-media::routes | Filesystem — Server, Thumbnails | Smoke |
capsule-api-media::shares (planned) | Share Links | Unit + Smoke |
capsule-api-sync (sync feed) | Import — Download & Sync | Unit + Smoke + 1 E2E |
capsule-api-sync::federation | Federation | Unit + Smoke + 1 E2E |
capsule-api-service::album | Organization | Unit |
capsule-api-service::asset | Authorization, Organization | Unit + Smoke |
capsule-api-service::quota (planned) | Quota | Unit |
capsule-api::moderation (planned) | Moderation | Smoke |
capsule-api-entity::* (Sea-ORM) | Filesystem — Server | Unit (Sea-ORM CRUD) |
capsule-api-migration | Versioning (forward-only migrations) | Smoke (migration run) |
capsule-api-environment | (configuration; no design owner) | Unit |
capsule-api-testing | (test utilities; no design owner) | n/a |
capsule-cli, capsule-media
Section titled “capsule-cli, capsule-media”| Crate | Owning design doc | Validation tier |
|---|---|---|
capsule-cli | Clients (treats CLI as a client) | Smoke |
capsule-media | (small utility crate; no specific design owner) | Unit |
Design Doc → Module (Reverse Lookup)
Section titled “Design Doc → Module (Reverse Lookup)”Navigation from a design doc back to where the code lives.
| Design doc | Implementing modules |
|---|---|
| Principles | (meta — no specific code module) |
| Cryptography — Primitives | capsule-core::crypto::primitives (planned) |
| Cryptography — Keys | capsule-core::crypto::keys, capsule-sdk::hardware-keys (both planned) |
| Cryptography — MLS | capsule-core::crypto::mls (planned, wraps OpenMLS) |
| Cryptography — Encryption | capsule-core::crypto::encryption (planned) |
| Cryptography — Provenance | capsule-core::crypto::provenance + verify_asset chokepoint (planned) |
| Cryptography — Failure Modes | Cross-cutting: capsule-core::backup, capsule-core::library, capsule-core::crypto::* |
| MLS Resilience | capsule-core::crypto::mls (extends main MLS module) |
| Device Enrollment | capsule-core::crypto::keys, capsule-api-auth::devices |
| Authentication | capsule-api-auth::{oidc,session,claims} |
| Authorization | capsule-api-auth::roles, capsule-core::crypto::provenance (verify_asset) |
| Clients | capsule-sdk + per-platform native code |
| Versioning | Cross-cutting: capsule-api (header enforcement), capsule-core::crypto::mls (upgrade ceremony), capsule-api-migration |
| Backup and Recovery | capsule-core::backup (planned), capsule-api-auth (escrow surface) |
| Metadata | capsule-core::{metadata,sidecar,exif}, capsule-api-library::schema |
| Filesystem — Server | capsule-api, capsule-api-entity, blob store glue |
| Filesystem — Client | capsule-core::{library,db}, per-platform native code |
| Filesystem — Maintenance | capsule-core::library::{scrub,rebuild,trash}, server-side scrub in capsule-api-upload |
| Import — Pipeline | capsule-core::import::* |
| Import — Upload Protocol | capsule-sdk::upload (client) + capsule-api-upload (server) |
| Import — Download & Sync | capsule-sdk (client) + capsule-api-sync (server) |
| Federation | capsule-api-sync::federation |
| Peering | capsule-sdk::peering (planned) + capsule-core::backup (artifact format) |
| Organization | capsule-core::domain::stack_type, capsule-api-service::{album,stack} |
| AI/ML Integrations | capsule-core::ml (planned), model registry + per-platform inference runners |
| Thumbnails | Client-side gen in capsule-sdk + serving in capsule-api-media |
| Share Links | capsule-core::sharing (planned), capsule-api-media::shares (planned) |
| Moderation | capsule-api::moderation (planned) |
| Quota | capsule-api-service::quota (planned) |
| Threat Model | Enforced 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 — Validation | capsule-api envelope checks (server-side), capsule-core::crypto::verify_asset (client-side) |
| Threat Model — Schema Rules | capsule-core::crypto decoders + capsule-api validators (closed-enum + Postel asymmetry) |
E2E Test Surface
Section titled “E2E Test Surface”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.”
- 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. - Full import + upload + finalize. Local scan → plan → execute → upload session → finalize → blob present at
blobs/{hash}+ index row marked uploaded. Coverscapsule-core::import×capsule-sdk::upload×capsule-api-upload×capsule-api-entity. - Sync feed pickup. Upload from device A → device B’s
/syncadvances → device B fetches metadata blob and (per scope) the original. Coverscapsule-api-sync×capsule-sdkdownload path ×capsule-core::librarywrite. - Federation cross-server pull. Alice on
home.tldshares to Bob onother.tld→ capability token → Bob’s server pulls metadata + blobs → Bob’s client renders. Coverscapsule-api-sync::federation(both sides) ×capsule-api-auth(capability issue). - 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. - 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. - 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. Coverscapsule-api-auth::roles×capsule-core::crypto::provenance× server purge worker. - 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. - Cross-version protocol gate. Client with
protocol_versionoutside server’s range attempts upload; receives426; UI surfaces actionable error. Coverscapsule-apihandshake ×capsule-sdkerror handling. - 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::dbvector index. - Server crash mid-finalization. Inject crash between blob rename and Postgres transaction commit; restart; assert session moves to
FailedProcessingcleanly, no orphaned blob, no zombie pending row. Coverscapsule-api-upload×capsule-api-entity×capsule-api’s startup scrub. - 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.
Using This Map
Section titled “Using This Map”- 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.