Files
continuwuity/docs/development/unstable_features.mdx
T

106 lines
5.2 KiB
Plaintext

# Unstable features policy
Like several other homeservers in the Matrix ecosystem, Continuwuity adopts a "disable by default"
approach to experimental features. This ensures every deployment gets the same baseline stability,
allowing users to opt in to potentially unstable features.
Historically, Continuwuity used maintainer discretion to decide whether an unstable feature should
be enabled by default. However, as the project has grown, and the pace of spec development has
increased, keeping up with unstable proposals becomes less and less feasible by the day, and this
causes the implementation of unstable proposals to gradually drift. This can lead to implementations
becoming so stale they're incompatible, with no bandwidth to get them fixed up.
Continuwuity is already selective about which unstable features it implements: the maintainer team
typically only accept implementations of proposals that seem like they are a net positive for a
large portion of the Matrix ecosystem, rather than aiming to "implement everything". As such, the
unstable feature list should typically be small and manageable.
**All** unstable proposals require an experiment before their implementation can be accepted.
Likewise, all experiments should default to being disabled, requiring explicit configuration to
enable.
**Draft proposals** will not be merged until their proposal is undrafted. Likewise, the pull request
that implements the draft proposal should itself be marked "WIP", to avoid being merged or
prioritised for review. Review is still possible for WIP PRs, so feel free to request a round of
feedback.
## Adding an unstable feature
First, navigate to `src/core/config/experiments.rs`. There, you have two options for adding an
experiment to the `Experiments` struct:
1. Use `SimpleExperiment` if the experiment only requires enabling with no further configuration.
2. Define a new struct that implements the `ToggledExperiment` trait.
All experiments must be optional and default to off (i.e. `is_enabled()` returns `false`).
`SimpleExperiment` is actually a wrapper around `Option<bool>`, and the omission of the
configuration OR setting it to `false` disables the experiment. `ToggledExperiment` impls should
copy similar behaviour.
Then, add a public field to the `Experiments` struct that is named the MSC's ID in lowercase.
Add a docstring to it, starting with the proposal title (including ID), then a brief paragraph or
so explaining what the proposal does in simple terms, and then finally end the docstring with a link
to the proposal.
### Advertising support for unstable features
If the proposal requires advertising an unstable feature flag, that flag must be added to
`unstable_features` in `src/core/matrix/versions.rs`. For example:
```diff
pub fn unstable_features(experiments: &Experiments) -> BTreeMap<String, bool> {
BTreeMap::from_iter([
// Always enabled feature (https://github.com/matrix-org/matrix-spec-proposals/pull/0000)
// Expected for spec v1.20
("org.matrix.msc0000".to_owned(), true),
+ // MSC9999: My Cool Feature (https://github.com/matrix-org/matrix-spec-proposals/pull/9999)
+ ("example.matrix.msc9999".to_owned(), experiments.msc9999.is_enabled())
])
}
```
This will allow the `/_matrix/client/versions` endpoint to dynamically advertise whether the unstable
feature is enabled on the current server.
## Removing unstable features
If a proposal is abandoned, becomes obsolete, or is accepted into the specification, the unstable
configuration should be removed (and possibly migrated) as soon as possible.
After removing a field from `experiments`, the key should be added to the `DEPRECATED_KEYS` slice in
`src/core/config/mod.rs` (really far down). This will ensure that a warning is printed on startup
when a configuration is using a now-removed config key. For example:
```diff
pub struct Experiments {
- pub msc9999: SimpleExperiment,
}
```
```diff
const DEPRECATED_KEYS: &[&str] = [
"foo",
+ "experiments.msc9999",
];
```
## Always-on experiments
Some experiments can be forcefully enabled (i.e. always-on), or enabled by default. This should only
be the case in exceptional circumstances, and must be adequately well documented. Some examples of
situations that may warrant an experiment being always-enabled:
* A proposal was implemented AFTER it was merged, but BEFORE it had a merged spec PR.
These proposals are typically as stable as they'll get, as major changes post-factum of an MSC
merge requires another MSC, so only minor changes can be made in the spec PR phase.
* The daily experience of users would be at a great detriment without the experiment being enabled.
* A proposal is so simple that making it opt-in would be pointless. This is *incredibly* rare.
The latter two require explicit maintainer approval, so discuss those with the maintainer team
first. You can exercise your own judgement for the first.
Always-on or enabled-by-default experiments must explain in detail why they're exempt from the
standard experiments policy via comments in surrounding areas, like
`src/core/config/experiments.rs` and `src/core/matrix/versions.rs`. Ideally, these features are not
unstable for too long, so explaining a timescale for how long before the feature is stabilised is
also helpful.