Skip to content

GitHub Apps par lane : les comptes machine sont bridés au tarif anonyme (60 req/h, GraphQL 0) et hors-limite CGU #17437

Description

@myia-ai-01

Verdict

Les quatre comptes myia-po-2024/25/26/27 ne sont pas récupérables par un PAT. Mesuré ce soir, bout en bout. La voie sanctionnée par GitHub pour ce besoin est la GitHub App, et il y a une raison de ne pas attendre : le motif qui a fait bloquer les trois nouveaux comptes s'applique aussi aux deux anciens, qui portent nos merges.

Ce qui a été mesuré (2026-09-22)

1. Les comptes existent, sont vérifiés, et sont bridés

Porte myia-po-2024
connexion web (user, navigation privée) OK
settings/emails jsboige+myia-po-2024@gmail.com — Primary, Verified
gh api user (PAT classique repo, workflow) login=myia-po-2024, id=332469827
invitation collaborateur posée et acceptée, rc=0
repos/jsboige/CoursIA → .permissions push: true
profil public users/myia-po-2024 404 — sous jsboige admin, sous myia-ai-01, et sans jeton
rate_limit REST 59/60 — le tarif non authentifié
rate_limit GraphQL 0/0 ; gh api graphql → RATE_LIMIT: already exceeded for user ID 332469827

Comptes sains du parc (myia-ai-01, créé 2026-04-17) : 5000/5000 sur les deux ressources.

Les scopes ne sont pas la cause : GitHub sert 5000 req/h à tout jeton authentifié quel que soit son scope. myia-ai-01 en porte cinq (gist, read:org, read:project, repo, workflow), po-2024 deux, et l'écart de débit est de 83×.

L'hypothèse « email non vérifié » est réfutée : l'adresse est Primary Verified.

2. La cause, au texte

CGU GitHub, verbatim :

« You must be a human to create an Account. Accounts registered by "bots" or other automated methods are not permitted. We do permit machine accounts: [...] You may maintain no more than one free machine account in addition to your free Personal Account. »

Sept comptes machine en service (myia-ai-01, myia-po-2023/24/25/26, MyIA-Web1, clusterManager-Myia) contre un autorisé. Toutes les adresses sont des alias plus-addressés d'une même boîte (jsboige+<lane>@gmail.com), et les trois derniers ont été créés à quelques minutes d'intervalle depuis une IP. C'est le motif de multi-comptes le plus détectable qui soit.

3. Le risque qui rend ça urgent

Si l'anti-abus a lié le cluster par l'adresse de base, myia-ai-01 et myia-po-2023 partagent le motif. Ils survivent aujourd'hui sur cinq mois d'activité organique. myia-ai-01 est l'identité de merge : la perdre coûte bien plus que les trois de ce soir.

Pourquoi la GitHub App répond, là où le PAT ne répond pas

Notre congestion vient du bucket GraphQL partagé : toutes les lanes sortent sous jsboige, et un rc=2 du merge-gate est une porte fermée, pas une pénurie de dossiers. Un PAT de compte machine reste un quota d'utilisateur. Un jeton d'installation d'App a un bucket par installation.

7 comptes machine 7 GitHub Apps
CGU hors-limite (1 autorisé) primitive prévue, aucune clause de ce type
Anti-abus bridage déjà subi sans objet, aucun faux humain
Quota 5000/h partagés entre PAT, OAuth et apps agissant pour le compte 5000/h par installation, +50/h par dépôt au-delà de 20, plafond 12500/h
Dépôt personnel d'autrui PAT classique obligatoire, repo entier (mesuré : jsboige/CoursIA a un propriétaire de type User, donc le fine-grained ne s'y applique pas) fonctionne, avec permissions fines
Durée de vie du secret PAT 1 an dans le coffre jeton d'installation 1 h, dérivé d'une clé privée
Traçabilité tout signe jsboige coursia-<lane>[bot], identité distincte

Les postes de la bascule, nommés

  • scripts/check_adjoint_prevalidation.py:524 — if dossier.author != SHARED_GITHUB_LOGIN exige que l'auteur du commentaire-dossier soit exactement jsboige. Sous identité [bot], tous les dossiers échoueraient sur comment author must be 'jsboige'. À élargir en ensemble d'auteurs acceptés. Même traitement pour COORDINATOR_LOGIN (ligne 265).
  • QUALIFYING_LANES — aucun changement requis, vérifié : il compare des chaînes machine:workspace lues dans le tag Grain: du body, indépendantes du login qui poste.
  • Organe de forge de jeton — app_id + clé privée → JWT → jeton d'installation. Il vit à côté de scripts/secrets/agent_keyring.py et réutilise le coffre : même organe, charge différente (clé privée au lieu de PAT).
  • Coffre — les clés privées remplacent les PATs dans MyIA-Keys.kdbx. Une clé par App, révocable indépendamment.
  • Création des Apps — geste user en web UI. Le flux App Manifest permet de pré-remplir permissions et nom : à préparer pour que le geste soit un clic, pas un formulaire.

Permissions par App : Contents rw, Pull requests rw, Issues rw, Metadata r, Actions r, Checks r, Commit statuses r. Workflows rw seulement pour les lanes qui éditent .github/workflows/**.

Décisions déjà prises

  • Ne pas créer myia-po-2027 — ce serait le huitième contre une limite d'un.
  • Ne pas générer les PATs de po-2025 et po-2026 — ils rendraient 60 req/h sans GraphQL, comme celui de po-2024.
  • Ne pas déposer d'appel sur les comptes bridés : l'appel demanderait de justifier sept comptes machine devant une règle qui en autorise un. La manière la moins chère de résoudre un flag est de cesser d'avoir besoin du compte.

Non mesuré — à ne pas surinterpréter

  • Le nombre d'Apps qu'un compte peut posséder n'a pas été vérifié à la source. La clause des CGU citée vise les comptes, pas les Apps, mais l'absence de plafond documenté n'est pas une mesure.
  • Le bridage de po-2024 est mesuré ; son extension aux comptes anciens est une hypothèse de mécanisme, pas un fait observé. myia-ai-01 rendait 5000/5000 ce soir.
  • Le PAT de po-2024 reste valide et utilisable à 60 req/h REST. Il est à rotater à la bascule.

See #17418.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions