Skip to content

Add self-service connector offboarding + approved-email-domain allowlist - #3

Merged
NextLevelManagementAdvisors merged 1 commit into
mainfrom
claude/connector-offboarding-approved-domains-v8l25d
Aug 5, 2026
Merged

Add self-service connector offboarding + approved-email-domain allowlist#3
NextLevelManagementAdvisors merged 1 commit into
mainfrom
claude/connector-offboarding-approved-domains-v8l25d

Conversation

@ai-nlma

@ai-nlma ai-nlma commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Offboarding was manual DBA work (README pointed at a raw DELETE), and the
only access gate was GITHUB_ALLOWED_USERS — a per-login list, so admitting a
whole company meant enumerating its people one at a time.

Access control:

  • GITHUB_APPROVED_EMAIL_DOMAINS admits any user with a verified GitHub email
    on an approved domain, subdomains included. Unverified addresses never count;
    anyone can type someone@your-company.com into a GitHub profile.
  • OR'd with GITHUB_ALLOWED_USERS: named individuals via one list, whole
    companies via the other, both empty = open as before.
  • Fails closed when a domain gate is configured but /user/emails is
    unreadable, with an error telling the user to re-authorize.
  • Adds user:email to the default scopes and stores the admitting email on
    github_users, preserved across token refreshes.

Offboarding — users turn their own connector off, on any approved domain:

  • GET /disconnect → POST /disconnect/start → GitHub → callback, reusing the
    existing redirect via a pending-state purpose column.
  • POST /disconnect for clients holding a bearer token.
  • Both delete every opaque token, in-flight auth code, the encrypted GitHub
    credentials and the tenants row in one transaction, then revoke the OAuth App
    grant on GitHub so the connector is off rather than merely forgotten.
  • audit_log rows are retained; they identify users only by a salted hash.
  • Deliberately not domain-gated: gating a privilege reduction would strand
    users whose domain was later removed from the allowlist.

Verified against a scratch Postgres 16: migrations idempotent across reruns,
22 DB-layer assertions (including that a token refresh can't blank a stored
email and that offboarding never touches a second user), the 15-case
allowlist decision matrix, and the HTTP surface end to end.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01HxTDjBKzBnaAvzMEY4DpQi

Offboarding was manual DBA work (README pointed at a raw DELETE), and the
only access gate was GITHUB_ALLOWED_USERS — a per-login list, so admitting a
whole company meant enumerating its people one at a time.

Access control:
- GITHUB_APPROVED_EMAIL_DOMAINS admits any user with a *verified* GitHub email
  on an approved domain, subdomains included. Unverified addresses never count;
  anyone can type someone@your-company.com into a GitHub profile.
- OR'd with GITHUB_ALLOWED_USERS: named individuals via one list, whole
  companies via the other, both empty = open as before.
- Fails closed when a domain gate is configured but /user/emails is
  unreadable, with an error telling the user to re-authorize.
- Adds user:email to the default scopes and stores the admitting email on
  github_users, preserved across token refreshes.

Offboarding — users turn their own connector off, on any approved domain:
- GET /disconnect → POST /disconnect/start → GitHub → callback, reusing the
  existing redirect via a pending-state `purpose` column.
- POST /disconnect for clients holding a bearer token.
- Both delete every opaque token, in-flight auth code, the encrypted GitHub
  credentials and the tenants row in one transaction, then revoke the OAuth App
  grant on GitHub so the connector is off rather than merely forgotten.
- audit_log rows are retained; they identify users only by a salted hash.
- Deliberately not domain-gated: gating a privilege reduction would strand
  users whose domain was later removed from the allowlist.

Verified against a scratch Postgres 16: migrations idempotent across reruns,
22 DB-layer assertions (including that a token refresh can't blank a stored
email and that offboarding never touches a second user), the 15-case
allowlist decision matrix, and the HTTP surface end to end.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HxTDjBKzBnaAvzMEY4DpQi
@NextLevelManagementAdvisors
NextLevelManagementAdvisors merged commit 3844bc4 into main Aug 5, 2026
1 check failed
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.

3 participants