Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ jobs:
- 'hk.pkl'
- '.cargo/**'
- 'capsule-server/**'
- 'capsule-wire/**'
- 'capsule-i18n/**'
- 'capsule-cli/**'
- 'capsule-core/**'
Expand Down
9 changes: 0 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ members = [
"capsule-sdk",
"capsule-wasm",
"capsule-server",
"capsule-wire",
"xtask",
]
# capsule-sdk's REST client is generated at build time by spargen from the committed
Expand All @@ -22,7 +21,6 @@ default-members = [
"capsule-core-ffi",
"capsule-i18n",
"capsule-server",
"capsule-wire",
]
resolver = "3"

Expand Down
1 change: 0 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ A closed set. A row's state is a claim about the package, not about the programm
| `capsule-core-ffi` | cargo | The app umbrella staticlib and the `capsule_core_ffi` uniffi namespace | stabilizing | `mise run check-rust` | [Module Map — Client Boundaries](capsule-docs/src/content/docs/design/module-map.md#client-boundaries) | — | Public-API freeze (#399) | Links `capsule-sdk`'s uniffi surface so one Rust library carries both namespaces an app consumes |
| `capsule-sdk` | cargo | Session, upload, sync, recovery and protocol-version orchestration over the spargen-generated REST client | stabilizing | `mise run check-rust` | [API Surfaces](capsule-docs/src/content/docs/design/api-surfaces.md) | `S-D9`, `S-D17`, `S-E3`, `S-N2` | Close the four contract gaps (#408) | Both items the tracker owed this crate landed: one transport (`GET /v1/sync` through the generated client) and one document (`capsule-server/openapi.json`) |
| `capsule-server` | cargo | The Kynos REST/OpenAPI application and the committed `capsule-server/openapi.json` contract | rebuilding | `mise run check-rust` | [Module Map — Server Modules](capsule-docs/src/content/docs/design/module-map.md#server-modules) | `S-C8`, `S-C39`, `S-C47`, `S-C49`, `S-C51`, `S-E2`, `S-E5`, `S-N1` | A serve binary, configuration and a serve task (#401) | Fifty-nine operations and a test suite over the real router. `src/bin/` holds one binary, `gen_openapi`, which only describes the router; there is no serve binary, no configuration loading and no Postgres or Valkey adapter |
| `capsule-wire` | cargo | Framework-free protocol headers and the response taxonomy across the retiring Salvo boundary | stabilizing | `mise run check-rust` | [API Surfaces](capsule-docs/src/content/docs/design/api-surfaces.md) | `S-C27` | Retired (#400) | Declared by `capsule-server` and called by nothing — the only mention of `capsule_wire` outside the crate is one prose reference in a module comment. `capsule-server` owns `problem`, `limits` and `body` |
| `capsule-wasm` | cargo | The browser boundary — share-link client-side open and guest-drop sealing | stabilizing | `mise run check-rust` | [Web Upload](capsule-docs/src/content/docs/design/web-upload.md) | — | Public-API freeze (#399) | `S-B14` owes it an `lqip` entry point; the encoder already compiles for `wasm32-unknown-unknown` |
| `capsule-i18n` | cargo | The generated Rust catalog bundle, the runtime formatter, and the `error.*` code contract | stabilizing | `mise run check-rust` | [i18n](capsule-docs/src/content/docs/design/i18n.md) | — | ICU plural evaluation (#414) | Generated from `locales/` by `mise run i18n`; `mise run i18n-check` fails on drift |
| `capsule-cli` | cargo | The `capsule` binary — local library commands plus auth, sync, push, import and cull | stabilizing | `mise run check-rust` | [Clients](capsule-docs/src/content/docs/design/clients.md) | `S-B17`, `S-B18`, `S-I8`, `S-Q1`, `S-Q2`, `S-Q3`, `S-Q4` | Help text from the catalogs and an enrichment read surface (#413) | The networked commands have no server to reach until #401 lands one |
Expand Down
15 changes: 13 additions & 2 deletions SLICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ lives.
| S-C24 | Album-upgrade server halves (quiescence/drain/lineage) | server | S-C42 | M-L | RETIRED | done\* | the ceremony's wire vocabulary was `mls`-gated and therefore unreachable; the projection deliberately gets no lineage |
| S-C25 | Album provisioning + UUID album ids (unblocks push) | server | S-C29 | M | RETIRED | done\* | also lands the first real `WriteAuthority`; sharing widens it → `S-C4`/`S-C5` |
| S-C26 | Retire the plaintext album name/description columns | server | S-C25 | S | RETIRED | done | the Kynos schema never declared them; a document tripwire keeps it that way |
| S-C27 | Wire-contract types on plain serde behind an adapter | server | — | M | RETIRED | part 1 done | DTO move → Kynos rebuild; status gaps → `S-C28` |
| S-C27 | Wire-contract types on plain serde behind an adapter | server | — | M | RETIRED | done | part 2 declined by the Kynos port; the crate retired with the Salvo tree |
| S-C28 | Publish the statuses the server actually returns | server | S-C27 | S | RETIRED | done\* | auth surface closed; folds into each remaining port |
| S-C29 | The two storage ports + typed ceremony stores | server | S-C27 | L | RETIRED | done\* | Valkey + Postgres adapters owed; counters → `S-C32` |
| S-C30 | Feed `manifest_cbor` carries the signed manifest | server | S-C1, S-C2 | M | RETIRED | done\* | server half stores and serves verbatim; client producer owed to `S-D1` |
Expand Down Expand Up @@ -2320,6 +2320,17 @@ working on a surface written after it.
crate may not depend on salvo at all) and an adapter crate cannot implement a foreign trait
for a foreign type. The structs move when Kynos replaces salvo as the schema source, which
is why the "Done when" above stays unmet and this row is not `done`.
- **Landed 2026-09-01 — done by retirement.** Part 2 is **declined, not deferred**: the Kynos
port removed the condition it was waiting on. The 39 `ToSchema` derives retired with the Salvo
tree (`S-C59`) instead of moving, `capsule-api` no longer exists, and the SDK generates from
`capsule-server/openapi.json`, so the "Done when" above — `rg salvo capsule-api/*/src/models`
empty plus a byte-identical `openapi.json` — is **vacuous rather than unmet**. The taxonomy's
live home is `capsule-server`'s `problem`, `limits` and `body` modules, where the status is part
of the return type and `tests/conformance.rs` asserts both directions of the agreement this
extraction existed to keep. `capsule-wire` itself moved to `legacy-review/server-salvo/wire/`
beside the 40 `salvo_responses!` call sites that are its only consumers, its manifest disabled,
and `architecture-check` lists it as a retired dependency so a member cannot declare it again
(ADR-0004).

### S-C28 — Publish the statuses the server actually returns

Expand Down Expand Up @@ -5787,7 +5798,7 @@ table hides what it would cost.

| Migration | Status | Measured cost today | Unblocks when |
| --- | --- | --- | --- |
| `salvo` → [`kynos`](https://github.com/getkono/kynos) | **started; the precondition has landed** | The measurement that scoped this row was 648 `salvo` occurrences across 84 files, including 51 `impl Writer` and 41 `EndpointOutRegister` blocks. `S-C27` part 1 has since deleted the mechanical half: **315 occurrences across 86 files, 12 `impl Writer`, 2 `EndpointOutRegister`**, with 40 call sites now expanding from one `salvo_responses!` table each, and `auth/src/models/responses.rs` down from 1440 to 1019 lines. What remains is the part that was never boilerplate: 63 `#[handler]`/`#[endpoint]` route fns, 68 `ToSchema` derives and 68 `Depot` reads. The `ToSchema` derives are exactly why **part 2 is owed to the port rather than to another refactor** — a framework-neutral crate cannot carry that derive (optional deps count against the boundary check) and an adapter cannot implement a foreign trait for a foreign type, so the DTO structs move when the framework does. `architecture-check` reports **63 boundary violations**, which is the rebuild worklist. | Kynos is **published at 0.1.0 and consumed from crates.io**; the git-rev pin this row used to require is retired. `capsule-server` exists with a conformance suite, so the port is incremental from here rather than a cutover. |
| `salvo` → [`kynos`](https://github.com/getkono/kynos) | **started; the precondition has landed** | The measurement that scoped this row was 648 `salvo` occurrences across 84 files, including 51 `impl Writer` and 41 `EndpointOutRegister` blocks. `S-C27` part 1 has since deleted the mechanical half: **315 occurrences across 86 files, 12 `impl Writer`, 2 `EndpointOutRegister`**, with 40 call sites now expanding from one `salvo_responses!` table each, and `auth/src/models/responses.rs` down from 1440 to 1019 lines. What remains is the part that was never boilerplate: 63 `#[handler]`/`#[endpoint]` route fns, 68 `ToSchema` derives and 68 `Depot` reads. The `ToSchema` derives are exactly why **part 2 is owed to the port rather than to another refactor** — a framework-neutral crate cannot carry that derive (optional deps count against the boundary check) and an adapter cannot implement a foreign trait for a foreign type, so the DTO structs move when the framework does. `architecture-check` reported **63 boundary violations** while the Salvo tree was still in the workspace, which was the rebuild worklist. Part 2 is now **declined rather than owed**: the `ToSchema` derives retired with the tree instead of moving, and the framework-free crate that carried the taxonomy went with them to `legacy-review/server-salvo/wire/` (`S-C27`, ADR-0004). | Kynos is **published at 0.1.0 and consumed from crates.io**; the git-rev pin this row used to require is retired. `capsule-server` exists with a conformance suite, so the port is incremental from here rather than a cutover. |
| `progenitor` → [`spargen`](https://github.com/getkono/spargen) | **done** | — | Complete. Progenitor is gone from `Cargo.lock` and every manifest; `generate_openapi.sh` was deleted in `2996a13`; spargen is shipped and on crates.io. Open items: spargen's object-typed-query-param lowering (gates table), and re-sourcing the SDK's schema from Kynos rather than the Salvo `gen_openapi` binary (`S-D8`). |
| Real image codecs (JXL/AVIF/WebP encode, RAW decode) | **deferred** | Nine format modules are decode/encode stubs; only JPEG and PNG are real. | `rawshift` stabilizes for RAW; the JXL/AVIF/WebP encode half is picked up separately against the thumbnails.md format table. `S-B13` makes the gap a typed `UnsupportedFormat` error and reports it at derivative time (`DerivativeStatus::DeferredNoCodec`, warned + counted per run); originals still import signed and verifiable, so the deferral cannot cause incorrect behaviour — only visibly absent thumbnails. |
| Test bootstrap: hand-rolled `docker` CLI → Kynos `TestClient` + the `S-C29` conformance suite | **deferred deliberately; retires rather than migrates** | `capsule-api-testing` is a declared default-member, so its 242 lines compile on every build, and it has **zero consumers** — `rg` for the package name outside itself returns nothing. Its `common.rs` shells out to the `docker` CLI via `std::process::Command` to start Postgres, which is a second container-bootstrap approach competing with the testcontainers six other sites hand-roll; its `schema.rs` is entirely `#[cfg(test)]` tests of sea-orm entity CRUD, and those three tests do run and pass in the workspace suite. | Nothing. This is recorded so it is not re-litigated as slimming: reviving it means teaching six call sites in the retiring Salvo tree to share a fixture, which is thrown away at Stage 7.5, and deleting it now removes the only live coverage of the sea-orm migration path while that path is still in use. It retires **with** `capsule-api`. The replacement needs no container at all — Kynos's `TestClient` drives a built `Service` in-process, and `S-C29`'s shared conformance suite is what lets the in-memory adapter stand in for Valkey. |
Expand Down
3 changes: 2 additions & 1 deletion adr/0004-capsule-wire-is-retired.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# ADR-0004 — `capsule-wire` is retired once no member depends on it

- **Status:** proposed
- **Status:** accepted
- **Date:** 2026-09-01
- **Supersedes:** —
- **Superseded by:** —
- **Contract:** [API Surfaces](../capsule-docs/src/content/docs/design/api-surfaces.md)
- **Slices:** S-C27, S-C59

## Context
Expand Down
1 change: 0 additions & 1 deletion capsule-docs/src/content/docs/design/module-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ whether something exists today, find its slice: `rg 'S-C16' SLICES.md`.
| `capsule-core` | Cryptography (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-server` | The Kynos REST/OpenAPI application — see [Server Modules](#server-modules) |
| `capsule-sdk` | The 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-wire` | The 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-wasm` | The 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::i18n` | Canonical ICU catalogs, runtime localization, generated platform catalogs |
| `capsule-core-ffi` | UniFFI bindings for native Swift and Kotlin consumers, on one UniFFI version across both surfaces |
Expand Down
3 changes: 0 additions & 3 deletions capsule-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ kynos = { workspace = true }
# refuse-by-default invariants — and the crypto types they read. The default `native` feature pulls
# SQLite, sqlite-vec, OpenMLS and libcrux, none of which a key-free server touches.
capsule-core = { path = "../capsule-core", default-features = false }
# The framework-free wire contracts (slice `S-C27`). The response taxonomy lives here so it
# outlives whichever framework renders it.
capsule-wire = { path = "../capsule-wire" }
serde = { workspace = true }
# The state ports (slice `S-C29`). `thiserror` because these are a library surface;
# `jiff` because every record and every TTL is a time and chrono is banned; `tracing` because
Expand Down
5 changes: 3 additions & 2 deletions capsule-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
//!
//! The previous server was Salvo, and its wire-contract types were themselves salvo-typed, so
//! replacing it was never a transport swap (`SLICES.md`, the salvo→kynos row). `S-C27` moved the
//! response taxonomy into the framework-free [`capsule_wire`]; this crate is where the surfaces
//! that taxonomy describes get rebuilt.
//! response taxonomy into a framework-free crate so the contract could outlive the transport;
//! that crate retired with the Salvo tree it adapted (ADR-0004), and this crate is where the
//! surfaces the taxonomy described get rebuilt. `problem`, `limits` and `body` own it now.
//!
//! # What the framework buys, and why it was chosen
//!
Expand Down
4 changes: 4 additions & 0 deletions legacy-review/server-salvo/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
## Do not reuse

- Salvo handlers, response writers, OpenAPI registration, or configuration projections.
- `wire/`'s `salvo_responses!` macro and the `WireResponses` taxonomy it expands. It was the
workspace crate `capsule-wire` until the Kynos port; `capsule-server`'s `problem`, `limits` and
`body` modules are the live response taxonomy, and Kynos makes the status part of the return
type, which is the defect the taxonomy was extracted to prevent.
- Server-side media decoding or metadata extraction. Those files were deleted during quarantine.
- The plaintext asset schema, transformation endpoints, filename-based storage layout, or upload
finalization that marks an asset visible before the complete encrypted bundle is durable.
Expand Down
2 changes: 1 addition & 1 deletion legacy-review/server-salvo/auth/Cargo.toml.disabled
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ capsule-core = { path = "../../capsule-core" }
capsule-api-model = { path = "../model" }
capsule-api-service = { path = "../service", features = ["auth"] }
capsule-i18n = { path = "../../capsule-i18n" }
capsule-wire = { path = "../../capsule-wire" }
capsule-wire = { path = "../wire" }
argon2 = { workspace = true }
bb8 = { workspace = true }
bb8-redis = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion legacy-review/server-salvo/media/Cargo.toml.disabled
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ capsule-api-upload = { path = "../upload" }
# crate's own capsule-core dependency unifies features in the workspace build anyway).
capsule-core = { path = "../../capsule-core", default-features = false }
capsule-i18n = { path = "../../capsule-i18n" }
capsule-wire = { path = "../../capsule-wire" }
capsule-wire = { path = "../wire" }
base64 = { workspace = true }
bytes = { workspace = true }
derive_more = { workspace = true, features = ["from"] }
Expand Down
2 changes: 1 addition & 1 deletion legacy-review/server-salvo/upload/Cargo.toml.disabled
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ capsule-api-model = { path = "../model" }
capsule-api-service = { path = "../service" }
capsule-core = { path = "../../capsule-core", features = ["media"] }
capsule-i18n = { path = "../../capsule-i18n" }
capsule-wire = { path = "../../capsule-wire" }
capsule-wire = { path = "../wire" }
bb8-redis = { workspace = true }
eyre = { workspace = true }
futures-util = { workspace = true }
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions xtask/src/architecture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const RETIRED_DEPENDENCIES: &[&str] = &[
"async-graphql",
"async-graphql-salvo",
"capsule-media",
"capsule-wire",
"graphql-client",
"object_store",
"progenitor",
Expand Down
Loading