Skip to content

chore(ci)(deps): bump actions/checkout from 4 to 6#2

Open
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/github_actions/actions/checkout-6
Open

chore(ci)(deps): bump actions/checkout from 4 to 6#2
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/github_actions/actions/checkout-6

Conversation

@dependabot
Copy link
Copy Markdown
Contributor

@dependabot dependabot Bot commented on behalf of github May 11, 2026

Bumps actions/checkout from 4 to 6.

Release notes

Sourced from actions/checkout's releases.

v6.0.0

What's Changed

Full Changelog: actions/checkout@v5.0.0...v6.0.0

v6-beta

What's Changed

Updated persist-credentials to store the credentials under $RUNNER_TEMP instead of directly in the local git config.

This requires a minimum Actions Runner version of v2.329.0 to access the persisted credentials for Docker container action scenarios.

v5.0.1

What's Changed

Full Changelog: actions/checkout@v5...v5.0.1

v5.0.0

What's Changed

⚠️ Minimum Compatible Runner Version

v2.327.1
Release Notes

Make sure your runner is updated to this version or newer to use this release.

Full Changelog: actions/checkout@v4...v5.0.0

v4.3.1

What's Changed

Full Changelog: actions/checkout@v4...v4.3.1

v4.3.0

What's Changed

... (truncated)

Changelog

Sourced from actions/checkout's changelog.

Changelog

v6.0.2

v6.0.1

v6.0.0

v5.0.1

v5.0.0

v4.3.1

v4.3.0

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

... (truncated)

Commits

@dependabot @github
Copy link
Copy Markdown
Contributor Author

dependabot Bot commented on behalf of github May 11, 2026

Labels

The following labels could not be found: ci, dependencies. Please create them before Dependabot can add them to a pull request.

Please fix the above issues or remove invalid values from dependabot.yml.

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>
@dependabot dependabot Bot changed the title chore(ci)(deps): Bump actions/checkout from 4 to 6 chore(ci)(deps): bump actions/checkout from 4 to 6 May 12, 2026
@dependabot dependabot Bot force-pushed the dependabot/github_actions/actions/checkout-6 branch from 2fe2ec2 to 136b4c5 Compare May 12, 2026 19:47
@dependabot dependabot Bot requested a review from kevinggraphiste-hub as a code owner May 12, 2026 19:47
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>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants