Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
444 commits
Select commit Hold shift + click to select a range
d38e148
Add missing backend modules
jagerman Jul 31, 2026
8a064a1
Merge pull request #108 from jagerman/drop-redeemed-at-pfs
jagerman Aug 1, 2026
dfc7295
Rename payment provider rangeproof -> stf
jagerman Jul 31, 2026
6490571
Merge pull request #111 from jagerman/rename-rp-to-stf-pfs
jagerman Aug 1, 2026
1bab2fe
Validate blinded IDs before matching
Ap4sh Aug 1, 2026
6dc1f5e
Merge remote-tracking branch 'origin/dev' into pfs
jagerman Aug 1, 2026
77d93ac
Drop error_report from get_pro_status
jagerman Aug 3, 2026
2002fa2
decrypt_group_message: parse via bt_dict_consumer require/maybe helpers
jagerman Aug 3, 2026
971ab77
ci: backend: kwarg rename fix
jagerman Aug 3, 2026
4954f41
Merge pull request #113 from jagerman/drop-error-report-pfs
jagerman Aug 3, 2026
e4e0a69
Merge remote-tracking branch 'origin/dev' into pfs
jagerman Aug 3, 2026
3e9d7da
pro_backend: throw on parse errors instead of an error vector
jagerman Aug 5, 2026
8eca20d
user_profile: fetch a proof when entitled but holding none
jagerman Aug 5, 2026
2445b43
Merge pull request #115 from jagerman/this-is-not-c-pfs
jagerman Aug 5, 2026
975b564
Merge pull request #119 from jagerman/renewal-target-no-proof-fetch-pfs
jagerman Aug 6, 2026
e682e6b
pro_backend: fix macOS build of the C response holders
Bilb Aug 6, 2026
b03709d
xed25519: throw from the string overloads on bad input sizes
jagerman Aug 6, 2026
f11143b
Merge remote-tracking branch 'origin/dev' into pfs
jagerman Aug 6, 2026
65c0377
user_profile: add pro auto-renewing status (config key `A`)
jagerman Aug 6, 2026
17a85f1
Merge remote-tracking branch 'jagerman/pro-auto-renewing-config-pfs' …
jagerman Aug 12, 2026
0763aff
multi_encrypt: match padding entries to ciphertext size
Ap4sh Aug 12, 2026
db19773
Bump version to 2.0.0
jagerman Aug 12, 2026
0dda3b6
tests: clang-format fixup for 0763aff6
jagerman Aug 12, 2026
3699813
Re-resolve the right swarm after a 421
Aug 12, 2026
ec91a11
SnodePool: don't let an undersized refresh wipe a good cache
mpretty-cyro Aug 12, 2026
f8ffbd3
Formatting & stale comment fix
Aug 12, 2026
85483fe
user_profile: add the pro grace period, and distinguish an unset auto…
mpretty-cyro Aug 12, 2026
4003a13
json helpers: session::json, without the json_ prefix
jagerman Aug 12, 2026
3706900
json: require_binary, accepting hex or base64
jagerman Aug 12, 2026
f3a71d5
Merge remote-tracking branch 'origin/dev' into pfs
jagerman Aug 12, 2026
8fe8739
Fix SQLite linking, unused header, uncommitted sql tx
jagerman Aug 6, 2026
d63591f
core: add a send_dm() overload taking a Content protobuf
jagerman Aug 6, 2026
b98189e
core: add Globals::erase()
jagerman Aug 6, 2026
c58f06b
core: stop hijacking the pfs_keys_fetched callback to flush queued sends
jagerman Aug 6, 2026
8751621
core: advance the swarm sync cursor only after handling a batch
jagerman Aug 6, 2026
6bfa70c
core: log callback exceptions as errors, and contain them around the …
jagerman Aug 6, 2026
475cf39
core: let a layer above Core register its own migrations
jagerman Aug 6, 2026
2fe9c35
Make the migration registry generator reusable across directories
jagerman Aug 6, 2026
7293ea0
Add missing v2 message design docs
jagerman Aug 7, 2026
f3c9d13
util: add trim_trailing() and use it for padding removal
jagerman Aug 7, 2026
5320c1d
core: match the spec's device key indicator personalization
jagerman Aug 7, 2026
effd839
core: fix the device group payload nonce derivation
jagerman Aug 7, 2026
b6a67ca
core: pad device group payloads to hide the device count
jagerman Aug 7, 2026
fc3a21e
core: expose the database and option helpers to layers above Core
jagerman Aug 7, 2026
19f391f
client: add a conversation-level data model over Core
jagerman Aug 7, 2026
c4850f8
util: split count_trailing() out of trim_trailing()
jagerman Aug 7, 2026
3a07bd2
client: rework the schema onto surrogate keys and content hashes
jagerman Aug 7, 2026
641650d
client: decompose the conversation key and cache message counts
jagerman Aug 7, 2026
701f5cf
schema: order migrations by name rather than filename
jagerman Aug 7, 2026
37496b7
schema: build fresh databases from full_schema.sql
jagerman Aug 7, 2026
f0ecaee
schema: make full_schema.sql the only creation path
jagerman Aug 7, 2026
14db345
schema: check that every published schema still upgrades
jagerman Aug 7, 2026
0b44b85
client: note where message requests will intervene
jagerman Aug 7, 2026
16f76d5
core: let the application choose the account identity
jagerman Aug 7, 2026
46f4282
mnemonics: fix the seed phrase checksum
jagerman Aug 7, 2026
9b4b7ca
mnemonics: canonicalise input before matching words
jagerman Aug 8, 2026
e0946a1
core: expose the event loop, and say what the database may be used for
jagerman Aug 8, 2026
61f5a50
client: run all database work on the event loop
jagerman Aug 8, 2026
86887fd
session-deps: add utf8proc, qrcodegencpp
jagerman Aug 8, 2026
f4d16e3
session-sqlite: fix potential object copy deadlock
jagerman Aug 8, 2026
6a9f50c
Fix storage server signature for the default namespace
jagerman Aug 8, 2026
ee0132c
Reflow the poll logging clang-format would have
jagerman Aug 8, 2026
aa50ea9
File our own sent messages under the recipient, not ourselves
jagerman Aug 8, 2026
0ac496c
Report note-to-self rather than making callers derive it
jagerman Aug 8, 2026
93ff71f
Do not require an identity to read conversations
jagerman Aug 8, 2026
417a8ab
Store to the destination's swarm under the destination's pubkey
jagerman Aug 8, 2026
6033d77
formatting
jagerman Aug 8, 2026
b2892d5
Trace a DM from the UI to the wire
jagerman Aug 8, 2026
2ab021c
Tell the application what changed instead of making it ask
jagerman Aug 10, 2026
15696d7
One set of callbacks, given at construction
jagerman Aug 11, 2026
0b92a55
Send outgoing messages to our own swarm as well as the recipient's
jagerman Aug 11, 2026
31c4867
Stop describing Core as the whole data model
jagerman Aug 11, 2026
299126a
Cover opening a conversation before sending into it
jagerman Aug 11, 2026
08c371f
Log the message row id as it is assigned
jagerman Aug 12, 2026
dfd95d8
Give up on snodes session-router cannot reach, and close the tunnels …
jagerman Aug 12, 2026
7ed1992
Hold session-router tunnels as claims, and act on why one failed
jagerman Aug 12, 2026
c87565f
Run the live tests through session-router by default
jagerman Aug 12, 2026
70b4b99
Drop partial_min_interval; on_data coalescing is not this layer's job
jagerman Aug 13, 2026
8080d1f
Let a download url name the file server's session router endpoint
jagerman Aug 14, 2026
5ac3e7e
Share the send dispatch between message sends
jagerman Aug 14, 2026
761ba39
Attachment surface for outgoing messages, and headers named for what …
jagerman Aug 14, 2026
b698070
Send messages with attachments
jagerman Aug 14, 2026
dcfcf8f
Distinguish a send that cannot work from one that did not
jagerman Aug 14, 2026
5c7f8ba
Retry a failed send, resuming rather than restarting
jagerman Aug 14, 2026
55b743f
Cover the attachment send success path against testnet
jagerman Aug 14, 2026
4551b00
Note the blob view's lifetime where it is copied out
jagerman Aug 14, 2026
381571c
Name the attachment pointer for what it is
jagerman Aug 14, 2026
d4c5ec3
Require the whole file id to be the number
jagerman Aug 14, 2026
612ec44
Do not promise attachments upload one at a time
jagerman Aug 14, 2026
61b284e
Report an attachment as started, and let a send with attachments be a…
jagerman Aug 14, 2026
e9965ea
Move the blocking calls to a SyncClient, leaving Client asynchronous
jagerman Aug 14, 2026
d7a00f8
Deliver every handler through an application-supplied dispatcher
jagerman Aug 14, 2026
6af8c1a
Tell a caller when an asynchronous call fails, instead of logging and…
jagerman Aug 14, 2026
7cfb0ba
Rate limit handlers that report continuously
jagerman Aug 14, 2026
2e97656
Stub the network, not Core's own send path, in the client tests
jagerman Aug 14, 2026
03e7a17
Record the swarm hash of a message we sent
jagerman Aug 14, 2026
bed7c8b
Share the store-request test helpers
jagerman Aug 14, 2026
e61a9f7
Stub the network in the DM send tests, not Core's own send path
jagerman Aug 14, 2026
5426bc5
Delete send_to_swarm; Core's callbacks are Client's alone
jagerman Aug 14, 2026
03b3c3c
Drop the last references to send_to_swarm
jagerman Aug 14, 2026
9e55f01
Complete quic::Loop where client.hpp uses it
jagerman Aug 14, 2026
ddce7eb
Report a message's attachments, and send their real size
jagerman Aug 15, 2026
0d4724f
Infer an attachment's content type when the sender names none
jagerman Aug 15, 2026
32fa3c4
Say how an attachment is encrypted in the url that points at it
jagerman Aug 15, 2026
9694394
Decrypt legacy attachments
jagerman Aug 15, 2026
fcd3f6e
Receive attachments, and fetch them on request
jagerman Aug 15, 2026
15df4cc
Give messages an identifier, and drop the content hash
jagerman Aug 15, 2026
6542785
Reference messages by id, not by timestamp alone
jagerman Aug 15, 2026
fa73d64
Carry msgIds on receipts, spell out attIndex, drop KeyPair
jagerman Aug 15, 2026
8d72db4
Tell a sender we saved their attachment, unless asked not to
jagerman Aug 15, 2026
9817cf0
Test the attachment save path against a stubbed network
jagerman Aug 15, 2026
72cd694
Round-trip an attachment, and save a legacy one, without a network
jagerman Aug 17, 2026
45319ac
session_protocol: make the proof version a wire selector, not a store…
jagerman Aug 17, 2026
34aad73
session_protocol: degrade unknown-version proofs instead of dropping …
jagerman Aug 17, 2026
f447513
json: recognize scoped enums in require/maybe
jagerman Aug 17, 2026
94cb991
Pin the tunneled QUIC connection's MTU to 1200
jagerman Aug 17, 2026
39b2345
Record when an attachment was saved, at either end
jagerman Aug 17, 2026
c266aa1
Move a swarm request to the next member when a node is unreachable
jagerman Aug 17, 2026
33812a8
Test the swarm walk against a scripted router
jagerman Aug 17, 2026
96c35d8
Give the client schema somewhere to put the synced configs
jagerman Aug 18, 2026
e762889
Fetch, merge and keep the account's configs
jagerman Aug 18, 2026
f26abd0
Push the configs that have changed
jagerman Aug 18, 2026
6f578a3
Tell the application which configs a merge changed
jagerman Aug 19, 2026
75f2d48
Give a streaming upload more buffer to coast on
jagerman Aug 19, 2026
564da90
Cover the merge cases a seqno comparison could have missed
jagerman Aug 19, 2026
ea09ae2
Check what merging a config identical to our own costs
jagerman Aug 19, 2026
d4f62e0
Cover what a skipped seqno costs the device that catches up
jagerman Aug 19, 2026
efd399d
session_protocol: the pro proof has no version field at all
jagerman Aug 19, 2026
f5c228d
Reconcile UserProfile into the conversation model
jagerman Aug 19, 2026
5c26b3f
Reconcile every config at startup, not only on change
jagerman Aug 20, 2026
0871765
Allow config pushing to be switched off
jagerman Aug 20, 2026
c40448b
Give one-to-one conversations a delete-before
jagerman Aug 20, 2026
a2bf2fd
Say that an attachment path is informational, not owned
jagerman Aug 20, 2026
c039735
Project the Contacts config into the conversation model
jagerman Aug 20, 2026
ca265c4
Delete a contact removed on another device
jagerman Aug 20, 2026
fced660
Block, clear, delete: the four destructive operations
jagerman Aug 20, 2026
b5d0543
Message requests: a conversation nobody answered yet
jagerman Aug 20, 2026
b54ead2
Look contacts up rather than scanning for them
jagerman Aug 20, 2026
6bad326
Say when we are the ones waiting to be accepted
jagerman Aug 20, 2026
915a34a
Sync read state through ConvoInfoVolatile
jagerman Aug 20, 2026
14c6006
Drop an access specifier that introduced nothing
jagerman Aug 21, 2026
3e9fa17
Give a conversation a kind
jagerman Aug 21, 2026
d3a9ff0
Name a blocking call where it is made
jagerman Aug 21, 2026
2765251
Put a conversation's operations on the conversation
jagerman Aug 21, 2026
634873a
Move the tests onto the conversation API
jagerman Aug 21, 2026
3951474
Delete SyncClient
jagerman Aug 21, 2026
b1bebe0
Do not reach back into the conversation from a handler
jagerman Aug 21, 2026
e5a3d04
Do not claim they saved a file when we saved our own copy
jagerman Aug 21, 2026
9491326
Ask "is this me?" once
jagerman Aug 21, 2026
1a1151a
Stop a save from destroying two files it was not asked to touch
jagerman Aug 21, 2026
98190f7
Claim the scratch name by opening it, where the standard allows
jagerman Aug 21, 2026
9cdc9c6
Let an account say not to report its saves
jagerman Aug 21, 2026
a050738
Report the contact settings the config already carried
jagerman Aug 21, 2026
d7588af
Split test_client.cpp into tests/test_client/
jagerman Aug 21, 2026
fb80d26
Reconcile on the loop, not on the thread that built the Client
jagerman Aug 21, 2026
d9110b6
Delete a message without letting it come back
jagerman Aug 22, 2026
394f884
Show a message as it was on the wire
jagerman Aug 22, 2026
d300585
Derive the poll cursor from a history of hashes
jagerman Aug 22, 2026
9c8c352
Delete a message everywhere, and honour being asked to
jagerman Aug 22, 2026
2ff20e2
Expose our own name and the save-notification preference
jagerman Aug 22, 2026
ae2a5e1
Let an attachment be encrypted under a key we choose
jagerman Aug 22, 2026
aa20899
A disk cache for what we download
jagerman Aug 22, 2026
3638f93
Extract downloading-and-decrypting from saving
jagerman Aug 22, 2026
089df3d
Fetch a conversation's picture, through the cache
jagerman Aug 22, 2026
025907a
Leave the progress callback empty when nobody is watching
jagerman Aug 22, 2026
da591bf
Share the progress dispatch hop rather than writing it twice
jagerman Aug 22, 2026
fe10134
Decrypt a display picture from before the stream scheme
jagerman Aug 22, 2026
d9ff462
Choose the decryption in one place, and prove all three work
jagerman Aug 22, 2026
9f4e5e2
Record a sender's picture, and stop corrupting the key we publish
jagerman Aug 22, 2026
c1a594f
Merge pull request #131 from jagerman/proproofversion-scoped-enum-pfs
jagerman Aug 24, 2026
bcb6936
Say what an attachment size actually is
jagerman Aug 24, 2026
e211602
Fix spurious seqno increment when a merge adopts an incoming config
Aug 24, 2026
ed14944
tests: cover attachment file-encryption input validation
Ap4sh Aug 24, 2026
6190cca
Merge remote-tracking branch 'origin/dev' into pfs
jagerman Aug 24, 2026
e66af40
Stop verifying the legacy attachment digest
jagerman Aug 24, 2026
9e05166
Hold a sender to the attachment size they declared
jagerman Aug 24, 2026
ebe89db
Add the per-conversation auto-download column
jagerman Aug 24, 2026
7c11020
Do not require legacy padding to be zeroes
jagerman Aug 24, 2026
0831223
Notice a too-long stream attachment as it happens
jagerman Aug 24, 2026
0d23731
Report a transfer to whoever did not ask for it
jagerman Aug 24, 2026
0e1ebca
Index the attachment cache
jagerman Aug 24, 2026
f66eb5f
Let a conversation say what it fetches unasked
jagerman Aug 24, 2026
937dcfa
Gallery messages, whole-attachment reads, and one transfer per file
jagerman Aug 24, 2026
e09e0b8
Cover a save joining a fetch already under way
jagerman Aug 24, 2026
6fdfe20
Fetch on arrival what the conversation asked for
jagerman Aug 24, 2026
accc98a
Keep the cache under the limit it was given
jagerman Aug 24, 2026
115487a
Drop a profile picture the moment nobody points at it
jagerman Aug 24, 2026
8149d9d
Sweep the cache once against what the database says is in it
jagerman Aug 24, 2026
6ee227f
Fetch a picture through the same registry an attachment uses
jagerman Aug 24, 2026
805a010
Fetch a display picture when we learn its url
jagerman Aug 24, 2026
e111241
Say what sync() does not settle
jagerman Aug 24, 2026
d59a2e3
Give a new account a device group to be the only member of
jagerman Aug 31, 2026
b49a31d
Record what a message replies to, as the sender addressed it
jagerman Aug 31, 2026
07ecebb
Resolve a reply's target on every read
jagerman Aug 31, 2026
8feea72
Store the reference a quote carries
jagerman Aug 31, 2026
77b0205
Tell a display when a reply's target changes under it
jagerman Aug 31, 2026
6600a70
Carry the message a reply answers, one level down
jagerman Aug 31, 2026
131317c
Build an outgoing message's content in one place
jagerman Aug 31, 2026
df73df8
Send a reply, and say so on the wire
jagerman Aug 31, 2026
d394a54
Bump session-router to one that has what we link against
jagerman Aug 31, 2026
86fc1e7
Own the loop jobs rather than borrowing the loop's
jagerman Aug 31, 2026
2fae54b
fix: point the Pro access-not-found url at getsession.org/pro-recover
Bilb Aug 31, 2026
1dcea7a
file server: carry the port in download urls, and treat its pubkey as…
mpretty-cyro Aug 31, 2026
f7ef6e5
tests: pin that a valueless `d=` is not the stream-encryption fragment
mpretty-cyro Aug 31, 2026
8f569af
Merge remote-tracking branch 'origin/dev' into pfs
jagerman Aug 31, 2026
55e9afa
Construct the network in place
jagerman Sep 1, 2026
4ee353e
Give a kicked device a tombstone, not a key
jagerman Sep 1, 2026
a7d6f35
Name the protocol spec for what it covers
jagerman Sep 1, 2026
04da501
Describe removals in the device group
jagerman Sep 1, 2026
ba6bbbd
Fix a single-recipient device group being unreadable
jagerman Sep 1, 2026
3d0e764
Drop schema provenance comments naming files that do not exist
jagerman Sep 2, 2026
fba6291
Build the device group message the swarm gets
jagerman Sep 2, 2026
4ec5f24
Poll until the swarm has no more, and report an empty fetch
jagerman Sep 2, 2026
e19ebd5
Give session-cli a device type of its own
jagerman Sep 2, 2026
933c33d
Give a change handler its payload by value
Bilb Sep 8, 2026
24156d5
Hand a change handler its payload by rvalue reference
jagerman Sep 9, 2026
ac90169
Hand over the conversation id too, where it is handed over
jagerman Sep 9, 2026
5e72bb5
Update the live attachment test to the send_message struct
jagerman Sep 9, 2026
66a6aea
Run clang-format over the branch
Bilb Sep 7, 2026
5639878
More formatting
jagerman Sep 9, 2026
6bc8814
Fix system lib libutf8proc usage
jagerman Sep 4, 2026
0407ee1
Read a device's state before moving its info
jagerman Sep 4, 2026
ef68eae
Set the poll interval on the loop that owns the ticker
jagerman Sep 4, 2026
b84556c
Say what a Client's callbacks and off-thread reads actually do
jagerman Sep 4, 2026
3df4ae5
Describe a conversation's last message, not just its body
jagerman Sep 4, 2026
8432768
Rank device states so a merge can decide a transition
jagerman Sep 4, 2026
fc73e5a
Bind a variable-length IN list through the normal path
jagerman Sep 5, 2026
5c4af83
Name a preview's attachments rather than counting them
jagerman Sep 5, 2026
eeba023
Bump session-deps and session-router for the cross-build fixes
Bilb Sep 10, 2026
7e5874d
Merge pull request #146 from Bilb/chore/bump-deps-router
jagerman Sep 10, 2026
488fb3d
Add an optional IP-to-country lookup behind a cmake option
jagerman Sep 10, 2026
061d1b7
Rename the blocking-call tag from `wait` to `block`
jagerman Sep 10, 2026
c4d4fe3
Merge pull request #148 from jagerman/rename-wait-to-block
jagerman Sep 10, 2026
6597823
Merge pull request #147 from jagerman/ip-country
jagerman Sep 10, 2026
61f9529
Merge pfs into client
jagerman Sep 10, 2026
6aa2608
fix: android refund redirect is /refund-android
Bilb Sep 10, 2026
a8805d8
chore: run static ios first
Bilb Sep 10, 2026
83acc2f
Merge remote-tracking branch 'origin/dev' into client
jagerman Sep 10, 2026
3187875
Rename the blocking-call tag to `await`
jagerman Sep 10, 2026
b0a523f
Merge pull request #151 from jagerman/rename-block-to-await
jagerman Sep 10, 2026
bca23e3
Let a logger be taken back off
Bilb Sep 11, 2026
f07374b
Bump session-router to bump libquic to bump logging
jagerman Sep 11, 2026
9934ab8
Refuse a page size that is not a page
Bilb Sep 13, 2026
d4ff59c
Merge pull request #159 from Bilb/require-page
jagerman Sep 14, 2026
787fa42
Merge pull request #153 from Bilb/logger-handles
jagerman Sep 14, 2026
c77c1f8
Fix oxen-logging requirement
jagerman Sep 14, 2026
521be4a
Fix the testnet file server pubkey holding the X25519 form
jagerman Sep 15, 2026
1373aec
Validate the `p=` pubkey in a download url
jagerman Sep 15, 2026
7100e86
Check the pubkey in a session-router address is a pubkey
jagerman Sep 15, 2026
916e6c5
Merge pull request #167 from jagerman/fix/testnet-file-server-pubkey
jagerman Sep 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
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
26 changes: 25 additions & 1 deletion .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,16 @@ local windows_cross_pipeline(name,
}] else [])
);

local live_test_step(image, mode) = {
name: 'live tests (' + mode + ')',
image: image,
pull: 'always',
commands: apt_setup(image, default_test_deps) + [
'cd build',
'./tests/testLive --' + mode + ' --log-level warning --colour-mode ansi -d yes "[file]"',
],
};

// Live Pro-backend integration test: build testAll with the dev-server hook, stand up an ephemeral
// backend (throwaway postgres + flask, provider_dry_run) via tests/pro_backend/run-dev-backend.sh,
// and run the [pro_live] suite against it. The backend is a separate Python service, checked out at
Expand Down Expand Up @@ -409,6 +419,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'),
],
},

// Live Pro-backend integration tests (ephemeral backend + [pro_live]).
pro_backend_live_pipeline('Debian sid (Pro backend live)', docker_base + 'debian-sid'),

Expand All @@ -433,7 +457,7 @@ local static_build(name,
]),

// Macos builds:
mac_builder('macOS Intel (Release)', allow_test_fail=true/*the current intel mac has issues*/),
//mac_builder('macOS Intel (Release)', allow_test_fail=true/*the current intel mac has issues*/),
mac_builder('macOS Arm64 (Release)', arch='arm64'),
mac_builder('macOS Arm64 (Debug)', arch='arm64', build_type='Debug'),

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/build*/
/compile_commands.json
# Downloaded and generated by utils/update-ip-country-db.py, required by -DWITH_IP_GEOLOCATION=ON
/src/network/ip_country/data.cpp
/.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
83 changes: 83 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 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)
- `-DWITH_IP_GEOLOCATION=ON` — bundle the DB-IP IP-to-country database, +1.79MB (default OFF, in
which case `session::ip_country` lookups all report unknown). Requires running
`utils/update-ip-country-db.py` first: the generated table is not committed, and cmake fails with
instructions if it is missing.

## 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.
63 changes: 39 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if(CCACHE_PROGRAM)
endif()

project(libsession-util
VERSION 1.9.1
VERSION 2.0.0
DESCRIPTION "Session client utility library"
LANGUAGES ${LANGS})

Expand All @@ -28,6 +28,7 @@ set(LIBSESSION_LIBVERSION ${PROJECT_VERSION})
include(GNUInstallDirs)

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(SessionSchema)

# No in-source building
include(MacroEnsureOutOfSourceBuild)
Expand Down Expand Up @@ -58,11 +59,16 @@ 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)" ${BUILD_STATIC_DEPS})

if(STATIC_BUNDLE AND NOT BUILD_STATIC_DEPS)
message(FATAL_ERROR "STATIC_BUNDLE requires BUILD_STATIC_DEPS=ON (cannot build a static bundle when using shared/system libs)")
message(FATAL_ERROR "STATIC_BUNDLE requires BUILD_STATIC_DEPS to be enabled")
endif()

if(BUILD_SHARED_LIBS OR libsession_IS_TOPLEVEL_PROJECT)
Expand All @@ -79,16 +85,20 @@ else()
set(use_lto_default ON)
endif()

option(WARNINGS_AS_ERRORS "Treat all compiler warnings as errors" OFF)
option(WARN_UNUSED_PARAMETERS "Enabled unused parameter warnings" ON)
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})

option(USE_LTO "Use Link-Time Optimization" ${use_lto_default})

# Provide this as an option for now because GMP and Desktop are sometimes unhappy with each other.
option(ENABLE_NETWORKING "Build with networking functionality" ON)
option(ENABLE_NETWORKING_SROUTER "Build with session-router networking support (requires ENABLE_NETWORKING)" ON)
option(ENABLE_NETWORKING_SROUTER "Build with session-router networking support" ON)

# Off by default: it adds ~1.8MB of database to the binary, and a client that already ships its own
# geo data wants nothing to do with it. With it off the lookup API still exists and reports every
# address as unknown, so nothing needs an #ifdef.
option(WITH_IP_GEOLOCATION "Build with the bundled DB-IP IP-to-country database" OFF)

if(USE_LTO)
include(CheckIPOSupported)
Expand All @@ -107,6 +117,17 @@ if(IPO_ENABLED AND NOT DEFINED CMAKE_INTERPROCEDURAL_OPTIMIZATION)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
endif()

# USE_LTO is the single LTO knob. Two submodule-provided options default ON independently of it:
# SESSIONDEPS_LTO (session-deps, several copies sharing one cache variable) controls LTO for static
# dependency builds, and WITH_LTO (session-router's enable_lto.cmake) controls LTO for session-router's
# own targets. Leaving either ON in a non-LTO build breaks the link: LTO'd static archives can't be
# consumed by a non-LTO link -- clang in particular emits pure bitcode archives that a plain bfd link
# reports as "file format not recognized", or silently drops the members (undefined references). Force
# both to follow USE_LTO, seeding these shared cache variables before any submodule evaluates its own
# option() so there is exactly one LTO switch.
set(SESSIONDEPS_LTO ${USE_LTO} CACHE BOOL "Use LTO for static dependency builds, where supported" FORCE)
set(WITH_LTO ${USE_LTO} CACHE BOOL "enable lto on compile time" FORCE)

if(STATIC_LIBSTD)
add_link_options(-static-libstdc++)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES Clang)
Expand All @@ -122,30 +143,24 @@ include(AddStaticBundleLib)
# Always build PIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# For a static-deps build we build everything from source; don't let oxen-logging pick up system
# fmt/spdlog via find_package. Beyond the usual reasons to prefer our own versions, a system
# fmt/spdlog is built against libstdc++ and cannot be linked into a libc++ build (undefined
# std::__1 symbols), so force the bundled submodules which build with our toolchain.
if(BUILD_STATIC_DEPS)
set(OXEN_LOGGING_FORCE_SUBMODULES ON CACHE INTERNAL "")
endif()


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()
endif()
session_dep(nettle 3)
# Unicode normalisation and case folding for mnemonic input; see src/mnemonics/mnemonics.cpp.
session_dep(libutf8proc 2.5)

add_subdirectory(src)
add_subdirectory(proto)

if (BUILD_STATIC_DEPS)
include(StaticBuild)
endif()

if(STATIC_BUNDLE)

include(combine_archives)
Expand Down
Loading