brainclaw 1.23.0 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,80 @@
1
+ # Idéation — repenser l'appairage de la fédération v2 (dec#158)
2
+
3
+ **Direction opérateur (2026-08-09) :** un compte cloud doit gérer le solo-dev **et** l'équipe
4
+ sans deux modèles distincts. L'admin du compte invite des utilisateurs **humains** par leur
5
+ email ; chaque humain appaire ensuite **ses propres** agents.
6
+
7
+ ## État mesuré aujourd'hui — vérifié sur le code, ne pas re-supposer
8
+
9
+ - `handleAddProjectMember` (`src/handlers/projects.ts`) cherche l'utilisateur **par email**
10
+ mais exige qu'il **existe déjà** : sinon `404 No user found with email`. Aucun flux
11
+ d'invitation — la personne doit s'inscrire d'abord, puis être ajoutée.
12
+ - **Aucun envoi d'email** dans tout le backend.
13
+ - `enrollments` porte `invited_by_user_id` (qui a invité) mais **aucun lien** vers l'humain
14
+ **propriétaire** de l'appareil.
15
+ - L'invitation d'agent est créée par quiconque détient `enrollments.invite` sur le projet.
16
+ - Cycle actuel d'un appareil : invite → claim → PoP → attestation X25519 → approbation
17
+ humaine → active.
18
+ - Le scellement se fait sous une **clé d'epoch de projet**
19
+ (`buildEnvelope(keyEpoch)`, `epochPublicKey(cloudProjectId, epoch)`), **pas par appareil**.
20
+ Chaque appareil détient un **jeu** d'epochs (`heldEpochs`, `storeEpochPrivateKey`).
21
+ - **Rien ne projette encore** : `buildEnvelope` a zéro appelant hors sa définition, l'outbox
22
+ v2 n'est jamais alimentée, 0 enveloppe reçue côté cloud.
23
+
24
+ ## Les trois conséquences à traiter, pas à redécouvrir
25
+
26
+ 1. **Qui approuve un agent doit changer.** L'approbation repose sur la comparaison hors
27
+ bande de deux empreintes entre l'écran web et le terminal de l'appareil. Un admin ne peut
28
+ pas vérifier le terminal d'un tiers : lui faire approuver l'agent d'autrui transforme la
29
+ vérification en clic de confiance et rouvre l'attaque de l'homme du milieu que la
30
+ cérémonie ferme (dec#8).
31
+ 2. **Un nouveau membre ne lit que les epochs qu'on lui remet.** Il ne peut rien lire du passé
32
+ tant qu'un membre existant ne lui transmet pas les epochs antérieurs, ou ne rescelle pas.
33
+ 3. **Chargement de l'historique et invitation d'équipe sont le même problème** : qui remet
34
+ quelles clés d'epoch à qui, et quand. Les traiter séparément produirait deux mécanismes de
35
+ transfert de clés — donc deux endroits où une clé peut aller où elle ne devrait pas.
36
+
37
+ ## Ce qui est attendu
38
+
39
+ Proposez une conception, en la défendant sur les points **durs** plutôt que sur la partie
40
+ facile — le formulaire d'invitation par email est trivial et n'intéresse pas.
41
+
42
+ **(a) Modèle d'entités.** Où vivent les humains, où vivent les appareils, quel lien entre les
43
+ deux. Un `owner_user_id` sur `enrollments` suffit-il ?
44
+
45
+ **(b) Qui approuve quoi**, et comment le solo-dev ne subit **pas** la cérémonie d'équipe. Le
46
+ solo doit rester un cas dégénéré du même modèle, pas une branche parallèle.
47
+
48
+ **(c) La remise des clés d'epoch — le cœur du sujet.** Qui la fait, quand, sous quelle
49
+ autorité, avec quelle preuve ? Un membre existant doit-il être **en ligne** pour qu'un
50
+ nouveau membre rejoigne ? Que se passe-t-il si le seul détenteur d'un epoch quitte l'équipe
51
+ ou perd sa machine ? Une clé d'epoch remise **ne se reprend pas** — comme la révocation ne
52
+ retire pas ce qui a déjà été déchiffré.
53
+
54
+ **(d) L'horizon d'un nouveau membre** : tout l'historique, rien, ou borné ? Argumentez le
55
+ défaut, et dites ce qui devient **impossible à corriger après coup**.
56
+
57
+ **(e) La rotation d'epoch sur changement d'appartenance.** Au départ d'un membre, faut-il
58
+ tourner ? Quel est le coût réel, et que protège-t-on exactement sachant que le partant garde
59
+ ce qu'il détient déjà ?
60
+
61
+ **(f) Ce qui casse si le cloud est hostile.** Il orchestre l'appairage, donc il choisit qui
62
+ voit quelle empreinte et quand. Où sa malveillance reste-t-elle **indétectable** ?
63
+
64
+ ## Contraintes dures
65
+
66
+ - **dec#154** — le cloud est projection + relais, le local est source de vérité ; chemins
67
+ locaux, hôtes, sessions, clés et secrets **ne sortent jamais**.
68
+ - **dec#155** — le relais cloud n'a ni session, ni cwd, ni contexte ambiant : seulement un id
69
+ d'entité et un `base_rev`.
70
+ - **dec#8** — aucune clé collée à la main, aucune variable d'environnement ; l'humain compare
71
+ des empreintes.
72
+ - Zéro dépendance runtime au-delà de `commander`/`yaml`/`zod` côté core.
73
+
74
+ ## Méthode attendue
75
+
76
+ Ne convergez pas trop vite. **Nommez les alternatives que vous écartez** et pourquoi. Si une
77
+ partie du sujet demande un arbitrage **produit** plutôt qu'une réponse technique, dites-le
78
+ explicitement au lieu de trancher à la place de l'opérateur. **Signalez toute prémisse de ce
79
+ brief que le code contredit** — plusieurs affirmations ci-dessus ont été mesurées, mais la
80
+ mesure peut avoir manqué un chemin.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainclaw",
3
- "version": "1.23.0",
3
+ "version": "1.24.0",
4
4
  "description": "Shared project memory for humans and coding agents.",
5
5
  "type": "module",
6
6
  "repository": {