Skip to content

fix(channels): unblock the first live deploy (slug, handshake, reference key, space kind, listing) - #6646

Draft
mmabrouk wants to merge 8 commits into
feat/channelsfrom
channels/fix-deploy-blockers
Draft

fix(channels): unblock the first live deploy (slug, handshake, reference key, space kind, listing)#6646
mmabrouk wants to merge 8 commits into
feat/channelsfrom
channels/fix-deploy-blockers

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Sep 8, 2026

Copy link
Copy Markdown
Member

Context

Stacked on #6644. These are the defects that stopped a fresh channels stack from answering a Slack message at all, found on the first deploy of the takeover branch. Each one is small and has a unit test that fails without it.

Changes

  • A connection gets a name and a slug without the user typing one. The setup form sends only credentials, so the insert died on the slug column and the error said "already exists". The service names the connection after the workspace Slack reports and derives a slug from that name with a short random suffix. A failed insert no longer leaves an orphaned secret, and an unrelated integrity error names the violated constraint.
  • Slack's URL handshake is answered. The events route echoes a url_verification challenge, unsigned and shape-strict. Everything else on the route stays signed.
  • The agent form files the workflow under a key the runtime resolves (workflow_variant), and the API refuses a reference key outside the resolvable families at write time.
  • The stored event carries the space kind the adapter classified, so a kind-level grant such as "allow in DMs" matches. This is F79 from the findings ledger.
  • Space discovery lists every channel. Read methods send their arguments as query parameters, which Slack requires, and discovery follows the listing cursor to the end.
  • The web pages import the two helpers the release moved, and the settings sidebar knows the channels page.

Tests

  • API unit, channels: 682 pass. Integration, channels, against the stack's Postgres: 65 pass. Acceptance, channels: 17 of 18 pass. The remaining one is a fixture that reuses a fixed installation id across two tests and collides with itself on a second run.
  • Live: the Slack handshake echoes through the tunnel, the QA channel appears in discovery, and the Agenta channel control answers end to end.

https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT

…ce key

Three defects from the August live deploy (F70, F71, F73) kept a fresh
stack from ever answering a Slack message.

- A connection created from the setup form has no slug, so the insert
  died on a NOT NULL constraint and the error read "already exists".
  The service now names the connection after what verification
  discovered (Slack's workspace name) and derives a slug from that name
  with a short random suffix. A caller-supplied name or slug is kept.
  An unrelated integrity error now names the violated constraint, and
  a failed insert discards the credential secret it just wrote instead
  of leaving one orphan per retry.
- Slack registers an events URL only after the endpoint echoes its
  url_verification challenge. The Slack ingress now echoes it, unsigned
  and shape-strict; everything else on the route stays signed.
- The settings form filed the agent's workflow under a key nothing
  resolves. It now uses workflow_variant, and the agent data DTO refuses
  a reference key outside the families the workflows service resolves,
  so a bad key fails at write time instead of on the first turn.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
The release moved two helpers the channels pages imported: the date
formatter now lives in @agenta/shared, and the API key call in
@agenta/settings, which returns the key string directly. The settings
sidebar's exhaustive icon switch gets a channels case. The generated
update-secret payload type gains the channel secret member the API
already declares, so the secret state code type-checks again.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
The ingress dropped the adapter's space classification when it stored an
inbound event, so every space landed as a group and a kind-level grant
such as "allow in DMs" never matched. The event now carries the kind
through, and the DM seam test that exercises the real ingress passes.

Three integration and acceptance fixtures also learn what the code
grew after they were written: the ingress seam's duck-typed adapter
answers the deactivation probe, the deactivation seam sets the hosted
app secret the adapter verifies against, the DM seam marks its
connection verified, and the live Slack adapter test builds the adapter
the way the composition root does, with the real base URL.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
… ones

Space discovery called conversations.list once, with its arguments in a
JSON body. Slack ignores a JSON body on its read methods, so the call
always got the defaults: one page of 100 public channels, no cursor. A
workspace with more channels than that silently hid the rest, the QA
channel included.

Read methods (conversations.list, .history, .replies) now send their
arguments as query parameters, and discovery follows the cursor to the
end of the listing, public and private channels alike. The fake
workspace used by the unit tests reads query parameters the same way,
and a live test against the real workspace now finds the channel.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
agenta-documentation Ready Ready Preview Sep 8, 2026 1:25pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
📝 Summary

Summary by CodeRabbit

  • New Features

    • Slack integrations now support URL-verification handshakes and discover all available channels across multiple pages.
    • Channel connections automatically receive meaningful names and slugs when not provided.
    • Inbox events now retain the correct space classification.
    • Settings now use workflow variant references when creating or editing agents.
    • Added a dedicated Channels icon to the settings sidebar.
  • Bug Fixes

    • Improved connection error messages and cleanup after failed connection setup.
    • Added validation to prevent unsupported agent reference types.

Walkthrough

The pull request updates Slack ingress verification, channel discovery pagination, connection write handling, agent reference validation, and channel settings UI integration. It also updates test doubles and acceptance fixtures for the changed contracts.

Changes

Channel integrations

Layer / File(s) Summary
Slack ingress handling and event classification
api/oss/src/apis/fastapi/channels/ingress.py, api/oss/tests/pytest/integration/channels/*, api/oss/tests/pytest/unit/channels/test_channels_ingress.py
Slack URL verification challenges bypass signature checks and return a JSON response. Inbox events preserve space_kind. Integration fixtures match the updated adapter contract and connection state.
Slack discovery pagination and request transport
api/oss/src/core/channels/adapters/slack/adapter.py, api/oss/tests/pytest/unit/channels/slack/*, api/oss/tests/pytest/acceptance/channels/*
Slack discovery requests public and private active channels across cursor pages. Read arguments use query parameters, while write arguments use JSON bodies.
Connection defaults and cleanup
api/oss/src/core/channels/service.py, api/oss/tests/pytest/unit/channels/test_channels_connection_write_path.py
Missing connection names and slugs receive generated values. Failed inserts remove created secrets when possible. Conflict messages include the violated constraint or column.
Agent reference validation and form payloads
api/oss/src/core/channels/dtos.py, api/oss/tests/pytest/unit/channels/test_channels_agent_references.py, web/oss/src/components/pages/settings/Channels/components/AgentFormDrawer.tsx
Agent references are restricted to six resolvable families. The settings form uses workflow_variant and workflow_variant_id.
Channel settings UI wiring
web/oss/src/components/pages/AgentaChannelSurface/components/ConversationPanel.tsx, web/oss/src/components/pages/settings/Channels/components/*, web/packages/agenta-settings/src/sidebar.tsx
The channel UI uses shared date utilities, the updated API key return shape, and a channels sidebar icon.

Priority: ➖ Normal — Schedule the Channels stack changes because they address first-live-deploy blockers across Slack ingress, channel discovery, connection setup, agent references, and settings UI.

Estimated code review effort: 4 (Complex) | ~45 minutes

Severity of issue fixed: Low

Merge Risk: 🟠 High · up to 03db9

Editing some channel agents can break their target, empty targets remain accepted, and failed hosted installations can retain orphaned credentials. These should be fixed before merge.

Sequence Diagram(s)

sequenceDiagram
  participant Slack
  participant ingest_slack_event
  participant _slack_url_verification_challenge
  Slack->>ingest_slack_event: Send url_verification payload
  ingest_slack_event->>_slack_url_verification_challenge: Parse request body
  _slack_url_verification_challenge-->>ingest_slack_event: Return challenge
  ingest_slack_event-->>Slack: Return JSON challenge
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.81% which is insufficient. The required threshold is 60.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 59 functions across 21 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the deployment-blocking Channels fixes, including slug generation, Slack handshake handling, reference keys, space classification, and channel listing.
Description check ✅ Passed The description directly explains the changes, their deployment context, and the associated test results. It is fully related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch channels/fix-deploy-blockers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The two differential acceptance tests shared one Slack team id, app id,
and bridge source. The connection identity key is unique across projects,
so the second test collided with the first one's rows. Each fixture
instance now mints its own ids, and the file passes as a whole.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
@mmabrouk

mmabrouk commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

Codex (astra, medium, with the simplify skill) reviewed this lane. Verdict: mostly sound, no architecture changes. Four points, all applied in the last commit:

  1. The channel listing had a 50-page cap that could still truncate silently. Removed; discovery follows the cursor until Slack returns none.
  2. The fake Slack workspace accepted read arguments from both the query string and a JSON body, which would hide a regression of the query-parameter fix. It now reads query parameters only for read methods, as Slack does.
  3. Two tests strengthened: the reference-key test states the contract explicitly, and a new test proves a failed secret cleanup still surfaces the conflict.
  4. Renames: the helper is _fill_connection_name_and_slug, the form field is workflow_variant_id.

Channels unit tier after the changes: 681 pass.

- Space discovery follows the listing cursor until Slack returns none;
  the page cap is gone, since Slack filters after paging and a cap can
  truncate a real workspace.
- The fake Slack workspace reads a read method's arguments from the
  query string only, as Slack does, so an adapter that sends a JSON body
  gets the defaults and the test sees it. The paging test asserts cursor
  progression rather than a call count.
- The reference-key test spells out the contract instead of reading it
  back from the implementation, and a new test proves a failed secret
  cleanup still surfaces the real conflict.
- The name-and-slug helper is named for what it does, and the agent
  form's field is named for what it holds: a variant id.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
@mmabrouk

mmabrouk commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/oss/src/core/channels/service.py (1)

310-313: 🔒 Security & Privacy | 🛡️ Analyzed with Security Review | 🟠 Major | ⚡ Quick win

Sensitive Data Exposure (CWE-459)

Reachability: External · Exploitability: Moderate

Clean up the new secret on this insert failure path.

When no connection exists, install_connection writes credentials to the vault before create_connection. If the insert raises IntegrityError, the handler raises the conflict but leaves the new secret stored without a connection record. Delete only that newly created secret before raising the conflict.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 3f440bb9-c610-48fb-ba21-0aedf4e1edc7

📥 Commits

Reviewing files that changed from the base of the PR and between 0009112 and 03db9fd.

⛔ Files ignored due to path filters (1)
  • web/packages/agenta-api-client/src/generated/api/types/UpdateSecretPayloadDto.ts is excluded by !**/generated/**
📒 Files selected for processing (21)
  • api/oss/src/apis/fastapi/channels/ingress.py
  • api/oss/src/core/channels/adapters/slack/adapter.py
  • api/oss/src/core/channels/dtos.py
  • api/oss/src/core/channels/service.py
  • api/oss/tests/pytest/acceptance/channels/differential/test_slack_in_process_vs_bridged.py
  • api/oss/tests/pytest/acceptance/channels/test_slack_adapter_live.py
  • api/oss/tests/pytest/integration/channels/test_channels_ingress_seam.py
  • api/oss/tests/pytest/integration/channels/test_channels_ingress_slack_seam.py
  • api/oss/tests/pytest/integration/channels/test_channels_slack_deactivation_seam.py
  • api/oss/tests/pytest/unit/channels/slack/fake_slack.py
  • api/oss/tests/pytest/unit/channels/slack/test_slack_adapter.py
  • api/oss/tests/pytest/unit/channels/slack/test_slack_over_fake.py
  • api/oss/tests/pytest/unit/channels/test_channels_agent_references.py
  • api/oss/tests/pytest/unit/channels/test_channels_connection_write_path.py
  • api/oss/tests/pytest/unit/channels/test_channels_ingress.py
  • web/oss/src/components/pages/AgentaChannelSurface/components/ConversationPanel.tsx
  • web/oss/src/components/pages/settings/Channels/components/AgentFormDrawer.tsx
  • web/oss/src/components/pages/settings/Channels/components/ConnectionsSection.tsx
  • web/oss/src/components/pages/settings/Channels/components/InboxEventsSection.tsx
  • web/oss/src/components/pages/settings/Channels/components/OutboxEventsSection.tsx
  • web/packages/agenta-settings/src/sidebar.tsx

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.

Comment thread api/oss/src/core/channels/dtos.py
- An agent's reference map must name something: an empty map is refused
  at write time, since such an agent would fail on its first turn. The
  placeholder fixtures name a revision now.
- The settings form keeps the reference family an existing agent was
  saved with when it edits the agent; only a new agent is filed as a
  variant.

Claude-Session: https://claude.ai/code/session_01HXt8WBUK9MrWKNTYbUKpaT
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.

1 participant