|
|
@@ -219,28 +219,60 @@ Lesstime expose un serveur MCP (Model Context Protocol) permettant aux assistant
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Configuration réseau (HTTP)
|
|
|
|
### Configuration réseau (HTTP) — par poste, hors git
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Le transport HTTP nécessite un **token API** (Bearer), qui est un **secret** : il ne va **jamais**
|
|
|
|
|
|
|
|
dans le `.mcp.json` versionné (celui-ci ne contient que le serveur STDIO local, sans secret).
|
|
|
|
|
|
|
|
Chaque développeur configure le serveur HTTP dans sa **config Claude Code locale**.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Méthode recommandée (identique sur Fedora, Windows et macOS) :**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
claude mcp add --transport http --scope user lesstime \
|
|
|
|
|
|
|
|
http://project.malio-dev.fr/_mcp \
|
|
|
|
|
|
|
|
--header "Authorization: Bearer <api-token>"
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
- En prod : `http://project.malio-dev.fr/_mcp`
|
|
|
|
|
|
|
|
- En réseau local : `http://<ip-serveur>:8082/_mcp`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Où c'est stocké** (si tu édites le fichier à la main, sous la clé `mcpServers`) :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| OS | Fichier de config Claude Code |
|
|
|
|
|
|
|
|
|----|-------------------------------|
|
|
|
|
|
|
|
|
| **Fedora / Linux** | `~/.claude.json` |
|
|
|
|
|
|
|
|
| **Windows** (collègue) | `%USERPROFILE%\.claude.json` (ex. `C:\Users\<user>\.claude.json`) |
|
|
|
|
|
|
|
|
| **macOS** | `~/.claude.json` |
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"mcpServers": {
|
|
|
|
"mcpServers": {
|
|
|
|
"lesstime": {
|
|
|
|
"lesstime": {
|
|
|
|
"type": "url",
|
|
|
|
"type": "http",
|
|
|
|
"url": "http://<ip-serveur>:8082/_mcp",
|
|
|
|
"url": "http://project.malio-dev.fr/_mcp",
|
|
|
|
"headers": {
|
|
|
|
"headers": { "Authorization": "Bearer <api-token>" }
|
|
|
|
"Authorization": "Bearer <api-token>"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Après modification, relancer la connexion avec `/mcp` dans Claude Code.
|
|
|
|
|
|
|
|
|
|
|
|
### Gestion des tokens API
|
|
|
|
### Gestion des tokens API
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Générer / régénérer un token pour un utilisateur :
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
```bash
|
|
|
|
|
|
|
|
# En dev (container local)
|
|
|
|
docker exec -u www-data php-lesstime-fpm php bin/console app:generate-api-token <username>
|
|
|
|
docker exec -u www-data php-lesstime-fpm php bin/console app:generate-api-token <username>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# En prod (sur le serveur, dans infra/prod)
|
|
|
|
|
|
|
|
sudo docker compose exec -T -u www-data app php bin/console app:generate-api-token <username>
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ Le token est **invalidé à chaque reset/reseed de la base**. Symptôme : `/mcp` renvoie
|
|
|
|
|
|
|
|
`HTTP 401 "Invalid API token"`. Il faut alors le **régénérer** (commande ci-dessus) puis remplacer
|
|
|
|
|
|
|
|
la valeur `Bearer ...` dans ta config locale (par poste).
|
|
|
|
|
|
|
|
|
|
|
|
## Déploiement
|
|
|
|
## Déploiement
|
|
|
|
|
|
|
|
|
|
|
|
La prod tourne en **Docker** : l'image est buildée par la CI Gitea sur push de tag `v*`
|
|
|
|
La prod tourne en **Docker** : l'image est buildée par la CI Gitea sur push de tag `v*`
|
|
|
@@ -270,7 +302,7 @@ INFRA #146.
|
|
|
|
|---|---|---|
|
|
|
|
|---|---|---|
|
|
|
|
| Nature | process PHP qui tourne en continu | fichiers JS/HTML **statiques** (`nuxt generate`) |
|
|
|
|
| Nature | process PHP qui tourne en continu | fichiers JS/HTML **statiques** (`nuxt generate`) |
|
|
|
|
| Quand le DSN est lu | au **runtime** | **figé au build** (baké dans le JS) |
|
|
|
|
| Quand le DSN est lu | au **runtime** | **figé au build** (baké dans le JS) |
|
|
|
|
| Où mettre le DSN | `infra/prod/.env` (runtime) | **secrets Gitea** → build-args de la CI |
|
|
|
|
| Où mettre le DSN | `.env` du serveur (`/var/www/lesstime/.env`) — runtime | **secrets Gitea** → build-args de la CI |
|
|
|
|
|
|
|
|
|
|
|
|
> Les erreurs partent **toujours vers GlitchTip**, jamais vers la CI. La CI ne sert qu'à *écrire*
|
|
|
|
> Les erreurs partent **toujours vers GlitchTip**, jamais vers la CI. La CI ne sert qu'à *écrire*
|
|
|
|
> le DSN front dans le bundle au moment du build (il n'y a aucun process front en prod qui
|
|
|
|
> le DSN front dans le bundle au moment du build (il n'y a aucun process front en prod qui
|
|
|
@@ -278,7 +310,7 @@ INFRA #146.
|
|
|
|
|
|
|
|
|
|
|
|
### Variables
|
|
|
|
### Variables
|
|
|
|
|
|
|
|
|
|
|
|
**Backend — fichier `infra/prod/.env` du serveur** (chargé via `env_file`) :
|
|
|
|
**Backend — fichier `.env` du serveur** (`/var/www/lesstime/.env`, chargé via `env_file` ; le repo ne fournit que le template `infra/prod/.env.example`) :
|
|
|
|
```env
|
|
|
|
```env
|
|
|
|
SENTRY_DSN=http://<clé>@glitchtip.interne:<port>/<id-projet-api>
|
|
|
|
SENTRY_DSN=http://<clé>@glitchtip.interne:<port>/<id-projet-api>
|
|
|
|
```
|
|
|
|
```
|
|
|
@@ -312,10 +344,76 @@ SENTRY_DSN=http://<clé>@glitchtip.interne:<port>/<id-projet-api>
|
|
|
|
|
|
|
|
|
|
|
|
1. Dans GlitchTip : créer les projets `lesstime-api` et `lesstime-front`, récupérer les 2 DSN
|
|
|
|
1. Dans GlitchTip : créer les projets `lesstime-api` et `lesstime-front`, récupérer les 2 DSN
|
|
|
|
(+ un auth token pour les source maps).
|
|
|
|
(+ un auth token pour les source maps).
|
|
|
|
2. Backend : ajouter `SENTRY_DSN` dans `infra/prod/.env` du serveur.
|
|
|
|
2. Backend : ajouter `SENTRY_DSN` dans le `.env` du serveur (`/var/www/lesstime/.env`).
|
|
|
|
3. Frontend : ajouter les secrets Gitea ci-dessus.
|
|
|
|
3. Frontend : ajouter les secrets Gitea ci-dessus.
|
|
|
|
4. Tagger une version (`v*`) → la CI build l'image avec le DSN front baké → `deploy.sh`.
|
|
|
|
4. Tagger une version (`v*`) → la CI build l'image avec le DSN front baké → `deploy.sh`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Certificat HTTPS interne (CA auto-signée)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GlitchTip est servi en **HTTPS** sur `https://logs.malio-dev.fr` (nginx devant), avec un certificat
|
|
|
|
|
|
|
|
**auto-signé** par une **CA interne** (« MALIO-DEV Local Root CA », cert serveur `*.malio-dev.fr`).
|
|
|
|
|
|
|
|
`malio-dev.fr` est un **domaine interne uniquement** (DNS local, pas de résolution publique).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> **Pourquoi pas Let's Encrypt ?** Une CA publique doit valider le domaine via Internet (challenge
|
|
|
|
|
|
|
|
> HTTP ou DNS public). Comme `malio-dev.fr` n'existe qu'en interne, aucune validation n'est
|
|
|
|
|
|
|
|
> possible → on reste sur la CA interne, qu'il faut faire **approuver partout** où la connexion TLS
|
|
|
|
|
|
|
|
> est établie. Tant que la CA n'est pas approuvée, **rien ne remonte** : le backend logue
|
|
|
|
|
|
|
|
> « Message not sent » (SDK Sentry) et le navigateur affiche « connexion non sécurisée » (le front
|
|
|
|
|
|
|
|
> n'envoie rien).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Qui doit faire confiance à la CA ?** La connexion à `logs.malio-dev.fr` part de deux endroits
|
|
|
|
|
|
|
|
différents, donc deux fixes distincts :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Émetteur des erreurs | Qui établit le TLS | Où approuver la CA |
|
|
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
| Backend (Symfony) | le **container PHP** | CA bakée dans l'**image Docker** (ci-dessous) |
|
|
|
|
|
|
|
|
| Frontend (SPA) | le **navigateur du poste** | CA poussée sur les **postes via GPO** (ci-dessous) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Fix backend — CA bakée dans l'image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Le certificat **public** de la root CA est committé dans le repo (`infra/prod/malio-dev-root-ca.crt`,
|
|
|
|
|
|
|
|
aucune clé privée) et installé dans le trust store du container au build (`infra/prod/Dockerfile`,
|
|
|
|
|
|
|
|
stage production — `ca-certificates` est déjà installé) :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```dockerfile
|
|
|
|
|
|
|
|
COPY infra/prod/malio-dev-root-ca.crt /usr/local/share/ca-certificates/malio-dev-root-ca.crt
|
|
|
|
|
|
|
|
RUN update-ca-certificates
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Le container fait alors confiance à tout `*.malio-dev.fr` interne et le SDK Sentry backend peut
|
|
|
|
|
|
|
|
envoyer. Vérification :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
|
|
curl --cacert infra/prod/malio-dev-root-ca.crt https://logs.malio-dev.fr/api/1/store/ # → HTTP 200
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Fix postes — CA poussée par GPO (Active Directory)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Le front est une SPA : c'est le **navigateur de l'utilisateur** qui contacte `logs.malio-dev.fr`,
|
|
|
|
|
|
|
|
donc c'est le **poste** qui doit faire confiance à la CA (la CA de l'image ne sert qu'au backend).
|
|
|
|
|
|
|
|
Sur le domaine Active Directory, on pousse la CA **une seule fois via GPO** plutôt que poste par poste :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1. Contrôleur de domaine → **Group Policy Management** → éditer une GPO.
|
|
|
|
|
|
|
|
2. `Configuration ordinateur → Stratégies → Paramètres Windows → Paramètres de sécurité → Stratégies
|
|
|
|
|
|
|
|
de clé publique → Autorités de certification racines de confiance`.
|
|
|
|
|
|
|
|
3. Clic droit → **Importer** → sélectionner `rootCA.crt` (« MALIO-DEV Local Root CA »).
|
|
|
|
|
|
|
|
4. Sur les postes : `gpupdate /force` (ou attendre le rafraîchissement), puis **redémarrer le navigateur**.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Chrome / Edge utilisent le magasin Windows → confiance automatique.
|
|
|
|
|
|
|
|
- ⚠️ **Firefox** a son propre magasin : activer `security.enterprise_roots.enabled = true`
|
|
|
|
|
|
|
|
(`about:config` ou via policy) pour qu'il lise le magasin Windows.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> **Validation poste** : ouvrir `https://logs.malio-dev.fr` → cadenas vert sans avertissement = CA
|
|
|
|
|
|
|
|
> approuvée = le front peut envoyer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Renouvellement / changement de CA
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Si la CA interne change (rotation, expiration) :
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1. Remplacer `infra/prod/malio-dev-root-ca.crt` par le nouveau certificat public, commit + **rebuild
|
|
|
|
|
|
|
|
de l'image** (re-tag `v*`) pour le backend.
|
|
|
|
|
|
|
|
2. **Re-pousser** la nouvelle CA via GPO (étapes ci-dessus) pour les postes.
|
|
|
|
|
|
|
|
|
|
|
|
## Licence
|
|
|
|
## Licence
|
|
|
|
|
|
|
|
|
|
|
|
Propriétaire — Tous droits réservés.
|
|
|
|
Propriétaire — Tous droits réservés.
|
|
|
|