atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git

Blame: labs/setup-pattern.md

7ff8adafe9e4atagen2026-10-22 12:30 UTC1
# The setup pattern
7ff8adafe9e4atagen2026-10-22 12:30 UTC2
7ff8adafe9e4atagen2026-10-22 12:30 UTC3
One pattern that bot developers might find useful when using the Matrix Rust SDK
7ff8adafe9e4atagen2026-10-22 12:30 UTC4
is to use a "setup" pattern, which, simply put, consists of having a bot user
7ff8adafe9e4atagen2026-10-22 12:30 UTC5
bootstrap the bot through a dedicated `setup` (sub)command, and then run the
7ff8adafe9e4atagen2026-10-22 12:30 UTC6
main executable.
7ff8adafe9e4atagen2026-10-22 12:30 UTC7
7ff8adafe9e4atagen2026-10-22 12:30 UTC8
Then, together with that, create an invariant in the main executable: Always
7ff8adafe9e4atagen2026-10-22 12:30 UTC9
expect state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC10
7ff8adafe9e4atagen2026-10-22 12:30 UTC11
The latter can be done by checking if the path to a stored and serialized
7ff8adafe9e4atagen2026-10-22 12:30 UTC12
[`Session`](https://docs.rs/matrix-sdk/latest/matrix_sdk/struct.Session.html)
7ff8adafe9e4atagen2026-10-22 12:30 UTC13
configuration exists (as created during the `setup` command), and/or by checking
7ff8adafe9e4atagen2026-10-22 12:30 UTC14
for files under the path provided to
7ff8adafe9e4atagen2026-10-22 12:30 UTC15
[`make_store_config`](https://docs.rs/matrix-sdk/latest/matrix_sdk/store/fn.make_store_config.html).
7ff8adafe9e4atagen2026-10-22 12:30 UTC16
7ff8adafe9e4atagen2026-10-22 12:30 UTC17
If the main executable can't find this configuration, abort running.
7ff8adafe9e4atagen2026-10-22 12:30 UTC18
7ff8adafe9e4atagen2026-10-22 12:30 UTC19
## Context
7ff8adafe9e4atagen2026-10-22 12:30 UTC20
7ff8adafe9e4atagen2026-10-22 12:30 UTC21
The context of this pattern document, and the reason for the crystallization of
7ff8adafe9e4atagen2026-10-22 12:30 UTC22
this idea, is that currently the "modus operandi" of Instant Messaging bots is
7ff8adafe9e4atagen2026-10-22 12:30 UTC23
quite stateless. Bots might still have state pertaining to users, databases and
7ff8adafe9e4atagen2026-10-22 12:30 UTC24
whatnot that contain explicit state of business logic, but it's not expected
7ff8adafe9e4atagen2026-10-22 12:30 UTC25
that the _bot itself_ has state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC26
7ff8adafe9e4atagen2026-10-22 12:30 UTC27
This expectation becomes especially problematic when combined with E2EE, where
7ff8adafe9e4atagen2026-10-22 12:30 UTC28
the running application has to not lose sight of it, or else it'll lose access
7ff8adafe9e4atagen2026-10-22 12:30 UTC29
to E2EE (group) chats.
7ff8adafe9e4atagen2026-10-22 12:30 UTC30
7ff8adafe9e4atagen2026-10-22 12:30 UTC31
This expectation exists both on the developer and user side of bots, and so to
7ff8adafe9e4atagen2026-10-22 12:30 UTC32
start fixing it, this pattern is recommended to bot creators, as then the
7ff8adafe9e4atagen2026-10-22 12:30 UTC33
lifetime cycle of the bot (and its data) is clear to every party involved, and
7ff8adafe9e4atagen2026-10-22 12:30 UTC34
errors are not necessarily "fatal" (or catastrophic while confusing).
7ff8adafe9e4atagen2026-10-22 12:30 UTC35
7ff8adafe9e4atagen2026-10-22 12:30 UTC36
## Consequence
7ff8adafe9e4atagen2026-10-22 12:30 UTC37
7ff8adafe9e4atagen2026-10-22 12:30 UTC38
Some of the consequences of the above invariant (setup phase initializes state,
7ff8adafe9e4atagen2026-10-22 12:30 UTC39
run phase expects it initialized) are the following;
7ff8adafe9e4atagen2026-10-22 12:30 UTC40
7ff8adafe9e4atagen2026-10-22 12:30 UTC41
- If the bot starts, but cannot find a state directory, it'll abort without
7ff8adafe9e4atagen2026-10-22 12:30 UTC42
  implicitly creating one.
7ff8adafe9e4atagen2026-10-22 12:30 UTC43
- If the setup command is ran while state already exists, it would either abort
7ff8adafe9e4atagen2026-10-22 12:30 UTC44
  or offer modification (such as a different client URL) to the operator.
7ff8adafe9e4atagen2026-10-22 12:30 UTC45
- E2EE state cannot easily become wedged or confusingly absent inbetween bot
7ff8adafe9e4atagen2026-10-22 12:30 UTC46
  runs, as the run phase will not run (and alter E2EE server state, such as
7ff8adafe9e4atagen2026-10-22 12:30 UTC47
  device keys) unless it can find the existing E2EE state, which should already
7ff8adafe9e4atagen2026-10-22 12:30 UTC48
  be initialized.
7ff8adafe9e4atagen2026-10-22 12:30 UTC49
  - This prevents problems where a bot will try to re-create a device after it
7ff8adafe9e4atagen2026-10-22 12:30 UTC50
    lost its state, and the new device/login is not verified and thus not
7ff8adafe9e4atagen2026-10-22 12:30 UTC51
    trusted in E2EE rooms, which is hard to debug.
7ff8adafe9e4atagen2026-10-22 12:30 UTC52
  - Instead, the bot will refuse to run at all, preventing it digging itself a
7ff8adafe9e4atagen2026-10-22 12:30 UTC53
    deeper ditch, letting the operator be notified something is wrong, and
7ff8adafe9e4atagen2026-10-22 12:30 UTC54
    either restore the state, or recover it.
7ff8adafe9e4atagen2026-10-22 12:30 UTC55
- During the setup phase, while the operator is actively interacting with the
7ff8adafe9e4atagen2026-10-22 12:30 UTC56
  bot to set it up, an E2EE recovery phrase / password / blob could be printed
7ff8adafe9e4atagen2026-10-22 12:30 UTC57
  to the terminal for safekeeping, to be used in case the original E2EE data
7ff8adafe9e4atagen2026-10-22 12:30 UTC58
  ever becomes lost.
7ff8adafe9e4atagen2026-10-22 12:30 UTC59
  - This would be done during setup instead of a run phase to make: a. make sure
7ff8adafe9e4atagen2026-10-22 12:30 UTC60
    the operator sees it, and b. if the operator forgets to point the bot's
7ff8adafe9e4atagen2026-10-22 12:30 UTC61
    state directories to a persistent file system, it has already taken note of
7ff8adafe9e4atagen2026-10-22 12:30 UTC62
    the recovery information separately, and so the problem with a lost E2EE
7ff8adafe9e4atagen2026-10-22 12:30 UTC63
    state can be resolved as long as they still have access to that information.
7ff8adafe9e4atagen2026-10-22 12:30 UTC64
7ff8adafe9e4atagen2026-10-22 12:30 UTC65
## Extra notes
7ff8adafe9e4atagen2026-10-22 12:30 UTC66
7ff8adafe9e4atagen2026-10-22 12:30 UTC67
This pattern would work well in a docker environment, as a bot developer could
7ff8adafe9e4atagen2026-10-22 12:30 UTC68
recommend the following;
7ff8adafe9e4atagen2026-10-22 12:30 UTC69
7ff8adafe9e4atagen2026-10-22 12:30 UTC70
They can recommend a `docker-compose.yml` file to be used for keeping track of a
7ff8adafe9e4atagen2026-10-22 12:30 UTC71
container lifecycle, and recommend the `docker-compose run bot setup` command
7ff8adafe9e4atagen2026-10-22 12:30 UTC72
before `docker-compose up -d`, to give bot operators an easy time setting it up,
7ff8adafe9e4atagen2026-10-22 12:30 UTC73
despite matrix's unconventional stateful nature (compared to other bot
7ff8adafe9e4atagen2026-10-22 12:30 UTC74
ecosystems).
7ff8adafe9e4atagen2026-10-22 12:30 UTC75
7ff8adafe9e4atagen2026-10-22 12:30 UTC76
## What this means for `matrix_sdk`
7ff8adafe9e4atagen2026-10-22 12:30 UTC77
7ff8adafe9e4atagen2026-10-22 12:30 UTC78
`matrix_sdk` could help this pattern by building in either a "create" or "open"
7ff8adafe9e4atagen2026-10-22 12:30 UTC79
intent for state, where it'll error if it can't do either.
7ff8adafe9e4atagen2026-10-22 12:30 UTC80
7ff8adafe9e4atagen2026-10-22 12:30 UTC81
Currently I don't see this in `make_store_config`, where it seems to implicitly
7ff8adafe9e4atagen2026-10-22 12:30 UTC82
choose either one, but if it's made more explicit to _either_ open the state
7ff8adafe9e4atagen2026-10-22 12:30 UTC83
database, _or_ create it, it would help guide developers a lot to this pattern,
7ff8adafe9e4atagen2026-10-22 12:30 UTC84
which in turn could guide bot operators to follow this pattern as well.