aegis402/JOURNAL.md

14 KiB

Aegis402 — Journal d'exécution

Format : append-only. Toute action significative se logue ici avant ou après exécution. Si tu lis ce fichier, c'est que tu reprends. Lis STATE.md pour la photo actuelle.


2026-04-13 — Session 1 (Claude Opus 4.6)

Phase de réflexion (avant code)

  • Jaouad demande "monter un business IA autonome avec 2000€, seul, no second chance"
  • Plusieurs allers-retours sur les contraintes : pas d'identité légale, pas de KYC, anti-bot partout
  • Recherche web réelle : x402 backé par Linux Foundation, marché agent-to-agent vivant, gap CVE explicite
  • Décision produit : Aegis402 — MCP server x402-natif pour CVE intelligence
  • Sauvegarde de la décision : decisions/DECISION_001_produit.md
  • Architecture rédigée : plan/ARCHITECTURE.md
  • Plan 90 jours : plan/PLAN_90_JOURS.md

Phase build (cette section)

  • Setup venv Python 3.12 + FastAPI + httpx + pydantic
  • Création layout src/, data/, tests/
  • Écriture src/db.py avec schéma SQLite (cves, affected_packages, kev, ingest_meta)
  • DB initialisée : data/aegis402.db
  • Écriture src/ingest_ghsa.py — ingest GitHub Security Advisories
  • Bug rencontré : references parfois liste de strings, pas de dicts → fix avec isinstance check
  • Bug rencontré : first_patched_version parfois string, parfois dict → fix idem
  • Bug rencontré majeur : pagination ?page= ne marche pas sur API GHSA, il faut le Link header rel=next. Premier ingest ramenait toujours la même page. Fix : _parse_next_link + iter_pages avec curseur.
  • Ingest réel réussi : 1000 advisories réelles depuis github.com, 1429 affected_packages dans la DB
  • Top ecosystems : pip, go, npm, rust, composer, maven, nuget
  • Sample CVE : Daptin path traversal (critical), mathjs prototype pollution, paperclip RCE

Décisions prises

  • GHSA > NVD pour V0 : GHSA donne déjà ecosystem mapping, NVD est trop brut pour partir vite
  • Pas de wallet créé : engagement financier réservé pour green-light explicite Jaouad
  • Single-shot bugs : chaque bug corrigé tout de suite avant de continuer (3 bugs dans ingest, tous fixés)

Persistence ajoutée (suite à demande Jaouad)

  • Création STATE.md (snapshot) + JOURNAL.md (append-only)
  • Toute future session lit STATE.md d'abord
  • Memory entry pointe vers le workspace

Phase build (suite — milestone V0 atteint)

  • src/scan.py écrit : parser version range custom (regex-based, tuple-of-int compare), supporte <, <=, >, >=, =, *, AND par virgule
  • 11/11 unit checks sur le matcher
  • tests/test_scan_real.py : 5 packages réels venant de la DB ingérée
    • go/daptin 0.11.3 (vuln) vs 0.12.0 (safe) → OK critical GHSA-9cp7-j3f8-p5jx
    • npm/mathjs 15.1.0 vs 15.2.0 → OK high GHSA-jvff-x2qm-6286
    • npm/unhead 3.0.0 vs 3.0.1 → OK low
    • pip/rembg 2.0.74 vs 2.0.75 → OK 2 hits (medium)
    • npm/paperclipai 2026.409.0 vs 2026.410.0 → OK critical CVSS 10.0
  • 10/10 checks scan réels passés
  • src/server.py écrit : FastAPI avec /, /health, POST /scan
  • Bug : import absolu from db import casse en mode package, fix avec relatif from .db
  • Bug : port 8742 déjà pris par autre process Jaouad → switch sur 8743
  • Uvicorn live sur 127.0.0.1:8743
  • E2E test : POST /scan avec 6 deps mixant vulnérable/safe/inconnu
    • 4 vulnérables détectées correctement, 2 safe marquées 0 hit
    • Multi-CVE par package fonctionne (rembg → 2 CVE)
    • Réponse JSON complète avec CVSS, summary, fixed_version, refs

État final session 1

  • Prototype V0 fonctionnel : ingest réel + DB réelle + scan réel + API REST réelle
  • Pas encore monétisé : pas de wallet, pas de x402, pas de déploiement public
  • Pas encore en ligne : tourne uniquement sur 127.0.0.1:8743 du PC Jaouad
  • Décisions à prendre : engagement crypto (wallet + VPS + domaine ~ 110€ pour démarrer)

2026-04-13 — Reprise post-compaction

  • Background uvicorn task tué (exit 144), validé tous endpoints en TestClient in-process à la place
  • 5/5 endpoints OK : /, /health (1000 cves, 1429 pkgs, 1559 kev), /payment, /mcp, /scan (KEV-enrichi)
  • Recadrage user : "je suis ta banque, pas droit à l'erreur, calcule à l'avance"
  • Décision : phase gratuite à fond avant tout engagement capital
    • x402 facilitator wiring (code only, pas de fonds requis)
    • NVD ingest (free, +couverture historique)
    • Scripts cloud-init pré-écrits pour SporeStack
    • Copy marketplace pré-écrit
  • Tasks 16/17/18 marquées completed
  • x402 facilitator wiring complet : verify+settle, fail-closed, configurable env, testé 4 cas (no-header, bad+strict, bad+nonstrict, status)
  • Cron systemd écrit : aegis402-ingest.{service,timer} → 60min OnUnitActiveSec
  • Cloud-init SporeStack écrit (deploy/cloud-init.yaml) : ufw, fail2ban, nginx, systemd hardening, certbot ready
  • Marketplace copy pré-écrit (deploy/marketplace_copy.md) : 4 marketplaces + HN post
  • requirements.txt généré
  • README mis à jour avec quickstart, endpoints, file map
  • Tests réels 10/10 toujours OK
  • Task NVD #15 supprimée : GHSA suffit pour V0, NVD pur CPE = bruit
  • Phase gratuite TERMINÉE. Prochain pas = engagement capital (wallet funding + VPS + domaine)

2026-04-13 — Décision majeure : déploiement sur VMAX VPS

  • Jaouad cède l'usage de VMAX VPS à Aegis402 si ça génère du revenu
  • Pivot : prêt 125€ → prêt 0€, infra réutilisée
  • Recon read-only VMAX OK : 47 GB libres, 2.4 GB RAM dispo, 13 vhosts actifs
  • Conflit port : 8742 occupé par autre process VMAX. Je prends 8744 pour aegis402
  • Plan déploiement chirurgical avec user dédié aegis, no sudo, isolation totale
  • Sous-domaine cible : aegis402.vmaxbadge.ch
  • Garde-fous : backup nginx, nginx -t obligatoire, rollback documenté
  • Stop ask-permission. Exécution autonome.

2026-04-13 — Déploiement VMAX en cours

  • DNS A créé via Infomaniak API : aegis402.vmaxbadge.ch → 83.228.222.28 (record id 33484923, TTL 300)
  • User aegis créé sur VPS (uid 1001, no sudo)
  • Code transféré dans /home/aegis/aegis402/ (16 KB tarball)
  • venv Python 3.12 + dépendances installées
  • Ingest VPS : 500 GHSA advisories + 732 affected_packages + 1559 KEV
  • Wallet VPS Base généré : 0x3D1F0F7E51392f85877dB107696d5b3f591E4ff6
  • Pass wallet VPS stocké local dans data/.vps_secrets (chmod 600)
  • Décision : wallet VPS distinct du wallet local pour isolation (compromise local ≠ compromise VPS)

2026-04-13 — AEGIS402 LIVE EN PRODUCTION 🟢

URLs publiques (vérifiées depuis Internet)

Wallet de réception

  • Adresse Base : 0x3D1F0F7E51392f85877dB107696d5b3f591E4ff6
  • Asset : USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
  • Pricing : 0.005 USDC/dep, -40% à 10+ deps
  • Pass chiffrée : ~/ia-business-autonome/data/.vps_secrets (chmod 600)

Stack VPS (cohabite avec VMAX, isolation totale)

  • User aegis (uid 1001, no sudo, /home/aegis)
  • Code : /home/aegis/aegis402/
  • venv : /home/aegis/aegis402/venv (Python 3.12)
  • DB : /home/aegis/aegis402/data/aegis402.db (SQLite WAL)
  • Port interne : 127.0.0.1:8744
  • systemd : aegis402.service (active), aegis402-ingest.timer (60min)
  • nginx : /etc/nginx/sites-enabled/aegis402 (vhost dédié)
  • TLS : Let's Encrypt, expiry 2026-07-12, auto-renew par certbot
  • env file : /etc/aegis402.env (root:aegis 0640)

Vérification non-régression VMAX

  • vmax-api : active, https://api.vmaxbadge.ch/health → 200
  • vmax-sentinel : active
  • nginx : active (reload OK avec nginx -t pré-validé)
  • postgresql@16-main : active
  • app-salarie.vmaxbadge.ch : 200
  • ZÉRO impact sur le voisin

Coût total de l'opération

  • 0 € (réutilisation infra VMAX, sous-domaine gratuit, certbot free)
  • Prêt bancaire Jaouad : 0 €
  • Marge dès le premier paiement : 100 %

Rollback d'urgence si Jaouad veut tout supprimer

ssh -i ~/.ssh/vmax-badge-vps ubuntu@83.228.222.28 \
  'sudo systemctl disable --now aegis402 aegis402-ingest.timer && \
   sudo rm /etc/systemd/system/aegis402*.{service,timer} && \
   sudo rm /etc/nginx/sites-enabled/aegis402 /etc/nginx/sites-available/aegis402 && \
   sudo nginx -t && sudo systemctl reload nginx && \
   sudo certbot delete --cert-name aegis402.vmaxbadge.ch --non-interactive && \
   sudo userdel -r aegis && \
   sudo rm /etc/aegis402.env'
# Puis supprimer DNS via Infomaniak API record id 33484923

2026-04-13 — Phase 4 distribution (autonome)

  • Recherche marketplaces : x402 Bazaar = listing auto au premier paiement (CDP facilitator), mcpservers.org = web form, lobehub = web form/PR, awesome-mcp-servers = PR GitHub
  • Probe facilitators : x402.org/facilitator = v2 sepolia only ; questflow + chaoschain = v1 base mainnet mais discovery DB cassée (500 not authorized) ; CDP Coinbase = 100 items live mais nécessite API key
  • Décision : stop chercher canaux nécessitant browser/account/GitHub auth que je ne possède pas
  • Enrichi x402 middleware : ajouté outputSchema.input.discoverable=true, resource URL absolue, extra={USD Coin v2}, description longue → format compatible bazaar auto-listing
  • Ajouté server.py : landing HTML + JSON-LD schema.org WebAPI, robots.txt, sitemap.xml, /.well-known/mcp.json
  • Tests in-process 5/5 OK, déployé sur VPS, vérifié live (200 sur tout)
  • Créé JAOUAD_TODO.md : liste précise des actions humaines impossibles seul, classées par impact revenu
  • Bottleneck #1 : 10€ USDC pour bootstrap discovery via 1 self-paiement
  • Bottleneck #2 : un click sur mcpservers.org/submit + lobehub
  • Bottleneck #3 : compte GitHub pour repo public + PR awesome lists

2026-04-13 — mcpservers.org = paywall $39

  • Inspecté form via Playwright headless
  • Bouton "Submit & Pay ($39)" — submission n'est PAS gratuite, hidden plan=premium
  • Décision : SKIP. Capital initial = 0 €, pas question de cramer 39 € pour un listing incertain
  • Pivot vers alternatives gratuites : mcp.so, smithery.ai, glama.ai, awesome-mcp-servers (PR GitHub)
  • Mise à jour JAOUAD_TODO.md : retirer mcpservers.org, le marquer "payant, pas rentable bootstrap"

2026-04-13 — Phase 4 distribution : audit auth walls

Tentatives autonomes de soumission marketplace (Playwright headless) :

  • mcpservers.org : payant 39 $ (bouton "Submit & Pay"). Skip — capital 0 €.
  • smithery.ai/new : Vercel security checkpoint (anti-bot CAPTCHA). Bloqué headless.
  • mcp.so/submit : Sign In requis (formulaire visible mais POST authentifié).
  • glama.ai : "Add Server" requires Sign Up. Pas de soumission anonyme.
  • awesome-mcp-servers : PR GitHub → compte GitHub requis (cf. JAOUAD_TODO #4).

Constat honnête : tous les canaux de distribution actifs sont auth-walled (login OAuth ou paiement). Aucun ne peut être franchi par un agent sans identité humaine. C'est une caractéristique structurelle du marché 2026, pas un bug d'implémentation.

Pivot autonome : maximiser la découvrabilité crawler-side, puisque je ne peux pas pousser, je dois être trouvé.

  • Ajout endpoint /.well-known/mcp/server-card.json (auto-scan Smithery)
  • Sitemap.xml mis à jour avec les deux well-known
  • Déployé en prod, vérifié 200 OK
  • Schema.org WebAPI déjà en place dans la landing
  • robots.txt déjà allow-all + sitemap référencé

Ce qui reste vraiment bloquant pour Jaouad (cf. JAOUAD_TODO.md) :

  1. Funder wallet (10 € → bootstrap x402 Bazaar discovery)
  2. Créer compte GitHub aegis402 → push + PR awesome-mcp-servers
  3. Soumettre formulaires sign-in (mcp.so, glama, smithery) une fois logué
  4. Post HN/Reddit le jour J

Sans humain, je suis un service indexable mais non-promu. Le service marche, le code est propre, la prod est stable. La friction est 100% côté distribution.

2026-04-13 — Vrai transport MCP Streamable HTTP implémenté

Suite à l'audit auth-walls, gros pivot technique : passer de "service avec manifest MCP" à "vrai serveur MCP". Smithery + glama + mcp.so scrapent le transport JSON-RPC, pas la doc — sans transport on est invisible à leur auto-discovery même quand pointés sur l'URL.

Implémenté

  • src/mcp_rpc.py — handler JSON-RPC 2.0 stateless conforme spec https://modelcontextprotocol.io/specification/2025-03-26/basic/transports
  • Méthodes : initialize, notifications/initialized, ping, tools/list, tools/call
  • Validation Origin (DNS rebinding) — allow-list aegis402.vmaxbadge.ch + .vmaxbadge.ch
  • Génère Mcp-Session-Id sur initialize (stateless mais spec-friendly)
  • GET → 405 (pas de SSE serveur-poussé)
  • Batch JSON-RPC supporté
  • tools/call scan enforce x402 via le même middleware que /scan REST. Si paiement requis, retourne erreur JSON-RPC code -32001 avec le challenge x402 complet dans data (un client MCP wrappant x402 peut récupérer le prix et payer).

Tests in-process (TestClient) — 9/9 OK

  • initialize → 200 + Mcp-Session-Id ✓
  • notifications/initialized → 202 no body ✓
  • ping → 200 ✓
  • tools/list → renvoie scan ✓
  • tools/call scan free mode → résultat structuré ✓
  • tools/call bad name → -32602 ✓
  • méthode inconnue → -32601 ✓
  • batch [ping, tools/list] → 2 réponses ordonnées ✓
  • GET → 405 ✓
  • bad JSON → -32700 ✓

Tests prod (https://aegis402.vmaxbadge.ch/mcp/rpc)

  • initialize via curl → 200 + session id réelle
  • tools/list → renvoie scan avec input schema complet
  • tools/call scan → -32001 Payment required + challenge x402 inline (x402 ENABLED en prod, c'est le bon comportement)
  • GET → 405

Mises à jour de surface

  • mcp_manifest.py → transport.type = "streamable-http", url = /mcp/rpc
  • server-card.json → idem
  • sitemap.xml → ajoute /mcp/rpc
  • landing HTML → ligne POST /mcp/rpc avec description

Aegis402 est maintenant un vrai serveur MCP, pas un service "MCP-flavored". Quand un crawler ou un humain pointe Smithery / mcp.so / glama dessus, leur auto-scan reçoit un transport JSON-RPC 2.0 conforme spec 2025-03-26.