Skip to content

Add Slack workspace assistant and Cloud integration-gateway client - #499

Merged
mortondev merged 16 commits into
mainfrom
feat/slack-agent-integration-gateway
Sep 7, 2026
Merged

Add Slack workspace assistant and Cloud integration-gateway client#499
mortondev merged 16 commits into
mainfrom
feat/slack-agent-integration-gateway

Conversation

@mortondev

@mortondev mortondev commented Sep 5, 2026

Copy link
Copy Markdown
Member

Adds a Slack workspace assistant. Linked teammates can ask in mentions, DMs, slash commands, and follow-up thread messages; they get cited answers, and writes (feedback posts or internal tickets) are proposed then approved by an authorized member.

  • Assistance is off by default. Identity linking, team-audience retrieval, streaming, approval cards, and uninstall/reinstall handling are included.
  • Self-hosted Slack talks directly to the tenant (/api/integrations/slack/hooks/*). Cloud uses the control-plane gateway (OAuth bounce and signed hook forwarder). Shared Cloud OAuth credentials are Railway INTEGRATION_<PROVIDER>_* environment variables on CP and the fleet — not a CP JSON settings overlay.
  • Thread follow-up: once the bot is in a thread, further messages are classified (reply / ignore / stop) with a 45-minute idle session (migration 0275_slack_thread_sessions).
  • Transport payloads are encrypted and short-lived. Successful slack-hook jobs discard the payload atomically.
  • Tenant migrations 0274_slack_agent_gateway and 0275_slack_thread_sessions. Slack manifest and rollout runbook included.

Validation: focused unit tests for hooks/addressing, assistant settings, migrator gate, jobs, OAuth/installs, and related suites. Typecheck is clean on the worktree. Live Slack evals need a real model and database; they are not a substitute for the rollout gates.

Cloud rollout: apply CP migration 0092_integration_installs, set INTEGRATION_SLACK_*, REDIS_URL, and INTEGRATION_GATEWAY_FORWARD_SECRET on CP and the fleet, then follow docs/integrations/integration-gateway-rollout.md. Self-host does not need the CP gateway. Nothing has been deployed.

Companion CP PR: https://github.com/QuackbackIO/quackback-cp/pull/198

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-07T15:41:47.895008Z 7f937c8 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Comment thread apps/web/src/integrations/slack/server/agent/handler.ts Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b3273051e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/lib/server/domains/assistant/workspace-retrieval.ts Outdated
Comment thread apps/web/src/integrations/slack/server/agent/handler.ts Outdated
Comment thread apps/web/src/lib/server/domains/assistant/assistant.toolspec.ts
@mortondev mortondev changed the title Add Slack workspace assistant for Cloud and self-hosted instances Add Slack workspace assistant and CP-managed Cloud OAuth Sep 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79f8dac975

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/lib/server/integrations/save.ts Outdated
Comment thread apps/web/src/lib/server/integrations/install-registry.ts Outdated
@mortondev mortondev changed the title Add Slack workspace assistant and CP-managed Cloud OAuth Add Slack workspace assistant and Cloud startup settings Sep 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c04f68c93

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/integrations/slack/scopes.ts
Comment thread apps/web/src/lib/server/domains/assistant/tools/feedback-tools.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 248297f1b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/lib/server/integrations/save.ts Outdated
…gration-gateway

# Conflicts:
#	apps/web/src/lib/server/policy/authz-matrix/MATRIX.md
#	apps/web/src/lib/server/policy/dep-graph/GRAPH.md
@mortondev

Copy link
Copy Markdown
Member Author

Addressed the current review findings:

  • Apply the member's conversation visibility filter before retrieval, and require private-feedback/ticket read permissions for the corresponding workspace sources and feedback tools.
  • Explicitly request and validate assistant:write.
  • Require only feedback creation permission for workspace feedback capture; conversation proxy-vote behavior retains its existing permissions.
  • Include provider ownership proof when registering an install. Reconnect queues durable cleanup of the previous team binding; cleanup checks the current install under the same lock before removing a binding. Disconnect and revocation preserve retry behavior when CP unregister fails.
  • Only the installed bot's token revocation disconnects the integration; user OAuth token revocations do not.

Also fixed CI findings: replay-safe migration guards, refusal of the older migration that downgrades the assistant default, schema constraint names, tool output gate envelopes, principal merge handling, queue registration wrappers, and generated policy documents. Merged current main and regenerated the two conflicting policy documents.

Local validation: fresh migration and schema drift passed; the broad tenant run passed 14,664 tests, followed by 24 passing principal-merge tests after fixing their shared mock. Slack follow-up tests (15), policy merge tests (76), and TypeScript passed. The local cross-repo vendor comparison still reports the pre-existing servingVersion contract mismatch between app main and CP; the app contract is unchanged by this PR. GitHub CI will validate the merged head.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8e749d277b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/integrations/slack/server/agent/handler.ts Outdated
Comment thread apps/web/src/integrations/slack/server/agent/handler.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 02ddd9b859

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/lib/shared/platform-settings.ts Outdated
Comment thread apps/web/src/integrations/slack/server/agent/settings.ts
Comment thread apps/web/scripts/backfill-integration-installs.ts Outdated
Comment thread apps/web/src/lib/server/domains/assistant/workspace-retrieval.ts Outdated
@mortondev

Copy link
Copy Markdown
Member Author

Addressed the latest two findings in 19b16ec:

  • Revocation now takes the same provider advisory lock as reconnect, re-reads the install, and checks its token/connection stamp before unregistering or disconnecting. Old Slack events are ignored after a later reinstall. CP unregister failures still propagate without changing local state.
  • Decision execution and Slack presentation are separate. Failed message updates propagate to the durable hook job; a retry reads the persisted terminal proposal and updates Slack without executing the feedback/ticket write again.

Validation: 20 focused Slack tests and TypeScript passed. The preceding merged head had all GitHub build, four test shards, smoke, live API and CodeQL checks green; this follow-up is running fresh CI.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19b16ec015

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/integrations/slack/server/agent/handler.ts
Comment thread apps/web/src/integrations/slack/server/agent/handler.ts Outdated
@mortondev

Copy link
Copy Markdown
Member Author

Addressed the six remaining findings in 2fe7b03:

  • Fleet root is bootstrap-only in both the app and CP settings validators.
  • Optional provider fields no longer prevent complete env credentials from being selected.
  • Cloud Slack enablement requires a current registered route; unavailable CP fails closed.
  • Explicit install backfill includes dormant workspaces; regular fleet sweeps retain dormancy behavior.
  • Conversation search selects one matching message per conversation before applying the result limit.
  • A failed local transaction compensates a successful CP registration under the provider lock, preserving a concurrently committed install; failed cleanup is queued durably for retry.

Validation: 42 focused settings/source/fleet tests, 8 real-database retrieval/rollback tests, and TypeScript passed. CP's matching bootstrap contract tests passed (15, with 2 database tests skipped).

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2fe7b03670

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/integrations/slack/server/agent/handler.ts
@mortondev

Copy link
Copy Markdown
Member Author

c484bdd fixes the remaining runtime review findings:

  • Workspace turns require the requesting actor, and Slack passes its resolved member actor through to the tool context. Missing actors fail closed rather than falling back to Quinn's wider permissions.
  • Revocation reads settings before acquiring the integration transaction, uses that transaction for the settings write, and invalidates settings cache after commit. It does not request a second pool connection while holding the first.
  • Terminal proposal message retries bypass decision permissions after validating the linked member and Slack thread binding, so later permission changes cannot strand the completed decision.
  • Updated the tenant settings-contract digest missed in the previous push.

Validation: 157 runtime/Slack/settings tests, 121 runtime/contract tests after the digest correction, and TypeScript passed.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c484bdd715

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/src/lib/shared/platform-settings.ts Outdated
Comment thread apps/web/src/lib/server/functions/integrations.ts Outdated
Disconnect now takes the same provider lock as reconnect and refuses to
delete a row that changed under it. Stale Slack revocations compare the
full millisecond install timestamp, and Cloud settings cannot override
control-database or cache URLs.
Main claimed 0091 for workspace activity; the gateway migrations moved.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@mortondev

Copy link
Copy Markdown
Member Author

Addressed the remaining review findings in 02c1dd0:

  • Disconnect takes the same provider advisory lock as reconnect, re-reads the row, and refuses to unregister/delete if the token or connectedAt stamp changed.
  • Stale Slack revocations compare the full millisecond install timestamp, so a same-second reinstall is treated as newer.
  • QUACKBACK_CONTROL_DATABASE_URL, DATABASE_URL, and REDIS_URL are bootstrap-only in the shared settings validator.

Also merged main. 34 focused tests passed locally, including the new disconnect-lock cases.

@mortondev

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@mortondev mortondev changed the title Add Slack workspace assistant and Cloud startup settings Add Slack workspace assistant and Cloud integration-gateway client Sep 7, 2026
Use first-party MCP tools for workspace Slack, run create/assign as the
asking teammate, serialize chat streams, and abort on agent_session_stopped.
Drop the Cloud settings overlay from the tenant image. Add thread sessions.
…gration-gateway

# Conflicts:
#	apps/web/src/lib/server/jobs/runner.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5fb54fec5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +34 to +38
function scopesFromActor(actor: Actor): ApiKeyScope[] {
if (!actor.permissions || actor.permissions.size === 0) {
return isTeamMember(actor.role) ? [...API_KEY_SCOPES] : []
}
return orderScopes([...actor.permissions].map(scopeForPermission))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve exact permissions when opening workspace MCP

For a custom-role teammate whose resolved permissions contain copilot.use but not post.create, scopeForPermission maps that AI permission to write:feedback, so the MCP session exposes create_post, triage_post, and other feedback mutations. Those MCP handlers then reconstruct actors from the legacy member role without the resolved permission set, and the workspace path marks several writes autonomous, allowing Slack to perform actions the teammate cannot perform in the app. Preserve the actor's exact permissions through MCP authorization rather than widening them into category-level scopes.

Useful? React with 👍 / 👎.

Comment on lines +1080 to +1083
let { tools, activeSpecs } = await assembleAssistantToolset(toolContext, builtInSpecs, [
...workspaceMcpSpecs,
...connectorSpecs,
])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Apply workspace action rules to MCP replacements

When an administrator disables capture_feedback or create_ticket on the workspace-assistant page, the saved rule is applied only to builtInSpecs, while all workspaceMcpSpecs are appended unfiltered here. The workspace role subsequently removes those built-ins anyway, but MCP still supplies create_post and create_ticket, so disabled feedback creation can execute autonomously and disabled ticket creation can still be proposed and approved. Filter the MCP catalogue using the workspace rules, including mapping capture_feedback to its create_post replacement.

Useful? React with 👍 / 👎.

Comment on lines +372 to +376
if (event?.type === 'agent_session_stopped') {
const channel = event.channel
const thread = event.thread_ts
const user = event.user
if (typeof channel === 'string' && typeof thread === 'string') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Persist native Stop in the thread session

When a teammate presses Slack's native Stop button in an already-active assistant thread, this branch resets Slack's presentation status and returns without calling stopSlackThreadSession. The database session therefore remains active, and the next ordinary unmentioned reply in that thread satisfies the followUp predicate and invokes the assistant again despite the explicit Stop. Mark the persistent session stopped before returning from this event handler.

Useful? React with 👍 / 👎.

Ledger the in-flight Slack abort map, regenerate dep-graph/contract/schema
goldens, and import the MCP server only when a workspace turn opens so
mocked db tests do not pull search/sql at load time.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f937c8ff2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const event = payload.event
// Abort before enqueue: slack-hook is serial, so a Stop job would otherwise
// wait until the in-flight turn finished.
if (kind === 'events') abortSlackTurnFromPayload(payload)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route Stop cancellation to the worker process

In split-role deployments where the hook receiver runs with QUACKBACK_ROLE=web and turns run in a worker, this calls abortSlackTurnFromPayload against the web process's in-memory map, while beginSlackTurn registered the controller in a different process. The call therefore cannot cancel the active model request, and the queued Stop event waits behind that same slack-hook job; use an inter-process cancellation signal or handle Stop through worker-visible state rather than a process-local map.

Useful? React with 👍 / 👎.

Comment on lines +28 to +29
export function formatSlackAnswer(text: string): string {
return text.replace(/<@/g, '&lt;@').trim()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Escape Slack broadcast mention syntax

When model or retrieved text contains Slack special mentions such as <!channel>, <!here>, <!everyone>, or <!subteam^…>, this sanitizer leaves them intact because it only rewrites <@. Those tokens then reach chatStream and can notify an entire channel or user group; neutralize all Slack mention forms before appending or posting generated text.

Useful? React with 👍 / 👎.

@mortondev
mortondev merged commit 9a0e74e into main Sep 7, 2026
15 checks passed
@mortondev
mortondev deleted the feat/slack-agent-integration-gateway branch September 7, 2026 16:02
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