open-swe/agent/utils/github_user_email_map.py
Johannes du Plessis 427bfe4f56
feat: Store-backed GitHub/Slack user mapping (self-service + admin) (#1369)
* Replace hardcoded GitHub-email map with Store-backed user mapping

Move the static GITHUB_USER_EMAIL_MAP to a Store-backed bidirectional
mapping (GitHub login <-> work email <-> optional Slack ID) with an
in-process cache, self-service onboarding, and admin management.

- agent/dashboard/user_mappings.py: Store CRUD + login/email/slack-id
  indexes, sync cache readers for hot paths, async fallthrough, and a
  bulk_import that preserves existing richer records.
- Migrate all read sites (auth.py, agent_overrides.py, authorship.py,
  github_comments.py, webapp.py x2) off the dict.
- Unmapped Slack tags now run on the GitHub App installation token
  (use_installation_token_fallback) and get an ephemeral "link your
  GitHub account" prompt carrying the Slack id + email via a signed
  account-link token threaded through the OAuth state.
- OAuth callback completes a self-service (org-gated) mapping from that
  token, falling back to the verified GitHub email.
- Admin CRUD endpoints + one-time legacy import; dashboard UI section.
- Legacy dict retained only as the import payload (no longer read).

Tests: mapping store, account-link round-trip + completion, mapped vs
unmapped Slack flows; existing trust-gate tests updated to prime cache.

* Address review: cold-cache email resolution + stale alias de-indexing

- agent_overrides: add resolve_login_from_email_async that falls through to
  the Store on a cold cache; use it at the async repo-resolution call sites
  (Slack repo config, Linear comment, owner-metadata) so a mapped user still
  resolves to their GitHub login + dashboard default_repo on a fresh worker.
- user_mappings.upsert_mapping: de-index the existing login before re-indexing
  so a changed email/Slack id no longer leaves stale aliases resolving to the
  login in-process.
- Tests for both fixes; update Slack repo-config test to patch the async resolver.
2026-06-01 14:37:19 -07:00

134 lines
5.8 KiB
Python

"""Legacy GitHub-username → LangSmith-email mapping.
This dict is **no longer read at runtime**. The live mapping is the
Store-backed bidirectional record managed in
``agent/dashboard/user_mappings.py`` (Admin → User mappings in the
dashboard). This file is retained only as the payload for the one-time
``POST /dashboard/api/admin/user-mappings/import`` bulk import (the
"Import legacy mapping" admin button), which seeds the Store with
``source="hardcoded"`` entries. It can be deleted once every deployment has
run that import.
"""
GITHUB_USER_EMAIL_MAP: dict[str, str] = {
"aran-yogesh": "yogesh.mahendran@langchain.dev",
"AaryanPotdar": "aaryan.potdar@langchain.dev",
"agola11": "ankush@langchain.dev",
"akira": "alex@langchain.dev",
"amal-irgashev": "amal.irgashev@langchain.dev",
"andrew-langchain-gh": "andrew.selden@langchain.dev",
"andrewnguonly": "andrew@langchain.dev",
"andrewrreed": "andrew@langchain.dev",
"angus-langchain": "angus@langchain.dev",
"ArthurLangChain": "arthur@langchain.dev",
"asatish-langchain": "asatish@langchain.dev",
"ashwinamardeep-ashwin": "ashwin.amardeep@langchain.dev",
"asrira428": "siri.arun@langchain.dev",
"ayoung19": "andy@langchain.dev",
"baskaryan": "bagatur@langchain.dev",
"bastiangerstner": "bastian.gerstner@langchain.dev",
"bees": "arian@langchain.dev",
"bentanny": "ben.tannyhill@langchain.dev",
"bracesproul": "brace@langchain.dev",
"brianto-langchain": "brian.to@langchain.dev",
"bscott449": "brandon@langchain.dev",
"bvs-langchain": "brian@langchain.dev",
"bwhiting2356": "brendan.whiting@langchain.dev",
"carolinedivittorio": "caroline.divittorio@langchain.dev",
"casparb": "caspar@langchain.dev",
"catherine-langchain": "catherine@langchain.dev",
"ccurme": "chester@langchain.dev",
"christian-bromann": "christian@langchain.dev",
"christineastoria": "christine@langchain.dev",
"colifran": "colin.francis@langchain.dev",
"conradcorbett-crypto": "conrad.corbett@langchain.dev",
"cstanlee": "carlos.stanley@langchain.dev",
"cwaddingham": "chris.waddingham@langchain.dev",
"cwlbraa": "cwlbraa@langchain.dev",
"dahlke": "neil@langchain.dev",
"DanielKneipp": "daniel@langchain.dev",
"danielrlambert3": "daniel@langchain.dev",
"DavoCoder": "davidc@langchain.dev",
"ddzmitry": "dzmitry.dubarau@langchain.dev",
"denis-at-langchain": "denis@langchain.dev",
"dqbd": "david@langchain.dev",
"elibrosen": "eli@langchain.dev",
"emil-lc": "emil@langchain.dev",
"emily-langchain": "emily@langchain.dev",
"ericdong-langchain": "ericdong@langchain.dev",
"ericjohanson-langchain": "eric.johanson@langchain.dev",
"eyurtsev": "eugene@langchain.dev",
"gethin-langchain": "gethin.dibben@langchain.dev",
"gladwig2": "geoff@langchain.dev",
"GowriH-1": "gowri@langchain.dev",
"hanalodi": "hana@langchain.dev",
"hari-dhanushkodi": "hari@langchain.dev",
"hinthornw": "will@langchain.dev",
"hntrl": "hunter@langchain.dev",
"hwchase17": "harrison@langchain.dev",
"iakshay": "akshay@langchain.dev",
"sydney-runkle": "sydney@langchain.dev",
"tanushree-sharma": "tanushree@langchain.dev",
"victorm-lc": "victor@langchain.dev",
"vishnu-ssuresh": "vishnu.suresh@langchain.dev",
"vtrivedy": "vivek.trivedy@langchain.dev",
"will-langchain": "will.anderson@langchain.dev",
"xuro-langchain": "xuro@langchain.dev",
"yumuzi234": "zhen@langchain.dev",
"j-broekhuizen": "jb@langchain.dev",
"jacobalbert3": "jacob.albert@langchain.dev",
"jacoblee93": "jacob@langchain.dev",
"jdrogers940 ": "josh@langchain.dev",
"jeeyoonhyun": "jeeyoon@langchain.dev",
"jessieibarra": "jessie.ibarra@langchain.dev",
"jfglanc": "jan.glanc@langchain.dev",
"jkennedyvz": "john@langchain.dev",
"joaquin-borggio-lc": "joaquin@langchain.dev",
"joel-at-langchain": "joel.johnson@langchain.dev",
"johannes117": "johannes@langchain.dev",
"joshuatagoe": "joshua.tagoe@langchain.dev",
"katmayb": "kathryn@langchain.dev",
"kenvora": "kvora@langchain.dev",
"kevinbfrank": "kevin.frank@langchain.dev",
"KiewanVillatel": "kiewan@langchain.dev",
"l2and": "randall@langchain.dev",
"langchain-infra": "mukil@langchain.dev",
"langchain-karan": "karan@langchain.dev",
"lc-arjun": "arjun@langchain.dev",
"lc-chad": "chad@langchain.dev",
"lcochran400": "logan.cochran@langchain.dev",
"lnhsingh": "lauren@langchain.dev",
"longquanzheng": "long@langchain.dev",
"loralee90": "lora.lee@langchain.dev",
"lunevalex": "alunev@langchain.dev",
"maahir30": "maahir.sachdev@langchain.dev",
"madams0013": "maddy@langchain.dev",
"mdrxy": "mason@langchain.dev",
"mhk197": "katz@langchain.dev",
"mwalker5000": "mike.walker@langchain.dev",
"mlo20030": "morgan.lo@langchain.dev",
"natasha-langchain": "nwhitney@langchain.dev",
"nhuang-lc": "nick@langchain.dev",
"niilooy": "niloy@langchain.dev",
"nitboss": "nithin@langchain.dev",
"npentrel": "naomi@langchain.dev",
"nrc": "nick.cameron@langchain.dev",
"Palashio": "palash@langchain.dev",
"PeriniM": "marco@langchain.dev",
"pjrule": "parker@langchain.dev",
"QuentinBrosse": "quentin@langchain.dev",
"rahul-langchain": "rahul@langchain.dev",
"ramonpetgrave64": "ramon@langchain.dev",
"rx5ad": "rafid.saad@langchain.dev",
"saad-supports-langchain": "saad@langchain.dev",
"samecrowder": "scrowder@langchain.dev",
"samnoyes": "sam@langchain.dev",
"seanderoiste": "sean@langchain.dev",
"simon-langchain": "simon@langchain.dev",
"sriputhucode-ops": "sri.puthucode@langchain.dev",
"stephen-chu": "stephen.chu@langchain.dev",
"sthm": "steffen@langchain.dev",
"steve-langchain": "steve@langchain.dev",
"SumedhArani": "sumedh@langchain.dev",
"suraj-langchain": "suraj@langchain.dev",
}