Compare commits

..

5 Commits

Author SHA1 Message Date
gitea-actions
8f2a688740 chore: bump version to v0.4.6
All checks were successful
Auto Tag Develop / tag (push) Successful in 6s
Build & Push Docker Image / build (push) Successful in 48s
2026-05-21 09:19:01 +00:00
Matthieu
6491943930 docs : ajoute la section Messagerie au centre d'aide + maj admin/intégrations (mail OVH)
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 11:18:42 +02:00
gitea-actions
a9f05fd819 chore: bump version to v0.4.5
All checks were successful
Build & Push Docker Image / build (push) Successful in 53s
Auto Tag Develop / tag (push) Successful in 6s
2026-05-21 08:57:40 +00:00
Matthieu
925be5d181 fix(ui) : sélecteur de statut Malio dans le drawer de création de workflow
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Remplace le <select> natif du navigateur par MalioSelect (catégorie de statut).
MalioSelect accepte les valeurs string (enum StatusCategory), contrairement à ce
qu'indiquait la note CLAUDE.md — note corrigée en conséquence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:53:19 +02:00
Matthieu
5da165f739 docs : corrige le déploiement prod (Docker) et documente les variables d'env mail
- README : section Variables d'environnement (ENCRYPTION_KEY, LOCK_DSN) + section Déploiement passée au flow Docker (deploy.sh)
- mail-cron-setup : sépare dev (make, php-lesstime-fpm) et prod (lesstime-app, docker compose exec), cron prod réel
- infra/prod/.env.example : ajoute ENCRYPTION_KEY et LOCK_DSN (manquaient, requis pour la sync mail)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:48:55 +02:00
10 changed files with 209 additions and 80 deletions

View File

@@ -101,7 +101,7 @@ Exemples : `feat : add login page`, `fix(auth) : prevent null token crash`
- Middleware global `auth.global.ts` protège les routes - Middleware global `auth.global.ts` protège les routes
- Traductions dans `frontend/i18n/locales/` (le module résout `langDir` depuis `i18n/`) - Traductions dans `frontend/i18n/locales/` (le module résout `langDir` depuis `i18n/`)
- 4 espaces d'indentation - 4 espaces d'indentation
- MalioSelect : options `{ label: string, value: string | number | null }`supporte les valeurs `string` (donc les enums string comme `StatusCategory`), pas seulement `number`. Vérifié dans la source `@malio/layer-ui` (`Select.vue` : `modelValue: string | number | null`). L'option vide `null` n'est ajoutée que si `empty-option-label` est passé (ne pas le passer pour un champ requis) - MalioSelect : options `{ label: string, value: string | number | null }`accepte les valeurs **string** (enums string OK, ex `category`/`StatusCategory`), pas seulement `number` (vérifié dans la source `Select.vue` : `modelValue: string | number | null`). L'option vide `null` n'est ajoutée que si `empty-option-label` est passé (ne pas le passer pour un champ requis). Largeur via `group-class` (pas de prop `minWidth`/`min-width`). ⚠️ Le `COMPONENTS.md` de la lib est inexact sur ce composant (il indique une clé `text` et une prop `minWidth` inexistantes) : la clé d'affichage réelle est `label`. Ne jamais modifier la lib `malio-layer-ui` depuis ce projet.
- Portal client : pages sous `/portal/`, layout `portal.vue`, middleware redirige `ROLE_CLIENT` (sans `ROLE_ADMIN`) vers `/portal` - Portal client : pages sous `/portal/`, layout `portal.vue`, middleware redirige `ROLE_CLIENT` (sans `ROLE_ADMIN`) vers `/portal`
- Users admin+client : ne pas bloquer — vérifier `ROLE_CLIENT && !ROLE_ADMIN` pour les restrictions - Users admin+client : ne pas bloquer — vérifier `ROLE_CLIENT && !ROLE_ADMIN` pour les restrictions

View File

@@ -45,6 +45,10 @@ make install
L'application est accessible sur **http://localhost:8082**. L'application est accessible sur **http://localhost:8082**.
Les valeurs par défaut du `.env` committé suffisent pour démarrer en local. Pour la prod
(et pour activer la messagerie), surcharger les variables sensibles dans `.env.local`
voir « Variables d'environnement » ci-dessous.
### Comptes de test (fixtures) ### Comptes de test (fixtures)
| Utilisateur | Mot de passe | Rôle | Détails | | Utilisateur | Mot de passe | Rôle | Détails |
@@ -56,6 +60,25 @@ L'application est accessible sur **http://localhost:8082**.
| `client-liot` | `client` | ROLE_CLIENT | Client LIOT (projet SIRH) | | `client-liot` | `client` | ROLE_CLIENT | Client LIOT (projet SIRH) |
| `client-acme` | `client` | ROLE_CLIENT | Client ACME (projet CRM) | | `client-acme` | `client` | ROLE_CLIENT | Client ACME (projet CRM) |
## Variables d'environnement
Les variables sont définies dans `.env` (committé, valeurs par défaut pour le dev) et
peuvent être surchargées dans `.env.local` (jamais committé). En prod, elles vont dans le
`.env` du serveur (`/var/www/lesstime/.env`, voir `infra/prod/.env.example`).
| Variable | Rôle | Défaut dev | À fixer en prod |
|----------|------|-----------|-----------------|
| `APP_SECRET` | Secret Symfony | placeholder | ✅ (hex 32) |
| `JWT_PASSPHRASE` | Passphrase des clés JWT | placeholder | ✅ |
| `DATABASE_URL` | Connexion PostgreSQL | container `db` | ✅ (`host.docker.internal`) |
| `CORS_ALLOW_ORIGIN` | Origines CORS autorisées | localhost | ✅ (domaine prod) |
| **`ENCRYPTION_KEY`** | **Clé hex 32 bytes chiffrant les credentials IMAP/SMTP (feature mail)** | placeholder | ✅ — doit rester **stable**, sinon les credentials mail stockés deviennent illisibles |
| **`LOCK_DSN`** | **Store de verrous Symfony pour la sync mail (anti-chevauchement)** | `flock` | `flock` suffit |
> **Messagerie** : `ENCRYPTION_KEY` et `LOCK_DSN` sont introduites par l'intégration mail.
> Détails de config et cron de synchronisation : `docs/mail-integration.md` et `docs/mail-cron-setup.md`.
> Générer une clé : `php -r "echo bin2hex(random_bytes(32));"`.
## Commandes ## Commandes
### Docker ### Docker
@@ -218,13 +241,19 @@ docker exec -u www-data php-lesstime-fpm php bin/console app:generate-api-token
## Déploiement ## Déploiement
1. Déployer le code sur le serveur La prod tourne en **Docker** : l'image est buildée par la CI Gitea sur push de tag `v*`
2. `composer install --no-dev --optimize-autoloader` (`gitea.malio.fr/malio-dev/lesstime:<tag>`), puis déployée par le script `deploy.sh` sur
3. `php bin/console doctrine:migrations:migrate --no-interaction` le serveur (dossier `/var/www/lesstime`, container `lesstime-app`).
4. `php bin/console cache:clear --env=prod`
5. `cd frontend && npm install && npm run build:dist` ```bash
6. `docker restart nginx-lesstime` # Sur le serveur, depuis /var/www/lesstime
7. Ouvrir le port 8082 sur le firewall (LAN uniquement) sudo ./deploy.sh # déploie la dernière image (latest)
sudo ./deploy.sh v0.4.2 # déploie une version précise
```
Le script active la maintenance, pull l'image, redémarre le container, lance les migrations
et vide le cache. Guide complet (première installation, BDD, Nginx, JWT, rollback) :
**`doc/deployment-docker.md`**.
## Licence ## Licence

View File

@@ -1,2 +1,2 @@
parameters: parameters:
app.version: '0.4.4' app.version: '0.4.6'

View File

@@ -3,44 +3,24 @@
## Vue d'ensemble ## Vue d'ensemble
La synchronisation IMAP est déclenchée par un cron OS toutes les 10 minutes. La synchronisation IMAP est déclenchée par un cron OS toutes les 10 minutes.
Elle appelle la commande Symfony `app:mail:sync` qui s'exécute dans le container PHP. Elle appelle la commande Symfony `app:mail:sync` qui s'exécute **dans le container PHP**.
Un Symfony Lock (`mail.sync`, TTL 10 min, store `flock` via `LOCK_DSN=flock`) empêche Un Symfony Lock (`mail.sync`, TTL 10 min, store `flock` via `LOCK_DSN=flock`) empêche
les runs de se chevaucher si une sync prend plus de 10 min. les runs de se chevaucher si une sync prend plus de 10 min.
> **Dev vs prod** — en dev le container s'appelle `php-lesstime-fpm` et on passe par `make`.
> En **production** le container s'appelle `lesstime-app` (service `app` du `docker-compose.yml`
> dans `/var/www/lesstime`), il n'y a **pas de `make`** : tout passe par `docker compose` / `docker exec`.
## Prérequis ## Prérequis
- Container `php-lesstime-fpm` démarré (`make start`) - `MailConfiguration.enabled = true` (configurable depuis l'admin — onglet « Mail »)
- `MailConfiguration.enabled = true` (configurable depuis l'admin — Phase 7) - `ENCRYPTION_KEY` (clé hex 32 bytes) défini dans l'environnement :
- `ENCRYPTION_KEY` défini dans `infra/dev/.env.docker.local` (ou production env) - **dev** : `infra/dev/.env.docker.local`
- **prod** : `/var/www/lesstime/.env`
## Installation du cron - Container démarré :
- **dev** : `make start` (container `php-lesstime-fpm`)
Sur la **machine hôte** (pas dans le container) : - **prod** : déployé via `sudo ./deploy.sh` (container `lesstime-app`)
```bash
crontab -e
```
Ajouter la ligne suivante (adapter le chemin) :
```cron
*/10 * * * * cd /home/r-dev/malio-dev/Lesstime && make mail-sync >> /var/log/lesstime-mail-sync.log 2>&1
```
Ou directement via `docker exec` (sans dépendance à `make`) :
```cron
*/10 * * * * docker exec php-lesstime-fpm php bin/console app:mail:sync >> /var/log/lesstime-mail-sync.log 2>&1
```
### Avec un utilisateur système dédié
Si le cron est configuré pour un utilisateur système spécifique (ex: `www-data` ou `deploy`) :
```bash
sudo crontab -u deploy -e
```
## Variables d'environnement nécessaires ## Variables d'environnement nécessaires
@@ -49,63 +29,100 @@ sudo crontab -u deploy -e
| `ENCRYPTION_KEY` | Clé hex 32 bytes pour déchiffrer le password IMAP | `$(php -r "echo bin2hex(random_bytes(32));")` | | `ENCRYPTION_KEY` | Clé hex 32 bytes pour déchiffrer le password IMAP | `$(php -r "echo bin2hex(random_bytes(32));")` |
| `LOCK_DSN` | DSN du store de verrous Symfony | `flock` (défaut, fichier local) | | `LOCK_DSN` | DSN du store de verrous Symfony | `flock` (défaut, fichier local) |
La clé doit être la même que celle utilisée pour chiffrer le password lors de la configuration. La clé `ENCRYPTION_KEY` doit être **identique** à celle utilisée pour chiffrer le password
lors de la configuration depuis l'admin. Si elle change, les credentials stockés deviennent illisibles.
## Checklist setup production ---
1. [ ] Définir `ENCRYPTION_KEY` dans les variables d'environnement production ## Dev
2. [ ] Créer le compte mail dédié (ex: `lesstime@votre-domaine.fr`) chez OVH
3. [ ] Accéder à `/admin` → onglet "Mail" → renseigner les credentials IMAP/SMTP
4. [ ] Cliquer "Tester la connexion" → vérifier le succès
5. [ ] Cocher "Activer la synchronisation" → Enregistrer
6. [ ] Installer le cron OS (voir section "Installation du cron")
7. [ ] Vérifier les logs après la première sync : `make logs-dev` (chercher `mail.sync`)
## Commandes utiles ### Lancer une sync à la main
```bash ```bash
# Sync complète (toutes les boîtes) make mail-sync # sync complète (toutes les boîtes)
make mail-sync make mail-sync FOLDER=INBOX # un seul dossier (doit déjà exister en base)
make mail-sync DRYRUN=1 # simulation (dry-run, pas d'écriture BDD)
```
# Sync d'un seul dossier (le dossier doit déjà exister en base) Ou directement dans le container :
make mail-sync FOLDER=INBOX
# Simulation (dry-run, pas d'écriture BDD) ```bash
make mail-sync DRYRUN=1
# Directement dans le container
docker exec php-lesstime-fpm php bin/console app:mail:sync docker exec php-lesstime-fpm php bin/console app:mail:sync
docker exec php-lesstime-fpm php bin/console app:mail:sync --folder=INBOX docker exec php-lesstime-fpm php bin/console app:mail:sync --folder=INBOX
docker exec php-lesstime-fpm php bin/console app:mail:sync --dry-run docker exec php-lesstime-fpm php bin/console app:mail:sync --dry-run
``` ```
## Logs ### Logs (dev)
Les logs Symfony sont dans `var/log/dev.log` (ou `prod.log` en production).
Suivre les logs en temps réel :
```bash ```bash
make logs-dev make logs-dev # tail -f var/log/dev.log
``` ```
Les messages loggés par `MailSyncService` sont préfixés `mail.sync`. Les messages loggés par `MailSyncService` sont préfixés `mail.sync`.
---
## Production
En prod, l'app tourne dans le container `lesstime-app` déployé par `sudo ./deploy.sh`
(dossier `/var/www/lesstime`). La commande s'exécute en tant que `www-data` (uid 33),
comme les migrations lancées par `deploy.sh`.
### Lancer une sync à la main
Depuis `/var/www/lesstime` :
```bash
sudo docker compose exec -T -u www-data app php bin/console app:mail:sync
sudo docker compose exec -T -u www-data app php bin/console app:mail:sync --folder=INBOX
sudo docker compose exec -T -u www-data app php bin/console app:mail:sync --dry-run
```
### Installer le cron
Sur la **machine hôte** (pas dans le container). Comme `docker` requiert `sudo` en prod,
installer le cron sous root :
```bash
sudo crontab -e
```
Ajouter :
```cron
*/10 * * * * cd /var/www/lesstime && docker compose exec -T -u www-data app php bin/console app:mail:sync >> /var/log/lesstime-mail-sync.log 2>&1
```
> Le crontab de root exécute déjà les commandes en root → pas de `sudo` à l'intérieur de la ligne cron.
> La commande est **idempotente** (UIDs uniques en base) : la relancer ne duplique pas les données.
### Logs (prod)
```bash
cd /var/www/lesstime
docker compose logs -f --tail=100 app # logs container
docker compose exec app cat var/log/prod.log # log Symfony (volume lesstime_logs)
```
### Checklist setup production
1. [ ] Définir `ENCRYPTION_KEY` (hex 32 bytes) et `LOCK_DSN=flock` dans `/var/www/lesstime/.env`
2. [ ] Créer le compte mail dédié (ex: `lesstime@votre-domaine.fr`) chez OVH
3. [ ] Accéder à `/admin` → onglet « Mail » → renseigner les credentials IMAP/SMTP
4. [ ] Cliquer « Tester la connexion » → vérifier le succès
5. [ ] Cocher « Activer la synchronisation » → Enregistrer
6. [ ] Lancer une sync manuelle pour valider (commande ci-dessus)
7. [ ] Installer le cron OS (voir « Installer le cron »)
8. [ ] Vérifier les logs après la première sync (`docker compose logs -f app`, chercher `mail.sync`)
---
## Sécurité ## Sécurité
- Le password IMAP est **toujours stocké chiffré** (libsodium secretbox) - Le password IMAP est **toujours stocké chiffré** (libsodium secretbox)
- Les corps de mails, passwords et pièces jointes ne sont **jamais loggés** - Les corps de mails, passwords et pièces jointes ne sont **jamais loggés**
- Le lock `flock` évite les runs parallèles (fichier dans `/tmp/sf.mail.sync.<hash>.lock`) - Le lock `flock` évite les runs parallèles (fichier dans `/tmp/sf.mail.sync.<hash>.lock`)
## Rappels sécurité
- La page `/mail` et tous les endpoints `/api/mail/*` sont refusés aux `ROLE_CLIENT` exclusifs - La page `/mail` et tous les endpoints `/api/mail/*` sont refusés aux `ROLE_CLIENT` exclusifs
- Le sidebar "Messagerie" est masqué pour les utilisateurs ROLE_CLIENT sans ROLE_USER - Le sidebar « Messagerie » est masqué pour les utilisateurs `ROLE_CLIENT` sans `ROLE_USER`
- Le password IMAP est chiffré via libsodium secretbox avant stockage (jamais en clair en base) - Les corps de mails sont sanitisés via DOMPurify avant affichage (`frontend/utils/sanitizeMailHtml.ts`)
- Les corps de mails sont sanitisés via DOMPurify avant affichage (voir `frontend/utils/sanitizeMailHtml.ts`) - Les pixels de tracking distants sont remplacés par un placeholder
- Les pixels tracking distants sont remplacés par un placeholder
- Aucun body mail, password ou contenu de pièce jointe n'est loggé
## Production
En production, préférer un cron système ou un job scheduler (Kubernetes CronJob, ECS Scheduled Task, etc.).
La commande est idempotente : relancer plusieurs fois ne duplique pas les données (UIDs uniques en base).

View File

@@ -50,8 +50,7 @@
v-model="s.category" v-model="s.category"
:options="categoryOptions" :options="categoryOptions"
label="Catégorie" label="Catégorie"
min-width="w-44" group-class="w-48 shrink-0"
group-class="shrink-0"
/> />
<button <button
type="button" type="button"

View File

@@ -64,3 +64,13 @@ L'admin (`/admin`) est divisé en plusieurs onglets, chacun gérant une ressourc
- Configure le calendrier CalDav par défaut - Configure le calendrier CalDav par défaut
- Test de connexion intégré - Test de connexion intégré
- Active la **sync calendrier** sur les tâches planifiées - Active la **sync calendrier** sur les tâches planifiées
## Onglet *Mail*
Configure la **boîte mail partagée** (OVH) lue dans la section *Messagerie*.
- **Réception (IMAP)** : hôte, port (993 par défaut), chiffrement (SSL / TLS / aucun)
- **Envoi (SMTP)** : hôte, port (465 par défaut), chiffrement
- **Identifiants** : nom d'utilisateur + mot de passe (chiffré côté serveur, jamais réaffiché — un indicateur signale qu'un mot de passe est déjà enregistré), et chemin du dossier *Envoyés*
- **Toggle `enabled`** : active la messagerie
- **Test de connexion** intégré (vérifie l'accès IMAP et compte les dossiers)

View File

@@ -1,6 +1,6 @@
# Intégrations # Intégrations
Lesstime s'intègre avec **3 outils externes** pour fluidifier le workflow dev. Lesstime s'intègre avec **4 outils externes** pour fluidifier le workflow dev.
## 🌳 Gitea ## 🌳 Gitea
@@ -64,3 +64,29 @@ Sur une tâche avec **scheduled start + end** :
- **Pas de retour Zimbra → Lesstime** : si tu modifies l'événement dans Zimbra, Lesstime ne le voit pas - **Pas de retour Zimbra → Lesstime** : si tu modifies l'événement dans Zimbra, Lesstime ne le voit pas
- **Récurrences** : les patterns RRULE basiques sont supportés (daily, weekly avec jours, monthly) - **Récurrences** : les patterns RRULE basiques sont supportés (daily, weekly avec jours, monthly)
## 📧 Messagerie (Mail OVH)
Boîte mail partagée OVH (IMAP) lue directement dans Lesstime.
### Configuration
1. **Admin → Mail** :
- Réception **IMAP** (hôte, port, chiffrement) et envoi **SMTP** (hôte, port, chiffrement)
- Identifiants (mot de passe chiffré côté serveur) + dossier *Envoyés*
- **Test de connexion** intégré
2. Active la config (toggle `enabled`)
### Utilisation
- La section **Messagerie** (barre latérale) affiche dossiers, messages et lecteur
- **Synchronisation IMAP à la demande** via le bouton *Rafraîchir* (traitée en asynchrone par Messenger)
- Depuis un mail : **créer une tâche** pré-remplie ou **lier à une tâche** existante
- Badge de non-lus dans la barre latérale, rafraîchi automatiquement (toutes les 30 s)
> 📖 Le guide complet de la messagerie est dans la section *Messagerie*.
### Limites
- **Lecture seule** : pas de rédaction / réponse / suppression de mail depuis l'interface
- Réservée aux rôles **admin** et **user** (pas les clients)

View File

@@ -0,0 +1,40 @@
# Messagerie
Lesstime intègre une **boîte mail partagée** (OVH, protocole IMAP) directement dans l'application. Tu lis les mails de l'équipe et tu les transformes en tâches sans quitter Lesstime.
> 📥 La messagerie est accessible depuis l'entrée **Messagerie** de la barre latérale (icône enveloppe). Un **badge** y affiche le nombre de mails non lus, toutes boîtes confondues.
> 🛡️ Réservée aux rôles **ROLE_ADMIN** et **ROLE_USER**. Les utilisateurs *client* sont redirigés vers leur portail.
## L'interface
L'écran est organisé en **3 colonnes** :
1. **Dossiers** — l'arborescence de la boîte (INBOX, Envoyés, sous-dossiers…), avec le compteur de non-lus par dossier. INBOX est sélectionné par défaut.
2. **Messages** — la liste du dossier sélectionné (expéditeur, objet, date). Les mails non lus sont mis en avant. Un bouton **Charger plus** récupère les messages suivants (pagination).
3. **Lecteur** — le mail sélectionné : en-tête (expéditeur, destinataires, date), corps du message et **pièces jointes**.
## Lire un message
- Clique sur un message dans la liste : son détail s'affiche et il est **automatiquement marqué comme lu**.
- Tu peux le repasser **non lu** ou l'**étoiler** (flag) pour le retrouver plus tard.
- Les **pièces jointes** sont listées dans le lecteur : clique pour les télécharger, les images peuvent être prévisualisées.
## Synchronisation
- Le bouton **Rafraîchir** (en haut de l'écran) déclenche une **synchronisation IMAP à la demande** : Lesstime va chercher les nouveaux mails sur le serveur. Le traitement est asynchrone, la liste se met à jour quelques secondes après.
- En arrière-plan, le **compteur de non-lus** de la barre latérale se rafraîchit automatiquement (toutes les 30 s).
## Transformer un mail en action
Depuis le lecteur, deux boutons relient un mail au suivi de projet :
- **Créer une tâche** — ouvre une tâche pré-remplie à partir du mail (objet, contenu). Tu choisis le projet et les métadonnées, le mail reste lié à la tâche.
- **Lier à une tâche** — rattache le mail à une tâche **existante**.
> 💡 C'est le pont entre la boîte mail de l'équipe et le kanban : une demande reçue par mail devient une tâche traçable en deux clics.
## Limites
- **Lecture seule** : l'interface ne permet pas (encore) de **rédiger, répondre ou transférer** un mail, ni de supprimer un message.
- La configuration du serveur (IMAP/SMTP, identifiants) se fait dans **Admin → Mail** — voir la section *Administration*.

View File

@@ -24,6 +24,7 @@ const META: Record<string, { title: string, icon: string, accent: string, roles:
'07-admin': { title: 'Administration', icon: 'mdi:shield-crown-outline', accent: 'from-rose-500 to-pink-600', roles: ['admin'] }, '07-admin': { title: 'Administration', icon: 'mdi:shield-crown-outline', accent: 'from-rose-500 to-pink-600', roles: ['admin'] },
'08-integrations': { title: 'Intégrations', icon: 'mdi:puzzle-outline', accent: 'from-blue-500 to-indigo-500', roles: ['admin', 'user'] }, '08-integrations': { title: 'Intégrations', icon: 'mdi:puzzle-outline', accent: 'from-blue-500 to-indigo-500', roles: ['admin', 'user'] },
'09-mcp-api': { title: 'Token MCP & API', icon: 'mdi:robot-outline', accent: 'from-slate-700 to-slate-900', roles: ['admin', 'user'] }, '09-mcp-api': { title: 'Token MCP & API', icon: 'mdi:robot-outline', accent: 'from-slate-700 to-slate-900', roles: ['admin', 'user'] },
'10-messaging': { title: 'Messagerie', icon: 'mdi:email-outline', accent: 'from-teal-500 to-cyan-600', roles: ['admin', 'user'] },
} }
const sections = computed<Section[]>(() => { const sections = computed<Section[]>(() => {

View File

@@ -15,6 +15,13 @@ JWT_COOKIE_SAMESITE=lax
JWT_TOKEN_TTL=86400 JWT_TOKEN_TTL=86400
JWT_COOKIE_TTL=86400 JWT_COOKIE_TTL=86400
# Mail (intégration IMAP/SMTP)
# Clé hex 32 bytes chiffrant les credentials mail stockés en base.
# Générer : php -r "echo bin2hex(random_bytes(32));" — doit rester STABLE.
ENCRYPTION_KEY=change-me
# Store de verrous Symfony pour la sync mail (anti-chevauchement du cron).
LOCK_DSN=flock
# CORS # CORS
CORS_ALLOW_ORIGIN='^https?://project\.malio-dev\.fr$' CORS_ALLOW_ORIGIN='^https?://project\.malio-dev\.fr$'