Skip to content

feat: per-user external account connections (GitHub, Google, etc.) #484

@ShaerWare

Description

@ShaerWare

Problem

External service accounts (GitHub token, Google OAuth, etc.) are currently stored globally or per-workspace, not per-user. This means:

  • GitHub repos sync uses a single github_token per project (GitHubRepoProject.github_token) — all users share one GitHub identity
  • Two developers on the same server push commits and clone repos under the same GitHub account — impossible to distinguish who did what
  • Google integration (future: Calendar, Docs, Sheets) would have the same problem — one OAuth token for all users
  • amoCRM stores a single OAuth config per workspace (AmoCRMConfig) — shared credentials

This is a security and audit issue: actions taken by different users appear identical to external services.

Proposed Solution

New model: UserExternalAccount

user_external_accounts:
  id            INTEGER PK
  user_id       INTEGER FK → users (NOT NULL)
  provider      VARCHAR(50) — "github", "google", "amocrm", etc.
  provider_uid  VARCHAR(255) — external username/email (e.g. GitHub login)
  access_token  VARCHAR(500) — encrypted at rest
  refresh_token VARCHAR(500) — nullable (for OAuth2 providers)
  token_expires DATETIME — nullable
  scopes        TEXT — JSON list of granted scopes
  metadata      TEXT — JSON (avatar_url, display_name, etc.)
  created       DATETIME
  updated       DATETIME
  UNIQUE(user_id, provider)

Integration points

  1. GitHub repos: GitHubRepoProject gets optional synced_by_user_id — sync uses that user's GitHub token instead of project-level token. Fallback to project token if user has none.

  2. Admin UI: User profile page → "Connected accounts" section with OAuth connect/disconnect buttons per provider.

  3. GitHub commits: When Claude Code or bots make commits on behalf of a user, use that user's token so commits are correctly attributed.

  4. Google OAuth (future): Per-user Google account for Calendar, Docs, Sheets integrations.

  5. amoCRM (future consideration): Per-user amoCRM tokens for audit trail — who changed which lead.

Security

  • Tokens encrypted at rest (AES-256 with ADMIN_JWT_SECRET as key or separate ENCRYPTION_KEY)
  • Token scopes validated on connect
  • Revoke on user deactivation (GDPR cascade)
  • Never expose tokens in API responses (only has_token: true/false + provider_uid)

Scope

Phase 1 (MVP):

  • UserExternalAccount model + migration
  • GitHub OAuth connect flow in user profile
  • GitHub repos sync uses per-user token

Phase 2:

  • Google OAuth connect flow
  • Token refresh automation
  • Admin view of all connected accounts

Phase 3:

  • amoCRM per-user tokens
  • Audit log enrichment with external identity

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions