-
Notifications
You must be signed in to change notification settings - Fork 5
Description
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_tokenper 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
-
GitHub repos:
GitHubRepoProjectgets optionalsynced_by_user_id— sync uses that user's GitHub token instead of project-level token. Fallback to project token if user has none. -
Admin UI: User profile page → "Connected accounts" section with OAuth connect/disconnect buttons per provider.
-
GitHub commits: When Claude Code or bots make commits on behalf of a user, use that user's token so commits are correctly attributed.
-
Google OAuth (future): Per-user Google account for Calendar, Docs, Sheets integrations.
-
amoCRM (future consideration): Per-user amoCRM tokens for audit trail — who changed which lead.
Security
- Tokens encrypted at rest (AES-256 with
ADMIN_JWT_SECRETas key or separateENCRYPTION_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):
UserExternalAccountmodel + 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