chore(ci)(deps): bump actions/checkout from 4 to 6#2
Open
dependabot[bot] wants to merge 1 commit into
Open
Conversation
Contributor
Author
LabelsThe following labels could not be found: Please fix the above issues or remove invalid values from |
kevinggraphiste-hub
pushed a commit
that referenced
this pull request
May 11, 2026
Premier sprint de la trilogie Token Hygiene (réduction tokens injectés
au LLM sans dégrader la qualité). Cible le plus gros poste de gaspillage
observé : les outputs de tools volumineux (web_fetch, kb_read, mcp_*)
qui s'accumulent à chaque round du tool-loop.
**Module backend/core/agents/token_hygiene/ (NEW)** :
- __init__.py : doc générale des 3 couches + niveau opt-in
- result_compression.py : compress_result(output, tool_name, conv_id)
qui tronque head+tail au-delà de COMPRESSION_THRESHOLD (2K tokens),
stocke le full content en cache mémoire indexé par result_id (UUID).
Cache TTL 1h, auto-purge à chaque store.
- HEAD_TOKENS = 500, TAIL_TOKENS = 500
- Marker explicite "[...TRUNCATED — N tokens omis. result_id: XXX]"
- fetch_result(result_id, conv_id, start_char?, end_char?) pour
récupérer full content ou tranche
- cache_stats() pour diagnostic
**Tool agent tool_result_fetch (wolf_tools.py)** :
- Schéma + executor _tool_result_fetch
- L'agent peut récupérer le contenu complet d'un result tronqué
uniquement si nécessaire — tranche start_char/end_char possible
pour rester économe
**Hooks dans agent_loop.py + chat.py** :
- Avant injection au LLM, chaque tool_result est passé par
compress_result()
- Skip explicite sur tool_result_fetch (évite boucle de truncation)
- Fallback hard cap si > 2× tool_result_char_limit (sécurité)
Coût : ZÉRO appel LLM additionnel. String slicing + dict cache mémoire.
~1ms par compression. Pleinement BYOK-compatible (marche pour trial
users, Ollama-only, Standard, Compliance, etc.).
Gain estimé :
- Question simple : -27% (déjà sous le seuil souvent)
- Tâche avec 2 tools lourds : -65%
- Recherche web profonde (4-5 tools) : -77%
- Conversation longue avec accumulation : -70%
Mesurable : chaque appel à compress_result log les tokens originaux
vs displayés. À aggréger dans Analytics au sprint #5 (UI counter).
À suivre :
- #2 Tool gating dynamique (filter schemas par intent regex)
- #3 Conversation pruning (sliding window + metadata summary)
- #4 LLM compression opt-in (Settings → toggle)
- #5 UI token savings counter
Bumps : app 3.34.0 → 3.35.0 (MINOR — nouveau pkg infra).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
kevinggraphiste-hub
pushed a commit
that referenced
this pull request
May 11, 2026
**#2 — token_hygiene/tool_gating.py (NEW)** Filtre les schemas tools selon l'intent du message user (regex). Au PREMIER round seulement (les suivants gardent tout pour ne pas couper une chaîne d'appels). Si un tool est absent du set filtré, l'agent peut appeler `tool_directory` (toujours CORE) pour le découvrir. CORE tools (toujours présents) : tool_directory, tool_result_fetch, web_search, web_fetch, consciousness_*, soul_*, kb_*, finalize_onboarding, provider_manage, mode_set. 14 groupes thématiques avec regex FR + EN : gmail, calendar, drive, chat_messaging, code_dev, valkyrie_pm, forge_workflow, webhooks_integrations, personality_identity, skill_subagent, voice_audio, browser_huntr, image_gen, analytics_budget. Stratégie sécurité : "false positives > false negatives". Si aucun groupe matché ET message non-trivial → on garde TOUT (better safe). Si message vide → uniquement CORE. Hooks dans agent_loop.py et chat.py au round 0. **#3 — token_hygiene/conversation_pruning.py (NEW)** Sliding window sur l'historique. Garde toujours : - Tous les messages role=system - Les KEEP_RECENT (6) derniers messages user/assistant/tool verbatim Les messages plus anciens (au-delà du seuil PRUNE_THRESHOLD=10) sont remplacés par UN message system synthétique généré sans LLM : - Comptes user/assistant - Sujets abordés (extraits par regex sur 13 patterns FR) - Tools les plus utilisés (count) - Rappel : "utilise consciousness_recall pour rappeler un échange" La conscience vectorielle Qdrant prend le relais pour la mémoire long-terme — pas de perte d'info, juste un changement de medium. Hooks dans agent_loop.py + chat.py AVANT chaque appel LLM (pas seulement au round 0 — l'historique peut grossir à chaque round). try/except non-bloquant : si le pruning plante, le chat continue avec l'historique non-prune. **Gains cumulés (sprints #1 + #2 + #3)** : - Question simple : -27% (mostly #1) - Tâche 2 tools : -65% → -75% (compression + gating) - Conv longue 30 msg : -63% → -78% (compression + pruning) - Recherche web profonde : -77% → -82% (les 3 cumulés) Bumps : app 3.35.0 → 3.36.0. Reste à livrer : #4 LLM compression opt-in + #5 UI counter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
2fe2ec2 to
136b4c5
Compare
11 tasks
kevinggraphiste-hub
added a commit
that referenced
this pull request
May 27, 2026
…rketplace, WS, path traversal) (#23) * fix(security): hardening critique — 5 fixes audit 2026-05-26 Cinq trous chirurgicaux relevés par l'audit sécu d'hier soir. Items #5, #6, #7, #8, #10 du rapport (OAuth #2/#3 et impersonation #9 reportés à demain car trop sensibles pour passer à 23h). ## #10 — IDOR Tasks (task_routes.py) Les 5 routes /conversations/{id}/tasks* ne vérifiaient AUCUNE ownership. Tout user authentifié pouvait lister/créer/modifier/wiper la to-do d'un autre. Fix : helper _ensure_owned_conversation au top de chaque route. Mode setup (≤1 user, middleware skip) toléré comme avant. ## #6 — Marketplace install ouvert à tous (marketplace_routes.py) POST /marketplace/install et /uninstall n'exigaient qu'auth (pas admin). Installer un plugin = exécution Python globale + accès vault secrets de TOUS les users → RCE instance-wide via trial user. Gate require_admin ajoutée sur les deux endpoints. ## #7 — Path traversal plugin_id (marketplace.py) shutil.rmtree(EXTERNAL_PLUGINS_DIR / plugin_id) prenait n'importe quoi. Un admin pouvait wiper la prod avec ../../backend. Whitelist regex ^[a-z0-9][a-z0-9_.-]{0,63}$ + ceinture .resolve() qui vérifie que le chemin reste sous EXTERNAL_PLUGINS_DIR (anti-symlink). ## #8 — SSRF KB ingest URL (kb/extractors/url.py) POST /api/plugins/kb/ingest/url ne checkait que le scheme. Un user pouvait hit 169.254.169.254 (cloud metadata → IAM creds) ou les services internes (Postgres, Redis, MCP, Ollama) et stocker la réponse dans sa KB. Fix : _is_private_url (helper existant dans web_fetch) + suivi manuel des redirects avec re-check à chaque hop (sinon site public peut rediriger vers IP privée — cf. fix C2 du browser plugin). ## #5 — Voice WebSocket auth bypass (voice_routes.py) Le handler /voice/realtime/{engine} lisait user_id depuis query_params sans validation. Anyone pouvait ?user_id=1 et burner les clés API de l'admin. Pattern fix existait déjà dans plugins/code/routes/lsp.py (cookie HttpOnly pendant le handshake WS). Adaptation locale : helper _authenticate_voice_ws, refus avant accept() si pas d'auth valide. Pas de migration DB. Pas de touche aux outils agent (WOLF, file_*). Autoamélioration intacte. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security): suite ultrareview PR #23 — voice WS open-mode + KB streaming Ultrareview PR #23 a remonté 3 findings. Cette commit fixe les deux fixables sans refacto large. Le 3e (SSRF helper IPv6 + DNS rebinding, pre-existing dans web_fetch.py) est documenté comme reporté. ## #4 — Voice WS open-mode bypass (régression introduite par cette PR) Mon helper _authenticate_voice_ws (copié du pattern LSP) retournait user_id=0 dès que `has_tokens == False`. Le middleware HTTP exige aussi `user_count <= 1` (cf. main.py:949-967, incident 2026-05-05 : quand tout le monde fait logout dans une instance multi-users, les api_token deviennent NULL → has_tokens=False → open mode ré-ouvert à tout attacker non auth). Fix : aligner exactement sur le middleware (`has_tokens=False AND user_count <= 1`). Sans ça, l'attacker pouvait se connecter en WS comme share user et burner les clés API instance-wide — exactement ce que la PR voulait fermer. Note : le pattern original dans plugins/code/routes/lsp.py a le même défaut pré-existant. Sera fixé en PR séparée (out-of-scope ici). ## #10 — KB extract_url buffere le body avant le check de taille httpx.Client.get() est NON-streaming : le body entier est matérialisé en RAM avant que MAX_FETCH_BYTES soit testé. Un serveur hostile peut annoncer text/html + servir un body multi-GB → OOM du worker. Fix : passage à client.stream("GET", ...) + iter_bytes() qui coupe dès que la taille cumulée dépasse le cap. Bonus : reject précoce si Content-Length annonce > MAX_FETCH_BYTES. ## #1 — REPORTÉ (PR séparée) SSRF helper _is_private_url (web_fetch.py) a deux trous pré-existants qui défont partiellement la garde KB ajoutée par cette PR : - IPv6 non validé (socket.gethostbyname est IPv4-only ; literals comme [fd00:ec2::254] passent → AWS IMDS v6 reste exfiltrable) - DNS rebinding TOCTOU (helper résout, puis httpx re-résout au connect ; un DNS attacker peut flip entre les deux lookups) Le vrai fix demande de refactor le helper avec ipaddress.ip_address() + getaddrinfo AF_UNSPEC + custom httpx transport qui pin l'IP validée (Host/SNI préservés). Trop large pour 23h. Tracking : à faire en priorité dans la prochaine PR sécu. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Kevin <kevin@gungnir.dev> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
9 tasks
kevinggraphiste-hub
added a commit
that referenced
this pull request
May 27, 2026
… purge plugin claude code (#24) * fix(security): OAuth hardening + purge plugin claude code (118 MB) Suite à l'audit sécu 2026-05-26 et aux retours de l'ultrareview PR #23, on ferme les 2 critiques OAuth qui restaient + une purge hygiène opportuniste. ## #2 — OAuth state secret hardcodé (oauth_core.py) Avant : `_state_secret()` retournait `"gungnir-default-state-secret-change-me"` quand `GUNGNIR_OAUTH_STATE_SECRET` n'était pas posé. Secret publique connu = state HMAC forgeable = un attacker pouvait forger un state valide et faire avaler un callback falsifié → login-CSRF et account-link hijack possibles sur les ~20 connecteurs OAuth en plus du login Google/GitHub. Fix : fallback runtime aléatoire (`secrets.token_bytes(32)` au boot). Trade-off assumé : un restart serveur invalide les flows OAuth en cours (l'user doit recliquer "Continuer avec Google") — préférable à un secret universellement connu. Si l'admin pose `GUNGNIR_OAUTH_STATE_SECRET` en env, il survit aux restarts comme avant. ## #3 — OAuth account pre-hijacking via email link (oauth_login.py) Avant : `_create_or_link_user` linkait `google_sub` / `github_id` à tout compte existant matchant l'email, SANS vérifier `email_verified=True` côté compte existant. Pire, il forçait `email_verified=True` au passage. Vecteur Microsoft 2022 : un attacker s'inscrit avec `victim@gmail.com` via le register normal (sans cliquer le lien de vérif). Plus tard, la victime clique "Continuer avec Google" → notre code link son `google_sub` au compte de l'attacker → la victime se logue dans le compte de l'attacker, qui garde son mot de passe et peut récupérer le contrôle à tout moment. Fix : nouvelle exception `OAuthLinkRefused` levée si l'email du compte existant n'est pas vérifié. Les callbacks Google et GitHub la catchent et retournent un message clair en français à l'user. L'auto-promotion `email_verified=True` au link est supprimée (devient inutile : on ne link plus que des comptes déjà vérifiés). ## Hygiène — purge `backend/plugins/claude code/` 118 MB / 57 fichiers, plugin test marketplace npm, zéro référence dans le code core ou frontend. Relevé par l'audit 2026-05-26 #5 (dette technique). Suppression nette. ## Pas inclus dans ce commit - Refonte impersonation (#9) : reportée — pas exploitable en configuration mono-admin (Kevin), à faire avant de promouvoir un 2e admin - SSRF helper IPv6 + DNS rebinding (#1) : reportée — pas exploitable sur VPS hors-AWS (pas d'IMDS) et requiert refacto httpx custom transport - 102 `print()` → `logger.*` : mécanique, à faire en chantier dédié Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security): OAuth state cookie binding + message OAuthLinkRefused Suite à l'ultrareview PR #24 — on ferme proprement le chapitre OAuth. ## #3 — Message OAuthLinkRefused inutile pour la victime (nit) Avant : on disait à la victime de "vérifier l'email" ou "se connecter" sur le compte unverified. Or : - le token de vérification a 24h, donc plus dispo après l'attaque - forgot-password est aussi gated sur email_verified=True (anti-énum) - l'attacker connaît le mot de passe, pas la victime - pas de SMTP = pas d'email de vérif tout court Rewording : on dit clairement "contacte l'admin si tu n'as jamais créé ce compte". Pas de débat sécu — purement cosmétique. ## #5 — OAuth state sans cookie binding (login-CSRF / RFC 6749 §10.12) Pre-existing, mais le moment naturel de fermer. Le state HMAC-signé empêche la forge, mais rien ne lie ce state au browser qui a fait /start : un attacker peut faire /start chez lui, intercepter (code, state) avant que Google redirige, et tricker la victime à hit /callback?code=X&state=Y → la victime se logue silencieusement dans le compte de l'attacker. Fix RFC 6749 §10.12 standard : - /start génère un nonce aléatoire, l'écrit en cookie HttpOnly samesite=lax max-age=600, et embarque sha256(nonce) dans le state via le nouveau paramètre `cookie_binding` de encode_state - /callback récupère le cookie, recalcule sha256, et compare en temps constant à state.c (decode_state remonte maintenant `c`) - /callback supprime le cookie après finalize_session (one-shot) Les autres callers de encode_state (connecteurs webhooks Notion, Linear, etc.) appellent sans cookie_binding et restent intacts — rétrocompat assurée. ## Coût opérationnel - 2 cookies posés par flow OAuth login : gungnir_oauth_state (10 min) puis gungnir_session (7 jours). - Restart serveur en plein flow OAuth invalide le cookie (le user recommence — acceptable, déjà le cas avec le fallback state secret introduit par cette PR). - Aucune migration, aucun impact UX hors le cas attaque. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Kevin <kevin@gungnir.dev> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
kevinggraphiste-hub
added a commit
that referenced
this pull request
May 31, 2026
…umaine (v5.3.0) (#50) * feat(consciousness): Phase 1 Conscience v2 — reconnecter les nerfs Audit 2026-05-30 : la boucle perception→état→comportement était cassée au milieu. Bugs : - NameError consolidation (__init__.py:1624, memory_id non défini → res.get()) - Purge thoughts Qdrant inopérante (range.lt sur timestamp string) → réécrite scroll+parse+delete-by-IDs avec vrai compteur (core/vector/store.py) - collective_promote (curateur) bypassait sanitize_for_collective → caviardage PII ajouté (engine.py) Reconnexions : - A : fallback SQL au recall (engine.vector_recall + _sql_recall_fallback) — fin de l'amnésie quand vector_provider=none (le défaut) - B : perception→drives (perception.py, classifieur déterministe no-LLM câblé chat.py après record_interaction) — émet contradiction_found/open_question/user_asked_status selon le contenu du message AST OK + classifieur unit-testé (0 faux positif). Pas de release : chantier Conscience v2 livré en 1 seule release en fin de chantier. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(consciousness): Phase 2 Conscience v2 — espace de travail global (Global Workspace) get_self_state_block devient un Global Workspace gradué et TOUJOURS présent : - élit les éléments saillants (impulsion, auto-critique HIGH, tensions, mood, goal pertinent au message, pensée liée) par score = intensité + pertinence déterministe au message + statut - régime calme : 1 ligne de fond ultra-compacte (continuité de la conscience) ; régime actif : top éléments dans un budget ~6 lignes - corrige la déconnexion #2 (goals générés mais JAMAIS injectés au prompt) : un goal lié au message remonte enfin - absorbe la 'mood de fond continue' (ex-Phase 3) : la conscience n'est plus muette en régime calme - chat.py passe désormais le message pour le scoring de pertinence ; placement <self_state> en fin de message conservé (tool-calling) Rétrocompat : signature message='' par défaut (appelant déprécié channels/reminders intact). AST OK. Vérif comportementale fine = runtime Kevin. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(consciousness): Phase 3 Conscience v2 — narratif de soi Récit autobiographique évolutif (« qui je suis devenu ») : - engine : get/set_self_narrative + get_self_narrative_block (injecté près de la soul) + build_self_narrative_prompt (ancré sur faits : synthèse de conso fraîche + goals actifs + pensées récentes ; cappé 600 car, 1 paragraphe, anti-invention) - greffé sur la boucle de consolidation (cadence ~12h, analogue au sommeil) — best-effort, n'invalide pas la conso ; fallback no-key inclus - chat.py : narrative_block injecté dans full_system juste après la soul (continuité identitaire) AST OK. Vérif comportementale = runtime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(consciousness): Phase 4 Conscience v2 — drive relationnel, rebalance survie, saillance émotionnelle 1) Drive 'connexion' (besoin relationnel, priority 3) : monte sur frustration/ contradiction (perception émet user_frustration), redescend sur feedback positif (score_interaction composite>=0.7 soulage), mood 'attentif' à >=0.55. Rétrocompat : réconciliation des states à 5 besoins au chargement (DEFAULT_STATE.needs manquants ajoutés). 2) Rebalance survie (investigation Kevin) : priority 5->4 (ne rafle plus le top_need via score=priority*urgency) + system_pulse n'émet disk_low/error_in_logs qu'au seuil CRITIQUE (le warning 75%/3err ne bump plus → fin de la sur-stimulation permanente). 3) Saillance émotionnelle : charge affective (urgence max) taguée à l'encodage (memory_upsert → provenance_meta.affect) + re-rank au recall (_rerank_salience : souvenirs à forte charge remontent). Affect câblé sur le chemin SQL (le défaut) ; vecteur = lessons boost (category déjà en metadata). 4) Lessons recall boost (reco b) : les 'lesson' pèsent plus au rappel (on apprend de ses erreurs), Challenger laissé opt-in. AST OK + classifieur re-testé (0 faux positif). Vérif comportementale = runtime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * release: 5.3.0 — Conscience v2 (plugin conscience 4.18.0 → 4.19.0) Bumps app 5.2.0→5.3.0 + plugin conscience back/front 4.18.0→4.19.0 + badge README. CHANGELOG Conscience v2 (4 phases). Fix CLAUDE.md : la Conscience utilise Qdrant/Chroma/Supabase, PAS pgvector (= KB seulement). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Kevin <kevin@gungnir.dev> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps actions/checkout from 4 to 6.
Release notes
Sourced from actions/checkout's releases.
... (truncated)
Changelog
Sourced from actions/checkout's changelog.
... (truncated)
Commits
de0fac2Fix tag handling: preserve annotations and explicit fetch-tags (#2356)064fe7fAdd orchestration_id to git user-agent when ACTIONS_ORCHESTRATION_ID is set (...8e8c483Clarify v6 README (#2328)033fa0dAdd worktree support for persist-credentials includeIf (#2327)c2d88d3Update all references from v5 and v4 to v6 (#2314)1af3b93update readme/changelog for v6 (#2311)71cf226v6-beta (#2298)069c695Persist creds to a separate file (#2286)ff7abcdUpdate README to include Node.js 24 support details and requirements (#2248)08c6903Prepare v5.0.0 release (#2238)