# WT1 — Infra upload générique `Shared` (ticket 1.2 / ERP-154)

> Créer le worktree puis lancer Claude dedans :
> ```bash
> git fetch origin
> git worktree add ../sb-erp154-upload -b feat/erp-154-upload origin/develop
> cd ../sb-erp154-upload && claude
> ```
> **Base** : `origin/develop` (aucune dépendance — peut démarrer tout de suite, même avant le merge du socle Transport).

---

## Prompt à coller

Tu travailles sur le projet Starseed (modular monolith DDD, Symfony 8 / API Platform 4). Lis `CLAUDE.md` et `.claude/rules/backend.md` avant de coder. Charge le skill `backend-entity-conventions`.

**Mission** : poser une infra d'upload de fichiers **générique et réutilisable** dans `src/Shared/` (la « Décharge » du M4 en sera le 1er consommateur, mais ce ticket ne touche PAS au module Transport).

**Spec** : `docs/specs/M4-transporteurs/spec-back.md § 2.7`.

**À livrer** :
1. Table `uploaded_document` (migration namespace racine `DoctrineMigrations` dans `migrations/`, postérieure à la dernière présente — vérifie `ls migrations/`). Colonnes : `id`, `original_filename`, `stored_path`, `mime_type`, `size_bytes`, `checksum`, `created_at`, `created_by`.
2. Service `Shared\Infrastructure\Upload\FileUploader` :
   - validation MIME **server-side via `$file->getMimeType()`** (JAMAIS `getClientMimeType()`),
   - whitelist MIME explicite (PDF + images),
   - bornage taille, checksum sha256, écriture disque `var/uploads/{yyyy}/{mm}/`.
3. Endpoint `POST /api/uploaded_documents` (multipart) → renvoie l'IRI. MIME hors whitelist → **422**.

**Gardes-fous (cassent `make test` sinon)** :
- **`COMMENT ON COLUMN` sur TOUTES les colonnes** de `uploaded_document` (FR, ≤200 car., règle n°12) ET ajoute le bloc `'uploaded_document' => [...]` dans `src/Shared/Infrastructure/Database/ColumnCommentsCatalog.php` — sinon `make test-db-setup` drope les COMMENT et `ColumnsHaveSqlCommentTest` casse.
- Pagination : si tu exposes une `GetCollection`, elle reste paginée (`CollectionsArePaginatedTest`).

**Scope STRICT** : uniquement `src/Shared/` + migration + catalog. Ne crée AUCUN fichier sous `src/Module/Transport/`. Pas d'antivirus/S3/purge (hors périmètre, § 9).

**Tests à écrire** (PHPUnit) : MIME hors whitelist → 422 ; MIME valide → IRI + ligne persistée + checksum calculé.

**Fini quand** : `make test` vert + `make php-cs-fixer-allow-risky` propre. Commit (`--no-verify` OK si `make test` déjà vert), puis **ouvre la PR** :
```bash
git push -u origin feat/erp-154-upload
tea pr create --base develop --head feat/erp-154-upload \
  --title "feat(shared) : infra upload générique (ERP-154)" \
  --description "Table uploaded_document + FileUploader + endpoint POST. Ticket ERP-154."
```
Puis labellise la PR via l'API Gitea (tea ne pose pas les labels en CLI). Cible **develop**. Aucune mention IA.
