Skip to content

feat(integrations): support chatRoomFilter and chat rule types#433

Draft
AndyTWF wants to merge 7 commits into
mainfrom
integrations-chat-room-filter
Draft

feat(integrations): support chatRoomFilter and chat rule types#433
AndyTWF wants to merge 7 commits into
mainfrom
integrations-chat-room-filter

Conversation

@AndyTWF

@AndyTWF AndyTWF commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Ably Chat integration rules populate chatRoomFilter (top-level on the rule, alongside source) rather than source.channelFilter. ably integrations get/list previously had no way to display this, so chat-room-sourced rules looked like they had no filter configured. integrations get/list now show a "Chat Room Filter" line when set, and include chatRoomFilter in --json output.
  • integrations create/update gained a --chat-room-filter flag and chat.message as a --source-type option — but on their own these only covered the classic Reactor-style rule types (http, amqp, etc.), which turned out not to be the actual rule types Ably Chat rules use.
  • Investigating against the real Control API showed that chat-sourced rules (moderation vendors, before-publish webhooks, dashboards) use a structurally different schema: invocationMode + beforePublishConfig instead of requestMode, and a source object that rejects channelFilter entirely. integrations create had no way to create any of these rule types at all. This PR adds full support for all seven: http/before-publish, hive/text-model-only, hive/dashboard, bodyguard/text-moderation, tisane/text-moderation, azure/text-moderation, and aws/lambda/before-publish. Each gets its own typed target flags (--target-api-key, --target-endpoint, --target-function-name, --threshold key=value, etc.), and invocationMode/beforePublishConfig are set automatically per rule type (only hive/dashboard runs AFTER_PUBLISH; everything else is BEFORE_PUBLISH with a configurable retry/failure policy).
  • Fixed two bugs uncovered while building this: chatRoomFilter and source.channelFilter were being sent unconditionally (even as empty strings), which the Control API rejects outright for chat.message-sourced and before-publish rules — now both are only included when actually set. A modelUrl: null default was also rejected by the schema (it only accepts a string or omission) — now omitted when not provided.
  • Rule/RuleData interfaces in control-api.ts updated to match: invocationMode, beforePublishConfig added, requestMode/source.channelFilter made optional.
  • integrations get/list also surface invocationMode and no longer print a blank "Request Mode" line for rule types that don't have one.
  • Corrected channelFilter/chatRoomFilter example and test values to valid regex syntax (e.g. chat:.*, room:.*) instead of glob-style chat:* — both fields are regexps evaluated by the Control API, not globs.

Test plan

  • pnpm prepare (build + manifest)
  • pnpm exec eslint . — 0 errors
  • pnpm test:unit — full suite passes (2553 tests)
  • pnpm test:tty — passes
  • Unit tests added/updated for integrations create/get/list/update covering all seven chat rule types, required-flag validation per type, beforePublishConfig defaults/overrides, and the hive/dashboard AFTER_PUBLISH/no-beforePublishConfig exception
  • e2e suite (test/e2e/integrations/integrations-e2e.test.ts) extended with a full create/get/delete lifecycle for every chat rule type, plus a fix to the existing chat-room-sourced test which used the wrong (http) rule type. Actually run against the real Control API (with E2E_ABLY_ACCESS_TOKEN/E2E_ABLY_API_KEY) this time — all 10 tests pass, including app create/teardown
  • Manually verified all seven rule types create successfully via node bin/run.js integrations create ... against a real app, then cleaned up the test rules

Notes from live verification

  • azure/text-moderation's target.endpoint is validated via a live DNS lookup at rule-creation time (422 on ENOTFOUND), so the e2e test uses a real resolvable hostname rather than a placeholder.
  • Found (not fixed here, since it's unrelated to this feature and likely affects other ID-taking commands too): rule IDs can start with - (e.g. -MYkHg), which oclif's arg parser misreads as an unknown flag rather than a positional argument for integrations get/delete. Worked around it in the new e2e tests with a -- separator; flagging as a follow-up since it'd affect real users with an unlucky rule ID.

DX-1546

Manual testing

Run against a local build of this branch (pnpm prepare then node bin/run.js ...) — the globally installed ably CLI will be an older published version without this support.

  1. Create a before-publish webhook sourced from a chat room:
    node bin/run.js integrations create --rule-type "http/before-publish" --source-type "chat.message" --chat-room-filter "room:.*" --target-url "https://example.com/webhook"
    
    Confirm the output includes Chat Room Filter: room:.* and Invocation Mode: BEFORE_PUBLISH.
  2. Create a moderation rule, e.g. tisane:
    node bin/run.js integrations create --rule-type "tisane/text-moderation" --source-type "chat.message" --target-api-key "key" --threshold "profanity=1" --threshold "allegation=1" --default-language "*"
    
  3. Get the rule and confirm the new fields are shown:
    node bin/run.js integrations get <ruleId>
    node bin/run.js integrations get <ruleId> --json   # confirm "chatRoomFilter"/"invocationMode"/"beforePublishConfig" are present
    
  4. List rules and confirm chat rules show their filter/invocation mode, and pre-existing channel.message rules show neither:
    node bin/run.js integrations list
    node bin/run.js integrations list --json
    
  5. Update a rule's chat room filter and re-verify via get:
    node bin/run.js integrations update <ruleId> --chat-room-filter "chat:.*"
    node bin/run.js integrations get <ruleId>
    
  6. Delete the rule to clean up:
    node bin/run.js integrations delete <ruleId>
    

@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment Jul 23, 2026 6:44pm

Request Review

Rules created from Ably Chat rooms populate chatRoomFilter (top-level
on the rule, alongside source) instead of source.channelFilter. Surface
it in both human-readable and JSON output so `integrations get`/`list`
don't silently omit the filter for chat-room-sourced rules.

DX-1546

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
AndyTWF added 2 commits July 17, 2026 17:08
Rules can be sourced from Ably Chat rooms (source-type chat.message),
which requires setting chatRoomFilter rather than the channel-based
source.channelFilter. `integrations create`/`update` had no way to set
it, even though get/list already knew how to display it.

Also corrects the example/test filter values to valid regex syntax
(channelFilter/chatRoomFilter are regexps, not globs) — e.g. "room:.*"
instead of "room:*".

DX-1546
Extends the Control API e2e suite to create/get/list/delete a rule
with source-type chat.message and --chat-room-filter, verifying
chatRoomFilter round-trips through the real API end to end.
@AndyTWF AndyTWF changed the title feat(integrations): show chat room filter on rule get/list feat(integrations): support chatRoomFilter on rules Jul 17, 2026
…ests

channelFilter is a regexp, not a glob, so "chat:*" is invalid — the
trailing * has nothing to repeat. Switch examples and test fixtures to
"chat:.*" (and similarly for other filter values used in tests).
AndyTWF and others added 2 commits July 23, 2026 14:33
…sh rule types

Ably Chat rules (hive/text-model-only, hive/dashboard, bodyguard/text-moderation,
tisane/text-moderation, azure/text-moderation, aws/lambda/before-publish, and
http/before-publish) use a structurally different schema from the classic
Reactor rule types: invocationMode + beforePublishConfig instead of
requestMode, and vendor-specific target shapes discovered by inspecting
existing rules and probing the Control API directly. `integrations create`
had no way to create any of these — only the classic channel-sourced rule
types were supported.

Along the way, found and fixed two bugs that blocked this entirely:
chatRoomFilter and source.channelFilter were sent unconditionally (even as
empty strings), which the API rejects outright for chat.message-sourced and
before-publish rules. modelUrl was sent as an explicit null when unset,
which the API also rejects — now omitted instead.

DX-1546

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… test

Extends the Control API e2e suite with a full create/get/delete lifecycle
for every chat rule type (http/before-publish, hive/text-model-only,
hive/dashboard, bodyguard/text-moderation, tisane/text-moderation,
azure/text-moderation, aws/lambda/before-publish) against the real API.

Also fixes the existing chat-room-sourced rule test, which used the
"http" rule type — the real API rejects chatRoomFilter/chat.message on
that schema, so this test would have failed had it ever actually run
(it was silently skipped locally for lack of E2E_ABLY_ACCESS_TOKEN).

Running the new tests against the real API surfaced two more things
these tests now account for: the azure/text-moderation target.endpoint
is validated via a live DNS lookup at creation time, so a placeholder
domain 422s; and rule IDs can start with "-", which oclif misparses as
an unknown flag unless a "--" separator precedes the positional arg.

DX-1546

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@AndyTWF AndyTWF changed the title feat(integrations): support chatRoomFilter on rules feat(integrations): support chatRoomFilter and chat rule types Jul 23, 2026
@AndyTWF
AndyTWF requested a review from umair-ably July 23, 2026 17:03
…rule config

update.ts and delete.ts printed "Request Mode: undefined" for chat rule
types (they use invocationMode instead of requestMode) and never showed
invocationMode at all — the same display bug already fixed in create.ts/
get.ts/list.ts was missed in these two commands.

parseThresholds silently accepted "key=" and "key= " as a threshold of 0
instead of rejecting them, and discarded everything after a second "=".

create.ts had no validation that a chat rule type is paired with
--source-type chat.message (or vice versa), so a mismatched combination
only surfaced as an opaque Control API 4xx instead of a clear CLI error.

Replaces the CHAT_RULE_TYPES/AFTER_PUBLISH_CHAT_RULE_TYPES sets plus the
per-rule-type switch statement with a single declarative config table
(invocationMode, required target flags, target builder per rule type),
removes the duplicate local IntegrationData/BeforePublishConfig types in
favour of importing RuleData from control-api.ts, and extracts a shared
buildModerationTarget helper for the three moderation-vendor rule types.

DX-1546

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant