Skip to content

💡 [REQUEST] - Expliciter l'intention de mise Ă  jour des credentials de dĂ©pĂŽt (API v2) #2422

Description

@KepoParis

Description

Dans l'API v2 des dépÎts, la mise à jour des identifiants de miroir Vault est devinée à
partir du corps de la requĂȘte au lieu d'ĂȘtre exprimĂ©e par le client.

parseRepositoryCredentialUpdate (apps/server-nestjs/src/modules/repository/repository.utils.ts)
infÚre l'intention (set / clear / keep) de la présence ou de l'absence de champs :

if (updateRepositoryInfos.isPrivate === false) return { kind: 'clear' }
if (updateRepositoryInfos.externalToken) return { kind: 'set', externalToken: ... }
return { kind: 'keep' }

C'est la reprise du comportement legacy (qui signalait « inchangé » avec un jeton factice
fakeToken), conservée telle quelle pour ne pas élargir la migration. Mais on ne devrait
jamais deviner quoi que ce soit à partir des données d'entrée : soit le client sait ce
qu'il veut, soit il doit y rĂ©flĂ©chir avant d'envoyer sa requĂȘte. Le kind devrait ĂȘtre
dans la requĂȘte.

MĂȘme racine pour buildRepositoryUpdateData, dans le mĂȘme fichier : les deux if
(isPrivate !== undefined, isPrivate !== false && externalUserName !== undefined)
sont fragiles parce que isPrivate y est un tri-Ă©tat true | false | undefined lĂ  oĂč
ce devrait ĂȘtre un boolĂ©en. La sĂ©mantique de « rendre public » (qui conserve
l'externalUserName stocké mais supprime le secret Vault) est aujourd'hui implicite et
répartie entre deux fonctions.

PRs liées

#2416 — introduit parseRepositoryCredentialUpdate et le type
RepositoryMirrorCredentialUpdate avec le comportement legacy conservé.

Issues liées

Aucune.

Exemples simples

Aujourd'hui, trois requĂȘtes diffĂ©rentes produisent trois effets Vault diffĂ©rents sans
que le client ait exprimé la moindre intention :

// « je change le jeton »           → set (devinĂ© par la prĂ©sence du champ)
{ "externalToken": "glpat-xxx" }

// « je passe le dĂ©pĂŽt en public »  → clear (devinĂ© par isPrivate: false)
{ "isPrivate": false }

// « je change juste la branche »   → keep (devinĂ© par l'absence de jeton)
{ "deployRevision": "main" }

Cible : l'intention est portée explicitement par le corps, par exemple

{ "deployRevision": "main", "credentials": { "kind": "keep" } }
{ "isPrivate": false,       "credentials": { "kind": "clear" } }
{ "isPrivate": true,        "credentials": { "kind": "set", "externalUserName": "bot", "externalToken": "glpat-xxx" } }

Spécifications techniques

Zone concernée : apps/server-nestjs/src/modules/repository/ (+ packages/shared/src/schemas/v2/repository.ts).

  1. Porter le kind dans le contrat. Faire de UpdateRepositorySchema une union
    discriminée sur l'intention de credentials, comme CreateRepositorySchema l'est déjà
    sur isPrivate. parseRepositoryCredentialUpdate disparaĂźt alors : le boundary zod
    produit directement le RepositoryMirrorCredentialUpdate, et le service se contente
    d'exécuter (« parse, don't validate »).
  2. Rendre les combinaisons impossibles inexprimables. isPrivate: false avec
    kind: 'set' ne doit pas ĂȘtre reprĂ©sentable dans le type, plutĂŽt que d'ĂȘtre arbitrĂ© Ă 
    l'exécution par un ordre de if.
  3. Sortir isPrivate du tri-état dans buildRepositoryUpdateData : décider
    explicitement de la sĂ©mantique du passage public → l'externalUserName stockĂ©
    est-il conservé (legacy) ou effacé ? Cf. la question ouverte ci-dessous.
  4. Impact client : la webapp (apps/client) et les consommateurs de l'API v2 devront
    envoyer l'intention. Prévoir la période de transition (l'API v1 legacy reste sur
    apps/server et n'est pas concernée).

Questions ouvertes (à trancher avant implémentation)

  • Rendre un dĂ©pĂŽt public doit-il effacer l'externalUserName en base, ou conserver le
    comportement legacy qui le laisse intact ?
  • Le kind est-il un champ Ă  part (credentials: { kind: ... }) ou portĂ© par la mĂȘme
    union que isPrivate ?

Définition du fini

  • La sĂ©mantique du passage public est tranchĂ©e et documentĂ©e
  • Le kind est portĂ© explicitement par la requĂȘte, plus aucune infĂ©rence cĂŽtĂ© serveur
  • isPrivate n'est plus un tri-Ă©tat dans la construction de la mise Ă  jour
  • Les clients de l'API v2 (dont la webapp) sont adaptĂ©s
  • Les tests liĂ©s Ă  ce refactor ont Ă©tĂ© ajoutĂ©s

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions