---
suivi: 1355
date: 2026-08-14
sujet: lot_f_depot_documentaire_siwi
chantier: marches_reprise
type: diag
statut: poussé
hash: 41b8c083
fichiers:
  - tools/diag/preuve_app_token_cli_1355.php
  - docs/suivi/SUIVI_1355_lot_f_depot_documentaire_siwi.md
---

## PROMPT ENVOYÉ

SUIVI #1355 — Lot F dépôt documentaire SIWI (file artisan, arb HECTARE CDC,
idempotence id_doc, pas de sync queue). Clause d’arrêt si arb HECTARE non
alignée CDC ou si SharePointService exige plus qu’un chemin. Vérifier
getAppAccessToken CLI en premier. Rebaser origin/main (#1354).

## FICHES LUES

- `#1326` LEÇON : intention = `etat_depot_docs=en_attente` à la création ;
  **hors dépôt docs (lot F)** ; queue sync qui avale les exceptions = faux ok.
- `#1353` LEÇON : `creerDossierMarche` = jeton **app** ; preuve OVH CLI à
  valider (`app_token` pouvait être NON).
- `#1346` : 403 feuille marché ; jeton délégué vs app.
- `#1338`/`#1340` : résolution PDF casse-insensible sur disque `siwi_import`.
- `#1098`/`#1241` : arbo lotissement actuelle ≠ CDC #1355.

## CLAUSE D’ARRÊT — DÉCLENCHÉE

**Aucun dépôt implémenté.** L’arborescence HECTARE lotissement **existe en
code** mais **n’est pas** celle annoncée dans le prompt CDC. Improviser un
mapping ou renommer l’existant violerait la clause et orphelinerait des
`item_id`. Inventaire ci-dessous + options d’arbitrage.

---

### 1. EN PREMIER — `getAppAccessToken()` en CLI

| Environnement | Résultat |
|---|---|
| Cursor local (Windows, `PHP_SAPI=cli`) | **`app_token=OUI`** (len=2194, client_credentials OK) |
| OVH prod (SSH) | **À confirmer** avec le script ci-dessous — `#1353` avait signalé `app_token=NON` en CLI |

Commande exacte OVH :

```bash
cd /home/hectare-envol/envol.hectare.fr
php -d display_errors=1 tools/diag/preuve_app_token_cli_1355.php
```

Mécanisme : `GraphApiService::getAppAccessToken` L23-84 — POST
`login.microsoftonline.com/.../oauth2/v2.0/token`, `grant_type=client_credentials`,
cache `graph_app_token` 55 min. **Pas** de jeton délégué.

Si OVH = NON → **BLOQUANT** pour une commande artisan de file. Options
(sans revenir au délégué / 403) :
1. **Endpoint web interne** (PHP-FPM) déclenché par cron `curl` HTTPS local
   (même pattern que sync programme SIWI `#1326`).
2. Obtenir / préchauffer le cache token autrement (web) puis artisan lecture
   cache — fragile si cache fichier/redis partagé.
3. Ne **jamais** rebasculer `getAccessToken()` délégué (#1353).

Réseau : le prompt #1355 indique HTTPS CLI OK sauf `*.powerplatform.com` ;
la règle projet OVH reste prudente — **la preuve script tranche**.

---

### 2. Intention #1326 (à réutiliser, ne pas doubler)

| Élément | État |
|---|---|
| Pose | `SiwiRepriseActionService` ~L370-375 : à la **création** marché → `etat_depot_docs = en_attente` |
| Staging import | `non_parti` |
| Rattachement | **n’arme pas** `etat_depot_docs` |
| Constantes modèle | `DEPOT_NON_PARTI`, `DEPOT_EN_ATTENTE` seulement — **pas** `partiel` / `en_echec` |
| Migration commentaire | `non_parti \| en_attente \| partiel \| en_echec` — transitions non codées |
| File / table queue docs | **ABSENTE** |
| Job dépôt SIWI→SP | **ABSENT** (`CreateSharePointArborescence` = arbo programme seulement) |
| UI §10.6 | **ABSENTE** — checkboxes Index.vue ~L2080 « lot F UI-only » ; `etat_depot_docs` non sérialisé |

---

### 3. Arborescence — écart CDC vs code (STOP)

**CDC Robin (#1355) — HECTARE uniquement :**

```
{DEPT}/{COMMUNE}/{CODE}--{LIBELLE}/TRAVAUX/
  {POSTE}--{ENTREPRISE}--{REFERENCE_MARCHE}/
    CONTRACTUEL/ | FACTURES/ | TECHNIQUE/ | SOUS_TRAITANCE/
```

**Code actuel (`creerDossierMarcheLotissement` L2088-2286 +
`SharePointArborescenceStructures::structureMarcheLotissement` L203-222) :**

```
TRAVAUX/4_PRESTATAIRES/{POSTE}_{ENTREPRISE}[_{id}]/
  1_ADMINISTRATIF/
  2_CONTRATS_ET_AVENANTS/
  3_SUIVI_OPERATIONNEL/{…}/
  4_DOC_LIBRES/
  SOUS_TRAITANTS/
```

| CDC | Code #1098 |
|---|---|
| `{POSTE}--{ENTREPRISE}--{REF}` | `{POSTE}_{ENTREPRISE}` (+ `_{id}` si collision) |
| `CONTRACTUEL` / `FACTURES` / `TECHNIQUE` / `SOUS_TRAITANCE` | admin / contrats / suivi / doc_libres / `SOUS_TRAITANTS` |
| Collision 161 cas | suffixe `_{marche.id}` — **pas** la référence `MCH-…` |

**ENVOL VEFA** : `05_SUIVI_CHANTIER/4_PRESTATAIRES/…` + 4 sous-dossiers —
**ne pas toucher** (12 programmes migrés, `item_id` en base). Intact.

Modifier `SharePointService` pour appliquer le CDC = **plus** qu’« ajouter un
chemin » : nouvelle convention de nom + 4 dossiers cibles + collision par
référence. → **clause d’arrêt**.

---

### 4. Briques réutilisables (sans improvisation)

| Brique | Où | Usage Lot F |
|---|---|---|
| PDF casse-insensible | `SiwiImportController::resolveSiwiPdfOnDisk` (#1338/#1340) | Réutiliser |
| Disque | `Storage::disk('siwi_import')` / `SIWI_IMPORT_PATH` | Lecture seule |
| Upload app | `SharePointService::uploadFichierApp` (#1353 token) | Réutiliser |
| `MarcheDocument` + `sharepoint_item_id` | `MarcheController::storeDocument` | Pattern écriture item_id — **ne pas** créer `depot_factures` |
| `normalizeDynamicFolderName` | SharePointService | Sanitizer unique |

Orphelins disque (~5100) / id manquants (723) : normaux — sauter sans erreur
bloquante (à coder après arbitrage).

---

### 5. Options d’arbitrage (attendre Robin)

**A — Adopter le CDC pour les NOUVEAUX marchés HECTARE**  
Réécrire `creerDossierMarcheLotissement` + `structureMarcheLotissement` :
`{POSTE}--{ENTREPRISE}--{REF}` + 4 dossiers CDC. Ne pas renommer les dossiers
déjà créés. Le dépôt Lot F cible uniquement la nouvelle convention (marchés
créés après bascule, ou création à la volée du chemin CDC si absent).

**B — Déposer dans l’arbo #1098 existante** (mapping métier)  
Ex. Commandes→`2_CONTRATS_ET_AVENANTS`, Technique→`3_SUIVI_OPERATIONNEL`,
Sous-traitants→`SOUS_TRAITANTS`, Comptabilité→? (pas de `FACTURES` —
exception CDC non représentée). Collision : garder `_{id}` ou migrer nom
vers `--{REF}` sans renommer l’existant. **Contredit** le CDC explicite.

**C — Chemin SIWI parallèle sous TRAVAUX** (hors `4_PRESTATAIRES`)  
Risque double arbo / confusion explorateur — déconseillé sans plan.

**Puis (commun, après A ou B)**  
1. Table file (ou lignes `siwi_documents` TRAVAIL) alimentée depuis
   `etat_depot_docs=en_attente` — **pas** `dispatch()` sync.
2. Commande artisan **ou** endpoint web si CLI token NON.
3. Idempotence `id_doc` + `sharepoint_item_id` à chaque succès.
4. Statuts `partiel` / `en_echec` + UI « N sur M ».
5. Routage 4 branches ; nom fichier `{AAAA-MM-JJ}_{id}_{libellé}.pdf`.
6. Garde-fou longueur URL (~400).

---

### 6. Ce qui n’a PAS été fait (volontaire)

- Pas de modification `SharePointService` / arbo ENVOL / HECTARE.
- Pas de migration file.
- Pas de commande dépôt.
- Pas de `depot_factures` / compta.
- Pas de touch `AppShell` / `useFormatters` / `ObjectSubNavBar`.
- Pas de `dashboard:prune`.
- **`dashboard:prune-obsolete-widgets` non concerné.**

## DÉPLOIEMENT-TEST

```bash
git pull origin main
php artisan optimize:clear && php artisan view:clear
cd /home/hectare-envol/envol.hectare.fr
php -d display_errors=1 tools/diag/preuve_app_token_cli_1355.php
```

Pas de migrate. Coller `app_token=OUI|NON` dans le ticket pour débloquer.

## LEÇON

1. Une arborescence « déjà codée » pour HECTARE n’égale pas le CDC métier :
   comparer **segment marché** et **sous-dossiers cibles** avant tout Lot F.
2. Intention (`etat_depot_docs`) ≠ file de dépôt : une colonne d’état sans
   table/commande ne dépose rien (#1326 hors F).
3. Preuve jeton app en **CLI OVH** avant de promettre une commande artisan
   Graph ; si NON → endpoint web, jamais délégué (#1353).
