atagen

macltok

public
Star0
Watch0
1fe480c16a3c6db3270dce9e11f0afe67ebc17fc
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: README.md

96fdf90aacd6atagen2026-09-08 08:24 UTC1
# macltok
96fdf90aacd6atagen2026-09-08 08:24 UTC2
96fdf90aacd6atagen2026-09-08 08:24 UTC3
`macltok` is a compact Rust application backend built above `matrix-sdk` and
96fdf90aacd6atagen2026-09-08 08:24 UTC4
`matrix-sdk-ui`. It aims to provide the stateful behavior needed by a useful
96fdf90aacd6atagen2026-09-08 08:24 UTC5
Matrix client without depending on a GUI toolkit or inventing another protocol
96fdf90aacd6atagen2026-09-08 08:24 UTC6
SDK.
96fdf90aacd6atagen2026-09-08 08:24 UTC7
96fdf90aacd6atagen2026-09-08 08:24 UTC8
The crate currently provides
96fdf90aacd6atagen2026-09-08 08:24 UTC9
96fdf90aacd6atagen2026-09-08 08:24 UTC10
- typed commands, owned UI-safe events and bounded per-client transport
96fdf90aacd6atagen2026-09-08 08:24 UTC11
- Sliding Sync with normalized connection and room-list state
96fdf90aacd6atagen2026-09-08 08:24 UTC12
- independently retained live room timelines and backwards pagination
96fdf90aacd6atagen2026-09-08 08:24 UTC13
- text, emote, reply, edit, redaction, reaction, receipt and typing operations
96fdf90aacd6atagen2026-09-08 08:24 UTC14
- raw encrypted or unencrypted media acquisition with configurable byte limits
96fdf90aacd6atagen2026-09-08 08:24 UTC15
- encryption state, recovery-key import and SAS verification
96fdf90aacd6atagen2026-09-08 08:24 UTC16
- password login and session restoration with caller-owned encrypted SQLite stores
96fdf90aacd6atagen2026-09-08 08:24 UTC17
96fdf90aacd6atagen2026-09-08 08:24 UTC18
Matrix room, event, user, device and transaction identifiers remain strongly
96fdf90aacd6atagen2026-09-08 08:24 UTC19
typed. A toolkit timeline identity covers local echoes without pretending they
96fdf90aacd6atagen2026-09-08 08:24 UTC20
already have remote event IDs.
96fdf90aacd6atagen2026-09-08 08:24 UTC21
96fdf90aacd6atagen2026-09-08 08:24 UTC22
## Consuming the engine
96fdf90aacd6atagen2026-09-08 08:24 UTC23
31ce2453c82fatagen2026-09-24 13:07 UTC24
spawn `Engine::run`, drain the `EventStream` from its own task, and talk to the
31ce2453c82fatagen2026-09-24 13:07 UTC25
engine through `ClientHandle`. every command answers once, awaited
31ce2453c82fatagen2026-09-24 13:07 UTC26
(`handle.send_message(..).await?`) or as a `Pending` you can await later or
31ce2453c82fatagen2026-09-24 13:07 UTC27
drop. a sent message answers when the sdk send queue has it, delivery shows up
31ce2453c82fatagen2026-09-24 13:07 UTC28
as the timeline item's send state. reads like `rooms`, `members` and `media`
31ce2453c82fatagen2026-09-24 13:07 UTC29
go straight to the sdk. the stream only carries state
31ce2453c82fatagen2026-09-24 13:07 UTC30
31ce2453c82fatagen2026-09-24 13:07 UTC31
start a timeline from `TimelineReset`, then apply `TimelineChanged` diffs with
31ce2453c82fatagen2026-09-24 13:07 UTC32
`TimelineDiff::try_apply`. when one doesn't fit, stop applying, call `resync`,
31ce2453c82fatagen2026-09-24 13:07 UTC33
and pick up from the next `TimelineReset`
96fdf90aacd6atagen2026-09-08 08:24 UTC34
96fdf90aacd6atagen2026-09-08 08:24 UTC35
With `sqlite`, persist the initial `Session::record()` separately from its
96fdf90aacd6atagen2026-09-08 08:24 UTC36
encrypted SQLite store. On `SessionTokensChanged`, obtain a new record from
96fdf90aacd6atagen2026-09-08 08:24 UTC37
`ClientHandle::session_record()` and replace the saved record atomically in
fa9114fcf75fatagen2026-09-24 12:51 UTC38
protected storage. Restore with the same store path and passphrase.
fa9114fcf75fatagen2026-09-24 12:51 UTC39
fa9114fcf75fatagen2026-09-24 12:51 UTC40
`LoggedOut` and `SessionAccessRejected` both stop the engine. after a logout or a
fa9114fcf75fatagen2026-09-24 12:51 UTC41
hard rejection the record and the store are dead, bin them. a soft logout wants
fa9114fcf75fatagen2026-09-24 12:51 UTC42
the store kept and a fresh login with `PasswordLogin::device_id` set to the old
fa9114fcf75fatagen2026-09-24 12:51 UTC43
device, or the e2ee keys go with it. a bare `Stopped` means keep everything. one
fa9114fcf75fatagen2026-09-24 12:51 UTC44
store directory per login, the sdk won't share a crypto store between devices.
fa9114fcf75fatagen2026-09-24 12:51 UTC45
The headless example is
96fdf90aacd6atagen2026-09-08 08:24 UTC46
login-only; it does not persist sessions across runs.
96fdf90aacd6atagen2026-09-08 08:24 UTC47
96fdf90aacd6atagen2026-09-08 08:24 UTC48
## Dependency policy
96fdf90aacd6atagen2026-09-08 08:24 UTC49
96fdf90aacd6atagen2026-09-08 08:24 UTC50
UI frameworks, image decoders, application-directory discovery and logging
96fdf90aacd6atagen2026-09-08 08:24 UTC51
subscribers do not belong in this crate. SQLite remains optional through the
96fdf90aacd6atagen2026-09-08 08:24 UTC52
`sqlite` and `bundled-sqlite` features. Media decoding belongs to the consumer.
96fdf90aacd6atagen2026-09-08 08:24 UTC53
96fdf90aacd6atagen2026-09-08 08:24 UTC54
## Verification
96fdf90aacd6atagen2026-09-08 08:24 UTC55
96fdf90aacd6atagen2026-09-08 08:24 UTC56
```sh
96fdf90aacd6atagen2026-09-08 08:24 UTC57
nix develop --command cargo fmt -- --check
96fdf90aacd6atagen2026-09-08 08:24 UTC58
nix develop --command cargo test --all-targets
96fdf90aacd6atagen2026-09-08 08:24 UTC59
nix develop --command cargo test --all-targets --features sqlite
96fdf90aacd6atagen2026-09-08 08:24 UTC60
nix develop --command cargo clippy --all-targets -- -D warnings
96fdf90aacd6atagen2026-09-08 08:24 UTC61
nix develop --command cargo clippy --all-targets --features sqlite -- -D warnings
96fdf90aacd6atagen2026-09-08 08:24 UTC62
nix flake check
96fdf90aacd6atagen2026-09-08 08:24 UTC63
```