Skip to content

feat(bots): allow bots to fetch their own enabled features#18529

Open
ShapeShifter499 wants to merge 1 commit into
nextcloud:mainfrom
ShapeShifter499:feat/18523-bot-fetch-own-features
Open

feat(bots): allow bots to fetch their own enabled features#18529
ShapeShifter499 wants to merge 1 commit into
nextcloud:mainfrom
ShapeShifter499:feat/18523-bot-fetch-own-features

Conversation

@ShapeShifter499

Copy link
Copy Markdown

β˜‘οΈ Resolves

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

πŸ› οΈ Description

Adds GET /bot/{token}/features so a bot can check which features an administrator enabled for it, authenticated with its own shared secret instead of admin credentials.

Why polling instead of "try and report the error": a disabled feature is indistinguishable from a broken secret from the bot's side β€” getBotsForToken() filters by feature before the checksum trial, so a response-disabled bot gets the same 401 as one with a wrong secret. Webhook delivery can't be probed at all; it just silently never happens. My concrete case: a bot that offers reaction-based interactions (e.g. approve/deny via βœ…/❌) needs to know up front whether the reaction feature is enabled, rather than degrading mid-conversation.

Design: the endpoint reuses the existing X-Nextcloud-Talk-Bot-Random / X-Nextcloud-Talk-Bot-Signature HMAC scheme. Since GET has no body, the signature is computed over the random seed alone β€” modeled after the recording-settings endpoint in SignalingController, which signs random-only for the same reason (the SIP bridge variant signs random+token, but the conversation is already bound via the URL token in the bot lookup). Signing empty content also gives domain separation: the message and reaction endpoints reject empty content before authenticating (the reaction endpoints now enforce this explicitly), so a captured features-request signature cannot be replayed to post a message or reaction.

The bot lookup accepts any enabled bot of the conversation regardless of feature flags (Bot::FEATURE_NONE skips the filter) β€” the flags describe what a bot may do, not whether it may authenticate; a state-disabled bot still gets 401. Along the way the unreachable feature re-check inside the checksum loop was removed and the duplicated header/throttle handling was extracted into a shared getBotOrErrorResponse() helper.

πŸ› οΈ API Checklist

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not possible
  • πŸ“˜ API documentation in docs/ has been updated or is not required
  • πŸ”– Capability is added or not needed

Signed-off-by: Lance Gero3977@gmail.com
Assisted-by: Claude-Code:claude-fable-5

Bots previously had no way to learn which features (webhook, response,
event, reaction) an administrator enabled for them: the bot-list
endpoint requires admin credentials, and probing does not work either,
because a disabled feature yields the same 401 as an invalid secret,
while disabled webhooks simply never deliver. This made it impossible
for a bot to adapt its behavior, e.g. only offering reaction-based
interactions when the reaction feature is actually enabled.

Add GET /bot/{token}/features, authenticated with the same shared-secret
HMAC scheme as the other bot endpoints. As GET requests have no body,
the signature is computed over the random seed alone, following the
recording-settings precedent in SignalingController. Signing empty
content also gives domain separation: the message and reaction endpoints
reject empty content before authenticating (the reaction endpoints now
enforce this explicitly), so a captured features-request signature can
not be replayed against them.

The bot lookup accepts any enabled bot of the conversation regardless
of its feature flags (Bot::FEATURE_NONE skips the filter), because the
flags describe what a bot may do, not whether it may authenticate. The
previously unreachable feature re-check inside the checksum loop was
removed, and the per-endpoint header reading and error/throttle handling
was extracted into a shared getBotOrErrorResponse() helper, with the
RequestHeader attributes marked indirect accordingly.

The new endpoint is announced via the bot-features-api capability,
documented in docs/bots.md and covered by a new integration test
scenario. OpenAPI specs and TypeScript types were regenerated.

Resolves: nextcloud#18523

Signed-off-by: Lance <Gero3977@gmail.com>
Assisted-by: Claude-Code:claude-fable-5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Allow bots to fetch their own enabled features.

1 participant