Cookiebot
Features

Group settings over HTTP, admin-gated

every /config setting plus the rules and welcome text, readable and writable by a group's admins from the Mini App. groups:read / groups:write scopes, 404 (not 403) for a group you do not administer, PATCH semantics so two admins do not overwrite each other, and the same cb_core.group_texts upsert the Telegram handlers use

DoneM4apiplatform
v1 scenarios
—
Ported
—
Green
—
Failing
—

every /config setting plus the rules and welcome text, readable and writable by a group's admins from the Mini App. groups:read / groups:write scopes, 404 (not 403) for a group you do not administer, PATCH semantics so two admins do not overwrite each other, and the same cb_core.group_texts upsert the Telegram handlers use

v1 source: Configurations.py:150-211

What it does

Everything the /config menu can do in a private chat, an admin can now do over HTTP: read the group's settings, change some of them, set the rules and the welcome message. The writes land in the same tables through the same upsert the Telegram handlers use (cb_core.group_config, cb_core.group_texts), so a change made in the Mini App is live in the chat immediately and vice versa.

GET /me lists the groups the caller administers, which is how a Mini App knows what to show before any group has been chosen.

Behaviour that must not change

The authorisation boundary is the group. group_admins membership, or ownership of the tenant — nobody else. A caller who does not administer the group gets 404, the same answer an unknown group gets, so a logged-in stranger cannot walk chat ids. Membership is checked before scope, so a scope error never confirms that a group exists.

Reading and writing are separate scopes, and a token with no scopes can only read.

PATCH, not PUT. Absent fields are left alone: a form that round-tripped every column would silently overwrite whatever another admin changed while it was open.

The bounds match the menu. A value the Telegram menu would refuse to parse is a 422 here, and an unknown field is a 422 rather than a silent no-op.

How to verify it

packages/cb-api/tests/test_group_endpoints.py drives the boundary with four callers (an admin, a tenant owner, a stranger, and an admin holding a legacy scope-less token) plus the validation table. The shared upsert is exercised against a real database by qa/integration/test_group_config.py and the handlers' own suites, which still pass unchanged — that is what proves the refactor kept one write path rather than growing a second.

On this page