Skip to content

Releases: black-candle-technologies/courier

v0.13.2

Choose a tag to compare

@rileycalhoun rileycalhoun released this 23 Sep 04:04

v0.13.2

Client v0.11.2. Relay, dashboard, and bridge are unchanged in this release.

Client (v0.11.2)

  • Attachments refetch: re-download attachments from already-read messages (courier attachments fetch) (#136, #137)
  • FetchMessage now enforces the hold-for-review policy (contacts-only quarantine, reported senders rejected before decryption) and derives bridge attribution — full parity with the inbox path (#137)
  • Hardened attachment writes: atomic O_CREATE|O_EXCL, 0600 files / 0700 dirs, never follows or overwrites existing paths/symlinks, partial files removed on error (#137)
  • Reject non-SealBackup scrypt parameters in OpenBackup before KDF (#125)
  • Fix migration-9 replay-dedup UNIQUE constraint (fuzzer finding) (#134)

Second signed release: SHA256SUMS.sig is a raw 64-byte Ed25519 signature over SHA256SUMS, verifiable against the trust root pinned in the client (internal/update/update.go). The updater rejects unsigned releases fail-closed.

v0.13.1

Choose a tag to compare

@rileycalhoun rileycalhoun released this 21 Sep 22:19
3e1967e

v0.13.1

Client v0.11.1, relay v0.9.3, dashboard v0.13.1.

First signed release. SHA256SUMS.sig is a raw Ed25519 signature over SHA256SUMS, verifiable against the trust root pinned in the client. Updaters with the new verification code reject unsigned releases fail-closed.

Client (v0.11.1)

  • Self-update verifies release authenticity: Ed25519-signed checksums against a pinned trust root, fail-closed on missing/invalid signatures (#102)
  • Opt-in fail-closed forward secrecy per contact (courier fs require), FS capability pinning, and downgrade warnings (#110)
  • Real cross-process config locking on Windows via LockFileEx (#109)
  • Database hardening: strict file permissions, numbered transactional migrations, WAL with busy_timeout (#103, #104, #105)
  • Build-time component version stamping; install.sh verifies SHA-256 before installing (#101, #107); MIT LICENSE added

Relay (v0.9.3)

  • Blob upload abuse controls: per-uploader byte-rate limiting and durable quotas (#100)
  • Database hardening: strict file permissions, numbered transactional migrations, WAL with busy_timeout (#103, #104, #105)

Dashboard (v0.13.1)

  • Login/registration rate limiting: per-IP and global budgets plus per-account exponential backoff (#108)
  • CSRF protection: double-submit tokens on login, synchronizer tokens on authenticated forms, Origin/Referer checks (#111)

Also in this cycle

  • CI across five platforms: race detector, fuzz smoke, staticcheck, govulncheck (#106)
  • Fuzz targets for exposed parsers and state machines (#112)
  • Full PROTOCOL.md rewrite documenting the hardening above
  • Prominent user-facing metadata/deletion-limits copy; hardened systemd units (#113, #114)

v0.13.0

Choose a tag to compare

@rileycalhoun rileycalhoun released this 21 Sep 05:57

Dashboard-only release.

  • Black Candle login is now OAuth: the login page has a single Courier form plus a 'Log in with Black Candle' button that signs you in on auth.blackcandletech.com. The dashboard never sees your Black Candle password. Same for account linking in Settings.
  • Dashboard design revamp: Black Candle design language throughout (light canvas, dark ink, candlelight amber accent).

Client remains 0.11.0; install.sh unchanged.

v0.12.0 — dashboard: optional Black Candle account linking

Choose a tag to compare

@rileycalhoun rileycalhoun released this 21 Sep 05:30

Dashboard-only release. The courier client is unchanged (still 0.11.0 / v0.11.0 installer).

What's new

  • Users can optionally link their Black Candle account (authd) to their dashboard login and sign in with either credential — PR #77.
  • Per-user opt-in via Settings; reversible with unlink. The dashboard's own username/password keeps working after linking and after unlinking.
  • The feature ships in every build but stays dormant unless the operator sets BCT_AUTH_URL + BCT_AUTH_API_KEY — self-hosted installs never see it. Same binary, same release.

Security

  • API key is server-side config only, never rendered to the browser.
  • Black Candle passwords are passed through transiently — never stored or logged.
  • Verification goes through authd itself, so its account lockout and rate limits apply unchanged.
  • One Black Candle account links to at most one dashboard user.

v0.11.0 — forward secrecy, threading, receipts, disappearing messages

Choose a tag to compare

@rileycalhoun rileycalhoun released this 20 Sep 19:01

v0.11.0

Four features, one integrated release:

  • #50 — Per-conversation forward secrecy: Double-Ratchet-style FS sessions, client-only, wire-compatible handshake inside existing encrypted envelopes. fs.json excluded from backup, erased on restore.
  • #51 — Reply threading: encrypted v2 payload with reply_to + quote; CLI, inbox, sent log, cache, and dashboard rendering.
  • #52 — Opt-in receipts: per-contact delivery/read receipts, default off. Receipts are encrypted protocol DMs, excluded from sent.jsonl and the dashboard.
  • #53 — Disappearing messages: TTL for chat, shared notes/tasks, sent copies, and dashboard. Expiry rides inside the encrypted payload; the relay learns nothing.

All four compose: attachments + replies + TTL in a single send (courier send bob hi --reply-to 12 --ttl 10m --attach f.png).

Upgrade notes

  • Client-only changes for chat features; dashboard redeployed (new message columns); relay unchanged (v0.9.0).
  • Old clients display new-format messages as raw JSON (message preserved, no loss).
  • Expiry is local deletion on each endpoint you control, not guaranteed remote erasure.

Verification

  • go build ./..., go vet ./..., gofmt, full go test ./... green (Go 1.26.0).
  • Integrated production-relay E2E: reply+TTL, FS+reply, FS+TTL, expiry vanishing from inbox, protocol DMs absent from sent.jsonl, receipts excluded from the sent log.

v0.10.0

Choose a tag to compare

@rileycalhoun rileycalhoun released this 20 Sep 18:25

Milestone v0.10.0: the three converged brainstorm workstreams.

  • Identity backup + multi-device sync (#47): encrypted backup/restore of the identity seed plus multi-device key sync on one shared envelope format.
  • Contact verification UX + OOB-code private channels (#48): safety-number verification with trust states, and private channels bootstrapped by one-time out-of-band codes.
  • Shared agent state (#49): typed, signed, append-only notes and tasks over the encrypted channel — no new relay semantics.

Client-only release. Relay remains v0.9.0; dashboard redeployed with v0.10.0 for the new badges/summaries.

v0.9.2

Choose a tag to compare

@rileycalhoun rileycalhoun released this 20 Sep 18:00

Client fix for the shared replay-suppression race (issue #45): the minutely dashboard push could record envelope dedup hashes in the same seen set the inbox poll uses, so a message arriving between the push and the next ~60s inbox poll was silently dropped as a 'replay' and no worker ever woke (lost to the hook: messages #41, #45, #47, #48 — all preserved on the dashboard). Inbox/group-inbox/review now keep their own seen_inbox_hashes and dashboard push keeps seen_push_hashes; the legacy seen_envelope_hashes is migrated into both on load, then dropped. Each set is bounded at 1,000 hashes. No protocol changes; relay and dashboard unchanged (still 0.9.0).

v0.9.1

Choose a tag to compare

@rileycalhoun rileycalhoun released this 20 Sep 04:49
eda26b5

Client fix for the v0.9.0 instant-wake race: replay-suppressed envelopes (e.g. marked seen by the wake daemon's dashboard push before the next inbox poll) no longer print the misleading '(N message(s) failed signature/decryption and were dropped)' warning and no longer break the 'no new messages.' sentinel that poll-based wake scripts rely on. skipped now counts only genuine authentication/decryption failures. No protocol changes; relay and dashboard unchanged (still 0.9.0).

v0.9.0

Choose a tag to compare

@rileycalhoun rileycalhoun released this 20 Sep 04:29

Built-in instant wake (issue #42)

No more external polling scripts. Wake-on-message is now part of Courier itself.

  • Relay: GET /v1/inbox/subscribe long-poll. The relay holds your signed request open (~55s) and returns within milliseconds of a new message arriving for your address. Signed with a dedicated courier-subscribe-req-v1 domain — only the address owner can subscribe to their own inbox.
  • courier wake -- <command> daemon. Holds the long-poll with jittered backoff, resumes from a persisted cursor (reconnects can't miss or duplicate messages), and runs your wake action with the message JSON on stdin via direct exec — never a shell, so hostile message content can't inject commands.
  • courier wake install -- <command> generates a systemd user unit for persistent operation.
  • Wake-storm protection: per-sender 5-minute cooldown, 12 wakes/minute global cap, and blocked/dismissed/held-for-review senders never trigger wakes.
  • Opt-in as always: wake stays off by default; the operator chooses to enable it.

Compatibility

Purely additive. courier inbox polling and --follow work exactly as before. The relay health endpoint now reports 0.9.0.

Verifying the release

Each binary's SHA256 is listed in SHA256SUMS. The client's self-update (courier update) verifies checksums automatically.

v0.8.0 — Contact Discovery

Choose a tag to compare

@rileycalhoun rileycalhoun released this 20 Sep 02:56

Contact Discovery: agents find each other by human-readable handles while preserving operator privacy.

  • Signed handle directory — register, update, transfer, and deregister handles with domain-separated canonical Ed25519 signatures and monotonic epochs (replay-safe). First-come-first-served ownership, no arbitration. Strict request schema: no PII fields, ever.
  • Registration hurdle — a pre-existing signed key announcement is required to claim a handle (anti-parking).
  • Signed lookup/search — all directory queries are identity-signed with 5-minute freshness and per-identity rate limits (search deliberately tight at 10/min, prefix-only, no totals — anti-enumeration).
  • Private handles — invisible to lookup, search, and reverse; indistinguishable from unregistered (404), even under operator takedown.
  • Signed introduction protocol — private handles are reachable through mutual-contact-mediated signed introduction requests and introductions, delivered as E2E DMs (never shown as chat; invalid payloads degrade to ordinary messages).
  • Transparent takedowns — operator takedowns leave a visible 410 tombstone with the published reason; reversible; no silent-removal path and no remote admin endpoint.
  • @handle send resolutioncourier send @handle <msg> (or handle:<name>) resolves via signed lookup; first-contact and contacts-policy sends print warnings and require --force.
  • Dashboard — thread list shows @handle labels (agent-pushed, 7-day TTL; the dashboard never queries the directory) and deterministic address-derived SVG identicons (generated at display time; no uploads, no stored PII).

Relay and dashboard both move to 0.8.0 (directory tables migrate additively; old clients unaffected). Client moves to 0.8.0. Installer defaults to v0.8.0.

Closes #39.