Skip to content

feat(slack-app): Phase 1 MVP with Nango multi-workspace OAuth#1561

Closed
victor-inkeep wants to merge 1 commit intomainfrom
feat/slack-app-phase1-mvp
Closed

feat(slack-app): Phase 1 MVP with Nango multi-workspace OAuth#1561
victor-inkeep wants to merge 1 commit intomainfrom
feat/slack-app-phase1-mvp

Conversation

@victor-inkeep
Copy link
Copy Markdown
Contributor

Summary

Phase 1 MVP of the Inkeep Slack bot with multi-workspace OAuth via Nango.

What's Included

  • OAuth: Nango-managed flow with workspace credential caching (5-min TTL)
  • Commands: /inkeep, /inkeep login|logout|status|default|help
  • Conversations: @mentions (public threads), DMs (private), message shortcuts
  • Config: Channel default agent settings

OAuth Flow

POST /api/nango/connect → Nango Connect → Slack OAuth
    → Nango webhook saves workspace → /connect/success

Key Files

  • src/app/api/nango/ - OAuth endpoints
  • src/bolt/ - Bolt.js handlers (commands, events, actions)
  • src/lib/slack-credentials.ts - Token caching + workspace lookup

Testing

pnpm dev:tunnel   # ngrok + dev server
pnpm check        # typecheck, lint, tests

	Implement core Slack bot functionality:
	 - Nango OAuth flow with workspace credential caching
	 - Bolt.js handlers: commands, mentions, DM's shortcuts
	 - /inkeep command with ask modal (project -> agent selection)
	 - Channel default agent configuration
	 - Vercel deploymnet support
	 - Set up ngrok tunnel script for local development
@victor-inkeep victor-inkeep self-assigned this Jan 23, 2026
@victor-inkeep victor-inkeep added the enhancement New feature or request label Jan 23, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jan 23, 2026

⚠️ No Changeset found

Latest commit: bf572b8

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 23, 2026

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

Project Deployment Review Updated (UTC)
agents-api Ready Ready Preview, Comment Jan 23, 2026 5:26pm
agents-docs Ready Ready Preview, Comment Jan 23, 2026 5:26pm
agents-manage-ui Ready Ready Preview, Comment Jan 23, 2026 5:26pm

Request Review

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 23, 2026

Claude finished @victor-inkeep's task —— View job


Code Review: Slack App Phase 1 MVP

After conducting a comprehensive review of this Slack app implementation, I have several architectural and code quality considerations to share. This is a well-structured MVP with solid foundations, but there are opportunities for improvement across security, error handling, performance, and system design.

🏗️ System Architecture & Design

Strengths

  • Clean multi-workspace architecture: The use of dynamic authorization with Nango-managed OAuth connections is well-designed
  • Proper separation of concerns: Clear boundaries between Bolt.js handlers, credential management, and database operations
  • Database schema design: Well-normalized schema with proper foreign keys and indexes

Areas for Consideration

1. Database Access Layer Inconsistency ⚠️

The codebase has mixed approaches to database access:

  • src/lib/slack-credentials.ts:92 - Uses db.query.slackWorkspaces.findFirst() (Drizzle-style)
  • src/lib/db.ts:83-100 - Shows mock implementation with TODO comments
  • Actual database operations are stubbed with mock implementations

Recommendation: Consolidate on either the agents-core database client or implement a proper abstraction layer. The current mixed approach could lead to runtime errors.

2. Error Handling & Resilience

Several critical paths lack proper error boundaries:

// src/lib/slack-credentials.ts:91-108
const workspace = await db.query.slackWorkspaces.findFirst({ where: { teamId } });
// No handling if DB connection fails or times out
// src/bolt/app.ts:63-98
async function authorize({ teamId, enterpriseId }) {
  // Falls back to env token on ANY error, masking real issues
  if (env.SLACK_BOT_TOKEN) {
    console.warn('[Bolt authorize] Using SLACK_BOT_TOKEN fallback after error');
    return { botToken: env.SLACK_BOT_TOKEN };
  }
}

Recommendations:

  • Implement circuit breakers for external API calls (Nango, database)
  • Add structured error types instead of generic catches
  • Implement retry logic with exponential backoff
  • Add health checks for critical dependencies

3. Security Considerations 🔒

Webhook Verification:

// src/app/api/nango/webhook/route.ts:86-94
const verified = await nango.verifyIncomingWebhookRequest(rawBody, headers);

Good use of SDK verification, but consider adding rate limiting and IP allowlisting.

Token Caching:

// src/lib/slack-credentials.ts:42-58
const tokenCache = new Map<string, { token: string; expiresAt: number }>();

In-memory caching means tokens are lost on restart. Consider:

  • Using Redis for shared cache across instances
  • Encrypting cached tokens
  • Adding cache invalidation on security events

Environment Variables:
The src/lib/env.ts file properly validates env vars, but consider:

  • Adding runtime validation for secret rotation
  • Masking secrets in logs more comprehensively
  • Using a secrets manager instead of env vars for production

4. Performance & Scalability 📈

Connection Pool Management:

// src/lib/nango.ts:36-45
let nangoClient: Nango | null = null;
export function getNango(): Nango {
  if (!nangoClient) {
    nangoClient = new Nango({ secretKey: env.NANGO_SECRET_KEY });
  }
  return nangoClient;
}

Singleton pattern is good, but consider connection pooling and health checks.

Caching Strategy:

// src/lib/slack-credentials.ts:45
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes

5-minute TTL seems reasonable, but consider:

  • Different TTLs for different data types
  • Cache warming strategies
  • Monitoring cache hit rates

🧮 Code Quality & Patterns

Positive Patterns

  • Consistent use of TypeScript with proper typing
  • Good separation between configuration (env.ts) and business logic
  • Proper use of Zod for validation
  • Clean file organization following domain boundaries

Areas for Improvement

1. Type Safety 🔧

// src/lib/slack-credentials.ts:99, 208
const mapped = workspace as SlackWorkspace;

Type assertions should be replaced with proper validation using Zod schemas.

2. Consistent Error Patterns

// Multiple files show inconsistent error handling
console.error('[NangoWebhook] Error:', error);  // Some places
logger.error('[/inkeep login] Error:', error);  // Other places

Standardize on structured logging with correlation IDs.

3. Magic Numbers & Configuration

// src/lib/nango.ts:69, 172
setTimeout(() => reject(new Error('Nango API timeout')), 5000)  // 5s timeout
setTimeout(() => reject(new Error('Nango API timeout')), 10000) // 10s timeout

Extract timeouts to configuration constants.

🔄 Extensibility & Maintainability

Good Practices

  • Modular listener registration in Bolt.js
  • Clear interfaces and type definitions
  • TODO comments indicating future integration plans

Enhancement Opportunities

1. Configuration Management

Consider creating a centralized configuration system:

export const CONFIG = {
  cache: { ttlMs: 5 * 60 * 1000 },
  timeouts: { nango: 5000, database: 3000 },
  retry: { maxAttempts: 3, backoffMs: 1000 }
} as const;

2. Observability

Add structured metrics and tracing:

  • Request/response times for external calls
  • Cache hit/miss rates
  • OAuth flow completion rates
  • Error rates by type

3. Testing Strategy

The PR shows minimal test coverage. Consider adding:

  • Unit tests for core business logic
  • Integration tests for OAuth flows
  • End-to-end tests for Slack command flows
  • Contract tests for external API dependencies

📋 Specific Recommendations

High Priority

  1. Implement proper database client integration - Replace mock implementations
  2. Add comprehensive error handling - Especially for external API calls
  3. Secure token caching - Consider encryption and distributed cache
  4. Add webhook rate limiting - Prevent abuse of OAuth endpoints

Medium Priority

  1. Standardize logging - Use structured logging throughout
  2. Extract configuration constants - Remove magic numbers
  3. Improve type safety - Replace type assertions with validation
  4. Add health checks - For all external dependencies

Future Considerations

  1. Implement circuit breakers - For resilience
  2. Add comprehensive testing - Unit, integration, e2e
  3. Consider event sourcing - For audit trails
  4. Plan for horizontal scaling - Stateless design considerations

🎯 Summary

This is a solid MVP implementation that demonstrates good architectural thinking and clean code organization. The multi-workspace OAuth design is particularly well-thought-out. The main areas for improvement center around production readiness: error handling, observability, security hardening, and proper database integration.

The codebase shows clear planning for future integration with the broader agents-core system, which is excellent forward-thinking. I'd recommend prioritizing the database integration and error handling improvements before moving to production.

Overall Assessment: Good architectural foundation with clear improvement path for production readiness.


* Fallback (dev only):
* - Uses SLACK_BOT_TOKEN env var if workspace lookup fails
*/
async function authorize({
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: Add enterpriseId to workspace schema for Enterprise Grid support. Unique key should be enterpriseId + teamId

@@ -0,0 +1,163 @@
//agents-core/src/db/manage/slack-schema.ts
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: Add enterpriseId column

/**
* TODO: Replace with actual agents-core imports once monorepo is set up:
* import { getSlackWorkspaceByTeamId } from '@inkeep/agents-core/data-access/manage/slack';
*/
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: Add to SlackWorkspace interface enterpriseId

// src/app/api/nango/webhook/route.ts
// Nango webhook handler for OAuth and connection events
// ============================================================

Copy link
Copy Markdown
Contributor Author

@victor-inkeep victor-inkeep Jan 23, 2026

Choose a reason for hiding this comment

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

TODO: Update to capture enterpriseId from OAuth response

@victor-inkeep victor-inkeep deleted the feat/slack-app-phase1-mvp branch February 4, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant