liblogosdelivery is no longer consumed as a prebuilt Nix package; waku-bindings
compiles it from the Nim sources in its vendor submodule. The devShell drops the
prebuilt package and LOGOS_DELIVERY_LIB_DIR and instead supplies that build's
toolchain. CI checks out submodules recursively and caches the (slow, cold) Nim
build on the submodule commit; the toolchain-only jobs exclude every crate that
reaches the native lib, and format is scoped to workspace members so it never
rewrites the vendored generated sources.
Docs corrected along the way: the default transport is `file`, not
logos-delivery, and chat-cli no longer carries its own build.rs or a
logos_delivery transport module.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ai43sF2rymPFMG9iki9fwL
EmbeddedLogosDelivery now drives waku-bindings' LogosDeliveryCtx over the
reliable channels API (channel_create/channel_send + onChannelMessageReceived)
instead of the hand-written FFI, which is deleted (~1050 lines, including a
byte-identical duplicate build.rs). Each conversation maps to one SDS channel.
The node runs on a dedicated thread that is the sole caller of the ctx, with
DeliveryService methods handing it commands over a queue. Every ctx call is
blocking, and issuing one from libchat's inbound-draining thread — which
subscribes while processing a received frame — wedges, because the call is
made downstream of the node's own event dispatch. Serialising on one thread,
decoupled from the caller and the callback, is what the previous transport did
for the same reason, and it restores two-party delivery (join went from a
deterministic hang to reliable; a message sent in an established conversation
is received and displayed by the peer).
chat-cli derives the node's storage path from its data dir: SDS state is a
process-wide singleton keyed on that path, so two instances sharing it would
each read the other's causal history and drop messages as replays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ai43sF2rymPFMG9iki9fwL
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