Repository navigation
[GH-P1] Manifest flow : création de l'app GitHub en 1 clic + retour d'installation - #231
Merged
Merged
Conversation
…installation callback
bobdivx
force-pushed
the
feat/gh-app-p1-manifest
branch
from
October 13, 2026 21:26
3005175 to
526fab4
Compare
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[GH-P1] Manifest flow : création de l'app GitHub en 1 clic
Plan :
devforge-plan-github-app.md, phase P1. S'appuie sur P0 (#229, déjà mergée).Checklist d'acceptation
POST /api/v1/github-app/manifest(admin) :statede 32 octets aléatoires (TTL 10 min,github_manifest_states), renvoie{ post_url, manifest, state }.post_urlpointe vers/settings/apps/newou/organizations/{org}/settings/apps/new(org validée). Le manifest est exactement celui du plan. Permissions = liste blanchecontents:write, metadata:read, pull_requests:write, checks:write, statuses:write, deployments:write.workflows:writeseulement en opt-in (workflows: true, désactivé par défaut). Jamaisadministration,secretsnimembers.GET …/manifest/callback?code&state:stateà usage unique (supprimé même s'il est refusé), non expiré, même utilisateur ⇒ sinon 400. EnsuitePOST /app-manifests/{code}/conversionssans auth.pem,webhook_secretetclient_secretsont scellés (secret_box) puis upsert dansgithub_app. Redirection vers/apps/{slug}/installations/new?state=…avec un nouveaustatelié à l'utilisateur.GET …/installed?installation_id&setup_action&state: on ne fait pas confiance à l'installation_idde la query. Il est vérifié viaGET /app/installations/{id}avec le JWT RS256 de l'app, puis upsert dansgithub_installations. Les dépôts sont synchronisés dansgithub_installation_repos(token d'installation éphémère, puisGET /installation/repositories, paginé). Redirection vers/app/settings?tab=github&installed=1. Lestateest optionnel, carsetup_on_updaterappelle sans lui ; s'il est présent, il est vérifié et consommé.GET /api/v1/github-app: statut (app, slug, propriétaire, URL d'install/gestion, installations, permissions requises vs accordées,missing_permissions), sans aucun secret.DELETE /api/v1/github-app: oubli local (app + installations en cascade) et renvoi demanage_urlpour supprimer l'app côté GitHub.GithubAppSettingsPanel.tsx, intégré à la section GitHub des réglages (SettingsPage.tsx, rendu parsettings.astro), admin seulement. Le bouton « Créer l'app GitHub DevForge » appelle/manifestpuis soumet un<form method="post">caché avec le champmanifest. Le panneau propose aussi le champ Organisation, la liste des installations, « Installer sur un autre compte » et une alerte si des permissions manquent. Les erreurs de retour (?error=) et?installed=1sont affichées.api.ts: typesGithubAppStatus,GithubInstallation,GithubAppManifestet fonctionsgithubAppStatus,githubAppManifest,githubAppForget.Tests
github_app_routes_tests.rs) :stateréutilisé, autre utilisateur, expiré ou inconnu ⇒ erreur et réponse 400 ;wiremock) ⇒ secrets scellés en base (private_key_encsansBEGIN RSA), statut sans aucun secret ;missing_permissionscorrect ;iss,exp − iat ≤ 600,Debug=***.GithubAppSettingsPanel.test.tsx) : création ⇒ soumission du manifest ; liste des installations et alerte de permissions ; formulaire caché POST avec le champmanifestJSON.cargo test --workspace⇒ 604 passés, 0 échec. Web : 140 tests Vitest OK, contrôle des imports JSX et des marques interdites OK. Le build web n'a pas pu tourner localement (binaire natif tailwind absent) ; il est couvert par le job CIweb(Docker).Validation (manuelle, après merge + déploiement)
Depuis l'UI de prod : Réglages → GitHub → « Créer l'app GitHub DevForge », sur le compte
bobdivx→ installer sur 1 dépôt → retour dans DevForge avec l'installation listée, en moins d'1 min et sans copier de secret. Pas encore faite : la PR n'est pas mergée.Décisions / risques
DEVFORGE_GITHUB_APP).Authorization. L'authentification passe par le cookiedf_session(SameSite=Lax, envoyé sur une navigation de premier niveau). Nouvelle fonctionauth_routes::user_from_bearer_or_cookie.app_jwtminimal (RS256) est ajouté dès P1, car P1-03 doit vérifier l'installation. Il sera déplacé danscrates/github/src/app_auth.rsen P2. Le token d'installation utilisé pour synchroniser les dépôts n'est pas mis en cache (cache prévu en P2).github_app.owner_type(ALTER dont l'échec est toléré), qui sert au lien de gestion user vs org.DEVFORGE_GITHUB_API_URL/DEVFORGE_GITHUB_WEB_URL(facultatives) permettent de cibler un mock ou GHES. Par défaut : api.github.com / github.com.instance_settings.instance_url) doit être en https et joignable par GitHub pour le webhook (route webhook app-level en P3).