{"id":"32b08bb1-540e-43b0-bf40-dceb20934524","slug":"mindset-red","kind":"mcp","name":"Mindset-Red","summary":"Que du vrais","owner":"Redcreator1","repoUrl":"https://github.com/Redcreator1/Mindset-Red","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-07-07T03:29:09.000Z","addedAt":"2026-10-21T21:30:03.179Z","logoUrl":"https://avatars.githubusercontent.com/u/201516776?u=382d56898d13ae8a5472d82968643f7a604ba8e3&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":[],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T04:18:16.548Z","sample":false,"url":"https://conduits.dev/tools/mindset-red","language":"TypeScript","transports":["stdio"],"install":{"npm":"mindset-ctx"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Mindset-Red · `mindset-ctx`\n\n**Context-as-a-Service** pour projets open source & micro-SaaS.\n\nPour n'importe quel repo GitHub, `mindset-ctx` :\n\n- **génère et maintient automatiquement** le contexte dont les agents IA ont besoin :\n  `CLAUDE.md`, `AGENTS.md`, `docs/ARCHITECTURE.md`, `CONTRIBUTING.md` et des\n  templates de prompts (`.context/prompts.md`) ;\n- **expose une API et un CLI** pour que les outils IA (Claude Code, Cursor, …)\n  aient toujours le bon contexte, à jour ;\n- **ajoute un memory layer** : l'historique du repo (commits aujourd'hui,\n  PRs/issues/discussions demain) est indexé en JSONL et interrogeable, pour que\n  chaque agent réutilise les décisions passées au lieu de les re-découvrir.\n\n## Installation\n\n**Via npm** (recommandé) :\n\n```bash\nnpm install -g mindset-ctx   # ou : npx mindset-ctx <commande>\nctx generate .\n```\n\n**Depuis le repo** (pour contribuer ou suivre `main` de près) :\n\n```bash\ngit clone https://github.com/Redcreator1/Mindset-Red\ncd Mindset-Red\nnpm install\nnpm run build\nnode dist/cli.js generate .\n```\n\nNode ≥ 20. Une seule dépendance runtime : le SDK officiel `@anthropic-ai/sdk`\n(utilisé uniquement par le mode `--ai`, optionnel à l'exécution). Tous les\nexemples ci-dessous utilisent `node dist/cli.js` (installation depuis le\nrepo) — remplacez par `ctx` si vous avez installé via npm.\n\n## Utilisation\n\n```bash\n# Générer / rafraîchir tout le contexte d'un repo\nnode dist/cli.js generate [path]\n\n# Indexer l'historique git dans le memory layer (.context/memory.jsonl)\nnode dist/cli.js index [path] --limit 500\n\n# … et y ajouter les PRs, issues et discussions via l'API GitHub\n# (owner/repo déduit du remote origin, ou --repo owner/name ;\n#  GITHUB_TOKEN pour les repos privés / plus de rate limit)\nnode dist/cli.js index [path] --github\n\n# … ou via l'API GitLab (issues + merge requests ; GITLAB_TOKEN pour privé)\nnode dist/cli.js index [path] --gitlab\n\n# … ou via l'API Bitbucket Cloud (pull requests + issues ; BITBUCKET_TOKEN pour privé)\nnode dist/cli.js index [path] --bitbucket\n\n# … et calculer les embeddings pour la recherche sémantique\n# (Voyage AI, le partenaire embeddings d'Anthropic ; VOYAGE_API_KEY requis)\nnode dist/cli.js index [path] --embed\n\n# Chercher dans la mémoire depuis le terminal\n# (BM25 par défaut, --semantic pour les embeddings, --hybrid pour la fusion RRF)\nnode dist/cli.js search \"payment retry\" --repo-path [path] --hybrid\n\n# Servir un ou plusieurs repos en HTTP pour les outils IA\nnode dist/cli.js serve [path ...] --port 4870 --api-key SECRET\n\n# Mode hébergé multi-tenants : clés par client, scopes par repo, quotas\nnode dist/cli.js serve repoA repoB --tenants ctx.tenants.json\n\n# Webhooks GitHub temps réel : à chaque push/PR/issue, la mémoire est\n# ré-indexée et le contexte régénéré (signature HMAC vérifiée)\nnode dist/cli.js serve [path] --webhook-secret SECRET\n\n# GitHub App : imprime le manifest pour une création en un clic\nnode dist/cli.js app manifest --base-url https://mon-hote.example.com\n\n# Encaisser : génère une clé tenant + un lien de paiement Stripe\nCTX_STRIPE_API_KEY=sk_live_... STRIPE_PRICE_MAP='{\"price_123\":\"pro\"}' \\\n  node dist/cli.js checkout --plan pro\n\n# Facturation Stripe : les webhooks d'abonnement font basculer le plan\n# d'un tenant (free/pro/team/enterprise → quotas), persisté sur disque\nSTRIPE_PRICE_MAP='{\"price_123\":\"pro\"}' \\\n  node dist/cli.js serve [path] --tenants ctx.tenants.json --stripe-secret whsec_...\n\n# Génération enrichie par Claude : une synthèse narrative du projet est\n# rédigée par Claude Opus 4.8 (thinking adaptatif) et injectée dans\n# CLAUDE.md et docs/ARCHITECTURE.md (nécessite ANTHROPIC_API_KEY)\nnode dist/cli.js generate [path] --ai\n\n# Voir l'analyse brute du repo (JSON)\nnode dist/cli.js analyze [path]\n\n# Serveur MCP (Model Context Protocol) en stdio : Claude Code / Cursor\n# consomment le contexte et la mémoire comme des outils natifs\nnode dist/cli.js mcp [path]\n```\n\n### MCP (Model Context Protocol)\n\n`ctx mcp` expose trois outils via le standard MCP :\n\n| Outil | Description |\n| --- | --- |\n| `get_context` | Lit un fichier de contexte (`claude`, `agents`, `architecture`, `contributing`, `prompts`) |\n| `search_memory` | Recherche BM25 dans le memory layer (commits, PRs, issues) |\n| `analyze_repo` | Analyse structurée fraîche du repo |\n\nEnregistrement dans Claude Code :\n\n```bash\nclaude mcp add mindset-ctx -- node /chemin/vers/dist/cli.js mcp /chemin/vers/repo\n```\n\nEnregistrement dans **Cursor** — Cursor parle MCP nativement, aucun code\nsupplémentaire n'est nécessaire côté mindset-ctx. Ajoutez dans\n`.cursor/mcp.json` (à la racine du projet, ou dans les réglages MCP globaux\nde Cursor) :\n\n```json\n{\n  \"mcpServers\": {\n    \"mindset-ctx\": {\n      \"command\": \"node\",\n      \"args\": [\"/chemin/vers/dist/cli.js\", \"mcp\", \"/chemin/vers/repo\"]\n    }\n  }\n}\n```\n\nRechargez la fenêtre (ou redémarrez Cursor) — le serveur apparaît dans\n*Settings → MCP*, et `get_context`/`search_memory`/`analyze_repo` deviennent\ndes outils que l'agent Cursor peut appeler directement pendant une session de\nvibe coding. (Le nom exact du fichier de config peut évoluer selon la version\nde Cursor — vérifiez leur doc officielle MCP si l'emplacement a changé.)\n\n**Extension VS Code** (`editors/vscode/`, publiée sur le VS Code Marketplace\nsous `mindset-ctx.mindset-ctx`) : palette de commandes (\"mindset-ctx: Generate Context Files\", \"… Index\nMemory\", \"… Copy MCP Server Command\", \"… Open Hosted Dashboard\") + indicateur\ndans la barre de statut (`CLAUDE.md` présent ou non). Se teste en local via\n`F5` (Extension Development Host) ou en `.vsix` — voir\n`editors/vscode/README.md` pour le détail, y compris la limite honnête :\nla logique pure (construction de commande MCP, texte de statut) est testée\npar `node:test`, mais le code qui appelle l'API `vscode` elle-même ne l'est\npas — `@vscode/test-electron` a besoin de télécharger un vrai binaire VS Code\net d'un serveur d'affichage, indisponibles dans ce sandbox.\n\n### API\n\n| Route | Description |\n| --- | --- |\n| `GET /v1/health` | Liveness (jamais protégée) |\n| `GET /v1/repos` | Repos enregistrés (filtrés par le scope du tenant) |\n| `GET /v1/usage` | Consommation du tenant appelant (mode `--tenants`) |\n| `GET /v1/repos/:repo/analysis` | Analyse structurée du repo (JSON) |\n| `GET /v1/repos/:repo/context/claude` | `CLAUDE.md` (aussi : `agents`, `architecture`, `contributing`, `prompts`) |\n| `GET /v1/dashboard` · `/v1/dashboard/data` | Dashboard web (HTML/JSON) : repos, tenants, plans, quotas, mémoire — scopé par tenant |\n| `GET /v1/repos/:repo/memory/search?q=…&mode=…` | Recherche **BM25** (défaut), **sémantique** (`mode=semantic`) ou **hybride** (`mode=hybrid`, fusion RRF) |\n| `POST /v1/repos/:repo/webhook` | Webhook GitHub **ou** GitLab (push/issues/PR) : signature `X-Hub-Signature-256` ou token `X-Gitlab-Token` vérifié selon le fournisseur détecté, mémoire ré-indexée, contexte régénéré sur push |\n| `GET /v1/app/manifest` | Manifest GitHub App (création en un clic) |\n| `POST /v1/app/webhook` | Événements d'installation de l'App (HMAC vérifiée) : provisionne/déprovisionne un tenant automatiquement |\n| `GET /v1/app/installed?installation_id=…` | Redirection post-install : remet la clé API du tenant auto-provisionné (une seule fois) |\n| `GET /v1/checkout?plan=pro` | Crée un lien de paiement Stripe pour le tenant appelant (porte d'entrée paiement) — refusé (403) à un membre d'équipe non-owner |\n| `GET /v1/billing/portal` | Ouvre une session **Stripe Customer Portal** (annuler, changer de carte, voir les factures — self-service, hébergé par Stripe) pour le tenant appelant — refusé (403) à un membre non-owner, 400 si aucun abonnement Stripe n'existe encore |\n| `POST /v1/stripe/webhook` | Événements d'abonnement Stripe (signature vérifiée) → change le plan du tenant (et retient son `customer` Stripe pour `/v1/billing/portal`), ou de son **organisation** si c'est un siège d'équipe |\n| `GET /v1/team/invite?name=…` | L'owner invite un coéquipier — clé mintée, quota et plan partagés (organisation), montrée une seule fois |\n| `GET /v1/team/remove?key=…` | L'owner retire un coéquipier de l'organisation (pas soi-même) |\n| `GET /v1/sso/login?org=…` | Redirige vers la connexion hébergée WorkOS AuthKit (SSO Entreprise) |\n| `GET /v1/sso/callback` | Échange le code WorkOS contre l'identité, provisionne organisation/tenant, pose un cookie de session signé |\n| `GET /v1/sso/logout` | Efface le cookie de session |\n\nAvec un seul repo servi, les raccourcis sans préfixe (`/v1/analysis`,\n`/v1/context/claude`, `/v1/memory/search`) restent disponibles.\n\n**Auth** : `--api-key` (ou env `CTX_API_KEY`) exige\n`Authorization: Bearer <clé>` ou `x-api-key: <clé>` sur toutes les routes sauf\n`/v1/health` (le webhook, lui, est authentifié par sa signature HMAC).\n\n**Multi-tenants** (`--tenants ctx.tenants.json`) :\n\n```json\n{ \"tenants\": [\n    { \"key\": \"sk-alice\", \"name\": \"alice\", \"repos\": [\"frontend\"], \"plan\": \"pro\" },\n    { \"key\": \"sk-ops\", \"name\": \"ops\", \"repos\": \"*\", \"plan\": \"enterprise\", \"admin\": true }\n] }\n```\n\nChaque clé est scopée à ses repos (403 hors scope), le **plan** décide du quota\njournalier (`free` 200 · `pro` 5 000 · `team` 50 000 · `enterprise` illimité —\n429 au-delà), et `/v1/usage` expose le métering. Les webhooks Stripe font\nbasculer le plan automatiquement et le changement est persisté dans le fichier.\n`admin: true` doit être posé à la main (jamais déduit du scope `\"*\"`, que des\ncomptes clients légitimes utilisent aussi) — c'est ce qui donne la vue\ndashboard de toute la plateforme.\n\n**Organisations (Team multi-sièges)** — le plan Team est multi-utilisateurs\npar nature : le signup self-service (`/v1/signup?plan=team`) crée\nautomatiquement une organisation et met le premier compte en `role: \"owner\"`.\nFacturation et quota vivent sur l'organisation, pas sur chaque tenant :\n\n```json\n{ \"tenants\": [\n    { \"key\": \"sk-owner\", \"name\": \"owner\", \"repos\": \"*\", \"orgId\": \"org-1\", \"role\": \"owner\" },\n    { \"key\": \"sk-bob\",   \"name\": \"bob\",   \"repos\": \"*\", \"orgId\": \"org-1\", \"role\": \"member\" }\n  ],\n  \"organizations\": [\n    { \"id\": \"org-1\", \"name\": \"acme\", \"repos\": \"*\", \"plan\": \"team\" }\n] }\n```\n\n- Seul `role: \"owner\"` peut appeler `/v1/checkout` (changer le plan) ou\n  `/v1/team/invite` / `/v1/team/remove` (gérer les coéquipiers) — un `member`\n  reçoit 403.\n- `/v1/usage` et le quota journalier sont **partagés** entre tous les sièges\n  d'une organisation (un pool commun, pas un quota par personne).\n- Le dashboard d'un owner montre le roster de son organisation ; un `admin`\n  explicite voit toute la plateforme ; tout le monde d'autre ne voit que soi.\n\n**SSO (WorkOS AuthKit)** — alternative à la clé API partagée pour les équipes\nEntreprise : un employé se connecte via `GET /v1/sso/login` (redirige vers la\nconnexion hébergée WorkOS — email/mot de passe, Google, ou la connexion SSO\nde son entreprise si configurée côté WorkOS), puis `/v1/sso/callback` :\n\n- Premier employé d'une entreprise (identifiée par l'`organization_id` WorkOS)\n  à se connecter → une organisation mindset-ctx est créée automatiquement et\n  cette personne devient `role: \"owner\"`.\n- Employés suivants de la **même** entreprise → rejoignent la même\n  organisation en `role: \"member\"`, quota partagé, pas de doublon.\n- Un cookie de session signé (`ctx_session`, HttpOnly, 7 jours) authentifie\n  ensuite le dashboard exactement comme une clé `Authorization: Bearer`\n  l'aurait fait — pas de nouveau store de session, la signature (HMAC avec la\n  clé API WorkOS) suffit à le vérifier à la volée.\n- Connexion personnelle sans entreprise WorkOS derrière → simple tenant solo,\n  plan `free`, comme n'importe quel autre onboarding.\n\nConfiguration : créer une App sur [workos.com](https://workos.com) (gratuit\npour démarrer), déclarer `https://<votre-domaine>/v1/sso/callback` comme\nredirect URI, puis exposer `WORKOS_CLIENT_ID` et `WORKOS_API_KEY` (`sk_test_…`\nen bac à sable, `sk_live_…` en prod) — `--workos-client-id`/`--workos-api-key`\nen self-hosted, secrets Cloudflare en hébergé (voir la section déploiement).\n\n### Édition manuelle préservée\n\nChaque fichier généré contient un marqueur `ctx:manual`. Tout ce que vous\nécrivez **en dessous** est conservé lors des régénérations — le haut du fichier\nreste toujours synchronisé avec la réalité du code.\n\n## Repos privés — comment les devs l'utilisent\n\n**Le mode self-hosted est fait pour les repos privés** : l'outil lit le clone\nlocal (le tien), donc **ton code privé ne quitte jamais ta machine** — c'est un\nargument de confidentialité, pas une limite.\n\n```bash\n# 1. Dans ton repo privé déjà cloné\nnode /chemin/dist/cli.js generate .     # génère le contexte\nnode /chemin/dist/cli.js index .        # indexe la mémoire\n\n# 2. Branche-le dans Claude Code / Cursor via MCP (local, rien ne sort)\nclaude mcp add mindset-ctx -- node /chemin/dist/cli.js mcp /chemin/repo/prive\n```\n\nPour la mémoire des PRs/issues d'un repo privé, `ctx index --github` utilise ton\n`GITHUB_TOKEN` personnel (scope `repo`) ; `ctx index --gitlab` fait pareil côté\nGitLab avec `GITLAB_TOKEN`. Le webhook temps réel (`POST /v1/repos/:repo/webhook`)\ndétecte lui-même le fournisseur : signature `X-Hub-Signature-256` pour GitHub,\ntoken partagé `X-Gitlab-Token` pour GitLab — même endpoint, même secret configuré\ncôté `--webhook-secret` / `CTX_WEBHOOK_SECRET`.\n\nEn **mode hébergé**, installer la GitHub App (`ctx app manifest`) provisionne\nautomatiquement un tenant scopé aux repos accordés — pas besoin de compte\npréalable, symétrique du signup Stripe. La clé est remise sur la page de\nredirection `/v1/app/installed?installation_id=…` juste après l'install.\nPour lire le contenu d'un repo privé ainsi accordé, mint un token\nd'installation à la demande :\n\n```bash\nexport GITHUB_APP_ID=123456\nexport GITHUB_APP_PRIVATE_KEY=\"$(cat mindset-ctx.private-key.pem)\"\nnode dist/cli.js app token <installation-id>   # token 1h, scope = repos accordés\n```\n\nLe token imprimé s'utilise comme n'importe quel token GitHub pour cloner\n(`git clone https://x-access-token:<token>@github.com/owner/repo.git`) ou\nappeler l'API REST.\n\n## Développement\n\n```bash\nnpm test   # build + tests (node:test)\n```\n\nCe repo est **dogfoodé** : ses propres `CLAUDE.md`, `AGENTS.md` et\n`docs/ARCHITECTURE.md` sont générés par l'outil lui-même.\n\n## Roadmap\n\n- [x] v0.1 — analyse de repo, génération des 5 fichiers de contexte, memory layer (commits), API HTTP, CLI\n- [x] v0.2 — ingestion GitHub API (PRs, issues, discussions) dans le memory layer\n- [x] v0.2 — recherche classée par pertinence (BM25) derrière la même API\n- [x] v0.2 — GitHub Actions : CI (Node 20/22) + régénération auto du contexte à chaque push sur `main`\n- [x] v0.2 — serveur multi-repos + auth par clé API (graine du mode hébergé)\n- [x] v0.3 — serveur **MCP** (Model Context Protocol) en stdio : le contexte devient des outils natifs pour Claude Code / Cursor\n- [x] v0.3 — génération enrichie par l'**API Claude** (`generate --ai`, SDK officiel, Opus 4.8 + thinking adaptatif)\n- [x] v0.4 — recherche **sémantique par embeddings** (Voyage AI, `index --embed` + `mode=semantic`, pluggable à côté de BM25)\n- [x] v0.4 — **webhooks GitHub temps réel** : HMAC vérifiée, mémoire ré-indexée et contexte régénéré à chaque push\n- [x] v0.4 — **multi-tenants** : clés par client, scopes par repo, quotas journaliers, métering `/v1/usage`\n- [x] v0.5 — **GitHub App packagée** : manifest servi (`/v1/app/manifest`, création un clic) + webhook d'installation (`/v1/app/webhook`, HMAC vérifiée, cycle de vie classifié)\n- [x] v0.5 — **facturation Stripe** : `POST /v1/stripe/webhook` (signature vérifiée sans SDK) fait basculer le plan d'un tenant ; plans → quotas, store de tenants persistant\n- [x] v0.6 — **recherche hybride** BM25 + embeddings fusionnés par Reciprocal Rank Fusion (`mode=hybrid`, `ctx search --hybrid`)\n- [x] v0.6 — **dashboard web** auto-porté (`/v1/dashboard`) : repos, tenants, plans, quotas et mémoire, scopé par tenant\n- [x] v0.7 — **checkout Stripe** : `ctx checkout` / `GET /v1/checkout` créent un lien de paiement (clé tenant estampée dans les métadonnées) — la porte d'entrée « premier euro »\n- [x] v0.8 — **page pricing publique** (`/pricing`), **signup self-service** (`/v1/signup?plan=…`) et **`ctx stripe bootstrap`** auto-créent les produits/prix dans Stripe.\n- [x] v0.9 — **hébergé sur Cloudflare Workers** (`src/worker/`, `wrangler.toml`) : gratuit (100k req/j), edge, sans carte bancaire, état multi-tenant dans KV. `.github/workflows/deploy-cloudflare.yml` déploie sur chaque push vers `main`.\n- [x] v0.9 — **`ctx stripe webhook <url>`** crée (ou réutilise, idempotent) le webhook Stripe par API — plus besoin d'accéder au Dashboard Stripe à la main.\n- [x] v0.10 — **provisioning automatique par install GitHub App** (`/v1/app/webhook` crée/retire le tenant, `/v1/app/installed` remet la clé) + **`ctx app token <installation-id>`** mint un token d'installation (JWT App signé RS256 → échange) pour lire les repos privés accordés.\n- [x] v0.11 — **support GitLab** : `ctx index --gitlab` (issues + merge requests via l'API v4) et webhook temps réel (`X-Gitlab-Token`, détection automatique du fournisseur sur le même endpoint que GitHub)\n- [x] v0.12 — **support Bitbucket** : `ctx index --bitbucket` (pull requests + issues via l'API Cloud v2.0) — ingestion mémoire uniquement ; le webhook temps réel Bitbucket attend une vérification de son mécanisme de sécurité réel avant d'être câblé (Bitbucket n'a pas d'équivalent direct au HMAC GitHub / token GitLab)\n- [x] v0.12 — **déploiement dédié Enterprise** : `Dockerfile` + `docs/DEPLOYMENT.md` (Docker Compose, fichier de tenants monté en volume, variables d'env documentées) — ce que `/pricing` promettait sans l'avoir construit\n- [x] v0.12 — **doc Cursor** : `ctx mcp` fonctionnait déjà avec Cursor (MCP natif) mais n'était pas documenté — `.cursor/mcp.json` ajouté au README\n- [x] v0.13 — **vitrine du domaine racine** (`/`, `src/home.ts`) séparée de `/pricing`, **doc index** (`/docs`) qui pointe vers le README/docs plutôt que de le dupliquer ; runbook de branchement du domaine (`docs/DOMAIN-SETUP.md`) — au moment de l'achat de `mindset-ctx.dev`, ce n'est plus qu'une opération DNS\n- [x] v0.14 — **Teams multi-sièges** : signup Team crée une organisation (facturation + quota partagés, pas par siège) avec le premier compte en `role: \"owner\"` ; `/v1/team/invite` et `/v1/team/remove` gèrent le roster ; `/v1/checkout` refusé aux non-owners ; dashboard scopé (owner → son équipe, admin → toute la plateforme). C'est le prérequis RBAC identifié en v0.13 — désormais construit, sur Node **et** Cloudflare Workers.\n- [x] v0.15 — **parité GitHub App sur le Worker Cloudflare réellement déployé** : `/v1/app/manifest`, `/v1/app/webhook` (HMAC vérifiée via Web Crypto) et `/v1/app/installed` n'existaient que sur `server.ts` (self-hosted) depuis la v0.10, malgré ce que le changelog laissait entendre — le Worker en prod n'avait jamais le provisioning auto par install. Corrigé : les trois routes tournent maintenant sur KV (`store.findByInstallationId`), `CTX_WEBHOOK_SECRET` poussé par `.github/workflows/deploy-cloudflare.yml`.\n- [x] v0.16 — **SSO Entreprise via WorkOS AuthKit** : `/v1/sso/login` (redirige vers la connexion hébergée), `/v1/sso/callback` (échange le code, auto-provisionne organisation + tenant à partir de l'`organization_id`/`user.id` WorkOS, pose un cookie de session signé), `/v1/sso/logout`. Premier employé d'une entreprise → owner, suivants → members poolés, symétrique du signup Stripe et de l'install GitHub App. Le cookie de session est vérifié par HMAC (signé avec la clé API WorkOS) sans store de session dédié — cohérent avec l'architecture stateless existante. Parité Node **et** Cloudflare Workers dès le départ.\n- [x] v0.17 — **extension VS Code** (`editors/vscode/`) : commandes de palette pour générer le contexte/indexer la mémoire, copier la commande MCP, ouvrir le dashboard hébergé ; indicateur de statut (`CLAUDE.md` présent ou non). Package séparé (son propre `package.json`/`tsconfig.json`, manifeste VS Code différent du reste du projet). **Publiée sur le VS Code Marketplace** (`mindset-ctx.mindset-ctx`, logo inclus depuis la v0.1.1) juste après. 6 tests sur la logique pure ; la partie qui appelle l'API `vscode` se vérifie manuellement via `F5`, pas par une suite automatisée (`@vscode/test-electron` a besoin d'un vrai binaire VS Code + d'un display, indisponibles dans ce sandbox).\n- [x] v0.18 — **publication npm** (`npm install -g mindset-ctx` / `npx mindset-ctx`) : le CLI ne s'installait jusque-là que par clone GitHub — limite découverte en construisant l'extension VS Code (pas de `npx` par défaut possible). `.github/workflows/npm-publish.yml` publie automatiquement à chaque push sur `main` où la version a changé (idempotent — ne republie pas une version déjà en ligne). `LICENSE` (MIT) ajoutée — déclarée dans `package.json` depuis le début mais jamais présente en tant que fichier. `files`/`types`/`prepublishOnly` ajoutés pour un paquet propre (juste `dist/` + README + LICENSE, tests exclus).\n- [x] v0.19 — **durcissement sécurité** après une revue complète du code : cookie de session passé en `SameSite=Strict` (le `Lax` initial laissait une fenêtre CSRF sur les routes GET mutantes `/v1/team/*` et `/v1/checkout` depuis l'arrivée de l'auth par cookie) ; paramètre `state` OAuth ajouté au flux SSO WorkOS (nonce en cookie, vérifié au callback en temps constant — bloque le login-CSRF) ; extension VS Code 0.1.2 : `execFile` sans shell à la place d'`exec` et réglages passés en `scope: \"machine\"` (un repo malveillant ne peut plus planter une commande via `.vscode/settings.json`), défaut `npx mindset-ctx` maintenant que le paquet est sur npm.\n- [x] v0.20 — **blog natif** (`GET /blog`, `/blog/:slug`) plutôt qu'un embed X/Twitter tiers sur le site : zéro script externe, zéro tracking tiers, visuels de couverture en SVG inline (pas d'image à héberger séparément) dans la même palette que le reste du site. Premier article : présentation de mindset-ctx. Parité Node + Worker.\n- [x] v0.21 — **balises Open Graph / Twitter Card** sur `/`, `/docs`, `/pricing`, `/blog` et `/blog/:slug` : un lien partagé sur X/Slack/Discord affiche maintenant un vrai aperçu (titre, description, image) au lieu d'une URL nue. Image de prévisualisation (1200×630) servie par `GET /og-image.png`, encodée en base64 dans `src/og-image.ts` plutôt qu'hébergée comme fichier séparé — fonctionne à l'identique sur le serveur Node et sur le Worker Cloudflare (qui n'a pas de système de fichiers), sans dépendance tierce. `og:image`/`og:url` ne sont émis que si un `baseUrl` est configuré (sinon on n'imprime pas une URL relative cassée, invalide pour Open Graph).\n- [x] v0.22 — **favicon** (`/favicon.svg`, même logo que partout ailleurs, redirection depuis `/favicon.ico`), **page 404 stylée** (`/v1/*` garde du JSON pour les clients API, tout le reste voit une vraie page) et **robots.txt/sitemap.xml** pour l'indexation. Bug réel trouvé et corrigé en construisant la 404 : sur les deux runtimes, une route inconnue tombait dans la porte d'authentification *avant* d'atteindre le routage — un visiteur non-authentifié sur une URL mal tapée recevait \"401 unauthorized\" au lieu de \"404 not found\" dès que l'auth tenant était configurée (le cas permanent du Worker hébergé). Corrigé en sortant la 404 du chemin non-`/v1/*` avant la porte d'auth, sur `server.ts` et `worker/index.ts`.\n- [x] v0.23 — **Rank v0** (`src/rank.ts`) : première brique de la Phase 4 (\"Moat technique\"). Pas un modèle entraîné — un reranker linéaire explicable au-dessus de la fusion RRF existante (`hybridSearch`), avec des poids réglés à la main (accord des deux moteurs de recherche, correspondance du titre avec la requête, décroissance de fraîcheur). Honnête sur la portée : entraîner un vrai modèle demande un jeu de données de pertinence réel (clics/retours d'usage) et du budget de calcul — ni l'un ni l'autre n'existe encore. Ce qui est livré ici est la partie réelle et testée faisable aujourd'hui : l'interface de scoring, et un reranker qui améliore mesurablement le RRF seul. Les poids sont explicitement la pièce prévue pour être remplacée plus tard par des poids appris. Branché directement dans `hybridSearch` — `ctx search --hybrid` et `mode=hybrid` en profitent automatiquement, aucun nouveau paramètre d'API.\n- [x] v0.24 — **Rank ML** (`src/rank-ml.ts`, `notebooks/train_rank_ml.py`) : succède à Rank v0 avec un vrai cross-encoder pré-entraîné (`cross-encoder/ms-marco-MiniLM-L-6-v2`), fine-tunable sur un T4 gratuit via Colab (notebook fourni) sur des paires faiblement labellisées tirées de l'historique du repo. **Node uniquement, décision assumée** : notre prod (Cloudflare Workers) n'a ni GPU ni moyen d'exécuter de l'inférence neuronale sans passer par un service payant (Workers AI ou un hébergement externe) — le Worker garde donc Rank v0 pour l'instant, écart de parité documenté plutôt que masqué. Chargement 100% local (`CTX_RANK_ML_MODEL_DIR`, `@huggingface/transformers` en `optionalDependencies`) : aucun appel réseau au runtime, jamais de HuggingFace au moment de la requête. Repli automatique et silencieux vers Rank v0 si le dossier de modèle est absent ou le chargement échoue — jamais de crash. Honnête sur les limites de vérification : la logique de blend/scoring (`mlRerank`) est testée (6 tests, reranker simulé) ; le câblage réel du pipeline `@huggingface/transformers` n'a pas pu être exécuté de bout en bout dans l'environnement où c'est écrit (huggingface.co et les binaires natifs de `sharp`/`onnxruntime` y sont bloqués par le proxy — confirmé par `curl`, même catégorie de blocage que JetBrains) — à vérifier après avoir fait tourner le notebook. Corrigé en route : le notebook utilisait initialement `@xenova/transformers` (nom historique du projet) et son ancien script `scripts/convert.py`, qui n'existe plus — le projet a déménagé vers `@huggingface/transformers` et l'export ONNX standard `optimum-onnx`, découvert en faisant réellement tourner le notebook et en lisant le vrai README du projet. Bénéfice inattendu du changement de paquet : la vulnérabilité critique `protobufjs` (transitive via `onnxruntime-web`) qu'`@xenova/transformers` traînait a disparu avec `@huggingface/transformers` — `npm audit` est repassé à 0 vulnérabilité.\n- [x] v0.25 — **`llms.txt`** (`GET /llms.txt`, convention llmstxt.org) : carte Markdown du site (résumé, dépôt GitHub, docs, tarifs, legal, blog) pour les agents/crawlers IA qui le lisent avant de crawler le HTML — préparation au référencement dans les annuaires MCP (awesome-mcp-servers, registre officiel MCP, Smithery, mcp.so, glama.ai). Mots-clés `mcp`/`model-context-protocol`/`mcp-server`/`cli` ajoutés à `package.json` pour la recherche npm. Mention obsolète corrigée dans le README (l'extension VS Code disait \"mindset-ctx pas encore sur npm\" — faux depuis la v0.18). Parité Node + Worker. 2 nouveaux tests — 144/144.\n- [x] v0.26 — **Stripe Customer Portal** (`GET /v1/billing/portal`) : un client (ou l'owner d'une équipe) peut annuler son abonnement, changer de carte ou voir ses factures lui-même, sur une page hébergée par Stripe — jusque-là seul l'opérateur pouvait le faire, à la main, dans le Dashboard Stripe. `Tenant`/`Organization` gagnent `stripeCustomerId`, rempli automatiquement par le webhook `/v1/stripe/webhook` (déjà en place, juste étendu). Même garde d'autorisation que `/v1/checkout` (`tenantCanManageBilling` — refusé à un membre d'équipe non-owner) et jamais accessible via le fallback `?key=` du dashboard : une session portal, une fois son lien en main, permet d'annuler un abonnement sans authentification supplémentaire côté Stripe — aussi sensible qu'un lien de paiement. Nécessite une seule configuration manuelle côté Stripe Dashboard (Settings → Billing → Customer portal) — aucune API ne permet de la créer à la place de l'opérateur. Parité Node + Worker. 8 nouveaux tests — 153/153.\n- [x] v0.27 — **page `/security` publique** : rend visible et vérifiable la posture de sécurité au lieu de la laisser enfouie dans les commits — open source/MIT, 150+ tests en CI sur chaque push (Node 20/22), `npm audit` à 0, principe « le code ne quitte jamais votre machine », contrôles techniques (signatures webhooks constant-time, cookies `SameSite=Strict`, porte de paiement), méthode d'audit en deux passes (lien vers l'article). Discipline anti-survente verrouillée par un test : la page **liste ce qu'elle ne prétend pas** (pas de SOC 2, pas de pentest tiers, pas de bug bounty) — un futur commit ne peut pas silencieusement sur-vendre une certification absente. Ajoutée au sitemap, à `llms.txt` et au pied de page. Parité Node + Worker. 3 nouveaux tests — 155/155.\n- [x] v0.30 — **thème clair sur tout le site** : navbar sombre + corps clair + titre géant audacieux, aligné à gauche (structure inspirée d'un design courant type NVIDIA Developer, mais avec l'accent bleu de mindset-ctx, pas une couleur de marque tierce). Appliqué de façon cohérente sur toutes les pages (accueil, docs, tarifs, blog, sécurité, legal, support, dashboard) — pas juste la page d'accueil, pour éviter un flash de thème sombre en naviguant. Les blocs de code (`pre`) restent volontairement sombres pour le contraste (même motif que GitHub/Stripe). Aucun changement de logique, uniquement CSS/couleurs — vérifié visuellement page par page avant livraison. 155/155.\n- [x] v0.31 — **refonte du footer** : bandeau sombre en colonnes (Produit / Ressources / Légal) + barre de copyright, sur le modèle structurel d'un footer SaaS courant (ex. NVIDIA Developer) mais avec uniquement des liens réels du site — pas d'icônes de réseaux sociaux ni de formulaire newsletter pour des canaux qui n'existent pas encore. Appliqué à `home.ts` (partagé par accueil/docs/sécurité/blog/legal/support), `pricing.ts` et `dashboard.ts`. CSS uniquement, aucun changement de logique. 155/155.\n- [x] v0.32 — **refonte de `/docs`** : bandeau titre \"Centre de documentation\" en grand gras (même langage typographique que la home), barre de recherche client-side (filtre les cartes par texte, sans backend) et onglets \"Parcourir par catégorie\" en ancres réelles vers chaque section — structure inspirée d'un centre de doc SaaS courant (ex. NVIDIA Developer), sans bannière sombre ni image de marque tierce, cohérent avec le thème clair du site. Grille de cartes de doc inchangée en dessous. CSS + un peu de JS vanilla, aucune route serveur ajoutée. 155/155.\n- [ ] Extension JetBrains (stack différente : Kotlin/Gradle plutôt que TypeScript — mérite sa propre session) ; intégrations Slack/Linear/Notion ; programme de referral — voir `docs/VISION.md` (bloqués sur un tooling différent, ou des identifiants que seul le fondateur peut créer)\n\n## Déploiement en production (0 → premier euro)\n\nLe mode hébergé tourne sur **Cloudflare Workers** (gratuit, sans carte bancaire,\n100 000 requêtes/jour). Runbook zéro-configuration :\n\n```bash\n# 1. Créer les produits/prix Stripe (idempotent)\nexport CTX_STRIPE_API_KEY=sk_live_...\nnode dist/cli.js stripe bootstrap    # → imprime STRIPE_PRICE_MAP='{...}'\n\n# 2. Déployer sur Cloudflare Workers (wrangler.toml livré, KV créé une fois)\nnpx wrangler kv namespace create CTX_KV     # une seule fois ; colle l'id dans wrangler.toml\nnpx wrangler secret put CTX_STRIPE_API_KEY\nnpx wrangler secret put STRIPE_PRICE_MAP\nnpx wrangler deploy\n\n# 3. Créer le webhook Stripe SANS toucher au Dashboard (idempotent, réutilise\n#    l'endpoint s'il existe déjà) :\nnode dist/cli.js stripe webhook https://<ton-worker>.workers.dev/v1/stripe/webhook\n#    → imprime CTX_STRIPE_SECRET='whsec_...' à coller :\nnpx wrangler secret put CTX_STRIPE_SECRET\nnpx wrangler deploy\n\n# 4. (une seule fois, à la main) Activer le Customer Portal pour que\n#    GET /v1/billing/portal fonctionne : Dashboard Stripe → Settings →\n#    Billing → Customer portal → Activate. Sans ça, Stripe refuse de créer\n#    une session portal (erreur claire, pas un plantage) — aucune API ne\n#    permet de configurer ça à la place du Dashboard.\n\n# 5. (optionnel) GitHub App — provisioning automatique par install, même sur\n#    le Worker déployé (pas seulement en self-hosted) :\nnpx wrangler secret put CTX_WEBHOOK_SECRET   # même secret que celui déclaré dans l'App GitHub\nnpx wrangler deploy\n#    Crée l'App depuis le manifest : POST https://<ton-worker>.workers.dev/v1/app/manifest\n#    vers https://github.com/settings/apps/new\n\n# 6. (optionnel) SSO Entreprise via WorkOS — créer une App sur workos.com,\n#    déclarer https://<ton-worker>.workers.dev/v1/sso/callback comme redirect URI :\nnpx wrangler secret put WORKOS_CLIENT_ID\nnpx wrangler secret put WORKOS_API_KEY\nnpx wrangler deploy\n\n# 7. C'est tout. /pricing est publique, /v1/signup prend l'argent, la clé\n#    API est activée automatiquement par le webhook (Stripe, GitHub App ou SSO).\n#    Zéro humain dans la boucle.\n```\n\n**Via GitHub Actions (recommandé, zéro terminal)** : configure les secrets\n`CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`, `CTX_STRIPE_API_KEY`,\n`STRIPE_PRICE_MAP` sur le repo, lance le workflow **Deploy to Cloudflare\nWorkers**, puis le workflow **Stripe — bootstrap webhook** (crée le webhook\nvia l'API Stripe avec la clé déjà configurée — aucun accès au Dashboard\nrequis) et colle le `CTX_STRIPE_SECRET` imprimé dans les secrets GitHub avant\nde relancer le déploiement.\n\n> **Repo privé, code sensible ?** Aucun code source ne quitte jamais votre\n> machine : `ctx generate` / `index` / `serve` — l'analyse du repo, la\n> génération de contexte, la recherche mémoire et MCP — tournent toujours en\n> local, sur tous les plans, gratuits comme payants. Le mode hébergé (Worker)\n> ne fait que la facturation, le compte client et le tableau de bord de\n> quota ; il n'a aucune route pour analyser un repo ou servir du contexte\n> (Cloudflare Workers ne peut ni cloner ni lire un dépôt git).\n"}