onbot 0.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- onbot/__init__.py +7 -0
- onbot/__main__.py +6 -0
- onbot/app.py +171 -0
- onbot/auth/__init__.py +19 -0
- onbot/auth/token_provider.py +153 -0
- onbot/cli.py +80 -0
- onbot/clients/__init__.py +5 -0
- onbot/clients/authentik.py +123 -0
- onbot/clients/base.py +243 -0
- onbot/clients/mas_admin.py +65 -0
- onbot/clients/matrix.py +457 -0
- onbot/clients/synapse_admin.py +159 -0
- onbot/clients/versions.py +61 -0
- onbot/config.py +653 -0
- onbot/events.py +51 -0
- onbot/healthcheck.py +134 -0
- onbot/identity.py +44 -0
- onbot/lifecycle/__init__.py +2 -0
- onbot/lifecycle/accounts.py +309 -0
- onbot/logging.py +26 -0
- onbot/media.py +46 -0
- onbot/models.py +74 -0
- onbot/onboarding/__init__.py +5 -0
- onbot/onboarding/listener.py +103 -0
- onbot/onboarding/welcome.py +116 -0
- onbot/reconciler/__init__.py +2 -0
- onbot/reconciler/effectors.py +78 -0
- onbot/reconciler/engine.py +348 -0
- onbot/reconciler/membership.py +54 -0
- onbot/reconciler/power_levels.py +96 -0
- onbot/reconciler/rooms.py +127 -0
- onbot/reconciler/state.py +77 -0
- onbot/utils.py +61 -0
- onbot-0.1.0.dev0.dist-info/METADATA +241 -0
- onbot-0.1.0.dev0.dist-info/RECORD +38 -0
- onbot-0.1.0.dev0.dist-info/WHEEL +4 -0
- onbot-0.1.0.dev0.dist-info/entry_points.txt +5 -0
- onbot-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Versioned onbot room-state schemas.
|
|
2
|
+
|
|
3
|
+
The bot has no database; it persists its own bookkeeping as **custom Matrix room-state events**
|
|
4
|
+
(AD-1 keeps this idea). Event types are namespaced with the reversed server name, e.g.
|
|
5
|
+
``org.company.onbot.group_room``. Legacy stored these as bare, unversioned dicts; we give them
|
|
6
|
+
explicit, validated pydantic schemas carrying a ``schema_version`` so future migrations are possible.
|
|
7
|
+
|
|
8
|
+
This module is pure (no I/O): the reconciler reads/writes these via the Matrix client (Phase 4).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from enum import StrEnum
|
|
14
|
+
from typing import Any, Literal
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel, Field
|
|
17
|
+
|
|
18
|
+
SCHEMA_VERSION = 1
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class OnbotRoomType(StrEnum):
|
|
22
|
+
space = "space"
|
|
23
|
+
group_room = "group_room"
|
|
24
|
+
direct_room = "direct_room"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def event_type_name(server_name: str, room_type: OnbotRoomType | str) -> str:
|
|
28
|
+
"""Fully-qualified custom state event type, e.g. ``org.company.onbot.group_room``.
|
|
29
|
+
|
|
30
|
+
Mirrors the legacy reversed-domain scheme so existing rooms keep matching.
|
|
31
|
+
"""
|
|
32
|
+
rt = room_type.value if isinstance(room_type, OnbotRoomType) else room_type
|
|
33
|
+
reversed_domain = ".".join(reversed(server_name.split(".")))
|
|
34
|
+
return f"{reversed_domain}.onbot.{rt}"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class _OnbotRoomState(BaseModel):
|
|
38
|
+
schema_version: int = SCHEMA_VERSION
|
|
39
|
+
authentik_server: str | None = None
|
|
40
|
+
avatar_source_url: str | None = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SpaceRoomState(_OnbotRoomState):
|
|
44
|
+
room_type: Literal[OnbotRoomType.space] = OnbotRoomType.space
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class GroupRoomState(_OnbotRoomState):
|
|
48
|
+
room_type: Literal[OnbotRoomType.group_room] = OnbotRoomType.group_room
|
|
49
|
+
group_id: str
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class DirectRoomState(_OnbotRoomState):
|
|
53
|
+
room_type: Literal[OnbotRoomType.direct_room] = OnbotRoomType.direct_room
|
|
54
|
+
user_id: str
|
|
55
|
+
marked_for_disabling_timestamp: float | None = None
|
|
56
|
+
disabled_user_timestamp: float | None = None
|
|
57
|
+
welcome_messages_sent: dict[str, str] = Field(default_factory=dict)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
AnyRoomState = SpaceRoomState | GroupRoomState | DirectRoomState
|
|
61
|
+
|
|
62
|
+
_STATE_MODEL_BY_TYPE: dict[OnbotRoomType, type[AnyRoomState]] = {
|
|
63
|
+
OnbotRoomType.space: SpaceRoomState,
|
|
64
|
+
OnbotRoomType.group_room: GroupRoomState,
|
|
65
|
+
OnbotRoomType.direct_room: DirectRoomState,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def parse_room_state(room_type: OnbotRoomType, content: dict[str, Any]) -> AnyRoomState:
|
|
70
|
+
"""Validate raw state-event content into the matching schema for ``room_type``."""
|
|
71
|
+
model = _STATE_MODEL_BY_TYPE[room_type]
|
|
72
|
+
return model.model_validate(content)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def dump_room_state(state: AnyRoomState) -> dict[str, Any]:
|
|
76
|
+
"""Serialise a room-state model to JSON-able content for a Matrix state event."""
|
|
77
|
+
return state.model_dump(mode="json")
|
onbot/utils.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Small, dependency-free helpers.
|
|
2
|
+
|
|
3
|
+
Ported from legacy ``onbot/utils.py`` — we keep the nested-dict helpers (used pervasively to read
|
|
4
|
+
dotted attribute paths out of Authentik objects) and drop the legacy ``synchronize_async_helper``
|
|
5
|
+
sync/async bridge (AD-7: async everything) and the ``requests``-based media download (Phase 6,
|
|
6
|
+
authenticated media). The ``Any``-as-sentinel hack is replaced with an explicit ``_MISSING`` marker.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
from typing import Any, Final
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class _Missing:
|
|
16
|
+
"""Sentinel distinguishing 'no fallback given' from a ``None`` fallback."""
|
|
17
|
+
|
|
18
|
+
__slots__ = ()
|
|
19
|
+
|
|
20
|
+
def __repr__(self) -> str: # pragma: no cover - debugging aid
|
|
21
|
+
return "<MISSING>"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_MISSING: Final = _Missing()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_nested_dict_val_by_path(
|
|
28
|
+
data: dict[str, Any],
|
|
29
|
+
key_path: Sequence[str],
|
|
30
|
+
fallback_val: Any = _MISSING,
|
|
31
|
+
) -> Any:
|
|
32
|
+
"""Read a nested value via a key path (e.g. ``["attributes", "matrix_name"]``).
|
|
33
|
+
|
|
34
|
+
Raises ``KeyError`` if the path is absent and no ``fallback_val`` was provided.
|
|
35
|
+
"""
|
|
36
|
+
current: Any = data
|
|
37
|
+
for key in key_path:
|
|
38
|
+
try:
|
|
39
|
+
current = current[key]
|
|
40
|
+
except KeyError, TypeError:
|
|
41
|
+
if fallback_val is _MISSING:
|
|
42
|
+
raise KeyError(key) from None
|
|
43
|
+
return fallback_val
|
|
44
|
+
return current
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def dict_has_nested_attr(
|
|
48
|
+
data: dict[str, Any],
|
|
49
|
+
key_path: Sequence[str],
|
|
50
|
+
*,
|
|
51
|
+
must_have_val: bool = False,
|
|
52
|
+
) -> bool:
|
|
53
|
+
"""Return whether ``data`` has the nested ``key_path`` (and a truthy value if ``must_have_val``)."""
|
|
54
|
+
current: Any = data
|
|
55
|
+
for key in key_path:
|
|
56
|
+
if not isinstance(current, dict) or key not in current:
|
|
57
|
+
return False
|
|
58
|
+
current = current[key]
|
|
59
|
+
if must_have_val:
|
|
60
|
+
return bool(current)
|
|
61
|
+
return True
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: onbot
|
|
3
|
+
Version: 0.1.0.dev0
|
|
4
|
+
Summary: Keep a Matrix (Synapse) homeserver in sync with Authentik and onboard new users.
|
|
5
|
+
Keywords: matrix,synapse,authentik,mas,bot,onboarding
|
|
6
|
+
Author: DZD
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Project-URL: Homepage, https://github.com/DZD-eV-Diabetes-Research/matrix-synapse-authentik-onbaording-bot
|
|
11
|
+
Requires-Python: >=3.14
|
|
12
|
+
Requires-Dist: httpx>=0.27
|
|
13
|
+
Requires-Dist: tenacity>=9.0
|
|
14
|
+
Requires-Dist: pydantic>=2.7
|
|
15
|
+
Requires-Dist: pydantic-settings>=2.3
|
|
16
|
+
Requires-Dist: pyyaml>=6.0
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# Onbot
|
|
20
|
+
|
|
21
|
+
A bot that keeps a **Matrix (Synapse)** homeserver continuously in sync with an
|
|
22
|
+
**[Authentik](https://goauthentik.io/)** identity provider and onboards every new user into the
|
|
23
|
+
right rooms with a friendly welcome. Authentik is the source of truth; Matrix mirrors it
|
|
24
|
+
(group → room, group membership → room membership, power levels), and new users get guided in with a
|
|
25
|
+
1:1 welcome DM.
|
|
26
|
+
|
|
27
|
+
Onbot targets **Matrix 2.0**: it assumes a [**Matrix Authentication Service
|
|
28
|
+
(MAS)**](https://element-hq.github.io/matrix-authentication-service/) deployment with Authentik as
|
|
29
|
+
an *upstream identity provider*, uses authenticated media, and drives the Client-Server and admin
|
|
30
|
+
APIs over a single async HTTP client (no `matrix-nio`).
|
|
31
|
+
|
|
32
|
+
See [`GOALS.md`](GOALS.md) for intent, [`BATTLE_PLAN.md`](BATTLE_PLAN.md) for the build plan, and
|
|
33
|
+
[`docs/adr/`](docs/adr/) for the architecture decisions.
|
|
34
|
+
|
|
35
|
+
> ⚠️ **Release blocker (maintainer):** the Phase 1 security items are **not done** — leaked
|
|
36
|
+
> credentials in git history still need rotating and the history scrubbing
|
|
37
|
+
> ([`BATTLE_PLAN.md`](BATTLE_PLAN.md) §5 Phase 1). **Do not publish an image or tag a release until
|
|
38
|
+
> those are complete.** The packaging below is ready; the security hand-off is the gate.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## How it works — the MAS auth topology
|
|
43
|
+
|
|
44
|
+
The auth chain is **Matrix client → MAS → Authentik** (ADR-[0006](docs/adr/0006-auth-topology-mas-authentik.md)):
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
logs in via upstream IdP
|
|
48
|
+
Matrix client ───────────────▶ MAS ◀─────────────────────── Authentik
|
|
49
|
+
▲ │ (provisions Matrix accounts (source of truth:
|
|
50
|
+
│ │ on first login) users & groups)
|
|
51
|
+
│ welcome DM, │
|
|
52
|
+
│ room membership ┌────┴─────┐
|
|
53
|
+
└──────────────────────│ Onbot │── reads users/groups ──▶ Authentik API
|
|
54
|
+
└────┬─────┘
|
|
55
|
+
└── Synapse Admin API + CS API ──▶ Synapse ◀─ MAS
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Consequences that shape how you configure Onbot:
|
|
59
|
+
|
|
60
|
+
- **Onbot does not create accounts.** MAS auto-provisions a Matrix account the first time a user
|
|
61
|
+
logs in through Authentik. Onbot's job is **projection**: turn Authentik groups into rooms, group
|
|
62
|
+
membership into room membership, and group/role attributes into power levels — plus the
|
|
63
|
+
quarantined offboarding lifecycle.
|
|
64
|
+
- **The MXID localpart contract is critical.** Onbot computes a user's MXID
|
|
65
|
+
(`@<localpart>:server_name`) from an Authentik attribute, and it **must match the localpart
|
|
66
|
+
template MAS uses** when it provisions accounts from the same Authentik claim. Set
|
|
67
|
+
[`sync_authentik_users_with_matrix_rooms.authentik_username_mapping_attribute`](docs/CONFIG_REFERENCE.md)
|
|
68
|
+
to agree with MAS — get it wrong and Onbot's computed MXIDs won't match the real accounts, so
|
|
69
|
+
nobody gets added to rooms. (Verified by the integration suite's localpart-contract test.)
|
|
70
|
+
- **Lifecycle enforcement requires MAS.** When Authentik disables a user, MAS blocks *new* logins
|
|
71
|
+
but **existing Matrix sessions keep working**, and the *Synapse* admin API cannot revoke a
|
|
72
|
+
MAS-issued session — only MAS can (ADR-[0005](docs/adr/0005-quarantine-lifecycle.md), §7 Q1, proven
|
|
73
|
+
empirically). So to actually offboard a disabled user you must configure the
|
|
74
|
+
[`mas_admin`](docs/CONFIG_REFERENCE.md) block. Without it, offboarding is a **no-op against live
|
|
75
|
+
sessions** (it silently fails to revoke).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Configuration
|
|
80
|
+
|
|
81
|
+
Configuration is a single YAML file validated by a [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)
|
|
82
|
+
model ([`onbot/config.py`](onbot/config.py)). Every setting can also be supplied (or overridden) via
|
|
83
|
+
an environment variable: prefix `ONBOT_`, nest with `__`. E.g.
|
|
84
|
+
`ONBOT_SYNAPSE_SERVER__BOT_ACCESS_TOKEN=syt_…`.
|
|
85
|
+
|
|
86
|
+
- **Full reference:** [`docs/CONFIG_REFERENCE.md`](docs/CONFIG_REFERENCE.md) — every field, its type,
|
|
87
|
+
default, description and `ONBOT_*` env-var name.
|
|
88
|
+
- **Annotated template:** [`config.example.yml`](config.example.yml) — a commented, fillable YAML
|
|
89
|
+
template. Copy it to `config.yml` and fill in the required values.
|
|
90
|
+
|
|
91
|
+
Both are **generated from the model** (with [psyplus](https://pypi.org/project/psyplus/)) and kept in
|
|
92
|
+
sync by CI — regenerate after editing `onbot/config.py`:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pdm run gen-config-docs # rewrite docs/CONFIG_REFERENCE.md + config.example.yml
|
|
96
|
+
pdm run check-config-docs # fail if they drift from the model (runs in CI)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> 🔐 **Never commit a real config.** `config*.yml` is gitignored (only `config.example.yml` is
|
|
100
|
+
> tracked) and the Docker image carries no secrets — provide config at runtime.
|
|
101
|
+
|
|
102
|
+
### Bot credentials (pick one)
|
|
103
|
+
|
|
104
|
+
Onbot authenticates to Synapse as a bot user. Under MAS, choose one of:
|
|
105
|
+
|
|
106
|
+
| Option | Field | When |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| **Compatibility token** | `synapse_server.bot_access_token` | Near-term. Issue with `mas-cli manage issue-compatibility-token`. Provide the bare token. |
|
|
109
|
+
| **OAuth2 client-credentials** | `synapse_server.oauth2` | Forward-looking. The bot is a confidential MAS client and refreshes tokens automatically. |
|
|
110
|
+
|
|
111
|
+
Provide **exactly one**. The same identity drives both the Synapse Admin API and the Client-Server
|
|
112
|
+
API.
|
|
113
|
+
|
|
114
|
+
### Minimal `config.yml`
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
synapse_server:
|
|
118
|
+
server_name: company.org # your Matrix domain (the part after the ':')
|
|
119
|
+
server_url: https://internal.matrix # how the bot reaches Synapse (internal URL is fine)
|
|
120
|
+
bot_user_id: "@welcome-bot:company.org"
|
|
121
|
+
bot_access_token: syt_REPLACE_ME # or use an `oauth2:` block instead
|
|
122
|
+
|
|
123
|
+
authentik_server:
|
|
124
|
+
url: https://authentik.company.org/
|
|
125
|
+
api_key: REPLACE_ME # Authentik API token
|
|
126
|
+
|
|
127
|
+
# Required to enforce offboarding under MAS (omit on non-MAS deployments):
|
|
128
|
+
mas_admin:
|
|
129
|
+
url: https://auth.company.org # the MAS base URL
|
|
130
|
+
client_id: REPLACE_ME # a MAS admin client (in policy.data.admin_clients)
|
|
131
|
+
client_secret: REPLACE_ME
|
|
132
|
+
|
|
133
|
+
sync_authentik_users_with_matrix_rooms:
|
|
134
|
+
authentik_username_mapping_attribute: username # MUST agree with MAS's localpart template
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
See [`config.example.yml`](config.example.yml) for everything else (room mapping rules, power
|
|
138
|
+
levels, welcome messages, the dry-run lifecycle defaults, ignore lists, …).
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Run with Docker
|
|
143
|
+
|
|
144
|
+
The published image runs as a non-root user and ships only runtime dependencies (no crypto stack —
|
|
145
|
+
the bot operates outside encrypted rooms, ADR-[0009](docs/adr/0009-e2ee-stance.md)).
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
docker run --rm \
|
|
149
|
+
-v "$PWD/config.yml:/config/config.yml:ro" \
|
|
150
|
+
ghcr.io/dzd-ev-diabetes-research/matrix-synapse-authentik-onbaording-bot:latest
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The image defaults to `ONBOT_CONFIG_FILE_PATH=/config/config.yml` and the `run` command. It has a
|
|
154
|
+
built-in `HEALTHCHECK` that calls `onbot healthcheck` (see below).
|
|
155
|
+
|
|
156
|
+
### docker-compose
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
services:
|
|
160
|
+
onbot:
|
|
161
|
+
image: ghcr.io/dzd-ev-diabetes-research/matrix-synapse-authentik-onbaording-bot:latest
|
|
162
|
+
restart: unless-stopped
|
|
163
|
+
volumes:
|
|
164
|
+
- ./config.yml:/config/config.yml:ro
|
|
165
|
+
# Or skip the file and supply everything via env (no secrets on disk):
|
|
166
|
+
# environment:
|
|
167
|
+
# ONBOT_SYNAPSE_SERVER__SERVER_NAME: company.org
|
|
168
|
+
# ONBOT_SYNAPSE_SERVER__BOT_ACCESS_TOKEN: ${ONBOT_BOT_TOKEN}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### CLI commands
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
onbot run # long-running service: reconcile loop + event-driven onboarding (default)
|
|
175
|
+
onbot reconcile-once # one idempotent reconcile pass, then exit
|
|
176
|
+
onbot generate-config # print a minimal config template (use config.example.yml for the rich one)
|
|
177
|
+
onbot healthcheck # probe Synapse/Authentik/MAS with the real credentials; exit 0 healthy, 1 not
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`onbot healthcheck` is what the container's `HEALTHCHECK` runs: it issues one authenticated request
|
|
181
|
+
to the Matrix CS API (`/whoami`), the Synapse admin API, the Authentik API, and — when `mas_admin`
|
|
182
|
+
is configured — the MAS admin API, and exits non-zero if any is unreachable or rejects the
|
|
183
|
+
credentials.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Develop
|
|
188
|
+
|
|
189
|
+
Requires **Python 3.14** and **[PDM](https://pdm-project.org/)**.
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
pdm install # create the venv and install deps (incl. dev + docs)
|
|
193
|
+
pdm run pre-commit install # enable lint + secret-scan hooks
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Run & test
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
pdm run onbot --help
|
|
200
|
+
pdm run onbot reconcile-once
|
|
201
|
+
|
|
202
|
+
pdm run pytest -m "not integration" # fast unit + contract suite
|
|
203
|
+
pdm run pytest # full suite incl. live Synapse+MAS+Authentik (needs Docker)
|
|
204
|
+
pdm run ruff check . # lint
|
|
205
|
+
pdm run ruff format --check . # formatting
|
|
206
|
+
pdm run mypy onbot # type check
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The `run_*.sh` helper scripts at the repo root wrap the same PDM commands.
|
|
210
|
+
|
|
211
|
+
### Build the image locally
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
docker build -t onbot:dev .
|
|
215
|
+
docker run --rm onbot:dev --help
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Troubleshooting
|
|
221
|
+
|
|
222
|
+
| Symptom | Likely cause |
|
|
223
|
+
|---|---|
|
|
224
|
+
| Users never get added to rooms | The MXID localpart contract is broken — `authentik_username_mapping_attribute` doesn't match MAS's localpart template, so computed MXIDs don't exist. |
|
|
225
|
+
| Disabled users keep their Matrix access | `mas_admin` is not configured (the Synapse admin API can't revoke a MAS session), or lifecycle `dry_run` is still `true` (the default). |
|
|
226
|
+
| Nothing destructive ever happens | Expected by default — the lifecycle is quarantined (`dry_run: true`); it only logs to the `onbot.lifecycle.audit` channel until you opt in. |
|
|
227
|
+
| Welcome DM send fails with a 500 | The bot device isn't registered yet — Onbot registers it on startup (`ensure_device_registered`); check startup logs. |
|
|
228
|
+
| `healthcheck` reports a dependency FAIL | Read the per-dependency log line; it distinguishes unreachable from auth-rejected. The `matrix-cs` line also flags a token/`bot_user_id` mismatch. |
|
|
229
|
+
| Sliding sync unavailable | The homeserver doesn't advertise MSC4186; Onbot falls back to the reconciler signal path automatically. |
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Releasing
|
|
234
|
+
|
|
235
|
+
Versioned images are published to GHCR by the [release workflow](.github/workflows/release.yml) when
|
|
236
|
+
a `v*` tag is pushed. See [`CHANGELOG.md`](CHANGELOG.md) and the workflow's header comment for the
|
|
237
|
+
tag/version flow. **(Blocked on the Phase 1 security hand-off — see the note at the top.)**
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
MIT — see [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
onbot-0.1.0.dev0.dist-info/METADATA,sha256=pI9PGj7lF4Gt2wmN_TRK6wA9KHew7B_AqeHRNyiwLJ4,11164
|
|
2
|
+
onbot-0.1.0.dev0.dist-info/WHEEL,sha256=VP-D4TPS230sME9Z3vb3INXvo1yt0924YRm5AOsk_dE,90
|
|
3
|
+
onbot-0.1.0.dev0.dist-info/entry_points.txt,sha256=DGrxm-JKvVp239mGhGJC9xY-IvC-2AjjrdUg0L6yQXs,57
|
|
4
|
+
onbot-0.1.0.dev0.dist-info/licenses/LICENSE,sha256=TuZlsZ-MBR0SxDZR0I8eTSMK2oI-UPKSs8Du8cSpxU0,1101
|
|
5
|
+
onbot/__init__.py,sha256=PCI_AaMaoMIOSBLYD-84-oi2NaJ4vv5gKcOQr89b8w0,292
|
|
6
|
+
onbot/__main__.py,sha256=GO4R6IprVZwwwH3glDpQrNz2_MU0BrnN75lKDIDfaPc,119
|
|
7
|
+
onbot/app.py,sha256=_x-hJdEUQww4rHNLPTdL7XqKAP89nx3vlWqvmBsJRak,7046
|
|
8
|
+
onbot/auth/__init__.py,sha256=ur6qmM7E1fNUpxw2OaVr7vIxQK_EgurweB1knp9Afj8,496
|
|
9
|
+
onbot/auth/token_provider.py,sha256=1RjflnWDT2zubQH-wdvb9v251jbfDnm8mJ7PHmhOPdo,5958
|
|
10
|
+
onbot/cli.py,sha256=iiZ5Vk0ZQYH7o0BtTGmyn7mLFTSrD3LwIpSCrpBnvsE,3048
|
|
11
|
+
onbot/clients/__init__.py,sha256=2bZ_RF_0vjzaLj-Q8g8HWKJaS3fjZBBQT2ni7_vE3fQ,263
|
|
12
|
+
onbot/clients/authentik.py,sha256=DvBVgdKX6oxe0reXJ7_FmUNfd0_op-tnW-JfGenSbM8,4812
|
|
13
|
+
onbot/clients/base.py,sha256=8WSzLBuYXSWJJYnN5ZAyPY-k4_H7Nex5LQr3II41vq0,9302
|
|
14
|
+
onbot/clients/mas_admin.py,sha256=Snc76PcnIqT4PwUs4nH4OzK6Mv4x_T1ennHI8wwiLhI,2594
|
|
15
|
+
onbot/clients/matrix.py,sha256=WEwwnm3q9fmbc0vPfCGFHxbgfS_84OG6HWes-jlNJ3c,19693
|
|
16
|
+
onbot/clients/synapse_admin.py,sha256=kfrQtfy5M5Qq-sir1U4wRWFAiszMBsw9nJWTff-V56w,7467
|
|
17
|
+
onbot/clients/versions.py,sha256=RzM6BilIJLwCzjT7kuo-wrzF4o00DU4nqKQruETd5iU,2668
|
|
18
|
+
onbot/config.py,sha256=zq5Tk9kn7n6nz5WZTGkwO0U5kO86U7XgtFX07cVRw3o,26634
|
|
19
|
+
onbot/events.py,sha256=MTBBZ1bcWVukZzVwI4suqgzXluQy9PTLfwyHdEX2CnM,1563
|
|
20
|
+
onbot/healthcheck.py,sha256=loZWenxjg4H0nR9DcxDEdPFfHKinQ0zTQQzEvNwMlXk,5530
|
|
21
|
+
onbot/identity.py,sha256=ggK4pqmxvjMhPwFXRSAqJIectz8P0McU2DHDMLQ9M2I,1809
|
|
22
|
+
onbot/lifecycle/__init__.py,sha256=E8vfTN8AOjQO6c0wb1lKK26PaYG78-Phcidn5_AkbLk,148
|
|
23
|
+
onbot/lifecycle/accounts.py,sha256=6gIZOMZhfpnTa8471fW-jjF735i2x7gtw8lfLSty_uY,13269
|
|
24
|
+
onbot/logging.py,sha256=qASVDwcQLj4xowUL3lnETp7gkMWjdtAiAQ28k5amqG4,899
|
|
25
|
+
onbot/media.py,sha256=Uh53B_-HePoIXxCKVLcOBfJldDVHRDTiX_Ea-3XJ4Mo,1981
|
|
26
|
+
onbot/models.py,sha256=GyJelGYy2_5nZLMkKNnlA_dsIIyga720bF0kootlIfk,2092
|
|
27
|
+
onbot/onboarding/__init__.py,sha256=y4lt5sP_HhC7nfAKFTJLEoDWTfH1AUT_PY5R_SSzniI,267
|
|
28
|
+
onbot/onboarding/listener.py,sha256=fEh5wNfxABth8JpSpM3DTAuStN6ef_d3hRqVGh38tiY,4024
|
|
29
|
+
onbot/onboarding/welcome.py,sha256=Nzo9q29m7Lhq2AUAJjzlsa5ZaDmWps6KQFcq5zjgYnE,5001
|
|
30
|
+
onbot/reconciler/__init__.py,sha256=3X9zZTz6v6y1CgX6LSuBs_R4JOy2g6BEJdOR2CvQfs4,179
|
|
31
|
+
onbot/reconciler/effectors.py,sha256=9Ys6FaPMhDQIU71FayOcog0K2U7WpgQXp4kMdWRkIN8,3499
|
|
32
|
+
onbot/reconciler/engine.py,sha256=05T27P_ccxmIf-dkkYWulPYFW-J8IK-TAP1-v4N4T1U,15905
|
|
33
|
+
onbot/reconciler/membership.py,sha256=gLuH7pIYFpCWYqG8y6xHQucyGRmfav643sCe5GV473M,1938
|
|
34
|
+
onbot/reconciler/power_levels.py,sha256=HKlPLNNcxnc5e_2JS0SLC13GNgYEHQ6pYWKsfXhgkks,3524
|
|
35
|
+
onbot/reconciler/rooms.py,sha256=kjNnul402Nwg11DCe29Ypo5c_V2oIbmE-9zq8AINS1g,5262
|
|
36
|
+
onbot/reconciler/state.py,sha256=vqzy6JKCm45fe7CwpNGGYjsx7Hsg91uIHgcyQjvJQ1Q,2669
|
|
37
|
+
onbot/utils.py,sha256=xFHB-7MfFzxj_NJ5AYx4BRf-wAbhUaSp7PlhHG0p7Rs,1839
|
|
38
|
+
onbot-0.1.0.dev0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Deutsche Zentrum für Diabetesforschung e.V.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|