Skip to content

Commit e623802

Browse files
nick-inkeepclaudeamikofalvy
authored
feat: channel-based agent authorization for Slack (#2033)
* feat: add channel-based agent authorization for Slack Enable linked Slack users in channels with configured default agents to execute those agents without explicit SpiceDB project membership. Changes: - Extend JWT schema with channel auth claims (authorized, authSource, channelId, authorizedProjectId) - Add SpiceDB bypass in trySlackUserJwtAuth when channel-authorized with project binding verification (D8) - Extend BaseExecutionContext metadata with slack auth context - Switch app-mention.ts from resolveChannelAgentConfig to resolveEffectiveAgent (D7) and pass channel auth params - Update slash command background exec to pass channel auth params - Add comprehensive tests for bypass logic, project mismatch rejection, and graceful fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace non-null assertion with safe fallback in auth metadata Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update app-mention tests to use resolveEffectiveAgent Tests were mocking the old resolveChannelAgentConfig from utils, but the implementation now imports resolveEffectiveAgent from agent-resolution. Updated all test cases to mock the correct module and include the required `source` field in mock return values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback - schema invariant, tests, changeset Review feedback addressed: Major: - Add .refine() to SlackAccessTokenPayloadSchema enforcing that when authorized=true, authorizedProjectId and authSource are required - Add changeset for agents-core (patch) - Add signSlackUserToken channel auth param verification in app-mention test Minor: - Change BaseExecutionContext.metadata.slack.authorized to literal `true` since the field is only populated when authorization is granted Consider: - Add debug log in runAuth.ts when channel auth bypass is not applied - Add test for authSource default fallback to 'channel' - Add schema invariant enforcement tests (authorized without authorizedProjectId, authorized without authSource) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Phase 2 channel auth — modal/command slackAuthorized:false + OTel spans - Modal submissions (call sites 3-4): explicit slackAuthorized: false - /inkeep run and /inkeep list (call sites 6-7): explicit slackAuthorized: false - OTel: add AUTHORIZED and AUTH_SOURCE to SLACK_SPAN_KEYS - Set slack.authorized and slack.auth_source span attributes in app-mention and modal-submission handlers - Add modal-submission test file verifying slackAuthorized: false and span attributes - Add workspace auth source test to app-mention tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add configurable grantAccessToMembers toggle for channel agent auth Adds a per-channel-config boolean (default: true) that controls whether channel members get implicit project access via the Slack auth bypass. When disabled, members need explicit project access even if an agent is configured for the channel. Full stack: DB schema + migration, data access, agent resolution, JWT signing, API validation, and Manage UI toggle in channel agent popover. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback for grantAccessToMembers - Add aria-hidden to decorative ShieldCheck icon - Add grantAccessToMembers to listChannels API return type - Explicitly set grantAccessToMembers: true in bulk set operations - Add test for workspace config with explicit grantAccessToMembers: false - Add command-question tests verifying JWT authorization for grantAccessToMembers true/false cases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update changeset to cover grantAccessToMembers DB column and full-stack toggle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add channel-based authorization and grantAccessToMembers toggle to Slack docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update OpenAPI snapshot to include grantAccessToMembers field Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: trigger CI * fix formatting * fix: remove incomplete handleRunCommand and handleAgentListCommand handlers These handlers referenced three undefined functions (findAgentByIdentifier, fetchAgentsFromManageApi, createAgentListMessage) that were never implemented, breaking CI typecheck. The handlers were also not wired into the handleCommand switch statement. Removed them along with the orphaned createAgentListMessage test mock. The /inkeep run and /inkeep list commands can be added in a follow-up PR. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: docs mismatch and toggle clarity for grant access setting - Update configuration.mdx to say workspace defaults "grant access by default" instead of "always grant access", matching the implementation which supports explicit false via API - Replace double-negative toggle logic (!== false) with nullish coalescing (?? true) for clearer intent in channel-agent-cell.tsx Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * better iconigraphy * [US-001] Add tests for API error message surfacing in Slack responses Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: surface API errors, add workspace grant toggle, add Slack profile links - Surface actual API error messages in Slack instead of generic "Something went wrong" by parsing response body. Falls back to classified errors when body can't be parsed. Applied to streaming, commands, and modal submissions. - Add grantAccessToMembers toggle to workspace default section, mirroring the channel-level toggle. Includes handler, toast feedback, and read-only state for non-admins. - Add "View in Slack" profile link to MyLinkStatus and LinkedUsersSection using https://app.slack.com/team/{slackUserId}. Opens in new tab. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: add PR screenshots for channel auth UX Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: clarify workspace grant access toggle messaging Make it explicit that the toggle grants access to any Slack workspace member, not just vaguely "workspace members". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add aria-hidden to icons inside accessible span Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use mockFetch instead of global.fetch in streaming tests The streaming code uses getInProcessFetch() not global.fetch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update api-key-auth test assertions to include tenantId The canUseProjectStrict call now includes tenantId after a change on main. Update test expectations to match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix pixel match --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>
1 parent 4cd35aa commit e623802

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+5496
-121
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@inkeep/agents-core": patch
3+
---
4+
5+
Add channel-based agent authorization for Slack with configurable `grantAccessToMembers` toggle
6+
7+
- Extend `SlackAccessTokenPayloadSchema` with `authorized`, `authSource`, `channelId`, `authorizedProjectId` claims
8+
- Add `grantAccessToMembers` column to `work_app_slack_channel_agent_configs` table (default `true`)
9+
- Extend `BaseExecutionContext` with `metadata.slack` for channel auth context
10+
- Add `resolveEffectiveAgent` with `grantAccessToMembers` propagation from channel/workspace config
264 KB
Loading
276 KB
Loading
253 KB
Loading
278 KB
Loading

agents-api/__snapshots__/openapi.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38491,6 +38491,9 @@
3849138491
"agentName": {
3849238492
"type": "string"
3849338493
},
38494+
"grantAccessToMembers": {
38495+
"type": "boolean"
38496+
},
3849438497
"projectId": {
3849538498
"type": "string"
3849638499
},
@@ -38597,6 +38600,9 @@
3859738600
"agentName": {
3859838601
"type": "string"
3859938602
},
38603+
"grantAccessToMembers": {
38604+
"type": "boolean"
38605+
},
3860038606
"projectId": {
3860138607
"type": "string"
3860238608
},
@@ -38765,6 +38771,9 @@
3876538771
"agentName": {
3876638772
"type": "string"
3876738773
},
38774+
"grantAccessToMembers": {
38775+
"type": "boolean"
38776+
},
3876838777
"projectId": {
3876938778
"type": "string"
3877038779
},
@@ -38947,6 +38956,9 @@
3894738956
"agentName": {
3894838957
"type": "string"
3894938958
},
38959+
"grantAccessToMembers": {
38960+
"type": "boolean"
38961+
},
3895038962
"projectId": {
3895138963
"type": "string"
3895238964
},
@@ -39018,6 +39030,9 @@
3901839030
"agentName": {
3901939031
"type": "string"
3902039032
},
39033+
"grantAccessToMembers": {
39034+
"type": "boolean"
39035+
},
3902139036
"projectId": {
3902239037
"type": "string"
3902339038
},
@@ -39192,6 +39207,9 @@
3919239207
"agentName": {
3919339208
"type": "string"
3919439209
},
39210+
"grantAccessToMembers": {
39211+
"type": "boolean"
39212+
},
3919539213
"projectId": {
3919639214
"type": "string"
3919739215
},
@@ -39249,6 +39267,9 @@
3924939267
"agentName": {
3925039268
"type": "string"
3925139269
},
39270+
"grantAccessToMembers": {
39271+
"type": "boolean"
39272+
},
3925239273
"projectId": {
3925339274
"type": "string"
3925439275
},

0 commit comments

Comments
 (0)