Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 25 additions & 12 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,34 @@ jobs:
with:
backend: RAPT

# The cross-signing APIs are development releases published to drat.
# Install them before install_deps checks the hard mx.api floor. rapt
# otherwise selects an older r2u binary by name, ignoring that floor.
- name: Install Matrix development dependencies
run: |
Rscript -e 'install.packages(c("curl", "jsonlite"))'
Rscript -e '
if (isTRUE(getOption("rapt.enabled"))) rapt::disable()
floors <- c("mx.api" = "0.3.0.2", "mx.crypto" = "0.2.1.1")
utils::install.packages(names(floors),
repos = "https://cornball-ai.github.io/drat",
type = "source", dependencies = FALSE)
for (p in names(floors)) {
if (!requireNamespace(p, quietly = TRUE) ||
utils::packageVersion(p) < floors[[p]])
stop("CI needs ", p, " >= ", floors[[p]],
"; publish the upstream development release to drat first")
message(p, " ", utils::packageVersion(p))
}'

- name: Dependencies
run: ./run.sh install_deps

- name: Install suggested packages
# install_deps covers Imports only. Without mx.crypto every E2EE
# test calls exit_file() and CI goes green having exercised none of
# the encryption path -- which is how unverified homeserver keys
# shipped in the first place. simplermarkdown is needed for R CMD
# check to treat vignettes/e2ee.md as a vignette rather than a
# stray file.
#
# Both arrive as binaries (r2u on Linux, CRAN on macOS), so no Rust
# toolchain is needed despite mx.crypto being a Rust package. The
# runners ship rustc anyway if a source build is ever forced.
run: Rscript -e 'install.packages(c("mx.crypto", "simplermarkdown"))'
# mx.crypto above builds from its vendored Rust sources using the
# hosted runner's Rust toolchain. simplermarkdown is still needed for
# R CMD check to recognize vignettes/e2ee.md as a vignette.
- name: Install vignette builder
run: Rscript -e 'install.packages("simplermarkdown")'

- name: Test
run: ./run.sh run_tests
8 changes: 4 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: mx.client
Type: Package
Title: Stateful Matrix Client Helpers
Version: 0.2.0.7
Date: 2026-08-20
Version: 0.2.0.8
Date: 2026-09-04
Authors@R: c(
person("Troy", "Hernandez", role = c("aut", "cre"),
email = "troy@cornball.ai",
Expand All @@ -22,12 +22,12 @@ Depends:
R (>= 4.0)
Imports:
jsonlite,
mx.api (>= 0.3.0),
mx.api (>= 0.3.0.2),
stats,
tools,
utils
Suggests:
mx.crypto (>= 0.2.0),
mx.crypto (>= 0.2.1.1),
simplermarkdown,
tinytest
VignetteBuilder: simplermarkdown
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ export(mx_client_session)
export(mx_crypto_account)
export(mx_crypto_account_save)
export(mx_crypto_claim_otks)
export(mx_crypto_cross_signing_bootstrap)
export(mx_crypto_cross_signing_load)
export(mx_crypto_decrypt_event)
export(mx_crypto_device_keys)
export(mx_crypto_encrypt_event)
export(mx_crypto_encrypt_for_devices)
export(mx_crypto_handle_to_device)
export(mx_crypto_inbound_session)
export(mx_crypto_known_devices)
export(mx_crypto_mark_key_requests_sent)
export(mx_crypto_process_sync)
export(mx_crypto_publish_keys)
export(mx_crypto_room_key_payload)
export(mx_crypto_send_key_requests)
export(mx_crypto_sessions_load)
export(mx_crypto_sessions_new)
export(mx_crypto_sessions_save)
Expand Down
36 changes: 36 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
# mx.client 0.2.0.8

## New

* Missing Megolm sessions now create persistent `m.room_key_request`
messages, deduplicate repeated requests, accept requested
`m.forwarded_room_key` only from this user's cross-signed devices, and
emit request cancellations after recovery.

* `mx_crypto_cross_signing_bootstrap()` creates and durably stores Matrix
master, self-signing, and user-signing keys; publishes them through UIA;
signs the master with the current device; and signs that device with the
self-signing key. Existing server identities are never reset implicitly.
* `mx_crypto_known_devices()` now reports `cross_signed` and `master_key`
after verifying the server-provided master -> self-signing -> device chain.
The client's own devices additionally require a matching local
`self_master_key` pin to be marked cross-signed.
* `mx_crypto_process_sync()` now returns decryptable encrypted echoes of the
client's own messages with `is_self = TRUE`, as it already does for
cleartext echoes. Consumers can use this flag to ignore their own messages.
* Sent but unanswered room-key requests remain stored until recovery;
automatic expiry/pruning is deferred to a follow-up.

## Fixes

* Unsatisfied room-key requests now persist an explicit transport state and
retry with the same request id until successfully sent.
* Outbound Megolm sessions retain a local inbound copy so the client's own
echoed messages decrypt without requesting their keys from itself.
* Requests originating from this same device are not surfaced to key-sharing
policy, and forwarded keys never mark the original room sender verified.
* Malformed peer cross-signatures are treated as invalid instead of aborting
verification of every device returned by `/keys/query`.
* Rerunning cross-signing bootstrap skips valid signatures already on the
server. New request ids use integer milliseconds and one random suffix.

# mx.client 0.2.0.7

## Fixes
Expand Down
Loading