Skip to content

Fix(prevalidation,#17437): l'auteur accepte d'un dossier couvre les identites App par lane - #20013

Merged
myia-ai-01 merged 1 commit into
mainfrom
fix/17437-accepted-dossier-authors
Oct 9, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
fix/17437-accepted-dossier-authors

Conversation

@jsboige

@jsboige jsboige commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

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 :

# scripts/check_adjoint_prevalidation.py  et  scripts/check_closure_dossier.py
if dossier.author != SHARED_GITHUB_LOGIN:
    errors.append(f"comment author must be {SHARED_GITHUB_LOGIN!r}")

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. Mais check_closure_dossier.py portait 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.py

scripts/gh_identity.py est l'organe d'identité existant du dépôt : il porte déjà SHARED_LOGIN et HOST_ACCOUNTS, et il est déjà importé par check_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éexistant coursia-lane-ai-01. La table est figée plutôt que dérivée à l'exécution : github_app_manifest importe webbrowser/http.server et 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 Sans le correctif Verdict
test_fleet_app_identity_is_an_accepted_dossier_author (les deux gates) échoue contrôle de ce correctif
test_app_shaped_login_outside_the_frozen_lanes_is_refused (les deux gates) passe cliquet, pas un contrôle

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 accepterait coursia-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

python -m pytest scripts/tests/test_check_adjoint_prevalidation.py \
                 scripts/tests/test_check_closure_dossier.py \
                 scripts/tests/test_gh_identity.py -q
218 passed in 1.10s

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 --search avait rendu 4 PRs mergées comme si elles étaient ouvertes. Le résultat fiable : 5 PRs ouvertes touchent check_adjoint_prevalidation.py (#19995, #19980, #19966, #19926, #19661), aucune ne touche les comparaisons d'auteur ; et aucune PR ouverte ne touche check_closure_dossier.py ni gh_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

…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>
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@jsboige

jsboige commented Oct 9, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 20013
head: c40aa82
complete: true
body: read
comments-reviewed: 1
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 41b1010a86ecf086763424db4abc43ec1c7b5b53c7d9808f23a3cfc70004a22e
diff-files: 5
diff-additions: 145
diff-deletions: 5
checks: BLOCKED
b0: clear
scope: pass
domain: not-applicable
verdict: BLOCKED
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 20013
organ-rc: 3
[/ADJOINT PREFLIGHT]

@jsboige

jsboige commented Oct 9, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 20013
head: c40aa82
complete: true
body: read
comments-reviewed: 2
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: a6dc80c5a42c851101986c176e1e9eb52d6005bc2973f309a14f10c3b6ec7afb
diff-files: 5
diff-additions: 145
diff-deletions: 5
checks: latest-wins-green
b0: clear
scope: pass
domain: not-applicable
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 20013
organ-rc: 0
supersedes: 2
supersedes-why: re-stamp demande par ai-01 (DM msg-20261009T025911 fichier sans-dossier) ; derive vivant
[/ADJOINT PREFLIGHT]

@myia-ai-01
myia-ai-01 merged commit dce361b into main Oct 9, 2026
23 of 26 checks passed
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.

2 participants