Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
cc58678
Fix unpleasant string chopping
jagerman Feb 13, 2026
8dd64b4
Refactor internal dependencies to use session-deps
jagerman Mar 10, 2026
f831735
Drop libsodium-internal; add tweetnacl implementation for X->Ed
jagerman Mar 10, 2026
70d9463
API improvements for hashing, arrays, clearing, spans
jagerman Mar 10, 2026
2449c44
WIP - session db, PFS, device linking, etc.
jagerman Mar 10, 2026
9db1031
Add simdutf to session-deps
jagerman Mar 10, 2026
cb8499c
Various build fixes
jagerman Mar 11, 2026
3fdbd83
session-deps: session-router, libquic, and fix
jagerman Mar 11, 2026
90c95e4
Add devices message parsing
jagerman Mar 11, 2026
86f7c0b
Expose callbacks to components
jagerman Mar 11, 2026
8e92908
WIP: device linking
jagerman Mar 11, 2026
f91ac49
Add generic core message consumer
jagerman Mar 11, 2026
3983a21
formatting
jagerman Mar 11, 2026
edd15b6
Hash & type unification
jagerman Mar 12, 2026
1f8048c
Make hashing endian-safe; more blake2b_pers conversion
jagerman Mar 12, 2026
384666c
Use std::byte to avoid oxenc buggy overload
jagerman Mar 12, 2026
b265fde
array_ucNN -> ucNN, for test suite
jagerman Mar 12, 2026
559984d
Bake int_for_hashing into the hash helpers
jagerman Mar 12, 2026
5a07faf
Add emoji SAS support for link requests
jagerman Mar 12, 2026
851d90d
link request handling WIP
jagerman Mar 12, 2026
ac8b746
Merge link requests and devices into same namespace
jagerman Mar 13, 2026
e8c9576
Move device list to subkey of device group message
jagerman Mar 13, 2026
3c4bf00
WIP on device and account messages
jagerman Mar 16, 2026
2337208
Account key rotation tie-breaking
jagerman Mar 16, 2026
2bf96e9
bump session-deps for sqlite3mc namespacing patch
jagerman Mar 17, 2026
a416372
Add network to core + fixes
jagerman Mar 18, 2026
e201e59
devices: publish & distributed tracking
jagerman Mar 17, 2026
c410b92
Implement update_info
jagerman Mar 18, 2026
0e9ba19
Add a global adjustable system clock
jagerman Mar 18, 2026
6bbbf22
Add test helper friend class
jagerman Mar 19, 2026
68ad1c1
Add optional Core polling of device & account namespaces
jagerman Mar 19, 2026
5aa76f7
update session-deps
jagerman Mar 19, 2026
677cb2b
formatting & small code simplifications
jagerman Mar 19, 2026
d46ce27
add missing clock header
jagerman Mar 19, 2026
8acf6e9
Devices tests; various fixes
jagerman Mar 19, 2026
84d0d07
add missing files
jagerman Mar 19, 2026
b6bd345
fix merge conflict
jagerman Mar 19, 2026
89cf0a7
Update session-deps
jagerman Mar 19, 2026
f749015
Add Electrum word lists
jagerman Mar 20, 2026
69217d2
Add ability to use a predefined seed
jagerman Mar 20, 2026
1542652
Seed word handling fixes and improvements
jagerman Mar 20, 2026
825941d
Add checksum support to seed words
jagerman Mar 20, 2026
ad17263
Mnemonics secure mem & integration with predefined_seed
jagerman Mar 21, 2026
85959c5
Make last_hash cache node-dependent
jagerman Mar 20, 2026
49721e3
Add PFS+PQ remote session id cache & prefetching
jagerman Mar 21, 2026
39ca6da
Add negative-ack caching to PFS+PQ pubkey prefetching
jagerman Mar 21, 2026
6394a31
improve ScopedClockOffset variable names
jagerman Mar 21, 2026
c8b07bc
Add callback + status returns for remote PFS key prefetch
jagerman Mar 23, 2026
a304532
Switch to SHAKE256; improve SHAKE256 API
jagerman Mar 24, 2026
3278568
Add SHA3-256 hasher
jagerman Mar 24, 2026
7e82f4e
Abstract 32-or-64 seed input
jagerman Mar 24, 2026
395cf65
bump session-router
jagerman Mar 24, 2026
44ee036
Refactor: compile-time safe Ed25519 privkey args
jagerman Mar 24, 2026
8824b1e
Add live (testnet) network test script
jagerman Mar 25, 2026
a66684d
Add PFS + PQ encryption and decryption implementations
jagerman Mar 24, 2026
21db80b
Improve test db naming to avoid parallel invocation overlap
jagerman Mar 25, 2026
791bd94
Cache long-term x25519 private scalar alongside the seed
jagerman Mar 25, 2026
28b146a
Fix test suite
jagerman Mar 25, 2026
3f710cd
Refactor to use fixed-extent spans for fixed-size quantities
jagerman Mar 26, 2026
bb55fa9
uint8_t -> unsigned char for byte values
jagerman Mar 26, 2026
b41cc79
Add DM v1+v2 parsing and polling support
jagerman Mar 26, 2026
efe62b1
formatting
jagerman Mar 26, 2026
523fec7
Split up big nested functions
jagerman Mar 26, 2026
2a03826
session_protocol: Replace destination-dispatch pattern with typed enc…
jagerman Mar 26, 2026
12ec37e
Use hash::blake2b in more places
jagerman Mar 27, 2026
70a5c55
unsigned char -> std::byte refactor, part 1
jagerman Mar 27, 2026
18559f9
Add fallback "no-PFS" support
jagerman Mar 27, 2026
590b0d6
Replace snprintf_clamped with fmt-based helpers
jagerman Mar 28, 2026
7eee001
Add "v2" DM construction via Core
jagerman Apr 1, 2026
fd5bf57
QUIC file server over session-router support
jagerman Mar 31, 2026
914e27a
Add a streaming decryptor; tweak encrypt keygen
jagerman Mar 31, 2026
5518fc2
Make quic file uploader use streaming encryption
jagerman Apr 1, 2026
b3cbf69
update session-router/libquic to fix send_fin bug
jagerman Apr 1, 2026
ba100b2
Add -Werror=missing-declarations; fix issues it caught.
jagerman Apr 8, 2026
8ebfde3
QUIC file transfer improvements: progress, ready-gating; MTU config
jagerman Apr 8, 2026
01d7e74
unsigned char -> std::byte refactor, part 2: b32
jagerman Mar 27, 2026
58c821e
unsigned char -> std::byte refactor, part 3: crypto API reorganization
jagerman Apr 8, 2026
dd0b5bd
Merge conflicts
jagerman Apr 9, 2026
ffe66ea
Add generic fmt::formatter for std::byte spans
jagerman Apr 9, 2026
65c2958
std::byte refactor: cleanup, formatting, and API improvements
jagerman Apr 10, 2026
950feaf
std::byte refactor: final reformatting
jagerman Apr 10, 2026
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
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Cpp11BracedListStyle: 'true'
KeepEmptyLinesAtTheStartOfBlocks: 'true'
NamespaceIndentation: Inner
CompactNamespaces: 'true'
PenaltyBreakString: '3'
PenaltyBreakString: '1000'
SpaceBeforeParens: ControlStatements
SpacesInAngles: 'false'
SpacesInContainerLiterals: 'false'
Expand Down
29 changes: 29 additions & 0 deletions .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,21 @@ local windows_cross_pipeline(name,
}] else [])
);

local live_test_step(image, mode) = {
name: 'live tests (' + mode + ')',
image: image,
pull: 'always',
commands:
[apt_get_quiet + ' install -y eatmydata'] +
add_stf_repo(image) + [
'eatmydata ' + apt_get_quiet + ' update',
'eatmydata ' + apt_get_quiet + ' dist-upgrade -y',
'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y ' + std.join(' ', default_test_deps),
'cd build',
'./tests/testLive --' + mode + ' --log-level warning --colour-mode ansi -d yes "[file]"',
],
};

local clang(version) = debian_build(
'Debian sid/clang-' + version,
docker_base + 'debian-sid-clang',
Expand Down Expand Up @@ -351,6 +366,20 @@ local static_build(name,

// Various debian builds
debian_build('Debian sid', docker_base + 'debian-sid'),

// Debian sid with session-router + live file transfer tests
local live_image = docker_base + 'debian-sid';
debian_build(
'Debian sid (live tests)',
live_image,
cmake_extra='-DENABLE_NETWORKING=ON -DENABLE_NETWORKING_SROUTER=ON -DBUILD_LIVE_TESTS=ON',
) + {
steps: super.steps + [
live_test_step(live_image, 'onionreq'),
live_test_step(live_image, 'srouter'),
live_test_step(live_image, 'direct'),
],
},
debian_build('Debian sid/Debug', docker_base + 'debian-sid', build_type='Debug'),
debian_build('Debian testing', docker_base + 'debian-testing'),
clang(19),
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/build*/
/compile_commands.json
/.cache/
/.claude/
/.vscode/
.DS_STORE
15 changes: 6 additions & 9 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
[submodule "external/libsodium-internal"]
path = external/libsodium-internal
url = https://github.com/session-foundation/libsodium-internal.git
[submodule "tests/Catch2"]
path = tests/Catch2
url = https://github.com/catchorg/Catch2
[submodule "external/ios-cmake"]
path = external/ios-cmake
url = https://github.com/leetal/ios-cmake
[submodule "external/zstd"]
path = external/zstd
url = https://github.com/facebook/zstd.git
[submodule "external/protobuf"]
path = external/protobuf
url = https://github.com/protocolbuffers/protobuf.git
[submodule "external/session-router"]
path = external/session-router
url = https://github.com/session-foundation/session-router.git
[submodule "external/simdutf"]
path = external/simdutf
url = https://github.com/simdutf/simdutf.git
[submodule "external/session-sqlite"]
path = external/session-sqlite
url = https://github.com/session-foundation/session-sqlite.git
[submodule "external/date"]
path = external/date
url = https://github.com/HowardHinnant/date.git
[submodule "cmake/session-deps"]
path = cmake/session-deps
url = https://github.com/session-foundation/session-deps.git
79 changes: 79 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build Commands

```bash
# Configure (out-of-source build required)
cmake -G Ninja -S . -B build-claude

# Build
cmake --build build-claude --parallel --verbose

# Run tests
./build-claude/tests/testAll [test-tag-or-name]

# Regenerate protobuf files
cmake --build build-claude --target regen-protobuf --parallel
```

### Notable CMake Options

- `-DBUILD_STATIC_DEPS=ON` — force all deps to build statically (no system libs)
- `-DENABLE_ONIONREQ=ON/OFF` — include onion request / network functionality (default ON)
- `-DWARNINGS_AS_ERRORS=ON` — treat warnings as errors
- `-DSUBMODULE_CHECK=OFF` — skip submodule freshness checks (useful during dev)

## Architecture Overview

This is **libsession-util**, the C++20 utility library for Session clients. It provides:

1. **Cryptographic primitives** (`libsession::crypto`) — Ed25519/X25519 keys, blinding, hashing, encryption (session protocol, multi-encrypt, attachments), XEd25519 signatures.

2. **Config sync system** (`libsession::config`) — CRDT-style distributed config that syncs across Session devices via swarm storage. Each config type has a namespace:
- `UserProfile`, `Contacts`, `ConvoInfoVolatile`, `UserGroups` — per-user configs
- `GroupKeys`, `GroupInfo`, `GroupMembers` — shared group configs (closed groups)
- `Local` — device-local config (never pushed to swarm)
- Config messages use bt-encoding (bencode), seqno-based CRDT merge with deterministic tie-breaking. See `docs/api/docs/config_merge_logic.md` for protocol details.

3. **Core** (`libsession::core`) — Persistent client state backed by SQLite. The `Core` class owns `CoreComponent`-derived members (`Globals`, `Devices`, `Pro`) that share a connection pool. Migrations live in `src/core/schema/` as `NNN_name.sql` or `NNN_name.cpp` files.

4. **Onion requests** (`libsession::onionreq`, optional) — Builder/parser for onion-routed requests to the Session network.

### Library Targets and Dependencies

```
util ← file, logging, util (uses zstd, simdutf)
crypto ← util + libsodium (blinding, ed25519, session_encrypt, etc.)
config ← crypto + libsodium + protos (all config types)
core ← crypto + SQLite + mlkem768 (PQC key encapsulation)
onionreq ← crypto + quic + nettle (optional)
```

All targets are aliased as `libsession::util`, `libsession::crypto`, etc.

### Header Layout

Public headers are in `include/session/`:
- `include/session/config/` — config type headers (`.h` = C API, `.hpp` = C++ API)
- `include/session/config/groups/` — closed group configs (keys, info, members)
- `include/session/core/` — Core persistent state components
- `include/session/onionreq/` — onion request types

### Dependency System

Dependencies are managed via `cmake/session-deps/` which provides `session_dep()` and `session_dep_or_submodule()` macros. These first try system libraries; if not found they fall back to static builds. External submodules live in `external/` (oxen-logging, nlohmann-json, ios-cmake, protobuf, oxen-libquic).

### Tests

Tests use Catch2. Most tests are compiled into `testAll`; logging tests are isolated in `testLogging` because they modify global sink/level state. Filter tests with Catch2 tag syntax, e.g. `./Build/tests/testAll "[config]"`.

### Dual C/C++ API

Many headers come in pairs: `foo.h` (C API for FFI use) and `foo.hpp` (C++ API). The C API generally is a wrapper around the primary C++ API. When adding new public functionality, consider whether a C API is needed.

## Code Style

- **Prefer DRY code**: when logic is duplicated across two or more call sites, extract a shared helper. Do this proactively when writing new code, not only when asked.
- **Specify the shape upfront**: when asked to implement something that overlaps with existing code, identify and extract the shared piece before writing the new code, so duplication never appears in the first place.
28 changes: 12 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,18 @@ else()
set(static_default ON)
endif()

option(BUILD_STATIC_DEPS "Build all dependencies statically rather than trying to link to them on the system" ${static_default})
# Override the default OFF value set in cmake/session-deps/Deps.cmake so that BUILD_STATIC_DEPS
# defaults to the same value as BUILD_SHARED_LIBS (i.e. static by default).
set(BUILD_STATIC_DEPS ${static_default} CACHE BOOL "Build all dependencies statically rather than trying to link to them on the system")

include(cmake/session-deps/Deps.cmake)

option(STATIC_BUNDLE "Build a single static .a containing everything (both code and dependencies)" ${static_default})

if(STATIC_BUNDLE AND NOT BUILD_STATIC_DEPS)
message(FATAL_ERROR "STATIC_BUNDLE requires BUILD_STATIC_DEPS to be enabled")
endif()

if(BUILD_SHARED_LIBS OR libsession_IS_TOPLEVEL_PROJECT)
set(install_default ON)
else()
Expand All @@ -76,6 +85,7 @@ else()
endif()

option(WARNINGS_AS_ERRORS "Treat all compiler warnings as errors" OFF)
option(FATAL_MISSING_DECLARATIONS "Developer/CI option: fatal error on non-static definitions without prior declarations (-Werror=missing-declarations)" OFF)

option(STATIC_LIBSTD "Statically link libstdc++/libgcc" ${default_static_libstd})

Expand Down Expand Up @@ -121,26 +131,12 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(external)

if(ENABLE_NETWORKING)
if(NOT TARGET nettle::nettle)
if(BUILD_STATIC_DEPS)
message(FATAL_ERROR "Internal error: nettle::nettle target (expected via libquic BUILD_STATIC_DEPS) not found")
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(NETTLE REQUIRED IMPORTED_TARGET nettle)
add_library(nettle INTERFACE)
target_link_libraries(nettle INTERFACE PkgConfig::NETTLE)
add_library(nettle::nettle ALIAS nettle)
endif()
endif()
session_dep(nettle 3)
endif()

add_subdirectory(src)
add_subdirectory(proto)

if (BUILD_STATIC_DEPS)
include(StaticBuild)
endif()

if(STATIC_BUNDLE)

include(combine_archives)
Expand Down
Loading