// Préparation d'un environnement d'authentification git ÉPHÉMÈRE (P12). HTTPS (pat/app_password) : // les identifiants sont fournis via GIT_ASKPASS (script 0o700 lisant deux variables d'env), JAMAIS // dans l'URL ni dans `.git/config`. GIT_TERMINAL_PROMPT=0 (pas d'invite bloquante). Le script est // supprimé en `finally` ; le secret ne transite que par l'env du process enfant (jamais loggé). import { mkdtemp, writeFile, rm, chmod } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import type { GitService } from '@arboretum/shared'; import type { GitAuth } from './git-clients/index.js'; // Identité HTTPS par défaut quand l'utilisateur n'a pas fourni de username (token-as-password). const SERVICE_DEFAULT_USER: Record = { github: 'x-access-token', gitlab: 'oauth2', gitea: 'oauth2' }; export async function withGitAuth( service: GitService, auth: GitAuth, fn: (env: NodeJS.ProcessEnv) => Promise, ): Promise { const dir = await mkdtemp(join(tmpdir(), 'arb-gitauth-')); const askpass = join(dir, 'askpass.sh'); const user = auth.username || SERVICE_DEFAULT_USER[service]; await writeFile( askpass, "#!/bin/sh\ncase \"$1\" in\n Username*) printf '%s' \"$ARB_GIT_USER\" ;;\n *) printf '%s' \"$ARB_GIT_PASS\" ;;\nesac\n", { mode: 0o700 }, ); await chmod(askpass, 0o700); const env: NodeJS.ProcessEnv = { ...process.env, GIT_ASKPASS: askpass, GIT_TERMINAL_PROMPT: '0', ARB_GIT_USER: user, ARB_GIT_PASS: auth.secret, }; try { return await fn(env); } finally { await rm(dir, { recursive: true, force: true }).catch(() => {}); } }