From 93cbd48bf58a24385153d5cc4c71df94122c0f4c Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 19 May 2026 08:24:19 +0200 Subject: [PATCH] chore : rename Coltura to Starseed - Rename project name across code, configs, docs, dev/prod infra - Dev: DOCKER_APP_NAME + POSTGRES_DB switched to starseed, containers become php-starseed-fpm / nginx-starseed / starseed-db-1 - Dev: mount nginx.conf on default.conf instead of starseed.conf to avoid alphabetical-order clash with image's default site - Makefile: export CURRENT_UID/CURRENT_GID at top level so docker compose builds (db-reset etc.) get them - Prod: image registry path, container_name, volumes, vhost server_name + paths, DATABASE_URL, CORS, CI workflow - Add doc/prompt-rename-prod.md with the migration runbook for the prod server (DB rename, FS move, vhost, Let's Encrypt) --- .claude/rules/workflow.md | 14 +- .claude/skills/create-module/SKILL.md | 10 +- .gitea/workflows/build-docker.yml | 8 +- CHANGELOG.md | 2 +- CLAUDE.md | 4 +- README.md | 2 +- REVIEW.md | 8 +- TICKETS.md | 18 +- config/packages/api_platform.yaml | 2 +- doc/audit-log-review-backlog.md | 2 +- doc/deployment-docker.md | 54 ++-- doc/prompt-rename-prod.md | 236 ++++++++++++++++++ doc/review-PR1-ERP7-modular-monolith.md | 12 +- docker-compose.yml | 2 +- docs/rbac/ticket-343-spec.md | 64 ++--- docs/rbac/ticket-344-spec.md | 20 +- docs/rbac/ticket-345-spec.md | 36 +-- docs/sites/ticket-01-spec.md | 38 +-- docs/sites/ticket-02-spec.md | 56 ++--- docs/sites/ticket-03-spec.md | 30 +-- docs/sites/ticket-04-spec.md | 26 +- frontend/app/layouts/default.vue | 2 +- frontend/assets/css/main.css | 2 +- frontend/eslint.config.mjs | 2 +- frontend/i18n/locales/fr.json | 2 +- .../modules/sites/components/SiteSelector.vue | 2 +- frontend/package-lock.json | 4 +- frontend/package.json | 2 +- frontend/playwright.config.ts | 2 +- frontend/tailwind.config.ts | 6 +- infra/dev/.env.docker | 4 +- infra/prod/.env.prod.example | 4 +- infra/prod/Dockerfile | 2 +- infra/prod/deploy.sh | 4 +- infra/prod/docker-compose.prod.yml | 8 +- infra/prod/nginx-proxy.conf | 6 +- makefile | 8 +- migrations/Version20260417120000.php | 2 +- src/Module/Sites/Domain/Entity/Site.php | 2 +- .../DataFixtures/SitesFixtures.php | 2 +- 40 files changed, 476 insertions(+), 234 deletions(-) create mode 100644 doc/prompt-rename-prod.md diff --git a/.claude/rules/workflow.md b/.claude/rules/workflow.md index d23563b..8615c9e 100644 --- a/.claude/rules/workflow.md +++ b/.claude/rules/workflow.md @@ -41,8 +41,8 @@ Si une verification echoue ou ne peut pas etre lancee (ex : container pas demarr ## Time tracking Lesstime -Au demarrage de toute tache de dev sur Coltura, creer une time entry via l'API Lesstime (cf. `~/.claude/CLAUDE.md` pour la procedure complete). -- Projet : `/api/projects/6` (COLTURA) +Au demarrage de toute tache de dev sur Starseed, creer une time entry via l'API Lesstime (cf. `~/.claude/CLAUDE.md` pour la procedure complete). +- Projet : `/api/projects/6` (STARSEED) - Tags : choisir selon le type (Backend `3`, Frontend `2`, Infra `5`, UI/UX `4`, Maintenance `6`, Gestion projet `9`, etc.) ## Fix `make cache-clear` (permissions `var/`) @@ -50,17 +50,17 @@ Au demarrage de toute tache de dev sur Coltura, creer une time entry via l'API L Si `make cache-clear` echoue sur les permissions de `var/` : ```bash -docker exec -t -u root php-coltura-fpm chown -R www-data:www-data /var/www/html/var -docker exec -t -u www-data php-coltura-fpm php bin/console cache:clear +docker exec -t -u root php-starseed-fpm chown -R www-data:www-data /var/www/html/var +docker exec -t -u www-data php-starseed-fpm php bin/console cache:clear ``` A terme : integrer ce fix dans le `makefile` lui-meme. ## Docker — references utiles -- Container PHP : `php-coltura-fpm` -- Container Nginx : `nginx-coltura` (port 8083) +- Container PHP : `php-starseed-fpm` +- Container Nginx : `nginx-starseed` (port 8083) - Container DB : PostgreSQL port **5437** (interne et externe) - Config dev : `infra/dev/.env.docker` (override local : `infra/dev/.env.docker.local`) - Config prod : `infra/prod/` (Dockerfile multi-stage, `docker-compose.prod.yml`) -- Apres modif nginx : `docker restart nginx-coltura` +- Apres modif nginx : `docker restart nginx-starseed` diff --git a/.claude/skills/create-module/SKILL.md b/.claude/skills/create-module/SKILL.md index 406db9c..77f11f6 100644 --- a/.claude/skills/create-module/SKILL.md +++ b/.claude/skills/create-module/SKILL.md @@ -1,11 +1,11 @@ --- name: create-module -description: Scaffold a new Coltura module (backend + frontend) and optionally wire its entries into the sidebar config. Use when the user asks to create, add, scaffold, or generate a new module — e.g., "crée un module Paie", "add a Pointage module", "ajoute un module RH". The backend is the source of truth for activation and sidebar layout; the frontend scans modules automatically. +description: Scaffold a new Starseed module (backend + frontend) and optionally wire its entries into the sidebar config. Use when the user asks to create, add, scaffold, or generate a new module — e.g., "crée un module Paie", "add a Pointage module", "ajoute un module RH". The backend is the source of truth for activation and sidebar layout; the frontend scans modules automatically. --- -# Create a new Coltura module +# Create a new Starseed module -Scaffolds a new module across backend and frontend following Coltura's modular monolith DDD architecture. +Scaffolds a new module across backend and frontend following Starseed's modular monolith DDD architecture. ## Architecture reminder — read before acting @@ -178,8 +178,8 @@ Execute in this exact order: 6. **Backend: sidebar** — if the user wants sidebar entries, edit `config/sidebar.php`. 7. **Frontend: translations** — edit `frontend/i18n/locales/fr.json`. 8. **Verify** — run: - - `docker exec -t -u root php-coltura-fpm chown -R www-data:www-data /var/www/html/var` (avoid permission issues) - - `docker exec -t -u www-data php-coltura-fpm php bin/console cache:clear` (validates backend) + - `docker exec -t -u root php-starseed-fpm chown -R www-data:www-data /var/www/html/var` (avoid permission issues) + - `docker exec -t -u www-data php-starseed-fpm php bin/console cache:clear` (validates backend) - `cd frontend && npx nuxi prepare` (validates Nuxt auto-detection of the new layer) 9. **Report** — list files created, the route(s) to test, and the sidebar items added. diff --git a/.gitea/workflows/build-docker.yml b/.gitea/workflows/build-docker.yml index 43e08da..542607d 100644 --- a/.gitea/workflows/build-docker.yml +++ b/.gitea/workflows/build-docker.yml @@ -20,11 +20,11 @@ jobs: run: | docker build \ -f infra/prod/Dockerfile \ - -t gitea.malio.fr/malio-dev/coltura:${{ gitea.ref_name }} \ - -t gitea.malio.fr/malio-dev/coltura:latest \ + -t gitea.malio.fr/malio-dev/starseed:${{ gitea.ref_name }} \ + -t gitea.malio.fr/malio-dev/starseed:latest \ . - name: Push Docker image run: | - docker push gitea.malio.fr/malio-dev/coltura:${{ gitea.ref_name }} - docker push gitea.malio.fr/malio-dev/coltura:latest + docker push gitea.malio.fr/malio-dev/starseed:${{ gitea.ref_name }} + docker push gitea.malio.fr/malio-dev/starseed:latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 9641f98..8c39dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -Liste des évolutions du projet Coltura +Liste des évolutions du projet Starseed ## [0.0.0] diff --git a/CLAUDE.md b/CLAUDE.md index 2200b89..137720e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ -# Coltura +# Starseed ## Contexte CRM/ERP en architecture **modular monolith DDD**. Le backend est la source de verite unique (modules actifs, sidebar). Le frontend scanne `frontend/modules/*/` comme layers Nuxt et consomme l'API pour la navigation. Multi-tenant : chaque module est activable/desactivable. @@ -9,7 +9,7 @@ Doc humaine : @README.md — Spec audit : @doc/audit-log.md - Backend : PHP 8.4, Symfony 8, API Platform 4, Doctrine ORM, PostgreSQL 16 (port 5437) - Frontend : Nuxt 4 (SPA), Vue 3, Pinia, Tailwind, @malio/layer-ui, @nuxtjs/i18n - Auth : JWT HTTP-only cookie (Lexik), login a `/login_check` -- Containers : `php-coltura-fpm`, `nginx-coltura` (port 8083), dev Nuxt port **3004** +- Containers : `php-starseed-fpm`, `nginx-starseed` (port 8083), dev Nuxt port **3004** ## Regles ABSOLUES diff --git a/README.md b/README.md index 495c901..6a93517 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Coltura +# Starseed CRM/ERP — Symfony 8 (API Platform 4) + Nuxt 4 diff --git a/REVIEW.md b/REVIEW.md index c701728..0e37708 100644 --- a/REVIEW.md +++ b/REVIEW.md @@ -39,7 +39,7 @@ La branche est globalement solide : les trois miroirs RBAC sont synchronises, le - { path: ^/api/docs, roles: PUBLIC_ACCESS } ``` -La documentation Swagger/OpenAPI d'API Platform est accessible sans authentification, quel que soit l'environnement — y compris en production sur `coltura.malio-dev.fr`. Elle expose : +La documentation Swagger/OpenAPI d'API Platform est accessible sans authentification, quel que soit l'environnement — y compris en production sur `starseed.malio-dev.fr`. Elle expose : - la liste complete des endpoints (`/api/audit-logs`, `/api/users/{id}/rbac`, `/api/sites`, etc.) - les schemas de securite (`is_granted('core.audit_log.view')`) @@ -94,7 +94,7 @@ Le reverse proxy ecoute uniquement sur le port 80 (HTTP), sans redirection 301 v server { listen 80; listen [::]:80; - server_name coltura.malio-dev.fr; + server_name starseed.malio-dev.fr; # Redirection HTTPS obligatoire (ajouter un server block HTTPS par ailleurs). # Tant que le TLS n'est pas en place, au minimum poser les en-tetes suivants. @@ -123,7 +123,7 @@ User-Agent: * Disallow: ``` -La valeur `Disallow:` (vide) signifie "rien n'est interdit" — tous les crawlers peuvent indexer la totalite du site. Pour un outil CRM interne accessible sur un DNS public (`coltura.malio-dev.fr`), c'est un leak inutile : la page de login, les URLs `/admin/*`, les URLs des fiches clients peuvent remonter dans Google. +La valeur `Disallow:` (vide) signifie "rien n'est interdit" — tous les crawlers peuvent indexer la totalite du site. Pour un outil CRM interne accessible sur un DNS public (`starseed.malio-dev.fr`), c'est un leak inutile : la page de login, les URLs `/admin/*`, les URLs des fiches clients peuvent remonter dans Google. **Correction** : @@ -581,7 +581,7 @@ Et ajouter les cles manquantes dans `fr.json` : await loadSidebar() // apres chaque switch ``` -Commentaire : *"les filtres de modules peuvent dependre du site courant"*. En pratique, dans `config/sidebar.php` de Coltura aucun item ne depend du site. C'est un aller-retour reseau inutile a chaque switch, et la sidebar peut "flicker" pour l'utilisateur. +Commentaire : *"les filtres de modules peuvent dependre du site courant"*. En pratique, dans `config/sidebar.php` de Starseed aucun item ne depend du site. C'est un aller-retour reseau inutile a chaque switch, et la sidebar peut "flicker" pour l'utilisateur. **Correction** : rendre le rechargement opt-in ou documenter la raison actuelle (prevoir le futur). diff --git a/TICKETS.md b/TICKETS.md index 99b28e2..5b5957c 100644 --- a/TICKETS.md +++ b/TICKETS.md @@ -39,7 +39,7 @@ access_control: Comme `/api/docs` tombe desormais dans le dernier pattern (`^/api`), il faudra etre authentifie pour le voir. Les devs continueront de l'utiliser apres login — les attaquants non. 3. Recharger : `make cache-clear` puis `make restart`. -4. Tester : `curl -i https://coltura.malio-dev.fr/api/docs` doit retourner `401 Unauthorized` (avant : `200`). +4. Tester : `curl -i https://starseed.malio-dev.fr/api/docs` doit retourner `401 Unauthorized` (avant : `200`). **Fichiers :** `config/packages/security.yaml` @@ -47,12 +47,12 @@ Comme `/api/docs` tombe desormais dans le dernier pattern (`^/api`), il faudra e ### T-002 — Ajouter les en-tetes de securite HTTP de base en prod -**Pourquoi :** sans `X-Frame-Options`, quelqu'un peut integrer Coltura dans une iframe sur un site tiers et faire du clickjacking (faire croire a l'utilisateur qu'il clique sur un bouton anodin alors qu'il valide une action dans Coltura). Sans `X-Content-Type-Options: nosniff`, un navigateur peut deviner le type MIME et executer un fichier qui n'aurait pas du l'etre. Ce sont 3 lignes de config Nginx pour proteger l'application. +**Pourquoi :** sans `X-Frame-Options`, quelqu'un peut integrer Starseed dans une iframe sur un site tiers et faire du clickjacking (faire croire a l'utilisateur qu'il clique sur un bouton anodin alors qu'il valide une action dans Starseed). Sans `X-Content-Type-Options: nosniff`, un navigateur peut deviner le type MIME et executer un fichier qui n'aurait pas du l'etre. Ce sont 3 lignes de config Nginx pour proteger l'application. **A faire :** 1. Ouvrir `infra/prod/nginx-proxy.conf` (c'est le proxy expose au public). -2. Ajouter juste apres `server_name coltura.malio-dev.fr;` : +2. Ajouter juste apres `server_name starseed.malio-dev.fr;` : ```nginx # En-tetes de securite applicables a toutes les reponses @@ -62,13 +62,13 @@ add_header Referrer-Policy "strict-origin-when-cross-origin" always; ``` Explication : -- `X-Frame-Options: DENY` : personne ne peut mettre Coltura dans une iframe. +- `X-Frame-Options: DENY` : personne ne peut mettre Starseed dans une iframe. - `X-Content-Type-Options: nosniff` : le navigateur ne devine pas les types MIME, il fait confiance a ce que le serveur annonce. -- `Referrer-Policy: strict-origin-when-cross-origin` : limite ce que Coltura envoie comme Referer a des sites externes (evite de leaker `/admin/users/42` a un site tiers). +- `Referrer-Policy: strict-origin-when-cross-origin` : limite ce que Starseed envoie comme Referer a des sites externes (evite de leaker `/admin/users/42` a un site tiers). - `always` : envoyer ces en-tetes meme sur les reponses d'erreur (4xx/5xx). -3. Recharger Nginx : `docker restart nginx-coltura` (ou celui qui fait office de proxy public). -4. Verifier : `curl -I https://coltura.malio-dev.fr/` doit afficher ces trois en-tetes. +3. Recharger Nginx : `docker restart nginx-starseed` (ou celui qui fait office de proxy public). +4. Verifier : `curl -I https://starseed.malio-dev.fr/` doit afficher ces trois en-tetes. **Note :** si un reverse proxy externe (Traefik, Cloudflare) ajoute deja ces en-tetes, les poser ici ne fait que dupliquer, c'est sans risque (meme valeur). @@ -813,7 +813,7 @@ if (!is_array($payload)) { ```markdown # Changelog -Liste des evolutions du projet Coltura. +Liste des evolutions du projet Starseed. ## [0.1.34] - 2026-04-XX @@ -859,7 +859,7 @@ Liste des evolutions du projet Coltura. ### T-019 — Conditionner `loadSidebar()` apres switch de site -**Pourquoi :** apres chaque switch de site, `useCurrentSite` recharge la sidebar — mais la sidebar de Coltura ne depend d'aucun site. C'est un aller-retour reseau inutile par switch (~100ms + possible flicker visuel). +**Pourquoi :** apres chaque switch de site, `useCurrentSite` recharge la sidebar — mais la sidebar de Starseed ne depend d'aucun site. C'est un aller-retour reseau inutile par switch (~100ms + possible flicker visuel). **A faire :** diff --git a/config/packages/api_platform.yaml b/config/packages/api_platform.yaml index bc1233e..26cb836 100644 --- a/config/packages/api_platform.yaml +++ b/config/packages/api_platform.yaml @@ -1,5 +1,5 @@ api_platform: - title: Coltura API + title: Starseed API version: 1.0.0 # Scan du module Core pour decouvrir les classes ApiResource et ApiFilter. # Ajouter un chemin par module lors de l'ajout d'entites ApiResource dans d'autres modules. diff --git a/doc/audit-log-review-backlog.md b/doc/audit-log-review-backlog.md index 2fd7737..b935a24 100644 --- a/doc/audit-log-review-backlog.md +++ b/doc/audit-log-review-backlog.md @@ -210,7 +210,7 @@ Le `requestId` est set en `kernel.request` mais jamais cleared. En deploiement F **Fichiers** : `config/packages/framework.yaml`, `src/Module/Core/Infrastructure/Audit/AuditLogWriter.php:69` -Aucune entree `trusted_proxies` ni env `TRUSTED_PROXIES`. Coltura tourne derriere `nginx-coltura` → `php-coltura-fpm`. `Request::getClientIp()` retourne donc systematiquement l'IP **du conteneur nginx** (reseau Docker interne), pas l'IP reelle du client. Toute la valeur forensique de `ip_address` est nulle en prod. +Aucune entree `trusted_proxies` ni env `TRUSTED_PROXIES`. Starseed tourne derriere `nginx-starseed` → `php-starseed-fpm`. `Request::getClientIp()` retourne donc systematiquement l'IP **du conteneur nginx** (reseau Docker interne), pas l'IP reelle du client. Toute la valeur forensique de `ip_address` est nulle en prod. Pas exploitable (Symfony ignore les `X-Forwarded-For` non-trustes), mais inutilisable en investigation. diff --git a/doc/deployment-docker.md b/doc/deployment-docker.md index e1cbb4c..6d7ec5e 100644 --- a/doc/deployment-docker.md +++ b/doc/deployment-docker.md @@ -1,4 +1,4 @@ -# Deploiement Docker — Coltura +# Deploiement Docker — Starseed ## Pre-requis @@ -29,9 +29,9 @@ sudo systemctl start nginx ### PostgreSQL PostgreSQL tourne dans un conteneur Docker separe (voir le repo `infra-postgres`). -Il doit etre installe et accessible avant de deployer Coltura. +Il doit etre installe et accessible avant de deployer Starseed. -Creer la base de donnees pour Coltura : +Creer la base de donnees pour Starseed : ```bash cd /var/www/postgres @@ -43,7 +43,7 @@ docker compose exec postgres psql -U admin CREATE USER malio WITH PASSWORD 'motdepasse'; -- Creer la base -CREATE DATABASE coltura_prod OWNER malio; +CREATE DATABASE starseed_prod OWNER malio; \q ``` @@ -51,7 +51,7 @@ CREATE DATABASE coltura_prod OWNER malio; ## Premiere installation (nouvelle machine) -Guide complet pour mettre en ligne Coltura sur une machine vierge. Inclut les pre-requis, la BDD et l'app. +Guide complet pour mettre en ligne Starseed sur une machine vierge. Inclut les pre-requis, la BDD et l'app. ### 1. Installer les pre-requis @@ -60,9 +60,9 @@ Installer Docker, Nginx et PostgreSQL (voir section Pre-requis ci-dessus). ### 2. Creer le dossier de deploiement ```bash -sudo mkdir -p /var/www/coltura -sudo chown -R $(whoami):$(whoami) /var/www/coltura -cd /var/www/coltura +sudo mkdir -p /var/www/starseed +sudo chown -R $(whoami):$(whoami) /var/www/starseed +cd /var/www/starseed ``` ### 3. Se connecter au registry Docker de Gitea @@ -83,8 +83,8 @@ Creer `docker-compose.yml` : ```yaml services: app: - image: gitea.malio.fr/malio-dev/coltura:${COLTURA_IMAGE_TAG:-latest} - container_name: coltura-app + image: gitea.malio.fr/malio-dev/starseed:${STARSEED_IMAGE_TAG:-latest} + container_name: starseed-app env_file: .env ports: - "8083:80" @@ -105,9 +105,9 @@ set -euo pipefail cd "$(dirname "$0")" TAG="${1:-latest}" -export COLTURA_IMAGE_TAG="$TAG" +export STARSEED_IMAGE_TAG="$TAG" -echo "==> Deploying coltura:${TAG}..." +echo "==> Deploying starseed:${TAG}..." echo "==> Pulling image..." docker compose pull @@ -146,7 +146,7 @@ APP_DEBUG=0 APP_SECRET= # Database (host.docker.internal = la machine hote, ou le PG tourne en Docker) -DATABASE_URL="postgresql://malio:password@host.docker.internal:5432/coltura_prod?serverVersion=16&charset=utf8" +DATABASE_URL="postgresql://malio:password@host.docker.internal:5432/starseed_prod?serverVersion=16&charset=utf8" # JWT JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem @@ -158,10 +158,10 @@ JWT_TOKEN_TTL=86400 JWT_COOKIE_TTL=86400 # CORS -CORS_ALLOW_ORIGIN='^https?://coltura\.malio-dev\.fr$' +CORS_ALLOW_ORIGIN='^https?://starseed\.malio-dev\.fr$' # App -DEFAULT_URI=https://coltura.malio-dev.fr +DEFAULT_URI=https://starseed.malio-dev.fr ``` ### 6. Generer les cles JWT @@ -190,17 +190,17 @@ mkdir -p uploads Copier la config reverse proxy depuis le repo : ```bash -sudo cp infra/prod/nginx-proxy.conf /etc/nginx/sites-available/coltura.conf +sudo cp infra/prod/nginx-proxy.conf /etc/nginx/sites-available/starseed.conf ``` -Ou creer `/etc/nginx/sites-available/coltura.conf` manuellement (voir `infra/prod/nginx-proxy.conf`). +Ou creer `/etc/nginx/sites-available/starseed.conf` manuellement (voir `infra/prod/nginx-proxy.conf`). -La config inclut le **mode maintenance** : si le fichier `/var/www/coltura/maintenance.on` existe, Nginx renvoie une 503 avec `maintenance.html`. +La config inclut le **mode maintenance** : si le fichier `/var/www/starseed/maintenance.on` existe, Nginx renvoie une 503 avec `maintenance.html`. Activer le site : ```bash -sudo ln -sf /etc/nginx/sites-available/coltura.conf /etc/nginx/sites-enabled/coltura.conf +sudo ln -sf /etc/nginx/sites-available/starseed.conf /etc/nginx/sites-enabled/starseed.conf sudo nginx -t && sudo systemctl reload nginx ``` @@ -208,13 +208,13 @@ sudo nginx -t && sudo systemctl reload nginx ```bash # Activer la maintenance -touch /var/www/coltura/maintenance.on +touch /var/www/starseed/maintenance.on # Desactiver la maintenance -rm /var/www/coltura/maintenance.on +rm /var/www/starseed/maintenance.on ``` -Optionnel : creer une page `/var/www/coltura/public/maintenance.html` personnalisee. +Optionnel : creer une page `/var/www/starseed/public/maintenance.html` personnalisee. ### 9. Deployer @@ -232,7 +232,7 @@ Choisir `App\Entity\User`, taper le mdp, copier le hash. Puis : ```bash cd /var/www/postgres -docker compose exec -T postgres psql -U malio coltura_prod -c "INSERT INTO \"user\" (username, roles, password, created_at) VALUES ('admin', '[\"ROLE_ADMIN\"]', '', NOW());" +docker compose exec -T postgres psql -U malio starseed_prod -c "INSERT INTO \"user\" (username, roles, password, created_at) VALUES ('admin', '[\"ROLE_ADMIN\"]', '', NOW());" ``` Ou charger les fixtures (dev uniquement) : @@ -244,7 +244,7 @@ docker compose exec -T -u www-data app php bin/console doctrine:fixtures:load -- ### Structure finale du dossier ``` -/var/www/coltura/ +/var/www/starseed/ ├── docker-compose.yml ├── deploy.sh ├── .env @@ -261,7 +261,7 @@ docker compose exec -T -u www-data app php bin/console doctrine:fixtures:load -- Quand l'app est deja installee, deployer une mise a jour : ```bash -cd /var/www/coltura +cd /var/www/starseed ./deploy.sh # deploie la derniere version (latest) ./deploy.sh v0.2.0 # deploie une version specifique ``` @@ -293,7 +293,7 @@ docker compose exec -T -u www-data app php bin/console doctrine:migrations:migra Le workflow `.gitea/workflows/build-docker.yml` se declenche automatiquement sur push de tag `v*` : 1. Build l'image multi-stage -2. Push vers `gitea.malio.fr/malio-dev/coltura:` et `:latest` +2. Push vers `gitea.malio.fr/malio-dev/starseed:` et `:latest` Combine avec `auto-tag-develop.yml`, chaque push sur `develop` cree automatiquement un tag → build → image disponible. @@ -302,7 +302,7 @@ Combine avec `auto-tag-develop.yml`, chaque push sur `develop` cree automatiquem ## Voir les logs ```bash -cd /var/www/coltura +cd /var/www/starseed docker compose logs -f # tous les logs docker compose logs -f --tail=100 # 100 dernieres lignes ``` diff --git a/doc/prompt-rename-prod.md b/doc/prompt-rename-prod.md new file mode 100644 index 0000000..a00d72a --- /dev/null +++ b/doc/prompt-rename-prod.md @@ -0,0 +1,236 @@ +# Prompt — Migration prod Coltura -> Starseed + +Copier-coller integralement dans une session Claude lancee **sur le serveur de prod** apres que : +- le push develop + build CI ont publie l'image `gitea.malio.fr/malio-dev/starseed:latest`, +- le DNS `starseed.malio-dev.fr` resout vers ce serveur, +- un certificat Let's Encrypt existe (ou est pret a etre genere) pour `starseed.malio-dev.fr`. + +--- + +## Prompt a fournir au Claude prod + +Tu es sur le serveur de production d'une app Symfony+Nuxt qui s'appelait **Coltura** et qui doit etre renommee en **Starseed**. Le rename cote code est deja fait et merge. Le repo Gitea s'appelle deja `starseed`. L'image `gitea.malio.fr/malio-dev/starseed:latest` est publiee. + +Le DNS `starseed.malio-dev.fr` resout vers ce serveur. Le certificat Let's Encrypt pour ce nom de domaine est gere a la main par l'admin (a confirmer avant l'etape nginx). + +Objectif : basculer la prod sur le nouveau nom (registry, container, DB, path FS, vhost) **sans perdre les donnees** et avec downtime minimal (mode maintenance pendant la migration). + +**Etat actuel a verifier en premier** (donne-moi le retour de chaque commande avant de continuer) : + +```bash +# 1. Container actuel + image +sudo docker ps --filter name=coltura-app --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' + +# 2. DB existante +sudo -u postgres psql -c "\l" | grep -E "coltura|starseed" + +# 3. Path FS app +ls -la /var/www/coltura/ 2>/dev/null | head -5 +ls -la /var/www/starseed/ 2>/dev/null | head -5 + +# 4. Vhost nginx system +sudo ls -la /etc/nginx/sites-enabled/ | grep -E "coltura|starseed" + +# 5. Cert Let's Encrypt +sudo ls /etc/letsencrypt/live/ | grep -E "coltura|starseed" +``` + +**Apres confirmation de l'etat, executer dans cet ordre, en demandant validation utilisateur AVANT chaque etape destructive (DB drop, rm -rf, certificat) :** + +### Etape 1 — Mode maintenance + +```bash +cd /var/www/coltura +touch maintenance.on +# Verifier qu'une requete renvoie 503 +curl -s -o /dev/null -w "HTTP %{http_code}\n" https://coltura.malio-dev.fr/ +``` + +Doit renvoyer `503`. + +### Etape 2 — Backup DB (CRITIQUE — ne pas skipper) + +```bash +BACKUP_FILE="/root/coltura_prod_backup_$(date +%Y%m%d_%H%M%S).sql" +sudo -u postgres pg_dump -F c -f "$BACKUP_FILE" coltura_prod +ls -lh "$BACKUP_FILE" +``` + +**Stocker ce chemin** — il sera utilise pour le rollback. + +### Etape 3 — Creer la DB cible et migrer + +Recuperer l'owner et le user de connexion actuels : + +```bash +sudo -u postgres psql -c "\l coltura_prod" +grep DATABASE_URL /var/www/coltura/.env +``` + +Puis (adapter l'owner si different de `malio`) : + +```bash +sudo -u postgres psql <<'SQL' +CREATE DATABASE starseed_prod OWNER malio; +SQL + +sudo -u postgres pg_dump coltura_prod | sudo -u postgres psql starseed_prod +sudo -u postgres psql starseed_prod -c "\dt" | head -20 +``` + +Verifier que les tables sont bien copiees. Si le user PG s'appelle `coltura`, le renommer ou en creer un `starseed` est OPTIONNEL — la connexion peut continuer avec `coltura` tant que `GRANT` est OK. **Confirmer avec l'utilisateur** s'il veut renommer le role PG : + +```bash +# Optionnel : renommer le role PG (si user de connexion s'appelle 'coltura') +# sudo -u postgres psql -c "ALTER ROLE coltura RENAME TO starseed;" +``` + +### Etape 4 — Renommer le path FS + +```bash +sudo mv /var/www/coltura /var/www/starseed +# Verifier le contenu +sudo ls -la /var/www/starseed/ | head -10 +# Verifier que .env existe encore +sudo test -f /var/www/starseed/.env && echo ".env OK" +``` + +### Etape 5 — Mettre a jour .env de prod + +Editer `/var/www/starseed/.env` : +- `DATABASE_URL` : remplacer `/coltura_prod` -> `/starseed_prod` (et user si renomme a etape 3) +- `CORS_ALLOW_ORIGIN` : remplacer `coltura.malio-dev.fr` -> `starseed.malio-dev.fr` +- `DEFAULT_URI` : `https://starseed.malio-dev.fr` + +Diff attendu : + +```diff +- DATABASE_URL="postgresql://malio:xxx@host.docker.internal:5432/coltura_prod?..." ++ DATABASE_URL="postgresql://malio:xxx@host.docker.internal:5432/starseed_prod?..." +- CORS_ALLOW_ORIGIN='^https?://coltura\.malio-dev\.fr$' ++ CORS_ALLOW_ORIGIN='^https?://starseed\.malio-dev\.fr$' +- DEFAULT_URI=https://coltura.malio-dev.fr ++ DEFAULT_URI=https://starseed.malio-dev.fr +``` + +### Etape 6 — Stopper et supprimer l'ancien container + +```bash +cd /var/www/starseed +sudo docker compose down +# Verifier qu'il n'y a plus de coltura-app +sudo docker ps -a --filter name=coltura +``` + +### Etape 7 — Pull la nouvelle image et demarrer + +Le `docker-compose.prod.yml` du dossier deja a jour pointe sur `gitea.malio.fr/malio-dev/starseed:latest` et `container_name: starseed-app`. + +```bash +cd /var/www/starseed +sudo docker compose pull +sudo docker compose up -d +sleep 5 +sudo docker ps --filter name=starseed-app +sudo docker logs starseed-app --tail 30 +``` + +### Etape 8 — Migrations Doctrine + cache + +```bash +cd /var/www/starseed +sudo docker compose exec -T -u www-data app php bin/console doctrine:migrations:migrate --no-interaction +sudo docker compose exec -T -u www-data app php bin/console cache:clear --env=prod +sudo docker compose exec -T -u www-data app php bin/console cache:warmup --env=prod +``` + +### Etape 9 — Vhost nginx system + certificat + +Copier le nouveau vhost (a jour avec `server_name starseed.malio-dev.fr` et `root /var/www/starseed/public`) : + +```bash +sudo cp /var/www/starseed/infra/prod/nginx-proxy.conf /etc/nginx/sites-available/starseed.conf +sudo ln -sf /etc/nginx/sites-available/starseed.conf /etc/nginx/sites-enabled/starseed.conf +sudo rm -f /etc/nginx/sites-enabled/coltura.conf +sudo nginx -t +``` + +**Avant de reload nginx**, generer le certificat Let's Encrypt pour le nouveau domaine (l'utilisateur doit confirmer ; certbot peut casser temporairement le vhost actuel pendant la challenge) : + +```bash +# Verifier le DNS d'abord +dig +short starseed.malio-dev.fr + +# Generer le cert (l'utilisateur valide) +sudo certbot --nginx -d starseed.malio-dev.fr --non-interactive --agree-tos -m matthieu@malio.fr +``` + +Puis : + +```bash +sudo systemctl reload nginx +``` + +### Etape 10 — Desactiver le mode maintenance et tester + +```bash +rm -f /var/www/starseed/maintenance.on + +# Tests externes +curl -s -o /dev/null -w "HTTP %{http_code}\n" https://starseed.malio-dev.fr/ +curl -s https://starseed.malio-dev.fr/api/version +``` + +`/api/version` doit renvoyer du JSON avec la version courante. + +### Etape 11 — Cleanup (apres 24-48h de stabilite) + +A faire **plus tard**, seulement quand on est sur que tout marche : + +```bash +# Backup deja conserve en /root/coltura_prod_backup_*.sql. +# Apres validation utilisateur : +sudo -u postgres psql -c "DROP DATABASE coltura_prod;" +sudo rm -f /etc/nginx/sites-available/coltura.conf +sudo docker image prune # nettoie les vieilles images coltura +``` + +--- + +## Rollback (si echec apres etape 5) + +```bash +# 1. Remettre maintenance +touch /var/www/starseed/maintenance.on 2>/dev/null || touch /var/www/coltura/maintenance.on + +# 2. Restaurer le path FS +sudo mv /var/www/starseed /var/www/coltura 2>/dev/null || true + +# 3. Restaurer le vhost coltura +sudo rm -f /etc/nginx/sites-enabled/starseed.conf +sudo ln -sf /etc/nginx/sites-available/coltura.conf /etc/nginx/sites-enabled/coltura.conf +sudo systemctl reload nginx + +# 4. Redemarrer l'ancien container (l'image coltura est encore dans le registry) +cd /var/www/coltura +# Editer docker-compose.prod.yml pour pointer sur coltura:latest si necessaire +sudo docker compose up -d + +# 5. Si la DB starseed_prod a ete modifiee, restaurer depuis le backup +sudo -u postgres psql -c "DROP DATABASE IF EXISTS coltura_prod;" +sudo -u postgres pg_restore -C -d postgres "$BACKUP_FILE" + +# 6. Lever maintenance +rm -f /var/www/coltura/maintenance.on +``` + +--- + +## Regles de comportement pour le Claude prod + +- **Ne jamais skipper le backup** (etape 2). +- **Demander confirmation utilisateur** avant : `DROP DATABASE`, `rm -rf`, `certbot`, et avant de lever le mode maintenance final. +- **Une seule operation destructive a la fois**, attendre le retour utilisateur entre chaque. +- **Logger systematiquement** la sortie des commandes critiques (pg_dump, docker compose up, certbot). +- **Si une etape echoue**, NE PAS continuer — declencher le rollback. +- **Ne commit rien** sur le repo depuis le serveur prod. diff --git a/doc/review-PR1-ERP7-modular-monolith.md b/doc/review-PR1-ERP7-modular-monolith.md index 8e758c8..1f427cd 100644 --- a/doc/review-PR1-ERP7-modular-monolith.md +++ b/doc/review-PR1-ERP7-modular-monolith.md @@ -9,7 +9,7 @@ ## Résumé de la PR -Cette PR restructure Coltura (CRM/ERP) en **architecture modulaire DDD** (Domain-Driven Design) : +Cette PR restructure Starseed (CRM/ERP) en **architecture modulaire DDD** (Domain-Driven Design) : - **Backend** : introduction de bounded contexts (`Module/Core`, `Module/Commercial`) avec séparation Domain / Application / Infrastructure - **Shared** : couche partagée (events, value objects, contracts, bus interfaces) @@ -36,9 +36,9 @@ Cette PR restructure Coltura (CRM/ERP) en **architecture modulaire DDD** (Domain Liste des évolutions du projet Ferme ``` -Ce fichier appartient à **Coltura**, pas au projet Ferme. C'est une erreur de copier-coller lors du scaffolding initial. +Ce fichier appartient à **Starseed**, pas au projet Ferme. C'est une erreur de copier-coller lors du scaffolding initial. -**Correction** : Remplacer "Ferme" par "Coltura". +**Correction** : Remplacer "Ferme" par "Starseed". --- @@ -76,10 +76,10 @@ Mais la seule page du module commercial est `frontend/modules/commercial/pages/c |---|---| | **Sévérité** | Majeure | | **Fichier** | `infra/dev/.env.docker` | -| **Règle violée** | Workspace `CLAUDE.md` : "Coltura — 8083 / 3003 / **5436**" | +| **Règle violée** | Workspace `CLAUDE.md` : "Starseed — 8083 / 3003 / **5436**" | | **Confiance** | 75/100 | -**Constat** : Le fichier `.env.docker` définit `POSTGRES_PORT=5437`, alors que le port documenté pour Coltura est `5436`. +**Constat** : Le fichier `.env.docker` définit `POSTGRES_PORT=5437`, alors que le port documenté pour Starseed est `5436`. **Impact** : Tout développeur qui suit les ports documentés (ou qui utilise des scripts basés sur ces ports) ne pourra pas se connecter à la base. @@ -93,7 +93,7 @@ Mais la seule page du module commercial est `frontend/modules/commercial/pages/c |---|---| | **Sévérité** | Majeure | | **Fichiers** | `frontend/nuxt.config.ts` (ligne 40), `docker-compose.yml` (ligne 33) | -| **Règle violée** | Workspace `CLAUDE.md` : "Coltura — 8083 / **3003** / 5436" et `CLAUDE.md` projet : "make dev-nuxt # port 3003" | +| **Règle violée** | Workspace `CLAUDE.md` : "Starseed — 8083 / **3003** / 5436" et `CLAUDE.md` projet : "make dev-nuxt # port 3003" | | **Confiance** | 75/100 (confirmé par 3 agents indépendants) | **Constat** : diff --git a/docker-compose.yml b/docker-compose.yml index 451caf0..f3a5800 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,7 +41,7 @@ services: - "8083:80" volumes: - ./:/var/www/html:ro - - ./infra/dev/nginx.conf:/etc/nginx/conf.d/coltura.conf:ro + - ./infra/dev/nginx.conf:/etc/nginx/conf.d/default.conf:ro restart: unless-stopped db: image: postgres:16-alpine diff --git a/docs/rbac/ticket-343-spec.md b/docs/rbac/ticket-343-spec.md index 9ba04cb..a3b28fb 100644 --- a/docs/rbac/ticket-343-spec.md +++ b/docs/rbac/ticket-343-spec.md @@ -13,7 +13,7 @@ Ce ticket livre la base RBAC backend de l'epic en 5 tickets en remplacant le sto - Faire evoluer `User` avec une relation ManyToMany vers `Role`, une relation ManyToMany vers `Permission` pour les permissions directes et un booleen `is_admin`. - Faire evoluer `User::getRoles()` pour rester compatible Symfony en retournant toujours `ROLE_USER` et `ROLE_ADMIN` si `is_admin = true`. - Ajouter `User::getEffectivePermissions()` pour retourner l'union des codes de permissions provenant des roles et des permissions directes. -- Ajouter une methode statique `permissions()` sur `/home/matthieu/dev_malio/Coltura/src/Module/Core/CoreModule.php` et definir le pattern a reproduire pour les autres modules. +- Ajouter une methode statique `permissions()` sur `/home/matthieu/dev_malio/Starseed/src/Module/Core/CoreModule.php` et definir le pattern a reproduire pour les autres modules. - Ajouter une commande console `app:sync-permissions` transactionnelle, idempotente et non destructive avec gestion `orphan`. - Ajouter une migration Doctrine modulaire Core qui cree les tables RBAC, migre les donnees depuis `user.roles`, cree les roles systeme `admin` et `user`, puis supprime la colonne JSON `roles`. - Mettre a jour les fixtures Core pour creer les roles systeme et rattacher l'utilisateur admin au role `admin`. @@ -31,30 +31,30 @@ Ce ticket livre la base RBAC backend de l'epic en 5 tickets en remplacant le sto ### Domaine - Entités -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/Permission.php` : entite Doctrine de permission RBAC, code unique, module source et etat `orphan`. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/Role.php` : entite Doctrine de role RBAC avec relations vers permissions et garde de role systeme. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/Permission.php` : entite Doctrine de permission RBAC, code unique, module source et etat `orphan`. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/Role.php` : entite Doctrine de role RBAC avec relations vers permissions et garde de role systeme. ### Domaine - Repositories -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Repository/PermissionRepositoryInterface.php` : contrat de lecture/ecriture des permissions pour la commande de sync et les fixtures. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Repository/RoleRepositoryInterface.php` : contrat de lecture/ecriture des roles pour migration fonctionnelle, fixtures et usages futurs. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Repository/PermissionRepositoryInterface.php` : contrat de lecture/ecriture des permissions pour la commande de sync et les fixtures. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Repository/RoleRepositoryInterface.php` : contrat de lecture/ecriture des roles pour migration fonctionnelle, fixtures et usages futurs. ### Domaine - Exceptions -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Exception/SystemRoleDeletionException.php` : exception domaine levee si une suppression vise un role systeme. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Exception/SystemRoleDeletionException.php` : exception domaine levee si une suppression vise un role systeme. ### Infrastructure - Doctrine -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/DoctrinePermissionRepository.php` : implementation Doctrine de `PermissionRepositoryInterface`. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/DoctrineRoleRepository.php` : implementation Doctrine de `RoleRepositoryInterface`. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/DoctrinePermissionRepository.php` : implementation Doctrine de `PermissionRepositoryInterface`. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/DoctrineRoleRepository.php` : implementation Doctrine de `RoleRepositoryInterface`. ### Infrastructure - Doctrine Migrations -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/Migrations/Version.php` : migration modulaire RBAC Core avec schema + migration de donnees + rollback minimal. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/Migrations/Version.php` : migration modulaire RBAC Core avec schema + migration de donnees + rollback minimal. ### Infrastructure - Console -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Console/SyncPermissionsCommand.php` : commande `app:sync-permissions` qui scanne les modules actifs et synchronise la table `permission`. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Console/SyncPermissionsCommand.php` : commande `app:sync-permissions` qui scanne les modules actifs et synchronise la table `permission`. ### Infrastructure - DataFixtures @@ -62,12 +62,12 @@ Ce ticket livre la base RBAC backend de l'epic en 5 tickets en remplacant le sto ### Constantes domaine -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Security/SystemRoles.php` : constantes partagees `ADMIN_CODE = 'admin'` et `USER_CODE = 'user'`, utilisees a la fois par les fixtures et par la migration SQL. Place dans `Domain/Security/` (pas `ValueObject/` : ce n'est pas un VO, c'est un conteneur de constantes metier laissant de la place pour d'autres constantes de securite plus tard). +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Security/SystemRoles.php` : constantes partagees `ADMIN_CODE = 'admin'` et `USER_CODE = 'user'`, utilisees a la fois par les fixtures et par la migration SQL. Place dans `Domain/Security/` (pas `ValueObject/` : ce n'est pas un VO, c'est un conteneur de constantes metier laissant de la place pour d'autres constantes de securite plus tard). ## 4. Fichiers à modifier -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/User.php` : supprimer le stockage JSON `roles`, ajouter `isAdmin`, `roles`, `directPermissions`, initialiser les collections, configurer les relations ManyToMany en `fetch=EAGER`, ajouter `getEffectivePermissions()` et adapter `getRoles()` / mutateurs. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/CoreModule.php` : ajouter une methode statique `public static function permissions(): array` qui declare les permissions natives du module Core et sert de reference pour les autres modules. Contenu initial exact : +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/User.php` : supprimer le stockage JSON `roles`, ajouter `isAdmin`, `roles`, `directPermissions`, initialiser les collections, configurer les relations ManyToMany en `fetch=EAGER`, ajouter `getEffectivePermissions()` et adapter `getRoles()` / mutateurs. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/CoreModule.php` : ajouter une methode statique `public static function permissions(): array` qui declare les permissions natives du module Core et sert de reference pour les autres modules. Contenu initial exact : ```php public static function permissions(): array { @@ -80,17 +80,17 @@ Ce ticket livre la base RBAC backend de l'epic en 5 tickets en remplacant le sto } ``` La cle `module` n'est PAS presente dans le payload : elle est auto-injectee par la commande de sync a partir de `CoreModule::ID`. Le code de permission doit obligatoirement commencer par `self::ID . '.'` sous peine d'echec de la sync (garde anti-typo). -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php` : aucun changement attendu dans ce ticket. Les nouvelles relations `$roles`, `$directPermissions` sont chargees par Doctrine via leurs mappings `fetch=EAGER` declares sur l'entite. Si les tests d'integration revelent un lazy-load non voulu au refresh JWT ou a la desserialisation, ajouter une methode `findForSecurity(string $username): ?User` avec `leftJoin` + `addSelect` explicites sur `roles`, `roles.permissions`, `directPermissions`, et brancher le user provider dessus. A trancher par les tests, pas en prevention. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Repository/UserRepositoryInterface.php` : aucun changement dans ce ticket. Ajout eventuel de `findForSecurity()` uniquement si le cas ci-dessus se materialise. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php` : remplacer l'usage de `setRoles(array)` par la creation des roles systeme, le rattachement des utilisateurs a ces roles et le positionnement de `is_admin`. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Console/CreateUserCommand.php` : remplacer la gestion historique de `ROLE_ADMIN` par `setIsAdmin(true)` et rattachement au role systeme `admin` si l'option `--admin` est conservee. -- `/home/matthieu/dev_malio/Coltura/config/services.yaml` : ajouter 2 alias repository, aligne sur le pattern existant pour `UserRepositoryInterface` : +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php` : aucun changement attendu dans ce ticket. Les nouvelles relations `$roles`, `$directPermissions` sont chargees par Doctrine via leurs mappings `fetch=EAGER` declares sur l'entite. Si les tests d'integration revelent un lazy-load non voulu au refresh JWT ou a la desserialisation, ajouter une methode `findForSecurity(string $username): ?User` avec `leftJoin` + `addSelect` explicites sur `roles`, `roles.permissions`, `directPermissions`, et brancher le user provider dessus. A trancher par les tests, pas en prevention. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Repository/UserRepositoryInterface.php` : aucun changement dans ce ticket. Ajout eventuel de `findForSecurity()` uniquement si le cas ci-dessus se materialise. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php` : remplacer l'usage de `setRoles(array)` par la creation des roles systeme, le rattachement des utilisateurs a ces roles et le positionnement de `is_admin`. +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Console/CreateUserCommand.php` : remplacer la gestion historique de `ROLE_ADMIN` par `setIsAdmin(true)` et rattachement au role systeme `admin` si l'option `--admin` est conservee. +- `/home/matthieu/dev_malio/Starseed/config/services.yaml` : ajouter 2 alias repository, aligne sur le pattern existant pour `UserRepositoryInterface` : ```yaml App\Module\Core\Domain\Repository\RoleRepositoryInterface: '@App\Module\Core\Infrastructure\Doctrine\DoctrineRoleRepository' App\Module\Core\Domain\Repository\PermissionRepositoryInterface: '@App\Module\Core\Infrastructure\Doctrine\DoctrinePermissionRepository' ``` La commande `SyncPermissionsCommand` est auto-configuree via `autoconfigure: true`, aucun binding manuel necessaire. -- `/home/matthieu/dev_malio/Coltura/config/modules.php` : aucun changement de contenu requis, mais la commande `app:sync-permissions` devra s'appuyer sur ce fichier comme source de verite des modules actifs. +- `/home/matthieu/dev_malio/Starseed/config/modules.php` : aucun changement de contenu requis, mais la commande `app:sync-permissions` devra s'appuyer sur ce fichier comme source de verite des modules actifs. ## 5. Schéma cible — mappings Doctrine @@ -209,7 +209,7 @@ Etat final attendu : ## 6. Plan de migration Doctrine -La migration doit etre implementée dans `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/Migrations/Version.php` et executer `up()` dans cet ordre. +La migration doit etre implementée dans `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/Migrations/Version.php` et executer `up()` dans cet ordre. **Workflow recommande** : 1. Ecrire d'abord les entites `Permission`, `Role` et la mutation de `User` (section 5). @@ -287,7 +287,7 @@ Cas couverts explicitement : Le mapping Doctrine actuel (`array` PHP → default) peut avoir genere une colonne `JSON` OU `TEXT` selon la version de Symfony/Doctrine. Le cast `::jsonb` fonctionne directement sur `JSON`, mais pas sur `TEXT`. **Avant d'executer la migration en prod**, verifier avec : ```bash -docker exec -it db-coltura psql -U malio -d coltura -c '\d "user"' +docker exec -it db-starseed psql -U malio -d starseed -c '\d "user"' ``` - Si `roles | json` : le SQL ci-dessus fonctionne tel quel. @@ -306,11 +306,11 @@ Le rollback ne restitue pas la granularite RBAC complete, ce qui est acceptable ## 7. Algorithme sync-permissions -La commande `app:sync-permissions` doit vivre dans `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Console/SyncPermissionsCommand.php` et encapsuler toute l'operation dans une transaction Doctrine unique. +La commande `app:sync-permissions` doit vivre dans `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Console/SyncPermissionsCommand.php` et encapsuler toute l'operation dans une transaction Doctrine unique. ### Source de verite -- Le scan des modules actifs vient de `/home/matthieu/dev_malio/Coltura/config/modules.php`. +- Le scan des modules actifs vient de `/home/matthieu/dev_malio/Starseed/config/modules.php`. - Chaque classe module active peut exposer `public static function permissions(): array`. - Par compatibilite montante, si une classe module n'expose pas encore `permissions()`, elle est traitee comme retournant `[]`. @@ -330,7 +330,7 @@ Garde anti-typo : le sync command verifie que chaque `code` commence obligatoire ```text begin transaction -load active module classes from /home/matthieu/dev_malio/Coltura/config/modules.php +load active module classes from /home/matthieu/dev_malio/Starseed/config/modules.php desired_permissions = empty map keyed by code for each module class: @@ -439,7 +439,7 @@ Repasse `orphan` a `false` et remet a jour les metadonnees issues de la declarat ## 9. Fixtures mises à jour -Le fichier cible reste `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php`. +Le fichier cible reste `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php`. ### Principe cle : decouplage via `is_admin` @@ -519,7 +519,7 @@ Les tests d'integration migration up/down exigent une base de test dediee avec u - Risque de perte de donnees pendant la suppression de la colonne `user.roles`. - Mitigation : creer les roles systeme et inserer les jointures `user_role` avant tout `DROP COLUMN`, avec tests de migration sur etats mixtes. - Risque de divergence entre migration SQL brute et fixtures sur les codes des roles systeme. - - Mitigation : centraliser `admin` et `user` dans `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Security/SystemRoles.php` et documenter que la migration doit reprendre ces valeurs telles quelles. + - Mitigation : centraliser `admin` et `user` dans `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Security/SystemRoles.php` et documenter que la migration doit reprendre ces valeurs telles quelles. - Risque d'accumulation de permissions orphelines sur des environnements de dev ou apres refactors de codes. - Mitigation : conserver `orphan = true` pour la non-destruction, mais ajouter un suivi explicite dans les tests et dans la documentation d'exploitation; une strategie de purge pourra etre traitee plus tard si necessaire. - Risque de sync incoherente entre dev et prod si un module actif ne declare pas encore `permissions()`. @@ -533,12 +533,12 @@ Les tests d'integration migration up/down exigent une base de test dediee avec u 1. Creer `Permission`, `Role`, `SystemRoleDeletionException` et `SystemRoles`. 2. Creer `PermissionRepositoryInterface`, `RoleRepositoryInterface` et leurs implementations Doctrine. -3. Faire evoluer `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/User.php` avec `is_admin`, `roles`, `directPermissions`, `getRoles()` et `getEffectivePermissions()`. +3. Faire evoluer `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/User.php` avec `is_admin`, `roles`, `directPermissions`, `getRoles()` et `getEffectivePermissions()`. 4. Ajouter `CoreModule::permissions()` et documenter le pattern de declaration statique pour les autres modules. -5. Ajouter la commande `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Console/SyncPermissionsCommand.php`. -6. Ecrire la migration `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/Migrations/Version.php` avec schema + migration de donnees + down(). -7. Mettre a jour `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php` et `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Console/CreateUserCommand.php`. -8. Ajouter les alias repository dans `/home/matthieu/dev_malio/Coltura/config/services.yaml`. +5. Ajouter la commande `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Console/SyncPermissionsCommand.php`. +6. Ecrire la migration `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/Migrations/Version.php` avec schema + migration de donnees + down(). +7. Mettre a jour `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php` et `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Console/CreateUserCommand.php`. +8. Ajouter les alias repository dans `/home/matthieu/dev_malio/Starseed/config/services.yaml`. 9. Ecrire les tests unitaires et d'integration couvrant domaine, sync, fixtures et migration. ## 13. Critères d'acceptation (DoD) @@ -553,4 +553,4 @@ Les tests d'integration migration up/down exigent une base de test dediee avec u - La suppression d'un role systeme leve `SystemRoleDeletionException` au niveau domaine. - Les associations `User::$roles`, `User::$directPermissions` et `Role::$permissions` sont explicitement configurees en `fetch=EAGER` et ce point est verifie par tests. - Les fixtures attribuent `is_admin = true` + role `admin` a l'utilisateur `admin`, et le role `user` aux utilisateurs standards. -- Le spec est compatible avec l'architecture modulaire actuelle basee sur `/home/matthieu/dev_malio/Coltura/config/modules.php` et n'introduit aucune resource API Platform ni voter dans ce ticket. +- Le spec est compatible avec l'architecture modulaire actuelle basee sur `/home/matthieu/dev_malio/Starseed/config/modules.php` et n'introduit aucune resource API Platform ni voter dans ce ticket. diff --git a/docs/rbac/ticket-344-spec.md b/docs/rbac/ticket-344-spec.md index 80db2e6..8979224 100644 --- a/docs/rbac/ticket-344-spec.md +++ b/docs/rbac/ticket-344-spec.md @@ -38,28 +38,28 @@ Le ticket n'introduit **aucune logique d'autorisation metier** : toute la verifi ### Infrastructure - Processors -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/RoleProcessor.php` +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/RoleProcessor.php` Decorator de `ApiPlatform\Doctrine\Common\State\PersistProcessor` et `RemoveProcessor`. Charge de la garde `ensureDeletable()` et de la protection des champs immuables sur un role systeme. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessor.php` +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessor.php` Decorator de `PersistProcessor` specifique a l'operation `PATCH /api/users/{id}/rbac`. Persiste les mutations `isAdmin`, `roles`, `directPermissions` sans passer par `UserPasswordHasherProcessor`. ### Tests unitaires -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Infrastructure/ApiPlatform/State/Processor/RoleProcessorTest.php` -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessorTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Infrastructure/ApiPlatform/State/Processor/RoleProcessorTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessorTest.php` ### Tests fonctionnels -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Api/PermissionApiTest.php` -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Api/RoleApiTest.php` -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Api/UserRbacApiTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Api/PermissionApiTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Api/RoleApiTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Api/UserRbacApiTest.php` ## 4. Fichiers a modifier ### Entite `Permission` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/Permission.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/Permission.php` - Ajouter l'attribut `#[ApiResource]` avec operations `GetCollection` + `Get` uniquement. - Normalization context : groupe `permission:read` uniquement. @@ -89,7 +89,7 @@ Extrait attendu : ### Entite `Role` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/Role.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/Role.php` - Ajouter l'attribut `#[ApiResource]` avec operations `GetCollection`, `Get`, `Post`, `Patch`, `Delete`. - Normalization context : `role:read`. Denormalization context : `role:write`. @@ -107,7 +107,7 @@ Extrait attendu : ### Entite `User` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/User.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/User.php` - Ajouter dans la liste des operations `ApiResource` existantes une operation dediee : diff --git a/docs/rbac/ticket-345-spec.md b/docs/rbac/ticket-345-spec.md index 187bdd9..f377e00 100644 --- a/docs/rbac/ticket-345-spec.md +++ b/docs/rbac/ticket-345-spec.md @@ -39,50 +39,50 @@ A l'issue de ce ticket, l'application dispose d'un systeme d'autorisation applic ### Domaine - Securite -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Security/AdminHeadcountGuard.php` +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Security/AdminHeadcountGuard.php` Service domaine encapsulant l'invariant "au moins un admin reste apres l'operation". Depend uniquement de `UserRepositoryInterface::countAdmins()`. Aucune dependance infrastructure, testable en isolation. -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Exception/LastAdminProtectionException.php` +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Exception/LastAdminProtectionException.php` Exception metier levee par le guard. Traduite en `BadRequestHttpException` (400) dans les processors. ### Infrastructure - Security -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Security/PermissionVoter.php` +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Security/PermissionVoter.php` Voter Symfony etendant `Symfony\Component\Security\Core\Authorization\Voter\Voter`. Decouvert automatiquement par `autoconfigure: true`. ### Infrastructure - Processors -- `/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserProcessor.php` +- `/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserProcessor.php` Decorateur de `RemoveProcessor` cible sur `DELETE /api/users/{id}`. Appelle `AdminHeadcountGuard` avant de deleguer. Meme pattern qu'`UserRbacProcessor`/`RoleProcessor` : `final class`, `#[Autowire]` sur l'inner, `LogicException` fail-fast si le type entrant n'est pas `User`. ### Frontend - Composable -- `/home/matthieu/dev_malio/Coltura/frontend/shared/composables/usePermissions.ts` +- `/home/matthieu/dev_malio/Starseed/frontend/shared/composables/usePermissions.ts` Composable stateless qui lit `useAuthStore().user`. Pas de fetch propre, pas de reset (le cycle de vie est porte par l'auth store). ### Tests unitaires PHP -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Infrastructure/Security/PermissionVoterTest.php` -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Domain/Security/AdminHeadcountGuardTest.php` -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserProcessorTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Infrastructure/Security/PermissionVoterTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Domain/Security/AdminHeadcountGuardTest.php` +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserProcessorTest.php` ### Tests fonctionnels PHP -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Api/MeApiTest.php` (si absent — sinon extension) +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Api/MeApiTest.php` (si absent — sinon extension) Couvre l'enrichissement du payload `/api/me`. -- `/home/matthieu/dev_malio/Coltura/tests/Module/Core/Api/UserApiTest.php` (si absent — sinon extension) +- `/home/matthieu/dev_malio/Starseed/tests/Module/Core/Api/UserApiTest.php` (si absent — sinon extension) Couvre la garde "dernier admin global" sur `DELETE /api/users/{id}`. ### Tests frontend -- `/home/matthieu/dev_malio/Coltura/frontend/shared/composables/__tests__/usePermissions.test.ts` +- `/home/matthieu/dev_malio/Starseed/frontend/shared/composables/__tests__/usePermissions.test.ts` Vitest. Emplacement a adapter si le projet Nuxt a une autre convention (colocalise avec un fichier `.spec.ts`, ou repertoire `tests/`). A verifier au debut de la task frontend. ## 4. Fichiers a modifier ### `CoreModule.php` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/CoreModule.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/CoreModule.php` Ajouter une cinquieme entree au catalogue : @@ -103,7 +103,7 @@ La commande `app:sync-permissions` creera automatiquement `core.roles.view` a la ### Entite `Permission` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/Permission.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/Permission.php` Remplacer les 2 gardes placeholder : @@ -122,7 +122,7 @@ Supprimer les commentaires `// TODO ticket #345`. ### Entite `Role` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/Role.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/Role.php` Remplacer les 5 gardes placeholder : @@ -136,7 +136,7 @@ Supprimer les commentaires `// TODO ticket #345`. ### Entite `User` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Entity/User.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Entity/User.php` Remplacer les 6 gardes `ROLE_ADMIN` restantes : @@ -172,7 +172,7 @@ Supprimer tous les commentaires `// TODO ticket #345` rencontres. ### `UserRepositoryInterface` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Domain/Repository/UserRepositoryInterface.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Domain/Repository/UserRepositoryInterface.php` Ajouter la methode : @@ -187,7 +187,7 @@ public function countAdmins(): int; ### `DoctrineUserRepository` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php` Implementer `countAdmins()` via un `QueryBuilder` simple : @@ -204,7 +204,7 @@ public function countAdmins(): int ### `UserRbacProcessor` -`/home/matthieu/dev_malio/Coltura/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessor.php` +`/home/matthieu/dev_malio/Starseed/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessor.php` Ajouter la dependance `AdminHeadcountGuard` et l'invoquer **apres** la garde auto-suicide existante, **avant** de deleguer au persist processor. Supprimer le `TODO ticket #345` du docblock. diff --git a/docs/sites/ticket-01-spec.md b/docs/sites/ticket-01-spec.md index 68c43a9..6b3a775 100644 --- a/docs/sites/ticket-01-spec.md +++ b/docs/sites/ticket-01-spec.md @@ -10,14 +10,14 @@ Le resultat attendu est un socle de persistance activable par tenant via `config ### IN -- Creer le module `/home/m-tristan/workspace/Coltura/src/Module/Sites/SitesModule.php` avec `ID = 'sites'`, `LABEL = 'Sites'`, `REQUIRED = false`, et une methode statique `permissions()` declarant les deux codes RBAC `sites.view` et `sites.manage`. +- Creer le module `/home/m-tristan/workspace/Starseed/src/Module/Sites/SitesModule.php` avec `ID = 'sites'`, `LABEL = 'Sites'`, `REQUIRED = false`, et une methode statique `permissions()` declarant les deux codes RBAC `sites.view` et `sites.manage`. - Creer l'entite Doctrine `Site` avec `id`, `name` (unique), `city`, `postalCode`, `color`, `fullAddress`, `createdAt`, `updatedAt` et les contraintes de validation applicatives associees (NotBlank, Length, Regex hex `#RRGGBB`, Regex CP FR `^\d{5}$`, UniqueEntity). - Creer l'interface `SiteRepositoryInterface` et son implementation Doctrine `DoctrineSiteRepository`, avec un contrat CRUD complet (`findById`, `findByName`, `findAllOrderedByName`, `save`, `remove`) en anticipation du ticket 2. -- Creer une migration Doctrine creant la table `site` avec son index unique `uniq_site_name`. La migration est placee dans `/home/m-tristan/workspace/Coltura/migrations/` au namespace racine `DoctrineMigrations` conformement a l'exception documentee dans `CLAUDE.md` (bug de tri alphabetique des migrations multi-namespaces dans Doctrine Migrations 3.x). +- Creer une migration Doctrine creant la table `site` avec son index unique `uniq_site_name`. La migration est placee dans `/home/m-tristan/workspace/Starseed/migrations/` au namespace racine `DoctrineMigrations` conformement a l'exception documentee dans `CLAUDE.md` (bug de tri alphabetique des migrations multi-namespaces dans Doctrine Migrations 3.x). - Creer `SitesFixtures` creant trois sites de demonstration : `Chatellerault` (`#056CF2`), `Saint-Jean` (`#10B981`), `Pommevic` (`#F59E0B`). Fixtures idempotentes via lookup par nom lorsque le purger Doctrine est desactive. -- Enregistrer `SitesModule::class` dans `/home/m-tristan/workspace/Coltura/config/modules.php` pour l'activer par defaut. -- Declarer le mapping Doctrine du module dans `/home/m-tristan/workspace/Coltura/config/packages/doctrine.yaml` (inconditionnel, le mapping reste charge meme si le module est retire de `modules.php`). -- Enregistrer l'alias service `SiteRepositoryInterface → DoctrineSiteRepository` dans `/home/m-tristan/workspace/Coltura/config/services.yaml`. +- Enregistrer `SitesModule::class` dans `/home/m-tristan/workspace/Starseed/config/modules.php` pour l'activer par defaut. +- Declarer le mapping Doctrine du module dans `/home/m-tristan/workspace/Starseed/config/packages/doctrine.yaml` (inconditionnel, le mapping reste charge meme si le module est retire de `modules.php`). +- Enregistrer l'alias service `SiteRepositoryInterface → DoctrineSiteRepository` dans `/home/m-tristan/workspace/Starseed/config/services.yaml`. - Ajouter deux suites de tests PHPUnit : - `SiteTest` (pure `TestCase`) pour le comportement de l'entite (constructeur, getters/setters, lifecycle `PreUpdate`). - `SiteValidationTest` (`KernelTestCase`) pour la validation complete : regex hex, regex CP FR, NotBlank, Length, UniqueEntity via Doctrine. @@ -25,7 +25,7 @@ Le resultat attendu est un socle de persistance activable par tenant via `config ### OUT - Ticket `#02` : relation `User ↔ Site` (FK ou ManyToMany selon decision UX), expose les sites de l'utilisateur courant via `/api/me` et propage l'autorisation au niveau des ressources decoupees par site. -- Ticket `#03` : integration dans la navbar Coltura (selecteur de site actif, persistance du choix cote front, consommation du flux issu du ticket 2). +- Ticket `#03` : integration dans la navbar Starseed (selecteur de site actif, persistance du choix cote front, consommation du flux issu du ticket 2). - Ticket `#04` : ecran d'administration CRUD des sites (page admin/sites, DataTable, drawer creation/edition, modale suppression, API Platform `Site` resource avec voters RBAC). - Gestion des soft-deletes sur `Site` : non introduite dans ce ticket. - Rattachement historique ou audit trail des modifications : hors scope. @@ -34,38 +34,38 @@ Le resultat attendu est un socle de persistance activable par tenant via `config ### Domaine — Entité -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Domain/Entity/Site.php` : entite Doctrine porteuse des attributs metier (nom unique, ville, code postal FR, couleur hex, adresse complete multi-ligne) et des timestamps auto-maintenus via lifecycle callbacks. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Domain/Entity/Site.php` : entite Doctrine porteuse des attributs metier (nom unique, ville, code postal FR, couleur hex, adresse complete multi-ligne) et des timestamps auto-maintenus via lifecycle callbacks. ### Domaine — Repository -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Domain/Repository/SiteRepositoryInterface.php` : contrat d'acces domaine a l'entite Site (CRUD applicatif ; l'acces API Platform du ticket 4 utilisera le provider Doctrine par defaut). +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Domain/Repository/SiteRepositoryInterface.php` : contrat d'acces domaine a l'entite Site (CRUD applicatif ; l'acces API Platform du ticket 4 utilisera le provider Doctrine par defaut). ### Infrastructure — Doctrine -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/Doctrine/DoctrineSiteRepository.php` : implementation Doctrine de `SiteRepositoryInterface` basee sur `ServiceEntityRepository`. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/Doctrine/DoctrineSiteRepository.php` : implementation Doctrine de `SiteRepositoryInterface` basee sur `ServiceEntityRepository`. ### Infrastructure — Migration -- `/home/m-tristan/workspace/Coltura/migrations/Version.php` : migration racine (namespace `DoctrineMigrations`) qui cree la table `site` et son index unique. Emplacement racine et non modulaire, cf. exception documentee dans `CLAUDE.md` (bug Doctrine 3.x sur le tri alphabetique des migrations multi-namespaces). +- `/home/m-tristan/workspace/Starseed/migrations/Version.php` : migration racine (namespace `DoctrineMigrations`) qui cree la table `site` et son index unique. Emplacement racine et non modulaire, cf. exception documentee dans `CLAUDE.md` (bug Doctrine 3.x sur le tri alphabetique des migrations multi-namespaces). ### Infrastructure — DataFixtures -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php` : fixture Doctrine seedant les 3 sites de demonstration. Ne declare pas de `DependentFixtureInterface` (aucune dependance a AppFixtures dans ce ticket). +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php` : fixture Doctrine seedant les 3 sites de demonstration. Ne declare pas de `DependentFixtureInterface` (aucune dependance a AppFixtures dans ce ticket). ### Module — Declaration -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/SitesModule.php` : marker class du module avec `ID`, `LABEL`, `REQUIRED` et `permissions()`. Meme pattern que `CoreModule`. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/SitesModule.php` : marker class du module avec `ID`, `LABEL`, `REQUIRED` et `permissions()`. Meme pattern que `CoreModule`. ### Tests -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Domain/Entity/SiteTest.php` : tests unitaires purs (`TestCase`) couvrant constructeur, getters, setters et lifecycle `PreUpdate`. -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Domain/Entity/SiteValidationTest.php` : tests de validation (`KernelTestCase`) couvrant regex hex, regex CP FR, NotBlank, Length sur tous les champs, et `UniqueEntity` via la DB de test. +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Domain/Entity/SiteTest.php` : tests unitaires purs (`TestCase`) couvrant constructeur, getters, setters et lifecycle `PreUpdate`. +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Domain/Entity/SiteValidationTest.php` : tests de validation (`KernelTestCase`) couvrant regex hex, regex CP FR, NotBlank, Length sur tous les champs, et `UniqueEntity` via la DB de test. ## 4. Fichiers à modifier -- `/home/m-tristan/workspace/Coltura/config/modules.php` : ajouter `App\Module\Sites\SitesModule::class` dans le tableau de retour. Le module est actif par defaut. Le commenter suffit a le desactiver sans autre intervention (les permissions deviendront orphelines a la prochaine sync mais la table reste). -- `/home/m-tristan/workspace/Coltura/config/packages/doctrine.yaml` : ajouter une mapping `Sites:` alignee sur le pattern du module `Core:`. Le mapping est inconditionnel : il reste declare meme si `SitesModule::class` est retire de `modules.php`. Le commentaire doit etre explicite sur cette decoupe (activation fonctionnelle via `modules.php`, structure DB via la mapping Doctrine). -- `/home/m-tristan/workspace/Coltura/config/services.yaml` : ajouter l'alias `App\Module\Sites\Domain\Repository\SiteRepositoryInterface` → `App\Module\Sites\Infrastructure\Doctrine\DoctrineSiteRepository`. Pattern aligne sur les trois aliases Core existants. +- `/home/m-tristan/workspace/Starseed/config/modules.php` : ajouter `App\Module\Sites\SitesModule::class` dans le tableau de retour. Le module est actif par defaut. Le commenter suffit a le desactiver sans autre intervention (les permissions deviendront orphelines a la prochaine sync mais la table reste). +- `/home/m-tristan/workspace/Starseed/config/packages/doctrine.yaml` : ajouter une mapping `Sites:` alignee sur le pattern du module `Core:`. Le mapping est inconditionnel : il reste declare meme si `SitesModule::class` est retire de `modules.php`. Le commentaire doit etre explicite sur cette decoupe (activation fonctionnelle via `modules.php`, structure DB via la mapping Doctrine). +- `/home/m-tristan/workspace/Starseed/config/services.yaml` : ajouter l'alias `App\Module\Sites\Domain\Repository\SiteRepositoryInterface` → `App\Module\Sites\Infrastructure\Doctrine\DoctrineSiteRepository`. Pattern aligne sur les trois aliases Core existants. ## 5. Schéma cible — mapping Doctrine @@ -152,7 +152,7 @@ Sites: ## 6. Plan de migration Doctrine -La migration est placee dans `/home/m-tristan/workspace/Coltura/migrations/Version.php` au namespace racine `DoctrineMigrations`, conformement a l'exception documentee dans `CLAUDE.md`. Tant que le bug de tri alphabetique des `MigrationsComparator` multi-namespaces n'est pas resolu (via un comparator custom ou un upgrade Doctrine), toute migration d'initialisation (creation de table sur base vide) reste au namespace racine. +La migration est placee dans `/home/m-tristan/workspace/Starseed/migrations/Version.php` au namespace racine `DoctrineMigrations`, conformement a l'exception documentee dans `CLAUDE.md`. Tant que le bug de tri alphabetique des `MigrationsComparator` multi-namespaces n'est pas resolu (via un comparator custom ou un upgrade Doctrine), toute migration d'initialisation (creation de table sur base vide) reste au namespace racine. ### `up()` — ordre des instructions @@ -289,7 +289,7 @@ Trois sites de demonstration, avec des couleurs distinctes suffisamment contrast | Nom | Ville | CP | Couleur | Commentaire | |-----|-------|-----|---------|-------------| -| Chatellerault | Chatellerault | 86100 | `#056CF2` | Couleur imposee par le ticket (bleu Coltura). | +| Chatellerault | Chatellerault | 86100 | `#056CF2` | Couleur imposee par le ticket (bleu Starseed). | | Saint-Jean | Saint-Jean-de-Sauves | 86330 | `#10B981` | Vert emeraude (contraste avec le bleu). | | Pommevic | Pommevic | 82400 | `#F59E0B` | Ambre (troisieme teinte nettement distincte). | diff --git a/docs/sites/ticket-02-spec.md b/docs/sites/ticket-02-spec.md index 7fdb6f2..a521714 100644 --- a/docs/sites/ticket-02-spec.md +++ b/docs/sites/ticket-02-spec.md @@ -40,70 +40,70 @@ Le resultat attendu est un module Sites utilisable de bout en bout cote admin (c ### Backend — Module Sites -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Domain/Exception/SiteNotAuthorizedException.php` : exception domaine levee si un user tente de switcher vers un site qui ne fait pas partie de ses sites autorises. Porte un message i18n-able et le code du site cible. -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/ApiPlatform/Resource/CurrentSiteResource.php` : ressource API Platform **virtuelle** (pas de mapping Doctrine, pas de `#[ORM\Entity]`). Sert uniquement a porter l'operation `Patch` `/me/current-site`. Expose une propriete `site: Site` en denormalisation pour recevoir l'IRI du site cible, et re-expose l'user courant en normalisation via le groupe `me:read`. -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/ApiPlatform/State/Processor/CurrentSiteProcessor.php` : processor dedie a l'operation de switch. Valide l'appartenance du site aux `user.sites`, positionne `user.currentSite`, flush, retourne l'user. -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/ApiPlatform/EventListener/SiteNotAuthorizedExceptionListener.php` : listener Kernel qui convertit `SiteNotAuthorizedException` en `ForbiddenHttpException` (403) avec un code i18n stable (cf. pattern `SystemRoleDeletionException` du module Core dans les tickets RBAC precedents). +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Domain/Exception/SiteNotAuthorizedException.php` : exception domaine levee si un user tente de switcher vers un site qui ne fait pas partie de ses sites autorises. Porte un message i18n-able et le code du site cible. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/ApiPlatform/Resource/CurrentSiteResource.php` : ressource API Platform **virtuelle** (pas de mapping Doctrine, pas de `#[ORM\Entity]`). Sert uniquement a porter l'operation `Patch` `/me/current-site`. Expose une propriete `site: Site` en denormalisation pour recevoir l'IRI du site cible, et re-expose l'user courant en normalisation via le groupe `me:read`. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/ApiPlatform/State/Processor/CurrentSiteProcessor.php` : processor dedie a l'operation de switch. Valide l'appartenance du site aux `user.sites`, positionne `user.currentSite`, flush, retourne l'user. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/ApiPlatform/EventListener/SiteNotAuthorizedExceptionListener.php` : listener Kernel qui convertit `SiteNotAuthorizedException` en `ForbiddenHttpException` (403) avec un code i18n stable (cf. pattern `SystemRoleDeletionException` du module Core dans les tickets RBAC precedents). ### Backend — Migration -- `/home/m-tristan/workspace/Coltura/migrations/Version.php` : migration au namespace racine `DoctrineMigrations` (cf. exception Doctrine documentee dans `CLAUDE.md`). Cree la table `user_site` et la colonne `user.current_site_id` avec les FKs et cascades appropriees. +- `/home/m-tristan/workspace/Starseed/migrations/Version.php` : migration au namespace racine `DoctrineMigrations` (cf. exception Doctrine documentee dans `CLAUDE.md`). Cree la table `user_site` et la colonne `user.current_site_id` avec les FKs et cascades appropriees. ### Backend — Tests API -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Api/SiteApiTest.php` : CRUD complet `/api/sites` avec matrices RBAC (admin, user avec `sites.view`, user avec `sites.manage`, user sans permission). -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Api/CurrentSiteSwitchApiTest.php` : PATCH `/me/current-site` (OK avec site autorise, 403 avec site non autorise, 400 avec IRI invalide). -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Api/MeEndpointSitesTest.php` : `/api/me` expose bien `sites` et `currentSite` en objets. User sans site : `sites: []`, `currentSite: null`. -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Api/SiteCascadeTest.php` : suppression d'un site `X` → toutes les lignes `user_site` referencant `X` sont supprimees, tous les users ayant `X` en `currentSite` voient leur `currentSite` repasser a `NULL`. -- `/home/m-tristan/workspace/Coltura/tests/Module/Core/Api/UserRbacSitesApiTest.php` : extension du endpoint `/api/users/{id}/rbac` — ajout de `sites: []` dans le payload, retrait du `currentSite` quand le site retire etait le courant. +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Api/SiteApiTest.php` : CRUD complet `/api/sites` avec matrices RBAC (admin, user avec `sites.view`, user avec `sites.manage`, user sans permission). +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Api/CurrentSiteSwitchApiTest.php` : PATCH `/me/current-site` (OK avec site autorise, 403 avec site non autorise, 400 avec IRI invalide). +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Api/MeEndpointSitesTest.php` : `/api/me` expose bien `sites` et `currentSite` en objets. User sans site : `sites: []`, `currentSite: null`. +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Api/SiteCascadeTest.php` : suppression d'un site `X` → toutes les lignes `user_site` referencant `X` sont supprimees, tous les users ayant `X` en `currentSite` voient leur `currentSite` repasser a `NULL`. +- `/home/m-tristan/workspace/Starseed/tests/Module/Core/Api/UserRbacSitesApiTest.php` : extension du endpoint `/api/users/{id}/rbac` — ajout de `sites: []` dans le payload, retrait du `currentSite` quand le site retire etait le courant. ### Frontend — Module Sites (nouveau layer) -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/nuxt.config.ts` : marker de layer Nuxt (vide). Declenche l'auto-detection par `nuxt.config.ts` racine. -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/pages/admin/sites.vue` : page `/admin/sites`. Reutilise les composants Malio UI (`MalioDataTable`, `MalioButton`, `MalioInputText`, `MalioInputTextArea`). Pattern identique a `frontend/modules/core/pages/admin/roles.vue`. -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/components/SiteDrawer.vue` : drawer creation/edition. Formulaire 5 champs (nom, ville, CP, couleur avec preview puce, adresse). Valide cote front sur le submit avant d'envoyer. -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/components/SiteDeleteModal.vue` : modale de confirmation suppression. Pattern aligne sur `RoleDeleteModal.vue`. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/nuxt.config.ts` : marker de layer Nuxt (vide). Declenche l'auto-detection par `nuxt.config.ts` racine. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/pages/admin/sites.vue` : page `/admin/sites`. Reutilise les composants Malio UI (`MalioDataTable`, `MalioButton`, `MalioInputText`, `MalioInputTextArea`). Pattern identique a `frontend/modules/core/pages/admin/roles.vue`. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/components/SiteDrawer.vue` : drawer creation/edition. Formulaire 5 champs (nom, ville, CP, couleur avec preview puce, adresse). Valide cote front sur le submit avant d'envoyer. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/components/SiteDeleteModal.vue` : modale de confirmation suppression. Pattern aligne sur `RoleDeleteModal.vue`. ### Frontend — Types partages -- `/home/m-tristan/workspace/Coltura/frontend/shared/types/sites.ts` : types `Site`, `SiteInput`. Pattern identique a `frontend/shared/types/rbac.ts`. +- `/home/m-tristan/workspace/Starseed/frontend/shared/types/sites.ts` : types `Site`, `SiteInput`. Pattern identique a `frontend/shared/types/rbac.ts`. ### Tests frontend (optionnels mais recommandes) -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/pages/admin/sites.spec.ts` : smoke test Vitest (rendu + clic bouton "Nouveau site" ouvre le drawer). +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/pages/admin/sites.spec.ts` : smoke test Vitest (rendu + clic bouton "Nouveau site" ouvre le drawer). ## 4. Fichiers à modifier ### Backend — Module Core -- `/home/m-tristan/workspace/Coltura/src/Module/Core/Domain/Entity/User.php` : +- `/home/m-tristan/workspace/Starseed/src/Module/Core/Domain/Entity/User.php` : - Ajouter `private Collection $sites;` (M2M, `fetch: EAGER`, `JoinTable: user_site`), groupes `me:read`, `user:list`, `user:rbac:read`, `user:rbac:write`. - Ajouter `private ?Site $currentSite = null;` (M2O, `fetch: EAGER`, `onDelete: 'SET NULL'`), groupe `me:read`. - Initialiser `$this->sites = new ArrayCollection();` dans le constructeur. - Ajouter les accesseurs `getSites()`, `addSite(Site)`, `removeSite(Site)`, `hasSite(Site)`, `getCurrentSite()`, `setCurrentSite(?Site)`. - **Important** : `import` direct `App\Module\Sites\Domain\Entity\Site`. Ce ticket assume le couplage Core → Sites au niveau code PHP (cf. Risque 1). -- `/home/m-tristan/workspace/Coltura/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessor.php` : +- `/home/m-tristan/workspace/Starseed/src/Module/Core/Infrastructure/ApiPlatform/State/Processor/UserRbacProcessor.php` : - Etendre le contrat d'entree pour accepter le champ `sites` (collection d'IRIs denormalisees en `Collection`). - Apres l'application des roles et permissions directes, detecter si `currentSite` du user cible n'est plus dans la nouvelle collection `sites` → basculer `currentSite` a `null`. - Conserver toutes les gardes existantes (auto-suicide admin, dernier admin global). -- `/home/m-tristan/workspace/Coltura/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php` : +- `/home/m-tristan/workspace/Starseed/src/Module/Core/Infrastructure/DataFixtures/AppFixtures.php` : - Declarer l'implementation `DependentFixtureInterface` avec `getDependencies(): [SitesFixtures::class]` (inversion de l'ordre actuel : AppFixtures doit tourner **apres** SitesFixtures pour pouvoir reference les sites). - Rattacher chaque user a au moins un site : `admin` a tous les sites (`Chatellerault`, `Saint-Jean`, `Pommevic`), `alice` a `Chatellerault`, `bob` a `Saint-Jean`. - Positionner `currentSite` : `admin.currentSite = Chatellerault`, `alice.currentSite = Chatellerault`, `bob.currentSite = Saint-Jean`. ### Backend — Module Sites -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Domain/Entity/Site.php` : +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Domain/Entity/Site.php` : - Ajouter les attributs `#[ApiResource]` + operations (cf. section 5 Schema). - Ajouter les groupes de serialisation `site:read`, `site:write`, `me:read` sur les proprietes scalaires. - Ajouter la relation inverse `private Collection $users;` (M2M mappedBy=`sites`), **sans** groupe de serialisation (pas d'exposition API cote Site). - Initialiser `$this->users = new ArrayCollection();` dans le constructeur. - Ajouter les accesseurs `getUsers()` pour les besoins metier (count / cascade manuel si besoin). -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php` : aucun changement de contenu, mais verifier que la fixture n'est plus en bout de chaine de dependance (AppFixtures depend d'elle maintenant). +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php` : aucun changement de contenu, mais verifier que la fixture n'est plus en bout de chaine de dependance (AppFixtures depend d'elle maintenant). ### Backend — Configuration -- `/home/m-tristan/workspace/Coltura/config/sidebar.php` : inserer l'entree `Sites` dans la section `sidebar.general.section` entre `sidebar.core.users` et `sidebar.general.logout` : +- `/home/m-tristan/workspace/Starseed/config/sidebar.php` : inserer l'entree `Sites` dans la section `sidebar.general.section` entre `sidebar.core.users` et `sidebar.general.logout` : ```php [ 'label' => 'sidebar.core.sites', @@ -113,18 +113,18 @@ Le resultat attendu est un module Sites utilisable de bout en bout cote admin (c 'permission' => 'sites.view', ], ``` -- `/home/m-tristan/workspace/Coltura/config/services.yaml` : aucun changement requis. `CurrentSiteProcessor`, `SiteNotAuthorizedExceptionListener` sont autoconfigures. +- `/home/m-tristan/workspace/Starseed/config/services.yaml` : aucun changement requis. `CurrentSiteProcessor`, `SiteNotAuthorizedExceptionListener` sont autoconfigures. ### Frontend -- `/home/m-tristan/workspace/Coltura/frontend/modules/core/components/UserRbacDrawer.vue` : +- `/home/m-tristan/workspace/Starseed/frontend/modules/core/components/UserRbacDrawer.vue` : - Charger `GET /api/sites?itemsPerPage=999` a l'ouverture du drawer (parallelement aux roles et permissions deja charges). - Ajouter une section `sidebar.admin.usersDrawer.sitesSection` sous la section permissions directes, avec un groupe de `MalioCheckbox` par site (ou un `MalioMultiSelect` si le composant existe dans `@malio/layer-ui`). - Etendre le payload `PATCH /api/users/{id}/rbac` avec `sites: Array` (IRIs). - Auto-refresh de l'auth store apres save si `isSelfEdit` (deja present, conserver). -- `/home/m-tristan/workspace/Coltura/frontend/shared/types/rbac.ts` : ajouter le champ `sites: string[]` a `UserListItem` (IRIs de sites attaches). -- `/home/m-tristan/workspace/Coltura/frontend/shared/stores/auth.ts` : le store auth expose deja `user` via `/api/me`. Aucune modification requise, les nouveaux champs `sites` et `currentSite` suivent automatiquement via la typologie — a condition de mettre a jour le type `UserData` dans `shared/types/` (ajouter `sites: Site[]` et `currentSite: Site | null`). -- `/home/m-tristan/workspace/Coltura/frontend/i18n/locales/fr.json` : cles +- `/home/m-tristan/workspace/Starseed/frontend/shared/types/rbac.ts` : ajouter le champ `sites: string[]` a `UserListItem` (IRIs de sites attaches). +- `/home/m-tristan/workspace/Starseed/frontend/shared/stores/auth.ts` : le store auth expose deja `user` via `/api/me`. Aucune modification requise, les nouveaux champs `sites` et `currentSite` suivent automatiquement via la typologie — a condition de mettre a jour le type `UserData` dans `shared/types/` (ajouter `sites: Site[]` et `currentSite: Site | null`). +- `/home/m-tristan/workspace/Starseed/frontend/i18n/locales/fr.json` : cles - `sidebar.core.sites` = "Sites". - `admin.sites.title`, `admin.sites.newSite`, `admin.sites.editSite`, `admin.sites.createSite`, `admin.sites.noSites`. - `admin.sites.table.{name, city, postalCode, color, fullAddress}`. @@ -228,7 +228,7 @@ final class CurrentSiteResource ## 6. Plan de migration Doctrine -La migration est placee dans `/home/m-tristan/workspace/Coltura/migrations/Version.php` au namespace racine (cf. Risque 2 du ticket 1 et `CLAUDE.md`). +La migration est placee dans `/home/m-tristan/workspace/Starseed/migrations/Version.php` au namespace racine (cf. Risque 2 du ticket 1 et `CLAUDE.md`). ### `up()` — ordre des instructions diff --git a/docs/sites/ticket-03-spec.md b/docs/sites/ticket-03-spec.md index 8c62cd1..51e43c0 100644 --- a/docs/sites/ticket-03-spec.md +++ b/docs/sites/ticket-03-spec.md @@ -77,42 +77,42 @@ Resultat attendu : apres merge, un user avec ≥ 1 site voit une barre sous la n ### Frontend — Module Sites (layer deja cree au ticket 2) -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/components/SiteSelector.vue` : wrapper Vue autour de `MalioSiteSelector`. Branche `useCurrentSite()`, gere l'optimistic update et les toasts. -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/composables/useCurrentSite.ts` : composable global exposant l'etat `currentSite` / `availableSites`, les actions `switchSite`, `resetCurrentSite`, et un flag `switching: Ref` pour desactiver le selecteur pendant une requete en vol. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/components/SiteSelector.vue` : wrapper Vue autour de `MalioSiteSelector`. Branche `useCurrentSite()`, gere l'optimistic update et les toasts. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/composables/useCurrentSite.ts` : composable global exposant l'etat `currentSite` / `availableSites`, les actions `switchSite`, `resetCurrentSite`, et un flag `switching: Ref` pour desactiver le selecteur pendant une requete en vol. ### Frontend — Shared -- `/home/m-tristan/workspace/Coltura/frontend/shared/composables/useModules.ts` : composable qui charge `/api/modules` et expose `isModuleActive(id: string): boolean`. Pattern aligne sur `useSidebar()` : ref singleton au niveau module, chargement idempotent, `resetModules()` expose pour le logout. -- `/home/m-tristan/workspace/Coltura/frontend/shared/utils/color.ts` : fonctions utilitaires de couleur, au minimum : +- `/home/m-tristan/workspace/Starseed/frontend/shared/composables/useModules.ts` : composable qui charge `/api/modules` et expose `isModuleActive(id: string): boolean`. Pattern aligne sur `useSidebar()` : ref singleton au niveau module, chargement idempotent, `resetModules()` expose pour le logout. +- `/home/m-tristan/workspace/Starseed/frontend/shared/utils/color.ts` : fonctions utilitaires de couleur, au minimum : - `parseHex(hex: string): { r: number; g: number; b: number }` — tolere la casse, rejette les formats hors `#RRGGBB`. - `getRelativeLuminance({r, g, b}): number` — formule WCAG standard. - `getReadableTextColor(hex: string): 'black' | 'white'` — renvoie `'black'` si la luminance > 0.5, `'white'` sinon. Seuil simple, suffisant pour un CRM interne (pas WCAG AAA). ### Frontend — Tests -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/composables/__tests__/useCurrentSite.spec.ts` : Vitest. Tests : +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/composables/__tests__/useCurrentSite.spec.ts` : Vitest. Tests : - `switchSite` met a jour l'etat localement avant la requete (optimistic). - Si la requete reussit, l'etat reste aligne. - Si la requete echoue, l'etat rollback a l'ancien `currentSite`. - `resetCurrentSite` vide l'etat. -- `/home/m-tristan/workspace/Coltura/frontend/shared/composables/__tests__/useModules.spec.ts` : Vitest. Tests `isModuleActive` apres chargement, `resetModules` vide l'etat. -- `/home/m-tristan/workspace/Coltura/frontend/shared/utils/__tests__/color.spec.ts` : Vitest. Jeu de donnees sur `getReadableTextColor` : `#000000` → white, `#FFFFFF` → black, `#056CF2` (bleu Coltura) → white, `#F59E0B` (ambre) → black, `#10B981` (vert) → black ou white selon seuil (a verifier). Tester aussi le rejet de formats invalides. -- `/home/m-tristan/workspace/Coltura/frontend/modules/sites/components/__tests__/SiteSelector.spec.ts` : smoke test Vitest. +- `/home/m-tristan/workspace/Starseed/frontend/shared/composables/__tests__/useModules.spec.ts` : Vitest. Tests `isModuleActive` apres chargement, `resetModules` vide l'etat. +- `/home/m-tristan/workspace/Starseed/frontend/shared/utils/__tests__/color.spec.ts` : Vitest. Jeu de donnees sur `getReadableTextColor` : `#000000` → white, `#FFFFFF` → black, `#056CF2` (bleu Starseed) → white, `#F59E0B` (ambre) → black, `#10B981` (vert) → black ou white selon seuil (a verifier). Tester aussi le rejet de formats invalides. +- `/home/m-tristan/workspace/Starseed/frontend/modules/sites/components/__tests__/SiteSelector.spec.ts` : smoke test Vitest. ## 4. Fichiers à modifier -- `/home/m-tristan/workspace/Coltura/frontend/package.json` : upgrade `@malio/layer-ui` vers la version qui inclut `MalioSiteSelector`. Commit du `package-lock.json` dans le meme changeset. -- `/home/m-tristan/workspace/Coltura/frontend/shared/types/user-data.ts` : ajouter les champs +- `/home/m-tristan/workspace/Starseed/frontend/package.json` : upgrade `@malio/layer-ui` vers la version qui inclut `MalioSiteSelector`. Commit du `package-lock.json` dans le meme changeset. +- `/home/m-tristan/workspace/Starseed/frontend/shared/types/user-data.ts` : ajouter les champs ```ts sites: Site[] currentSite: Site | null ``` Import du type `Site` depuis `./sites`. Note : si le type `Site` a deja ete introduit au ticket 2, reutiliser ; sinon, ce ticket le cree dans `frontend/shared/types/sites.ts`. -- `/home/m-tristan/workspace/Coltura/frontend/shared/types/sites.ts` : si absent, creer avec l'interface `Site` (cf. section Schema ticket 2 pour la forme). Si present, aucune modification. -- `/home/m-tristan/workspace/Coltura/frontend/app/layouts/default.vue` : integrer `SiteSelector` sous le header, avant `
`, dans le flex column. Rendu conditionnel via `v-if="showSiteSelector"` ou via un `defineAsyncComponent` chargement lazy si on veut eviter l'import statique quand le module est off. -- `/home/m-tristan/workspace/Coltura/frontend/app/middleware/auth.global.ts` : ajouter le chargement de `useModules().loadModules()` apres `loadSidebar()`. Necessaire pour que `isModuleActive` soit resolu quand le layout se rend. -- `/home/m-tristan/workspace/Coltura/frontend/modules/core/pages/logout.vue` : appeler `useCurrentSite().resetCurrentSite()` et `useModules().resetModules()` apres le `auth.logout()`, aligne sur le pattern `resetSidebar()` deja present. -- `/home/m-tristan/workspace/Coltura/frontend/i18n/locales/fr.json` : ajouter les cles +- `/home/m-tristan/workspace/Starseed/frontend/shared/types/sites.ts` : si absent, creer avec l'interface `Site` (cf. section Schema ticket 2 pour la forme). Si present, aucune modification. +- `/home/m-tristan/workspace/Starseed/frontend/app/layouts/default.vue` : integrer `SiteSelector` sous le header, avant `
`, dans le flex column. Rendu conditionnel via `v-if="showSiteSelector"` ou via un `defineAsyncComponent` chargement lazy si on veut eviter l'import statique quand le module est off. +- `/home/m-tristan/workspace/Starseed/frontend/app/middleware/auth.global.ts` : ajouter le chargement de `useModules().loadModules()` apres `loadSidebar()`. Necessaire pour que `isModuleActive` soit resolu quand le layout se rend. +- `/home/m-tristan/workspace/Starseed/frontend/modules/core/pages/logout.vue` : appeler `useCurrentSite().resetCurrentSite()` et `useModules().resetModules()` apres le `auth.logout()`, aligne sur le pattern `resetSidebar()` deja present. +- `/home/m-tristan/workspace/Starseed/frontend/i18n/locales/fr.json` : ajouter les cles ```json "sites": { "selector": { diff --git a/docs/sites/ticket-04-spec.md b/docs/sites/ticket-04-spec.md index 62d5987..38959b1 100644 --- a/docs/sites/ticket-04-spec.md +++ b/docs/sites/ticket-04-spec.md @@ -34,50 +34,50 @@ Le ticket livre aussi une documentation developpeur (`docs/modules/site-aware.md ### Shared — Contrat -- `/home/m-tristan/workspace/Coltura/src/Shared/Domain/Contract/SiteAwareInterface.php` : interface minimale. Depends uniquement du type `App\Module\Sites\Domain\Entity\Site`, qui est deja couple cote Core depuis le ticket 2 — le placement dans Shared n'introduit pas de nouvelle dependance transversale non souhaitee. +- `/home/m-tristan/workspace/Starseed/src/Shared/Domain/Contract/SiteAwareInterface.php` : interface minimale. Depends uniquement du type `App\Module\Sites\Domain\Entity\Site`, qui est deja couple cote Core depuis le ticket 2 — le placement dans Shared n'introduit pas de nouvelle dependance transversale non souhaitee. ### Module Sites — Application -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Application/Service/CurrentSiteProvider.php` : service injecte partout ou le site courant doit etre lu (extensions, processor, futurs voters). Gere les trois cas de retour `null` : pas d'user, `currentSite` null, module desactive. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Application/Service/CurrentSiteProvider.php` : service injecte partout ou le site courant doit etre lu (extensions, processor, futurs voters). Gere les trois cas de retour `null` : pas d'user, `currentSite` null, module desactive. ### Module Sites — Infrastructure -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/ApiPlatform/Extension/SiteScopedQueryExtension.php` : une seule classe, implementant a la fois `QueryCollectionExtensionInterface` et `QueryItemExtensionInterface`. Le comportement est identique pour les deux, modulo que l'item manque retourne 404 (API Platform converti un `getOneOrNullResult` null en 404). -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/Infrastructure/ApiPlatform/State/Processor/SiteAwareInjectionProcessor.php` : decorator sur le persist processor Doctrine. Injecte le site courant sur `$data` si applicable, puis delegue a `$persistProcessor`. +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/ApiPlatform/Extension/SiteScopedQueryExtension.php` : une seule classe, implementant a la fois `QueryCollectionExtensionInterface` et `QueryItemExtensionInterface`. Le comportement est identique pour les deux, modulo que l'item manque retourne 404 (API Platform converti un `getOneOrNullResult` null en 404). +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/Infrastructure/ApiPlatform/State/Processor/SiteAwareInjectionProcessor.php` : decorator sur le persist processor Doctrine. Injecte le site courant sur `$data` si applicable, puis delegue a `$persistProcessor`. ### Documentation -- `/home/m-tristan/workspace/Coltura/docs/modules/site-aware.md` : guide developpeur (cf. contenu section 10). +- `/home/m-tristan/workspace/Starseed/docs/modules/site-aware.md` : guide developpeur (cf. contenu section 10). ### Tests -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Infrastructure/ApiPlatform/Extension/SiteScopedQueryExtensionTest.php` : tests d'integration (`KernelTestCase`) avec l'entite `FakeSiteAwareEntity` (declaree uniquement dans le dossier de tests). Verifie : +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Infrastructure/ApiPlatform/Extension/SiteScopedQueryExtensionTest.php` : tests d'integration (`KernelTestCase`) avec l'entite `FakeSiteAwareEntity` (declaree uniquement dans le dossier de tests). Verifie : - Le filtre s'applique sur une resource `SiteAware` quand le provider retourne un site. - Le filtre est no-op si `SiteAware` mais provider null. - Le filtre est no-op si resource non `SiteAware`. - Le filtre est no-op si user a `sites.bypass_scope`. - `totalItems` Hydra reflete bien le filtrage. -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Infrastructure/ApiPlatform/State/Processor/SiteAwareInjectionProcessorTest.php` : tests unitaires (`TestCase` pur) avec mocks. Verifie : +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Infrastructure/ApiPlatform/State/Processor/SiteAwareInjectionProcessorTest.php` : tests unitaires (`TestCase` pur) avec mocks. Verifie : - `$data` SiteAware sans site → injection du site courant. - `$data` SiteAware avec site deja positionne → pas d'overwrite. - `$data` non-SiteAware → delegation directe sans modification. - Provider retourne null (module off ou user sans site) ET `$data` SiteAware sans site → BadRequestHttpException (400) "aucun site selectionne". -- `/home/m-tristan/workspace/Coltura/tests/Module/Sites/Application/Service/CurrentSiteProviderTest.php` : tests unitaires `TestCase`. Couvre : +- `/home/m-tristan/workspace/Starseed/tests/Module/Sites/Application/Service/CurrentSiteProviderTest.php` : tests unitaires `TestCase`. Couvre : - User authentifie avec currentSite → retourne le Site. - User authentifie sans currentSite → null. - Pas d'user → null. - Module desactive dans config/modules.php de test → null meme si user.currentSite existe. -- `/home/m-tristan/workspace/Coltura/tests/Fixtures/SiteAware/FakeSiteAwareEntity.php` : entite Doctrine minimale (`id`, `name`, `site`) utilisee **uniquement** en tests. Mapping Doctrine declare via un `#[ORM\Entity]` mais la table n'existe jamais en prod car la fixture n'est jamais chargee hors tests. **Alternative** : utiliser un schema DB dedie au dossier de tests, cree a la volee par un helper setUp. A trancher a l'implementation. +- `/home/m-tristan/workspace/Starseed/tests/Fixtures/SiteAware/FakeSiteAwareEntity.php` : entite Doctrine minimale (`id`, `name`, `site`) utilisee **uniquement** en tests. Mapping Doctrine declare via un `#[ORM\Entity]` mais la table n'existe jamais en prod car la fixture n'est jamais chargee hors tests. **Alternative** : utiliser un schema DB dedie au dossier de tests, cree a la volee par un helper setUp. A trancher a l'implementation. ## 4. Fichiers à modifier -- `/home/m-tristan/workspace/Coltura/src/Module/Sites/SitesModule.php` : ajouter la permission `sites.bypass_scope` dans `permissions()` : +- `/home/m-tristan/workspace/Starseed/src/Module/Sites/SitesModule.php` : ajouter la permission `sites.bypass_scope` dans `permissions()` : ```php ['code' => 'sites.bypass_scope', 'label' => 'Voir les donnees site-scoped de tous les sites (bypass du filtrage)'], ``` **Note importante** : la methode `permissions()` signale l'existence de la permission mais c'est la commande `app:sync-permissions` (inchangee) qui la positionne en base. -- `/home/m-tristan/workspace/Coltura/config/services.yaml` : aucun changement requis. `SiteScopedQueryExtension`, `SiteAwareInjectionProcessor` et `CurrentSiteProvider` sont autoconfigures via les `_defaults` du module. Le decorator du persist processor est declare via `#[AsDecorator]` ou via tag (cf. section 8). -- `/home/m-tristan/workspace/Coltura/phpunit.dist.xml` : aucune modification requise si la config des fixtures de tests est autonome. Si `FakeSiteAwareEntity` necessite un mapping dedie, l'option la plus propre est un `doctrine.yaml.test` ajoute via `when@test`, sans polluer la config dev/prod (cf. Risque 3). +- `/home/m-tristan/workspace/Starseed/config/services.yaml` : aucun changement requis. `SiteScopedQueryExtension`, `SiteAwareInjectionProcessor` et `CurrentSiteProvider` sont autoconfigures via les `_defaults` du module. Le decorator du persist processor est declare via `#[AsDecorator]` ou via tag (cf. section 8). +- `/home/m-tristan/workspace/Starseed/phpunit.dist.xml` : aucune modification requise si la config des fixtures de tests est autonome. Si `FakeSiteAwareEntity` necessite un mapping dedie, l'option la plus propre est un `doctrine.yaml.test` ajoute via `when@test`, sans polluer la config dev/prod (cf. Risque 3). ## 5. Contrat `SiteAwareInterface` @@ -459,7 +459,7 @@ A mitiger par un test qui genere une entite `FakeSiteAwareEntity` via un POST `a ### Risque 8 — Doc developpeur en francais vs anglais -Le fichier `docs/modules/site-aware.md` s'adresse aux developpeurs de Coltura. Il est redige en **francais**, aligne sur la convention projet (CLAUDE.md : "commentaires en francais, code en anglais"). Aucun extrait de code ne doit etre traduit, seules les explications. +Le fichier `docs/modules/site-aware.md` s'adresse aux developpeurs de Starseed. Il est redige en **francais**, aligne sur la convention projet (CLAUDE.md : "commentaires en francais, code en anglais"). Aucun extrait de code ne doit etre traduit, seules les explications. ## 12. Plan de tests diff --git a/frontend/app/layouts/default.vue b/frontend/app/layouts/default.vue index 7669aa0..28cd990 100644 --- a/frontend/app/layouts/default.vue +++ b/frontend/app/layouts/default.vue @@ -62,6 +62,6 @@ watch(() => route.path, () => { }) useHead({ - titleTemplate: (title) => title || 'Coltura', + titleTemplate: (title) => title || 'Starseed', }) diff --git a/frontend/assets/css/main.css b/frontend/assets/css/main.css index c727348..482ecee 100644 --- a/frontend/assets/css/main.css +++ b/frontend/assets/css/main.css @@ -1 +1 @@ -/* Coltura - Custom styles */ +/* Starseed - Custom styles */ diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index 4172559..d2ee907 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -14,7 +14,7 @@ export default await nuxt( }, }, { - name: 'coltura/custom-overrides', + name: 'starseed/custom-overrides', rules: { // Indentation 4 espaces (convention CLAUDE.md) 'vue/html-indent': ['error', 4], diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index eb0f5a4..4d08443 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -36,7 +36,7 @@ }, "dashboard": { "title": "Tableau de bord", - "welcome": "Bienvenue sur Coltura" + "welcome": "Bienvenue sur Starseed" }, "commercial": { "title": "Commercial", diff --git a/frontend/modules/sites/components/SiteSelector.vue b/frontend/modules/sites/components/SiteSelector.vue index bb03007..e1c663c 100644 --- a/frontend/modules/sites/components/SiteSelector.vue +++ b/frontend/modules/sites/components/SiteSelector.vue @@ -78,7 +78,7 @@ async function onChange(site: { id: string; name: string; color: string }): Prom // intentionnellement supprimee pour garantir qu'un clic sur le tile // "actif selon cet onglet" envoie quand meme le PATCH et re-synchronise // l'etat. Amelioration future : ecouter l'evenement `storage` sur la - // cle `coltura:site-switch` pour mettre a jour les onglets inactifs + // cle `starseed:site-switch` pour mettre a jour les onglets inactifs // sans clic via auth.fetchUser() / auth.refreshUser(). try { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index db267bf..b00bb01 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,10 +1,10 @@ { - "name": "coltura-frontend", + "name": "starseed-frontend", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "coltura-frontend", + "name": "starseed-frontend", "hasInstallScript": true, "dependencies": { "@malio/layer-ui": "^1.5.0", diff --git a/frontend/package.json b/frontend/package.json index 8cbde9e..38380ff 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "coltura-frontend", + "name": "starseed-frontend", "type": "module", "private": true, "scripts": { diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index 67d90e7..57ee597 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -1,7 +1,7 @@ import { defineConfig, devices } from '@playwright/test' /** - * Config Playwright pour les tests E2E de Coltura. + * Config Playwright pour les tests E2E de Starseed. * * Pre-requis avant de lancer : * 1. Les containers Docker tournent (`make start`) diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts index 0730ee3..372606c 100644 --- a/frontend/tailwind.config.ts +++ b/frontend/tailwind.config.ts @@ -1,7 +1,7 @@ import type {Config} from 'tailwindcss' /** - * Config Tailwind du projet Coltura. + * Config Tailwind du projet Starseed. * * @nuxtjs/tailwindcss merge automatiquement les configs de chaque layer * Nuxt declare dans `nuxt.config.ts:extends`. Le layer `@malio/layer-ui` @@ -11,7 +11,7 @@ import type {Config} from 'tailwindcss' * success,btn-*,site-blue,site-yellow,site-green} * - fontFamily.sans (Helvetica Neue) * - * Cette config locale ne redeclare QUE ce qui est specifique a Coltura + * Cette config locale ne redeclare QUE ce qui est specifique a Starseed * ou absent de la config Malio — evite la duplication et les derives. */ export default >{ @@ -19,7 +19,7 @@ export default >{ theme: { extend: { colors: { - // Couleurs applicatives Coltura (hors namespace `m` reserve + // Couleurs applicatives Starseed (hors namespace `m` reserve // au design system Malio partage). primary: { 500: '#222783', diff --git a/infra/dev/.env.docker b/infra/dev/.env.docker index 90687ca..9adb62d 100644 --- a/infra/dev/.env.docker +++ b/infra/dev/.env.docker @@ -1,8 +1,8 @@ -DOCKER_APP_NAME=coltura +DOCKER_APP_NAME=starseed DOCKER_PHP_VERSION=8.4.6 DOCKER_NODE_VERSION=24.12.0 APP_USER=www-data -POSTGRES_DB=coltura +POSTGRES_DB=starseed POSTGRES_USER=root POSTGRES_PASSWORD=root POSTGRES_PORT=5437 diff --git a/infra/prod/.env.prod.example b/infra/prod/.env.prod.example index 026a6b5..67a7bc0 100644 --- a/infra/prod/.env.prod.example +++ b/infra/prod/.env.prod.example @@ -2,11 +2,11 @@ APP_ENV=prod APP_DEBUG=0 APP_SECRET=CHANGE_ME_IN_PRODUCTION -DATABASE_URL="postgresql://coltura:CHANGE_ME@host.docker.internal:5432/coltura?serverVersion=16&charset=utf8" +DATABASE_URL="postgresql://starseed:CHANGE_ME@host.docker.internal:5432/starseed_prod?serverVersion=16&charset=utf8" JWT_PASSPHRASE=CHANGE_ME_IN_PRODUCTION JWT_COOKIE_SECURE=1 JWT_TOKEN_TTL=86400 JWT_COOKIE_TTL=86400 -CORS_ALLOW_ORIGIN='^https://coltura\.malio-dev\.fr$' +CORS_ALLOW_ORIGIN='^https://starseed\.malio-dev\.fr$' diff --git a/infra/prod/Dockerfile b/infra/prod/Dockerfile index 3aa9cc3..bb99f00 100644 --- a/infra/prod/Dockerfile +++ b/infra/prod/Dockerfile @@ -60,7 +60,7 @@ RUN rm -f /etc/nginx/sites-enabled/default # Configs COPY infra/prod/supervisord.conf /etc/supervisor/conf.d/app.conf -COPY infra/prod/nginx.conf /etc/nginx/sites-enabled/coltura.conf +COPY infra/prod/nginx.conf /etc/nginx/sites-enabled/starseed.conf # Backend from stage 1 COPY --from=backend-build /app /var/www/html diff --git a/infra/prod/deploy.sh b/infra/prod/deploy.sh index 7407765..a37cc36 100755 --- a/infra/prod/deploy.sh +++ b/infra/prod/deploy.sh @@ -4,9 +4,9 @@ set -euo pipefail cd "$(dirname "$0")" TAG="${1:-latest}" -export COLTURA_IMAGE_TAG="$TAG" +export STARSEED_IMAGE_TAG="$TAG" -echo "==> Deploying coltura:${TAG}..." +echo "==> Deploying starseed:${TAG}..." echo "==> Enabling maintenance mode..." touch maintenance.on diff --git a/infra/prod/docker-compose.prod.yml b/infra/prod/docker-compose.prod.yml index 1a879b5..eafa4cc 100644 --- a/infra/prod/docker-compose.prod.yml +++ b/infra/prod/docker-compose.prod.yml @@ -1,16 +1,16 @@ services: app: - image: gitea.malio.fr/malio-dev/coltura:${COLTURA_IMAGE_TAG:-latest} - container_name: coltura-app + image: gitea.malio.fr/malio-dev/starseed:${STARSEED_IMAGE_TAG:-latest} + container_name: starseed-app env_file: .env ports: - "8086:80" volumes: - ./config/jwt:/var/www/html/config/jwt:ro - - coltura_logs:/var/www/html/var/log + - starseed_logs:/var/www/html/var/log extra_hosts: - "host.docker.internal:host-gateway" restart: unless-stopped volumes: - coltura_logs: + starseed_logs: diff --git a/infra/prod/nginx-proxy.conf b/infra/prod/nginx-proxy.conf index cb6dee5..0d7f416 100644 --- a/infra/prod/nginx-proxy.conf +++ b/infra/prod/nginx-proxy.conf @@ -1,12 +1,12 @@ server { listen 80; listen [::]:80; - server_name coltura.malio-dev.fr; + server_name starseed.malio-dev.fr; - root /var/www/coltura/public; + root /var/www/starseed/public; # Maintenance mode - if (-f /var/www/coltura/maintenance.on) { + if (-f /var/www/starseed/maintenance.on) { return 503; } diff --git a/makefile b/makefile index 5d00511..d046bba 100644 --- a/makefile +++ b/makefile @@ -9,6 +9,12 @@ ENV_FILE := $(if $(wildcard $(ENV_LOCAL)),$(ENV_LOCAL),$(ENV_DEFAULT)) include $(ENV_DEFAULT) -include $(ENV_LOCAL) +# Export du UID/GID host pour que docker compose les voie dans toutes les targets +# (sinon le build du Dockerfile dev fail sur `usermod -u ${CURRENT_UID}` quand l'image +# n'est pas en cache, ex: apres renommage du compose project). +export CURRENT_UID := $(shell id -u) +export CURRENT_GID := $(shell id -g) + PHP_CONTAINER = php-$(DOCKER_APP_NAME)-fpm SYMFONY_CONSOLE = $(EXEC_PHP) php bin/console @@ -26,7 +32,7 @@ FILES = # Affiche l'aide — cible par defaut (make ou make help) help: - @printf "\n \033[1mColtura — Commandes make\033[0m\n\n" + @printf "\n \033[1mStarseed — Commandes make\033[0m\n\n" @printf " \033[1;33mContainers\033[0m\n" @printf " \033[36m%-28s\033[0m %s\n" "start" "Demarrer les containers Docker" @printf " \033[36m%-28s\033[0m %s\n" "stop" "Arreter les containers" diff --git a/migrations/Version20260417120000.php b/migrations/Version20260417120000.php index 20d3c49..6ec9f44 100644 --- a/migrations/Version20260417120000.php +++ b/migrations/Version20260417120000.php @@ -11,7 +11,7 @@ use Doctrine\Migrations\AbstractMigration; * Module Sites - Ticket 1/4 : brique fondatrice de donnees. * * Cree la table `site` qui porte les etablissements physiques de l'instance - * Coltura. La table est creee inconditionnellement : meme si SitesModule est + * Starseed. La table est creee inconditionnellement : meme si SitesModule est * desactive dans `config/modules.php`, la structure DB existe (pas de * dependance dure depuis Core, mais pas de coin d'ombre schema non plus). * diff --git a/src/Module/Sites/Domain/Entity/Site.php b/src/Module/Sites/Domain/Entity/Site.php index 79f384b..fd0855d 100644 --- a/src/Module/Sites/Domain/Entity/Site.php +++ b/src/Module/Sites/Domain/Entity/Site.php @@ -24,7 +24,7 @@ use Symfony\Component\Serializer\Attribute\Groups; use Symfony\Component\Validator\Constraints as Assert; /** - * Site physique (usine / etablissement) appartenant a l'instance Coltura. + * Site physique (usine / etablissement) appartenant a l'instance Starseed. * * Adresse decomposee en champs structures (rue, complement, CP, ville) pour * permettre des recherches/tris fins ulterieurs et eviter les divergences diff --git a/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php b/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php index cd316fc..f7d7497 100644 --- a/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php +++ b/src/Module/Sites/Infrastructure/DataFixtures/SitesFixtures.php @@ -36,7 +36,7 @@ class SitesFixtures extends Fixture public function load(ObjectManager $manager): void { - // Chatellerault : bleu Coltura. + // Chatellerault : bleu Starseed. $this->ensureSite( $manager, name: 'Chatellerault',