fix(profiles): the Teams pipeline store and mem0.json are credential stores

teams_pipeline_store.json persists each Graph subscription's client_state, the shared secret
MSGraphWebhookAdapter._verify_client_state checks on every notification. mem0.json is read for
api_key (the documented self-hosted layout keeps the server key there). A named export shipped
both and a distribution could install both; they are on the shared inventory now.

The two invariant tests name both stores, the Teams one through the writer's own filename
constant, so they fail without the inventory entries at both boundaries.

(cherry picked from commit 6e44670c62c077521c90cb270c1ace3dacef6651)
This commit is contained in:
John Paul Soliva
2026-09-30 01:24:35 +09:00
committed by kshitij
parent 64a073ad88
commit b932c53264
4 changed files with 7 additions and 3 deletions

View File

@@ -161,7 +161,9 @@ PROFILE_CREDENTIAL_PATHS = frozenset({
"google_chat_user_token.json", "google_chat_user_oauth_pending", # legacy single-user layouts
"slack_tokens.json",
"honcho.json", # Honcho apiKey + OAuth grant (oauth.refreshToken)
"mem0.json", # Mem0 api_key (self-hosted server key) next to its settings
"webhook_subscriptions.json", # per-route HMAC secrets
"teams_pipeline_store.json", # Graph subscription client_state (webhook shared secret)
"mcp-tokens", # MCP OAuth tokens
"vault", # vault.key + vault.json.enc
"browser-profile", "browser_auth", "bot-desktop", # browser cookies / logins

View File

@@ -14,6 +14,7 @@ import tarfile
import pytest
from hermes_cli.profiles import export_profile
from plugins.teams_pipeline.store import DEFAULT_TEAMS_PIPELINE_STORE_FILENAME
# Long enough to match agent.redact prefix patterns (sk- + 10+ chars).
_LEAKED_KEY = "sk-or-v1-reallyLongSecretKeyValue12345678"
@@ -31,6 +32,7 @@ _EXTRA_STORES = {
".op.env", "npmrc", "honcho.json", "google_chat_user_token.json", "google_chat_user_oauth_pending",
"workspace/meetings/node_token.json", "weixin/accounts", ".copilot_jwt.json", "proxy", "chrome-debug",
"home/.git-credentials", "home/.config/gh/hosts.yml", "backups", "state-snapshots",
DEFAULT_TEAMS_PIPELINE_STORE_FILENAME, "mem0.json",
}

View File

@@ -87,7 +87,7 @@ Not a fit:
- **You want to hand someone your setup once, right now.** A distribution needs a repo, a manifest, and a `.gitignore`. `/export` needs none of that — see [Export and import a profile file](#export-and-import-a-profile-file). Same for backing up or moving a profile to a new machine.
- **You want to share your desktop theme and layout.** A distribution carries the agent — SOUL, config, skills, cron, MCP, plugins. An export made from the desktop app also carries the look: skin, light/dark mode, custom themes, rail color, and window layout.
- **You want to share API keys alongside the agent.** `auth.json`, `.env` and the other credential stores Hermes reads from a profile (`.op.env`, `npmrc`, OAuth and bot token files, `honcho.json`, `mcp-tokens/`, `vault/`, `proxy/`, browser profiles, platform sessions) are deliberately excluded from distributions. Each installer brings their own credentials. (Export files strip them too.)
- **You want to share API keys alongside the agent.** `auth.json`, `.env` and the other credential stores Hermes reads from a profile (`.op.env`, `npmrc`, OAuth and bot token files, `honcho.json`, `mem0.json`, `teams_pipeline_store.json`, `mcp-tokens/`, `vault/`, `proxy/`, browser profiles, platform sessions) are deliberately excluded from distributions. Each installer brings their own credentials. (Export files strip them too.)
- **You want to share memories / sessions / conversation history.** Those are user data, not distribution content. Never shipped. (Export files are different here — read [what an export contains](#what-an-export-file-contains) before sending one.)
:::caution
@@ -686,7 +686,7 @@ You cannot import as `default` — that name is the built-in root profile (`~/.h
### What an export file contains
Always excluded, both profile types: `auth.json`, `.env` and the other credential stores Hermes reads from a profile (OAuth and bot token files such as WeChat's `weixin/accounts/`, `honcho.json`, `mcp-tokens/`, `vault/`, the iron-proxy keys in `proxy/`, browser profiles including the `/browser connect` one in `chrome-debug/`, platform sessions and pairing stores). Your API keys never leave the machine. `honcho.json` holds the Honcho API key and OAuth grant next to its settings, so after an import run `hermes honcho setup` again.
Always excluded, both profile types: `auth.json`, `.env` and the other credential stores Hermes reads from a profile (OAuth and bot token files such as WeChat's `weixin/accounts/`, `honcho.json`, `mcp-tokens/`, `vault/`, the iron-proxy keys in `proxy/`, browser profiles including the `/browser connect` one in `chrome-debug/`, platform sessions and pairing stores, the Teams pipeline's `teams_pipeline_store.json` with its Graph webhook `clientState`). Your API keys never leave the machine. `honcho.json` and `mem0.json` can hold the provider's API key next to its settings, so after an import run `hermes honcho setup` or `hermes memory setup` again.
**The default profile** (`~/.hermes`) is exported through an allow-list — only known Hermes artifacts, so an unrelated file sitting in your home directory can't get swept in:

View File

@@ -66,7 +66,7 @@ hermes profile install github.com/you/my-research-agent --alias
不适合的场景:
- **你只想在自己的机器上备份一个 profile。** 使用 [`hermes profile export` / `import`](../reference/profile-commands.md#hermes-profile-export)——那正是这两个命令的用途。
- **你想随 agent 一起共享 API 密钥。** `auth.json`、`.env` 以及 Hermes 从 profile 读取的其他凭据存储(`.op.env`、`npmrc`、OAuth 与机器人 token 文件、`honcho.json`、`mcp-tokens/`、`vault/`、`proxy/`、浏览器 profile、平台会话)被刻意排除在分发之外。每个安装者使用自己的凭据。(导出文件同样会去除它们。)
- **你想随 agent 一起共享 API 密钥。** `auth.json`、`.env` 以及 Hermes 从 profile 读取的其他凭据存储(`.op.env`、`npmrc`、OAuth 与机器人 token 文件、`honcho.json`、`mem0.json`、`teams_pipeline_store.json`、`mcp-tokens/`、`vault/`、`proxy/`、浏览器 profile、平台会话)被刻意排除在分发之外。每个安装者使用自己的凭据。(导出文件同样会去除它们。)
- **你想共享记忆 / 会话 / 对话历史。** 这些是用户数据,不是分发内容,永远不会被发送。
## 生命周期:从作者到安装者再到更新