Repository navigation
Fix(prevalidation,#17437): l'auteur accepte d'un dossier couvre les identites App par lane - #20013
Conversation
…dentites App par lane Les DEUX gates qui lisent l'auteur d'un dossier -- prevalidation adjointe et fermeture d'issue -- comparaient ce login a `jsboige` seul. Le jour ou une lane poste sous son identite GitHub App (`coursia-lane-po-2024[bot]`, #17437), ils refusent un dossier pourtant legitime, et le refusent pour TOUTES les lanes d'un coup avec un message qui ne designe pas la cause. L'ensemble accepte vit dans l'organe d'identite existant `gh_identity.py`, lu par les deux gates. N'elargir que la prevalidation aurait laisse la migration a moitie faite : les dossiers de merge passeraient sous identite App, ceux de fermeture seraient refuses -- l'echec surviendrait a la derniere etape. `_is_coordinator_neutralisation` (check_adjoint_prevalidation.py:533) n'est PAS elargi, deliberement : il decide quels commentaires periment un dossier, et y admettre les identites App neutraliserait les commentaires des LANES, qui doivent continuer a le perimer. Controle mesure : les tests positifs echouent sans le correctif (verifie en memoire en retablissant l'ensemble a `{jsboige}`) ; les tests negatifs passent avant comme apres -- ce sont des cliquets contre un elargissement par forme, pas des controles de ce correctif. See #17437 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
|
[ADJOINT PREFLIGHT] |
|
[ADJOINT PREFLIGHT] |
Grain: MED/guard — lane myia-po-2024:CoursIA — prev: DEEP/tooling #19802
Ce que corrige cette PR
Les deux gates qui décident si un dossier est fiable le faisaient sur une comparaison à un seul login :
C'est la dernière étape restante de #17437. Les GitHub Apps par lane sont créées et installées (2026-10-06) ; les lanes signent encore sous le login partagé
jsboige. Le jour où une lane poste son dossier sous son identité d'App (coursia-lane-po-2024[bot]), tous les dossiers échouent — pour toutes les lanes d'un coup, avec un message qui ne désigne pas la cause.Pourquoi DEUX organes, et pas un
L'issue cite
check_adjoint_prevalidation.py. Maischeck_closure_dossier.pyportait la comparaison identique. N'élargir que la première aurait laissé la migration à moitié faite : les dossiers de merge passeraient sous identité App, ceux de fermeture d'issue seraient refusés. L'échec surviendrait à la dernière étape, sur l'issue qu'on allait fermer — exactement le genre de demi-correctif qui coûte plus cher à diagnostiquer que l'absence de correctif.Pourquoi l'ensemble vit dans
gh_identity.pyscripts/gh_identity.pyest l'organe d'identité existant du dépôt : il porte déjàSHARED_LOGINetHOST_ACCOUNTS, et il est déjà importé parcheck_adjoint_prevalidation.py. L'ensemble accepté (ACCEPTED_DOSSIER_AUTHORS) y est défini une fois et lu par les deux gates.Le poser dans chaque gate aurait produit deux copies qui divergeraient au premier changement de lanes — et l'une des deux refuserait alors des dossiers légitimes sans que personne ne le voie.
Les noms sont ceux de
scripts/secrets/github_app_manifest.py(APP_PREFIX = "coursia-lane-"+LANES), plus le pilote préexistantcoursia-lane-ai-01. La table est figée plutôt que dérivée à l'exécution :github_app_manifestimportewebbrowser/http.serveret lit.secrets/, ce qu'un gate appelé en CI ne peut pas se permettre. Un login absent de la table est refusé (échec fermé) : l'ensemble s'élargit par une édition consciente, jamais par une correspondance de forme.Ce qui n'est PAS touché, délibérément
_is_coordinator_neutralisation(check_adjoint_prevalidation.py:533,if author not in (COORDINATOR_LOGIN, SHARED_GITHUB_LOGIN)) n'est pas élargi. Ce prédicat décide quels commentaires périment un dossier ; y admettre les identités App neutraliserait les commentaires des lanes, qui doivent continuer de le périmer. Le périmètre est l'auteur accepté d'un dossier, pas l'auteur neutre.Contrôle — ce qui est prouvé, et ce qui ne l'est pas
Rapport honnête, mesuré :
test_fleet_app_identity_is_an_accepted_dossier_author(les deux gates)test_app_shaped_login_outside_the_frozen_lanes_is_refused(les deux gates)Le second passe avant comme après : avant le correctif, tout login autre que
jsboigeétait refusé, imposteurs compris. Il ne prouve donc pas ce correctif — il verrouille la propriété d'ensemble fermé contre un élargissement futur par forme (une implémentation qui accepteraitcoursia-lane-*[bot]par préfixe le ferait échouer).Le contrôle a été pris en mémoire, en rétablissant l'ensemble à
{jsboige}et en rejouant les tests — sans toucher au dépôt.Preuves
Ensemble accepté mesuré : 8 entrées —
jsboige+ les 7 identités d'App (po-2023..po-2027,web1,ai-01).Portée
Un seul sujet : quels auteurs un dossier accepte. Collision mesurée par l'API (
pulls/N/files), pas par--search— un garde bâti sur--searchavait rendu 4 PRs mergées comme si elles étaient ouvertes. Le résultat fiable : 5 PRs ouvertes touchentcheck_adjoint_prevalidation.py(#19995, #19980, #19966, #19926, #19661), aucune ne touche les comparaisons d'auteur ; et aucune PR ouverte ne touchecheck_closure_dossier.pynigh_identity.py. Le diff sur le gate adjoint est un seul hunk (l'ensemble vivant dans l'organe), ce qui limite la surface de conflit avec ces cinq.See #17437 — pas
Closes: la migration demande aussi que les lanes adoptent effectivement les jetons d'App.🤖 Generated with Claude Code