- Rust 51%
- QML 10.8%
- Python 7.7%
- Svelte 7.3%
- TypeScript 7.2%
- Other 16%
|
Some checks failed
Cords checks / Native Qt desktop (Windows x86_64) (push) Waiting to run
Cords checks / Native Qt desktop (macOS) (push) Failing after 46s
Cords checks / rust-and-frontend (push) Failing after 2m47s
Cords checks / containers (push) Failing after 30s
Cords checks / Native Qt desktop (Linux x86_64) (push) Successful in 6m57s
|
||
|---|---|---|
| .forgejo | ||
| assets/avatar-codec | ||
| bins | ||
| build-scripts | ||
| crates | ||
| deploy | ||
| docs | ||
| migrations | ||
| packaging | ||
| scripts | ||
| test-vectors | ||
| tests/e2e | ||
| tools/avatar-codec | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| .gitleaks.toml | ||
| AGENTS.md | ||
| aqtinstall.log | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHECKPOINT.md | ||
| compose.yaml | ||
| cords-up.sh | ||
| deny.toml | ||
| dissection.md | ||
| KEY-SYSTEM.md | ||
| LICENSE | ||
| README.md | ||
| ROADMAP.md | ||
| rust-toolchain.toml | ||
| test-e2e.ps1 | ||
| test-e2e.sh | ||
| UI-DESIGN.md | ||
Cords
Right on the wire
Cords is a self-hosted communication system designed to keep message and attachment plaintext on authorized client devices. The working tree now implements a development encrypted-channel slice: independent native identities, server pinning, device authentication, MLS, durable HTTP synchronization and WebSocket notifications.
New server operators should start with the Cords server operator guide, which covers OCI deployment with Docker or Podman and direct installation from the unpacked server tarball.
The CLI and native Qt Quick/QML desktop use the same Rust client core. The desktop
migration remains in progress; see its acceptance ledger.
See the
encrypted milestone guide and
validation report for reproducible commands,
real .54 evidence and remaining gates. Attachments, calls, DMs, full enrollment
and recovery remain deferred; this is not a production release claim.
Repository
bins/cords-client/qt: native Qt 6 Quick/QML desktop and typed Rust bridge.bins/cords-client/uiandsrc-tauri: temporary legacy reference pending parity/removal.bins/cords-server: Axum server executable and configuration.crates/cords-protocol: public schemas and deterministic signed encoding.bins/cords-dev: development CLI around the real client core.crates/cords-client-core: protected state, identity, trust, MLS orchestration and synchronization.crates/cords-server-core: persistent server identity and HTTP services.crates/cords-storage: PostgreSQL and SQLite lifecycle adapters.docs/adr: architecture decisions;AGENTS.mdis the normative product specification.
Run the server
docker compose up --build --wait
curl -i http://127.0.0.1:4849/health/ready
The base Compose topology exposes internal HTTP on loopback port 4849 for health diagnostics. It is not a client origin. Run the optional Caddy profile for local HTTPS:
docker compose --profile proxy up --build --wait
Caddy uses its internal CA for this local example. Trust that CA explicitly before inspecting https://localhost:4848; Cords never disables normal TLS validation. Production deployments should use a publicly trusted certificate and set CORDS_SERVER__PUBLIC_ORIGIN to the matching HTTPS origin.
The example server requires owner approval for new device membership by default. The owner reviews pending requests under Server settings → Members. Set server.join_policy = "public" explicitly for immediate admission. Approved members can discover channel names and stable channel IDs, but cannot read encrypted contents until added to each channel's MLS group. Channel creation is owner-only.
The Compose file uses a conspicuous development-only PostgreSQL password. A deployment must apply deploy/compose.production.example.yaml as an override and provide a matching, URL-encoded CORDS_DATABASE__URL; do not reuse the development credential publicly.
Clients join with the HTTPS URL only. Cords validates the certificate, verifies signed discovery, pins the discovered server identity on first use, and refuses later identity changes for that origin. The pinned fingerprint remains visible for inspection; it is not a join form field.
On a fresh database the server enters UNCLAIMED, generates a 256-bit one-time code, and writes the
plaintext once to its operator log. It persists only a server-bound verifier. Read the initial code:
docker compose logs cords-server
Connect the desktop client over its normal certificate-validated HTTPS origin. Signed discovery reports that the server is unclaimed and presents the claim form before ordinary joining. Enter the server-generated code there. The claim proves both the device key and account root key, atomically creates the first membership as owner, and permanently consumes the verifier. Restrict access to bootstrap logs. Before a successful claim, rotate a possibly exposed code with:
docker compose run --rm cords-server --config /opt/cords/server.toml ownership-bootstrap rotate
A populated legacy database without an owner is never assigned one implicitly; its operator must
run the same command with initialize instead of rotate. See the operator guide
for backup and migration details.
Run the desktop client
Install Rust 1.97.1, Qt 6.10.3, CMake, Python 3 and the native C++ toolchain. The platform build scripts build/test/package the new UI. For example on Linux:
export CORDS_QT_PREFIX="$HOME/Qt/6.10.3/gcc_64"
bash build-scripts/linux-client-tar.sh
# Extract dist/cords-client-linux-<arch>-<version>.tar.gz, then run bin/Cords.
The packaged desktop client also accepts --list-accounts and
--account <account-ID> --password-stdin. Listing returns only picker-safe labels
and IDs; hidden nicknames stay hidden. Unlocking verifies the existing vault
password and retains normal account isolation and auto-lock behavior. With no
arguments, startup still opens the account picker. A failed unlock exits nonzero.
Passwords are read from the first UTF-8 line of redirected stdin (maximum 4096 bytes). Do not put passwords in argv, environment variables, shell history or files. For example, a Python parent can prompt without echo and supply the pipe:
import getpass
import subprocess
client = r"C:\path\to\Cords.exe" # Use the installed executable on other platforms.
accounts = subprocess.run([client, "--list-accounts"], check=True, capture_output=True, text=True)
print(accounts.stdout)
account_id = input("Account ID: ")
password = getpass.getpass("Vault password: ")
process = subprocess.Popen([client, "--account", account_id, "--password-stdin"], stdin=subprocess.PIPE)
process.communicate((password + "\n").encode("utf-8"))
raise SystemExit(process.returncode)
The example waits until the desktop window closes. Python is only an example
pipe provider, not a client dependency. A password manager or another parent
process can provide the same redirected input. Native password buffers are
zeroized after verification; the caller remains responsible for its own memory.
Existing CORDS_CLIENT_STATE, CORDS_CLIENT_MIGRATIONS and CORDS_CLIENT_CA
overrides select the vault/resources and certificate trust as before. Windows
GUI builds expose help/list/errors when stdout/stderr are redirected by the caller.
Checks
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-features
cargo deny check
# Desktop builders also run QML lint and CTest with the selected Qt SDK.
Releases and containers
The sole canonical repository is firebadnofire/cords on Forgejo. CI/release
definitions, package scripts, public signing pins and policies live in this monorepo.
Privileged publication is disabled while execution isolation, protected-tag
authorization and authenticated artifact provenance are validated. The current
release workflow is an activation stop, not a passing release gate.
The selected release targets remain Linux client/server, native macOS DMG/PKG/server,
native Windows builds and multi-architecture OCI images. A Qt/MSVC Linux cross-build
is not yet validated. The proposed external
executor verifies mandatory tests and exact authorized source identity before
GPG .asc file signing, Cosign signing in Forgejo/GHCR, and verified GitHub mirroring.
Publication credentials belong outside ordinary Actions secret scope. See the
implementation plan,
executor contract and
validation evidence. Existing release history is preserved.
The public GitHub container is pulled with:
docker pull ghcr.io/firebadnofire/cords
Local native and cross-platform release builders are documented in
build-scripts/README.md. They produce client and
server file artifacts under dist/, plus a locally loaded server container
image, without publishing anything.
Validation boundary
Unit tests and Compose readiness alone do not prove encrypted messaging. The real-server acceptance runner supplies that evidence. A native Qt build does not substitute for native interaction testing, and neither establishes cross-platform signing, a published release, or complete production identity UX.