Aller au contenu

Projets

74 routes. Chemins relatifs à https://api.nexus-engine.eu/api/v1.

GET /projects

Les projets que je vois : tous pour un administrateur, mes affectations pour un développeur.

RéponseProjectDto[]
NotemyLocalPath est le dossier local de l’APPAREIL qui demande, nommé par les en-têtes facultatifs x-nexus-appareil (identifiant stable du poste, 1 à 100 caractères [A-Za-z0-9_-]) et x-nexus-plateforme (win32, darwin, linux). Sans en-tête — clé d’API, vue web, application ancienne — c’est le dernier chemin écrit par n’importe quel appareil du membre ; avec un en-tête mais sans chemin pour cet appareil, ce dernier chemin n’est rendu que si sa forme correspond à la plateforme annoncée, null sinon.
GET /projects/:id

La fiche complète d’un projet : client, stack, URLs, description, conventions, membres.

RéponseProjectDto
NotemyLocalPath est le dossier local de l’APPAREIL qui demande, nommé par les en-têtes facultatifs x-nexus-appareil (identifiant stable du poste, 1 à 100 caractères [A-Za-z0-9_-]) et x-nexus-plateforme (win32, darwin, linux). Sans en-tête — clé d’API, vue web, application ancienne — c’est le dernier chemin écrit par n’importe quel appareil du membre ; avec un en-tête mais sans chemin pour cet appareil, ce dernier chemin n’est rendu que si sa forme correspond à la plateforme annoncée, null sinon.
POST /projects Owner et Admin

Crée un projet.

Corpsname, clientId, serverId (la machine du projet : la colonne des fichiers de la session la montre à la place du dossier local ; null pour délier), projectTypeId, color (nom de la palette ou #rrggbb), stack (liste), repoProvider (GITHUB, GITLAB), repoUrl, urls (liste de {url, kind: PRODUCTION, STAGING, LOCAL, API, OTHER, inSites}), prodUrl, stagingUrl, localUrl, description (cahier des charges, markdown), figmaUrl, driveUrl, conventions, memberIds (affectés), excludedFromMemory, confidential. Le mode aveugle (dataLevel) ne se change PAS ici : réservé à un administrateur devant son écran
RéponseProjectDto
PATCH /projects/:id Owner et Admin

Modifie un projet (statut compris : ACTIVE, PAUSED, DELIVERED, ARCHIVED).

Corpsstatus, name, clientId, serverId (la machine du projet : la colonne des fichiers de la session la montre à la place du dossier local ; null pour délier), projectTypeId, color (nom de la palette ou #rrggbb), stack (liste), repoProvider (GITHUB, GITLAB), repoUrl, urls (liste de {url, kind: PRODUCTION, STAGING, LOCAL, API, OTHER, inSites}), prodUrl, stagingUrl, localUrl, description (cahier des charges, markdown), figmaUrl, driveUrl, conventions, memberIds (affectés), excludedFromMemory, confidential. Le mode aveugle (dataLevel) ne se change PAS ici : réservé à un administrateur devant son écran
RéponseProjetModifieDto
NoteLes sessions d’agents en cours sur ce projet reçoivent la fiche modifiée. serverId doit désigner une machine de l’entreprise (404 sinon) ; le changement est journalisé. Un membre RETIRÉ de l’équipe (plus dans memberIds, et qu’aucun dossier ne tient) est désaffecté de ses tâches OUVERTES de ce projet, dans la même transaction : `tachesDesaffectees` les nomme, par membre, dès que memberIds est envoyé (vide si rien n’a été perdu) — `GET /projects/:id/retrait-apercu` le dit avant.
GET /projects/:id/retrait-apercu

Ce qu’un changement d’équipe ferait perdre : par membre retiré, ses tâches ouvertes de ce projet — demandé AVANT le geste, sans rien écrire.

RequêtememberIds (obligatoire : la liste qu’on s’apprête à envoyer, séparée par des virgules ; vide = personne)
RéponseRetraitApercuDto
NoteMême règle que PATCH /projects/:id : un membre tenu aussi par un dossier n’est pas retiré, une affectation héritée ne sort pas d’ici. 404 pour un projet introuvable ou d’une autre entreprise, 403 pour un projet non affecté.
DELETE /projects/:id session de l’application seulement

Supprime un projet et tout ce qu’il porte (tâches, discussions, sessions, accès). L’archivage est la voie normale.

Réponse{ ok, sitesConserves, secretsATourner, …compteurs de ce qui est parti }
NoteRéservée à une personne en session (jamais une clé, jamais un agent). Owner et Admin toujours ; un développeur seulement pour un projet VIDE dont il est le seul membre — 403 avec le motif sinon. Les tâches, discussions, messages, documents, accès du projet, déploiements, connecteurs, accès portail et lignes de prix partent ; les sites, les accès de l’entreprise, la machine et les rattachements d’infrastructure sont DÉLIÉS, jamais supprimés ; les secrets du projet déjà révélés sonnent SECRET_ROTATION chez les administrateurs.
GET /projects/:id/suppression session de l’application seulement

Ce qu’emporterait la suppression du projet, ce qui serait délié, et si elle m’est permise — demandé AVANT le geste, sans rien écrire.

RéponseProjectDeletionPreviewDto
Note`autorise` peut être faux : `refus` (ROLE, PROJET_NON_VIDE) et `motif` disent pourquoi. 404 pour un projet introuvable ou d’une autre entreprise, 403 pour un projet non affecté.
GET /projects/:id/duplication session de l’application seulement

Ce qu’emporterait la duplication du projet, groupe par groupe, avec les défauts et ce qui ne suit jamais — demandé AVANT le geste.

RéponseProjectDuplicationPreviewDto
NoteUn groupe `disponible: false` (portail hors administrateur, discussions en mode aveugle) est ignoré même coché. `autorise` faux pour l’atelier d’une application. 404 hors de l’entreprise, 403 non affecté.
POST /projects/:id/duplication session de l’application seulement

Duplique un projet : un projet NEUF qui recopie les groupes choisis (détails, adresses sans site, dossiers locaux, équipe, coffre, modules, connecteurs, faits, tâches, créations, documents, dossier de la barre ; sur demande : discussions sans mesures, messages, portail).

Corps{ name, options?: { <groupe>: boolean }, taches?: "OUVERTES" | "TOUTES" }
RéponseProjectDuplicationResultDto { id, name, copies, ignores, secretsCopies, connecteursLaisses }
NoteSession seule — et l’assistant de la personne (7 novembre 2026), comme l’agent de la discussion d’une application dans un projet qu’elle conduit ; jamais une clé ni un agent de projet ordinaire. Une transaction : en échec, rien n’est créé. Groupe absent = son défaut, groupe inconnu = 400. Le mode aveugle suit toujours. Jamais : sites, coffre de l’entreprise, infrastructure, déploiements, liens de partage ; atelier d’application = 409.
POST /projects/:id/aveugle/purge Owner et Admin session de l’application seulement

Couvre l’HISTORIQUE d’un projet passé en mode aveugle : efface le contenu des discussions déjà enregistrées (conversation, résumé, prompts, commandes, fichiers touchés, titre) et les fragments de mémoire d’agence. Les lignes restent, avec leurs mesures — tokens, coût, temps actif.

Réponse{ sessions, fragments } — le nombre de discussions couvertes et de fragments retirés
NoteCocher le mode ferme l’avenir ; seule cette purge ferme le passé. Refusée (400) sur un projet qui n’est pas en mode aveugle, et refusée à un agent comme à une clé d’API : c’est le geste d’une personne.
PUT /projects/:id/clients Owner et Admin

ANCIENNE ROUTE, conservée jusqu’à la 0.11 pour REFUSER en l’expliquant (426) : le partage se fait désormais par personne. N’écrit rien. Sans elle, les applications 0.10.2 recevraient un 404 traduit par « elle marchera au prochain déploiement », ce qui est faux.

CorpsclientIds
Réponse426
PUT /projects/:id/contacts Owner et Admin

Ouvre les accès de ce projet à des personnes nommées, au-delà du client qui l’a commandé. Réservé aux administrateurs.

CorpscontactIds
Réponse{ ok }
PUT /projects/:id/stack

Pose la stack détectée du projet.

Corpsstack (liste, 12 au plus)
RéponseProjectDto
PUT /projects/:id/local-path application de bureau seulement

Le dossier local du projet sur CE poste.

CorpslocalPath
NoteLe chemin est enregistré pour l’appareil que nomment les en-têtes x-nexus-appareil (identifiant du poste) et x-nexus-plateforme (win32, darwin, linux) ; les autres appareils du membre gardent le leur, et localPath (sans en-tête) reste le miroir du dernier écrit. Sans en-tête, le chemin unique du membre est remplacé, comme avant la 0.10.24.
GET /projects/:id/suivi-dev

Le suivi Nexus Dev du projet : missions d’agent (état, branche, moteur, consommation mesurée, budget, blocage, prochaine décision, tâche et demande de fusion), revues (commit, verdict, défauts ouverts, corrigés, non examinés) et plans de surveillance après livraison (commit livré, environnement, verdict), tels que les postes de l’équipe les ont dits.

RéponseSuiviDevProjetDto
NoteDes RÉSUMÉS seulement : jamais le contenu d’une discussion, jamais de code, jamais un secret. Un élément qu’aucun poste n’a redit depuis 60 jours n’est plus rendu. Les lignes qu’une version plus récente du poste aurait écrites sous une autre forme sont comptées dans `ecartes`, jamais cachées.
PUT /projects/:id/suivi-dev application de bureau seulement

Le poste range l’ÉTAT ENTIER d’un de ses dossiers (missions, revues, plans de surveillance) : ce qu’il ne dit plus est retiré, un envoi rejoué ne double rien.

Corpsdossier (empreinte hexadécimale du chemin, jamais le chemin), missions (≤ 60), revues (≤ 40), surveillances (≤ 30) — la forme de `envoiSuiviDevSchema`
RéponseReponseEnvoiSuiviDevDto { ok, ranges, retires, masques }
NoteRéservé à un poste (en-tête x-nexus-appareil), sous la session de la personne : ni une clé, ni un agent. Les textes libres sont expurgés une seconde fois par le serveur. 8 dossiers par membre, appareil et projet (le plus ancien laisse sa place) ; 413 au-delà de 3 000 éléments par projet. N’émet aucun événement.
DELETE /projects/:id/suivi-dev application de bureau seulement

Retire ce que CE poste a envoyé au suivi du projet : un dossier (`dossier`), ou tous.

Requêtedossier (empreinte, facultatif)
Réponse{ ok, retires }
NoteRéservé à un poste (en-tête x-nexus-appareil). Journalisé.
GET /projects/:id/jeu/verrous

Jeux vidéos : les verrous de binaires du jeu tenus par Nexus (quand la forge ne sert pas ceux de Git LFS) — chemin, détenteur, discussion, depuis quand.

RéponseVerrousJeuDto { verrous, orphelinsLiberes }
NoteTout membre affecté. Un verrou dont la discussion est finie ou muette depuis plus de dix minutes est ORPHELIN : libéré au passage, et nommé dans `orphelinsLiberes`. Un verrou pris sans discussion (une personne) n’est jamais orphelin.
POST /projects/:id/jeu/verrous

Jeux vidéos : prend le verrou de chemins du dépôt pour le compte courant (et la discussion nommée). Chaque chemin répond PRIS, DEJA_A_NOUS ou VERROUILLE_PAR (qui, depuis quand).

Corpschemins (1 à 100, relatifs au dépôt), sessionId (facultatif : une discussion de ce projet et de ce compte)
RéponsePriseVerrousJeuDto { issues, orphelinsLiberes }
NoteJournalisé. Un verrou n’est jamais pris au nom d’un autre : la discussion nommée doit être celle du compte qui appelle.
DELETE /projects/:id/jeu/verrous

Jeux vidéos : rend ses verrous (RENDU, DEJA_LIBRE, PAS_A_NOUS). `forcer: true` : un administrateur libère le verrou d’un autre (FORCE).

Corpschemins (1 à 100), forcer (facultatif — une personne administratrice seulement, jamais un agent ni une clé)
RéponseRenduVerrousJeuDto { issues }
NoteJournalisé (`jeu.verrous.rendu`, `jeu.verrous.force`).
PUT /projects/arrangement Owner et Admin

Rangement complet des projets et dossiers (ordre, dossier parent).

Corpsprojects : liste de {id, folderId, orderIndex} ; folders : liste de {id, parentId, orderIndex}
POST /projects/:id/type-tasks

Pose sur ce projet les tâches déclarées par son type.

NoteRejouable sans dégât : les titres déjà présents sont sautés. Refusé (400) si le projet n’a pas de type.
GET /project-folders

Les dossiers de rangement de l’entreprise.

RéponseProjectFolderDto[]
POST /project-folders Owner et Admin

Crée un dossier de rangement.

Corpsname, icon, parentId, orderIndex
RéponseProjectFolderDto
PATCH /project-folders/:id Owner et Admin

Renomme ou déplace un dossier.

Corpsname, icon, parentId, orderIndex
RéponseProjectFolderDto
GET /project-folders/:id/contenu Owner et Admin

Ce qu’un dossier contient — l’enjeu d’une suppression.

RéponseFolderContentsDto
GET /project-folders/:id/members

Les membres attribués à un dossier, et le nombre de projets que cette attribution leur donne (sous-dossiers compris).

RéponseFolderMembersDto
PUT /project-folders/:id/members Owner et Admin

Remplace les membres attribués à un dossier : ils sont affectés à tous ses projets, sous-dossiers compris, et les retirer ici leur retire ces projets.

CorpsmemberIds
Réponse{ ok, projectCount, assignedCount, unassignedCount, tachesDesaffectees }
NoteL’héritage est recalculé à chaque changement de l’arbre. Une affectation posée à la main sur un projet (`fromFolder: false`) n’est jamais retirée par un dossier. Un membre qui quitte un projet par ce recalcul est désaffecté de ses tâches OUVERTES de ce projet (`tachesDesaffectees`, par membre et par projet) — `GET /project-folders/:id/retrait-apercu` le dit avant. Déplacer, supprimer un dossier ou ranger un projet rejoue le même recalcul, et rend le même champ.
GET /project-folders/:id/retrait-apercu Owner et Admin

Ce que remplacer les membres d’un dossier ferait perdre : par membre et par projet quitté, ses tâches ouvertes — demandé AVANT le geste, sans rien écrire.

RequêtememberIds (obligatoire : la liste qu’on s’apprête à envoyer, séparée par des virgules ; vide = personne)
RéponseRetraitApercuDto
NoteLe recalcul de l’héritage est simulé sur tout le sous-arbre avec cette liste, filtrée comme le geste la filtrera. 404 pour un dossier d’une autre entreprise.
DELETE /project-folders/:id Owner et Admin

Supprime un dossier ; ses projets remontent à la racine.

GET /version

Version est-il installé sur ce serveur, et sous quel hôte git (`version.<domaine>`) ? Ce que le relais git du poste lit avant de demander un identifiant.

RéponseVersionConfigDto { disponible, hote }
POST /version/identifiants session de l’application seulement

Les identifiants git du membre sur Version (un jeton délivré par Nexus), pour SON terminal ou pour SES agents. Avec `projectId`, le dépôt du projet est remis d’accord avec l’équipe avant la réponse.

Corpssorte ('PERSONNE' | 'AGENT'), projectId?
RéponseVersionIdentifiantsDto { hote, utilisateur, jeton }
NoteLe geste du POSTE en session (`ROUTES_SESSION_SEULE`) : un jeton ne passe ni par une clé d’API ni par un outil d’agent, qui l’écrirait dans un transcript. Jamais affiché ni journalisé ; journal `version.identifiants` sans le jeton. 503 `VERSION_INDISPONIBLE` quand Version n’est pas installé. Un jeton de plus d’un jour est renouvelé à la demande suivante ; le précédent reste valide jusqu’au renouvellement d’après.
GET /version/sante

La santé de Version sur ce serveur : configuré, joignable à l’instant, conduit par un compte d’administration — et la phrase de ce qui manque.

RéponseVersionSanteDto { configure, joignable, administrateur, hote, numero, diagnostic }
NotePropriétaires et administrateurs de l’espace (403 sinon). Aucun secret. `GET /version` ne dit que « configuré » ; celle-ci interroge le service.
POST /projects/:id/version/principal

Choisit LE dépôt du projet — celui que le poste clone et pousse : Version, ou le dépôt GitHub/GitLab qu’il portait. Rien n’est copié ni effacé, l’autre adresse est gardée.

Corpsdepot ('version' | 'externe')
RéponseVersionEtatDto
NotePropriétaires et administrateurs (403 sinon). 409 `VERSION_BASCULE` sans dépôt Version, ou sans dépôt externe vers lequel revenir. L’historique passe d’un dépôt à l’autre par `git push` ordinaire. Journal `version.depot-principal`.
POST /projects/:id/version/branches

Crée une branche depuis une branche, une étiquette ou un commit (`depuis`, la branche par défaut sans lui) — « repartir d’ici », sans rien réécrire.

Corpsnom, depuis?
RéponseVersionBrancheDto
Note409 si la branche existe déjà, 404 si `depuis` est inconnu, 402 `VERSION_GELEE` stockage plein. Journal `version.branche-creee`.
DELETE /projects/:id/version/branches

Retire une branche (`?nom=`), selon le droit du membre. Jamais la branche par défaut (400).

Réponse{ ok }
NoteLe nom voyage en paramètre de requête : une branche porte des barres obliques. Journal `version.branche-supprimee`.
GET /projects/:id/version/etiquettes

Les étiquettes du dépôt — les versions qu’on a nommées (`v1.2.0`) —, de la plus récente à la plus ancienne.

Réponse{ etiquettes: VersionEtiquetteDto[] }
POST /projects/:id/version/etiquettes

Nomme une version : pose une étiquette sur une branche ou un commit (`cible`, la branche par défaut sans elle), avec un message.

Corpsnom, cible?, message?
RéponseVersionEtiquetteDto
Note409 si l’étiquette existe déjà, 402 `VERSION_GELEE` stockage plein. Journal `version.etiquette-creee`.
DELETE /projects/:id/version/etiquettes

Retire une étiquette (`?nom=`) : propriétaires et administrateurs seulement, un repère que d’autres ont pu employer ne se défait pas à la légère.

Réponse{ ok }
NoteJournal `version.etiquette-supprimee`.
GET /projects/:id/version/comparer

Ce que `tete` (branche, étiquette ou commit) a de plus que `base` (la branche par défaut sans elle) : les commits et les fichiers touchés.

RéponseVersionComparaisonDto { base, tete, commits, totalCommits, fichiers }
NoteSans patch : les différences ligne à ligne se lisent commit par commit, ou sur une demande de fusion. 404 si une référence est inconnue.
GET /projects/:id/version/fichiers

Parcourt le dépôt à une référence (`ref`, la branche par défaut sans elle) : un dossier (`chemin`) rend ses entrées, un fichier son texte.

RéponseVersionFichiersDto { ref, chemin, entrees | fichier }
NoteUn fichier binaire ou de plus de 400 Ko n’est pas rendu, et `raison` le dit. Un chemin qui remonte (`..`) est refusé (400).
GET /projects/:id/version

Le dépôt Version du projet : adresse de clone, branche par défaut, taille relue sur la forge, gel, le droit du membre (et donc de ses agents), le stockage de l’espace.

RéponseVersionEtatDto { disponible, raison, depot, droit, stockage, depotExterne }
NoteVersion non installé : `disponible: false` et la raison, jamais une erreur. La taille compte dans le stockage facturé de l’espace (source `VERSION`).
POST /projects/:id/version

Crée le dépôt Version du projet s’il n’en a pas, et y met l’équipe (propriétaires, administrateurs, membres affectés). Un projet sans dépôt prend son adresse comme `repoUrl` ; un dépôt GitHub/GitLab existant est gardé.

Corps{}
RéponseVersionEtatDto
NoteUn projet NEUF le reçoit tout seul (sauf adresse de dépôt donnée ou projet de machine). 402 `VERSION_GELEE` quand le stockage de l’espace est plein ; 503 `VERSION_INDISPONIBLE`. Journal `version.depot-cree`.
GET /projects/:id/version/branches

Les branches du dépôt Version : nom, dernier commit, protégée, par défaut.

Réponse{ branches: VersionBrancheDto[] }
GET /projects/:id/version/commits

L’historique d’une branche (la branche par défaut sans `branche`), trente commits par page ; les auteurs sont nommés par leur nom Nexus.

Réponse{ commits: VersionCommitDto[], suite }
GET /projects/:id/version/commits/:sha

Un commit et ses différences, fichier par fichier (statut, ajouts, suppressions, patch borné ; `tronque` le dit).

RéponseVersionCommitDetailDto { commit, diff }
GET /projects/:id/version/fusions

Les demandes de fusion du dépôt Version, par état (`ouvertes` par défaut, `fermees`, `toutes`).

Réponse{ fusions: VersionFusionDto[] }
POST /projects/:id/version/fusions

Ouvre une demande de fusion d’une branche poussée (`tete`) vers `base` (la branche par défaut sans elle), au nom du membre.

Corpstitre, description?, base?, tete
RéponseVersionFusionDto
NoteLa forge rejuge le droit du membre (en-tête Sudo). 402 `VERSION_GELEE` stockage plein. Journal `version.fusion-creee`.
GET /projects/:id/version/fusions/:numero

Une demande de fusion : son fil de commentaires et ses différences.

RéponseVersionFusionDetailDto { …, fil, diff }
POST /projects/:id/version/fusions/:numero/commentaires

Commente une demande de fusion, au nom du membre.

Corpstexte
RéponseVersionCommentaireDto
NoteJournal `version.fusion-commentee`.
GET /projects/:id/entrepot

Les gros fichiers du projet gardés par le serveur (modèles, textures, vidéos, originaux de génération), cherchés par nom, chemin, prompt, origine et date, cinquante par page, avec l’occupation de l’entrepôt.

RéponseListeEntrepotDto { fichiers, suite, occupation }
GET /projects/:id/entrepot/lien

La version reliée à un chemin du dossier du projet (`chemin`), ou rien.

RéponseLienEntrepotDto | null
GET /projects/:id/entrepot/fichiers/:fichier

La fiche d’un fichier de l’entrepôt et toutes ses versions (état, empreinte, prompt et générateur d’un original).

RéponseFicheEntrepotDto
POST /projects/:id/entrepot/depots

Ouvre (ou reprend) le dépôt d’un fichier par son empreinte : un contenu déjà gardé n’est pas renvoyé, un envoi interrompu rend les parties déjà reçues.

Corpsnom, chemin?, fichierId?, octets, sha256, type?, origine?, prompt?, generateur?, modele?, note?
RéponseOuvertureDepotEntrepotDto
Note402 stockage de l’entreprise plein, 413 fichier trop lourd, 403 mode aveugle. Écrire exige le droit d’écrire au stockage du projet.
POST /projects/:id/entrepot/depots/:objet/parties

Signe des adresses d’envoi pour des parties d’un dépôt ouvert (seize au plus par appel).

Corpsparties: [{ numero, taille }]
Réponse{ parties: [{ numero, url, entetes }] }
POST /projects/:id/entrepot/depots/:objet/terminer

Termine un dépôt : le stockage assemble les parties, le serveur relit l’empreinte avant de dire « gardé ».

Corpsoctets
RéponseVersionEntrepotDto
NoteJournal `entrepot.depot-ouvert` à l’ouverture. Une empreinte fausse passe la version en CORROMPU (journal `entrepot.objet-corrompu`).
POST /projects/:id/entrepot/versions/:version/lire

Une adresse de lecture signée (une heure) d’une version gardée, lisible par parties (reprise).

RéponseLectureEntrepotDto { version, nom, url, expireA }
POST /projects/:id/entrepot/liens

Relie un chemin du dossier du projet à une version de l’entrepôt (ce que le pointeur `.entrepot` désigne).

Corpschemin, versionId
RéponseLienEntrepotDto
POST /projects/:id/version/fusions/:numero/fusionner

Fusionne une demande (merge, squash ou rebase), selon le droit du membre sur la forge.

Corpsmethode? ('merge' | 'squash' | 'rebase'), message?, supprimerBranche?
RéponseVersionFusionDto
NoteRefus de la forge (droit, conflit) : 403 ou 409 avec la raison. 402 `VERSION_GELEE` stockage plein. Journal `version.fusionnee` ; la taille du dépôt est relue aussitôt.
GET /projects/:id/cloud

Les archives du dossier local de ce projet mises au cloud pour libérer un poste : état (ENVOI, VERIFICATION, AU_CLOUD, CORROMPU, RAPATRIE), taille, appareil, empreintes. Jamais la clé.

Réponse{ archives: ProjetCloudDto[] }
POST /projects/:id/cloud

Ouvre l’envoi d’une archive du dossier local au stockage de Nexus : la place se juge sur la taille brute et se réserve (source PROJETS de l’abonnement). Rend la clé AES de l’archive et la taille d’une partie.

CorpsoctetsBruts, fichiers, appareil, nomDossier
RéponseOuvertureProjetCloudDto { archive, cle, taillePartie }
NoteRefus : stockage plein (402 `STOCKAGE_PLEIN`), la moitié de la capacité déjà rapatriée ce mois-ci (402 `SORTIE_EPUISEE`), trop gros (413 `TROP_GROS`), mode aveugle (403 `AVEUGLE`), stockage non configuré (503 `STOCKAGE`). Journal `projet.cloud.envoi`.
POST /projects/:id/cloud/:archive/parties

Signe des parties de l’envoi (20 au plus, 16 Mio chacune au plus) : des URL PUT que le poste emploie directement.

Corpsparties [{ numero, taille }]
Réponse{ parties: [{ numero, url, entetes }] }
POST /projects/:id/cloud/:archive/terminer

Termine l’envoi : les parties reçues par le stockage doivent faire la taille annoncée ; l’archive passe en VERIFICATION, le serveur la relit et ne la dit AU_CLOUD qu’avec la même empreinte SHA-256.

Corpsoctets, empreinte (SHA-256 hexadécimal)
RéponseProjetCloudDto
NoteTaille reçue différente : 409 `EMPREINTE`. Journal `projet.cloud.termine`.
POST /projects/:id/cloud/:archive/rapatrier

Rapatrie une archive AU_CLOUD : une URL de lecture signée (une heure) et la clé. Jamais refusé pour la place ou la sortie du mois, seulement compté.

RéponseRapatriementProjetCloudDto { archive, cle, url, expireA }
NoteJournal `projet.cloud.rapatriement`.
POST /projects/:id/cloud/:archive/rapatrie

Le poste a rapatrié et relu l’archive : avec l’empreinte relue au serveur, l’objet s’efface et la place revient (RAPATRIE). Une autre empreinte : 409 `EMPREINTE`, l’archive reste.

Corpsempreinte
RéponseProjetCloudDto
DELETE /projects/:id/cloud/:archive

Abandonne un envoi ouvert ou abîmé (sa place revient). Une archive AU_CLOUD ou en vérification ne s’abandonne pas (409) : elle se rapatrie.

RéponseProjetCloudDto
POST /projects/:id/cloud/:archive/retire

Le poste déclare avoir retiré son dossier après la relecture de l’archive (en-tête x-nexus-appareil). C’est ce qui permet à l’aperçu de suppression du projet de dire « seule copie ».

RéponseProjetCloudDto
GET /projets-cloud/orphelines

Les archives au cloud de l’espace dont le projet a été supprimé AVANT que la fenêtre de suppression ne les nomme : jamais purgées d’office, comptées dans le stockage. Administrateur.

Réponse{ archives: ArchiveOrphelineDto[] }
DELETE /projets-cloud/orphelines/:archive session de l’application seulement

Retire à la main une archive sans projet : l’objet est effacé, la place revient. Administrateur, en session (ni clé d’API, ni agent : 403). Une archive dont le projet existe, ou d’un autre espace : 404.

RéponseArchiveOrphelineDto
GET /projects/:id/pieces

Les pièces déposées dans le détail du projet pour ses agents : nom, type, poids, qui. Aucun contenu. Sous mode aveugle : `aveugle: true`, liste vide.

RéponsePiecesProjetDto { pieces, aveugle, totalOctets, limites }
POST /projects/:id/pieces

Dépose une pièce dans le détail du projet. Le même contenu sous le même nom rend la ligne existante (`existait`).

Corpsname, mimeType, dataBase64 (15 Mo décodés au plus)
RéponsePieceProjetDto
NoteTout membre affecté, comme pour la description. Refus : un nom de secret et un programme (400), trop lourd (413), 30 pièces ou 200 Mo par projet (409 `PLEIN`), mode aveugle (403 `AVEUGLE`). Journal `projet.piece-deposee`.
GET /projects/:id/pieces/:pieceId/contenu

Le contenu d’une pièce, en base64.

RéponsePieceProjetContenuDto
GET /projects/:id/pieces/:pieceId/texte

Ce que Nexus sait lire d’une pièce : le texte d’un PDF, d’un Office, d’un fichier texte ; sinon la raison. Relevé une fois dans un processus isolé, puis gardé.

RéponseExtractionPieceDto { genre, texte, coupe?, pages?, raison? }
NoteLe contenu vient souvent d’un client : une donnée, jamais une consigne.
DELETE /projects/:id/pieces/:pieceId

Retire une pièce du détail du projet. Journal `projet.piece-retiree`.

Réponse{ ok: true }