Growing a group to a realistic size by hand needs that many clients running at once, and chat-cli cannot simply be backgrounded: it has no headless mode, crossterm opens /dev/tty when stdin is not a terminal, and an instance without one exits at launch. The account address is only reachable through the TUI as well, since nothing logs it and the data dir keeps chats alone.
So each peer gets its own pty, is asked for its address once its delivery node reports in, and is held open until the script is interrupted.
* feat: publish key bundles and accounts via logos delivery
* chore: clear format
* feat: use protobuf for registry
* chore: update chat proto rev
* feat: merge http registry into logos delivery
* chore: renaming chat store for contact registry
PrivateV1 was the legacy prekey-handshake 1:1 protocol, superseded by
DirectV1 over InboxV2. Remove it and everything that existed only to
serve it.
- Delete PrivateV1Convo and its v1 inbox bootstrap: the Inbox,
Introduction, and InboxHandshake types, plus the support code only they
used (the crate::crypto module, EncryptionError, timestamp_millis, the
PrivateV1Domain HKDF domain, and the ServiceContext test doubles).
- Drop the public entry points that exposed it: Core::create_intro_bundle,
create_private_convo_v1, dispatch_to_inbox, and the matching
ChatClient::create_intro_bundle / create_conversation.
- Remove ConversationKind::PrivateV1 and its "private_v1" mapping, the
from_kind arm, and the orphaned inbox-v1 proto re-exports.
- Migrate the chat-cli /intro and /connect commands and the
message-exchange example to create_direct_conversation.
- Delete the PrivateV1 integration test; move the sqlite conversation
roundtrip test to GroupV1.
InboxOutcome, PayloadOutcome::Inbox, and ConversationClass::Private stay:
InboxV2 (DirectV1 and GroupV1 invites) still produces them.
Follow-ups, out of scope here:
- logos-chat-module still calls create_intro_bundle / create_conversation
and needs a companion change.
- remote_convo_id and EphemeralKeyStore are now vestigial (only PrivateV1
used them); dropping them is a storage-schema change for a later PR.
* feat: separate embedded p2p delievery to its own crate
* feat: separate p2p config in its own crate
* chore: split embed module
* chore: refactor registry config
* feat: split logos chat crate
* chore: refactor
Core is no longer account-aware: the client resolves an account address
to signer ids via the account directory, and the signer's verifying-key
hex serves as registry key, inbox subscription, and Welcome routing
target end to end. The MLS credential stays the full id().
- GroupV2 reads the de-mls member id from the fetched key package and
maps it to the signer id the welcome is delivered to.
- All account machinery (directory trait, bundle codec, resolution)
moves out of core into logos-account; the RegistrationService
supertrait and Core::account_directory() are gone, and the client
holds its own directory handle.
- The account exposes functionality, never a signer: add_delegate_signer
does the lamport upsert and signs internally.
- Every client acts for an account (ChatClientBuilder::new(account)).
DelegateSigner is a pure keypair; the client composes the wire
credential from the signer and the account, so the association is
client state. addr() is the account address.
- resolve_device_ids fails fast (NotAnAccountKey / NoDeviceBundle /
Directory) instead of falling back to treating an unresolved address
as a signer id. LogosChatClient::open and chat-cli mint and publish a
dev account each launch.
- EphemeralRegistry keys key packages by hex pubkey like HttpRegistry.
Supersedes #155 (routing_id).
* chore: gate logos-delivery transport on cargo feature, not env-dependent cfg
* chore: fix clippy
* feat: logos chat client use logos delivery as default
* feat: account to device store
* feat: accout traits and codec
* feat: integrate accounts abstraction
* chore: clean docs and naming
* remove account public key from payload
* chore: fix clippy
* feat: lamport check before update account store
* chore: rebase to core
* chore: register account in new core
* chore: rebase changes and use account pub for index account store
* chore: move chat store outside of libchat
* chore: use account pub for registry
The client, not the app, now drives the transport; events are delivered
asynchronously, per ADR 0001.
- ChatClient owns Arc<Mutex<Core>> + a worker thread.
- The worker select!s over the inbound and shutdown channels; Drop joins it.
Outbound runs on the caller's thread.
- A single Transport (DeliveryService + inbound()) owns both directions of the
boundary, so the client takes one transport rather than a (delivery, inbound)
pair. InProcessDelivery::new, CDelivery, and chat-cli's transports implement it.
- FFI replaces client_receive with client_push_inbound + client_poll_events.
- chat-cli drains Receiver<Event>; inbound and event channels are both crossbeam.
- Corrects ADR 0001's inbound sequence to push — the worker parks on select!,
it never polls.
* feat: http server based key package registry
* chore: instructions on running the registration service
* chore: remove duplicate post param
* chore: revert out sourced account id for multi devices support
* feat: signature on account id and key packages
* chore: include http registry in contact registry module
* refactor: use device id for retrieve key package
* chore: use string for device id
* feat: server verification on the register
* chore: doc the smoke test
* chore: fix data folder non exist
* chore: use payload for register and retrieve
* chore: fix clippy
* chore(flake): accept extra system attr; add perl for openssl-sys build
forAllSystems calls the lambda with {system, pkgs}; strict
destructuring requires `..` to ignore the system attribute.
`pkgs.perl` is needed because openssl-sys is pulled vendored via
libsqlite3-sys / rusqlite / chat-sqlite, and its `perl Configure`
step needs FindBin.pm, which Fedora's system perl doesn't ship.
* feat: introduce client event system
- Core processing yields a `PayloadOutcome` enum — `Empty`, `Convo`, or
`Inbox`. `ConvoOutcome` carries a conversation id and an optional
decrypted `Content`; `InboxOutcome` adds a `NewConversation`
(id + `ConversationClass`) for a peer-initiated conversation.
- Client translates `PayloadOutcome` into app-facing `Vec<Event>`
(`ConversationStarted`, `MessageReceived`) at the boundary, so the
application loop sees discrete events rather than core types.
- MLS group welcomes produce a `ConversationStarted` event with no
initial content, fixing the silent-group-join case where the inbox
layer dropped the observation.
- C FFI exposes an `EventList` opaque type with indexed accessors and
an `Invalid` sentinel for out-of-bounds / non-applicable reads.
- Symmetric `Inbox` / `InboxV2` handlers: both return
`Result<InboxOutcome, _>` and own the persistence + ephemeral-key
cleanup for the conversations they create.
- Updated and simplified `docs/adr/0001-client-event-system.md`.
* chore(flake): bump nixpkgs to nixos-unstable-small
Temporary. The two crates.io UA fixes (NixOS/nixpkgs#512735 for
fetchCargoVendor's python-requests UA, NixOS/nixpkgs#524985 for
importCargoLock's curl UA) haven't propagated to nixos-unstable yet.
Switch to nixos-unstable-small and force logos-delivery to follow so
the smoketest gets the same fix. Revert once nixos-unstable catches up.
Refs:
- https://github.com/rust-lang/crates.io/issues/13482
- https://github.com/rust-lang/crates.io/issues/13783
- https://crates.io/data-access
Both file and logos-delivery transports are now compiled into a single
binary and selected at runtime (default: logos-delivery), replacing the
env-var-driven build-time cfg.
Replace the direct use of `conversations::Context` with `client::ChatClient`,
which is the intended public API for library consumers.
Remove `MessageEnvelope` and the username-keyed session model. The envelope
was never part of the wire protocol — sender identity was only tracked in the
CLI's local state. Chats are now keyed by conversation ID; add `/nickname` as
the user-facing replacement for named sessions.
Add a logos-delivery (Waku) transport alongside the existing file transport.
The active transport is selected at compile time: set `LOGOS_DELIVERY_LIB_DIR`
to link liblogosdelivery, otherwise the file transport is used.
Add logos-delivery as a Nix flake input and expose `.#logos-delivery` so the
library can be built with `nix build` and referenced by `LOGOS_DELIVERY_LIB_DIR`.
CI: rename `c-ffi-smoketest` to `smoketest`; add logos-delivery build step
and a `--smoketest` invocation of chat-cli to verify startup.
* chore: remove ffi from double ratchet
* chore: format
* feat: chat cli demo app via file transport
* chore: fix the compile issues
* chore: fix long intro copy to clipboard
* chore: move chat cli to bin folder
* chore: use tmp data folder
* chore: update doc
* chore: use encrypted db with default db pass
* chore: fmt and clippy
* chore: fix clippy and refactor
* chore: utils for helper funcs
* chore: rename sessions to chats