pi-roundtable 0.33.0 → 0.34.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.34.0] - 2026-11-04
9
+
10
+ This is a minor release with a breaking default: an agent's shell no longer gets `GH_TOKEN`.
11
+
12
+ ### Changed
13
+
14
+ - `DEFAULT_SHELL_PASS` is empty: without `shellEnv.pass` no host secret reaches an agent's shell or a coding worker's `bash`, `GH_TOKEN` included. A public host's token is often broad, and 0.33.0 handed it to every agent's shell without the host asking. The coding shelf's git and gh calls (`repo_add`, fetch, `repo_push`) still get the token through the coding plugin's `githubToken`, which is unaffected.
15
+
16
+ ### Migration
17
+
18
+ - A host whose agents run `gh`, or `git push` through `gh auth git-credential`, in their shell names the token: `shellEnv: { pass: ["GH_TOKEN"] }`, or better a narrower token given in `set` as `GH_TOKEN`.
19
+
8
20
  ## [0.33.0] - 2026-11-04
9
21
 
10
22
  This is a minor release with breaking defaults: the agents' shell and the coding plugin's workers no longer inherit the host's environment, and more shell commands are held. See the migration notes below.
package/README.md CHANGED
@@ -274,7 +274,7 @@ pi-roundtable runs one assistant for one owner.
274
274
  - **Approvals.** A held call is approved only by the speaker whose turn held it, at a tier that still holds the call, or, in a shared conversation, by an owner, on its card or by a confirming message. In a private conversation nobody else may, and a call above the speaker's tier is not approved there.
275
275
  - **Conversations.** In Discord an agent's channel and a group room are shared: everyone who writes there adds to one conversation the agent reads. A web chat conversation belongs to the person who opened it: in the web chat only they may read it, write in it, or answer its prompts, but the owner can read it through the owner console ([pi-roundtable-web](packages/web)), and the operator through the database and the data directory.
276
276
  - **Memory isolation.** Memory follows the principal, not owner tier: a private conversation's person, or the current speaker in a shared room. Link accounts to share one person's memory across Discord and web. In shared requests and summaries, memory-tool and memory-loaded-worker exchanges (arguments and results together) are hidden from other speakers, and earlier reasoning is removed with provider-aware handling. Other tools' arguments and public assistant replies remain public, even if the model repeats private memory there; this is not general secret-flow prevention. Third-party compactors must use `privateCompaction` before summarizing shared history. `claude-bridge` shared turns refuse when raw reader records, including compacted turns, show another reader's private memory (even prompt-only memory and its reasoning), or an exchange is hidden from the current reader. A turn with no private memory does not block other readers, and disabling future memory does not bypass prior private history; admitting other people only warns at boot and in doctor. SYSTEM counts as primary owner for this core guard alone, so it can read and publicly repeat the owner's retained exchanges/reasoning; pre-0.9 untagged built-in memory results before the first scope record retain owner attribution. Sandbox party-wide prompt blocks must explicitly use `memory.visibility: "shared"`, and private turns require worker capabilities. Bridge replays unfiltered history outside these projections; see the [exact rule and remaining risk](docs/migration-0.9.md#claude-bridge-guard).
277
- - **The host shell.** An agent's shell runs as the host's user. Holds keep risky commands behind a card; they are not a sandbox. The shell gets only part of the host's environment (the paths, user, locale, terminal, `TMPDIR` and proxies, plus `GH_TOKEN` and what `shellEnv` adds), so the bot tokens, model logins, `DATABASE_URL` and keys the host holds stay in the host process; printing the environment, reading a secret file such as `.env` or `~/.ssh/*`, and `gh auth token` are held as `shell.secret-read`, which yolo mode always cards; a secret's value in a tool's output is replaced with `****`. This stops casual and accidental leaks, not a determined command run as the same user, which can read `/proc/<host pid>/environ` and any file that user can. To keep secrets from the agents, run their shells under a dedicated account without the `docker` group (membership in it equals root), or use [pi-roundtable-sandbox](packages/sandbox).
277
+ - **The host shell.** An agent's shell runs as the host's user. Holds keep risky commands behind a card; they are not a sandbox. The shell gets only part of the host's environment (the paths, user, locale, terminal, `TMPDIR` and proxies, plus what `shellEnv` adds), so the bot tokens, model logins, `GH_TOKEN`, `DATABASE_URL` and keys the host holds stay in the host process; printing the environment, reading a secret file such as `.env` or `~/.ssh/*`, and `gh auth token` are held as `shell.secret-read`, which yolo mode always cards; a secret's value in a tool's output is replaced with `****`. This stops casual and accidental leaks, not a determined command run as the same user, which can read `/proc/<host pid>/environ` and any file that user can. To keep secrets from the agents, run their shells under a dedicated account without the `docker` group (membership in it equals root), or use [pi-roundtable-sandbox](packages/sandbox).
278
278
  - **Model credentials.** Every turn, whoever speaks, runs on the host's model login and is billed to it. Per-person credentials are planned for a later release.
279
279
  - **Data.** Conversations, memory, and schedules sit unencrypted in PostgreSQL and the data directory.
280
280
 
package/README.zh-TW.md CHANGED
@@ -264,7 +264,7 @@ pi-roundtable 為一位擁有者執行騎士。
264
264
  - **核准。** 暫緩的呼叫只由當輪暫緩它的發言者核准,而且當下 tier 仍要足夠;在共用對話裡,擁有者也可以在卡片上或用確認訊息核准。私人對話裡別人都不能核准,高於發言者 tier 的呼叫在那裡也不會被核准。
265
265
  - **對話。** Discord 裡智慧體的頻道和群組房間是共用的:在那裡發言的每個人,都會寫進智慧體讀取的同一段對話。網頁聊天的對話屬於開啟它的人:在網頁聊天裡只有開啟者本人能讀、能發言、能回答它的提問,但擁有者可以透過擁有者主控台([pi-roundtable-web](packages/web))讀取,營運者也能從資料庫和資料目錄讀到。
266
266
  - **記憶隔離。** 記憶依 principal 分開,不依擁有者 tier 判斷。私人對話讀本人的,共用對話讀當輪發言者的;連結 Discord 與網頁身分後,同一個人共用一份記憶。在共用對話送給模型的請求和摘要裡,記憶工具與載入記憶的 worker 的呼叫(參數和結果成對)會對其他發言者隱藏,先前回合的 reasoning 則依 provider 清除。其他工具的參數和公開的騎士回覆仍是公開內容,即使模型在裡面重述私人記憶;這不是一般的秘密流向防護。第三方摘要器必須先使用 `privateCompaction`,才能摘要共用歷史。`claude-bridge` 的共用回合只在原始讀者紀錄(含已壓縮的回合)顯示另一位讀者的私人記憶(連只放進 prompt 的記憶與其 reasoning 也算),或某個呼叫已對當前讀者隱藏時才被拒絕。沒有私人記憶的回合不會擋其他讀者,關掉之後的記憶也繞不過先前的私人歷史;開放其他人進來只會在開機和 doctor 裡警告。SYSTEM 只在這項核心防護裡算作主要擁有者,所以它能讀取並公開重述擁有者保留的呼叫與 reasoning;0.9 之前、第一筆範圍紀錄之前未標記的內建記憶結果,仍歸屬擁有者。沙盒的全場共用 prompt 區塊必須明確使用 `memory.visibility: "shared"`,私人回合需要 worker 能力。Bridge 會在這些投影之外重播未過濾的歷史;見[確切規則與剩餘風險](docs/migration-0.9.md#claude-bridge-guard)。
267
- - **主機上的 shell。** 智慧體的 shell 以主機的使用者身分執行。暫緩只是把有風險的指令擋在卡片後面,不是沙箱。shell 只拿到主機環境變數的一部分(路徑、使用者、語系、終端機、`TMPDIR`、proxy,加上 `GH_TOKEN` 與 `shellEnv` 額外給的),所以主機持有的 bot token、模型登入、`DATABASE_URL` 和金鑰都留在主機行程裡;印出環境變數、讀取 `.env` 或 `~/.ssh/*` 這類秘密檔案、`gh auth token` 會以 `shell.secret-read` 暫緩,yolo 模式一律出卡片;工具輸出裡的秘密值會換成 `****`。這擋得住隨手和意外的外洩,擋不住以同一個使用者刻意執行的指令:它讀得到 `/proc/<主機 pid>/environ`,也讀得到那個使用者能讀的任何檔案。要讓智慧體碰不到秘密,請讓它們的 shell 以不在 `docker` 群組裡的專用帳號執行(加入這個群組等同 root),或改用 [pi-roundtable-sandbox](packages/sandbox)。
267
+ - **主機上的 shell。** 智慧體的 shell 以主機的使用者身分執行。暫緩只是把有風險的指令擋在卡片後面,不是沙箱。shell 只拿到主機環境變數的一部分(路徑、使用者、語系、終端機、`TMPDIR`、proxy,加上 `shellEnv` 額外給的),所以主機持有的 `GH_TOKEN`、bot token、模型登入、`DATABASE_URL` 和金鑰都留在主機行程裡;印出環境變數、讀取 `.env` 或 `~/.ssh/*` 這類秘密檔案、`gh auth token` 會以 `shell.secret-read` 暫緩,yolo 模式一律出卡片;工具輸出裡的秘密值會換成 `****`。這擋得住隨手和意外的外洩,擋不住以同一個使用者刻意執行的指令:它讀得到 `/proc/<主機 pid>/environ`,也讀得到那個使用者能讀的任何檔案。要讓智慧體碰不到秘密,請讓它們的 shell 以不在 `docker` 群組裡的專用帳號執行(加入這個群組等同 root),或改用 [pi-roundtable-sandbox](packages/sandbox)。
268
268
  - **模型憑證。** 每一輪不論誰發言,都用主機的模型登入執行、由它計費。每個人自己的憑證預計在之後的版本加入。
269
269
  - **資料。** 對話、記憶和排程以未加密的形式存在 PostgreSQL 和資料目錄裡。
270
270
 
package/docs/plugins.md CHANGED
@@ -1210,8 +1210,8 @@ const shell = shellHoldRuleFor({
1210
1210
 
1211
1211
  The agents' `bash` does not inherit the host process's environment.
1212
1212
  It gets the names in `SHELL_ENV_NAMES` (`PATH`, `HOME`, `USER`, `LOGNAME`, `SHELL`, `LANG`, `LANGUAGE`, `LC_*`, `TZ`, `TERM`, `TMPDIR`, the proxy variables in both cases, `SSL_CERT_FILE`, `SSL_CERT_DIR`, and Pi's `PI_*` session names), and what the host's `shellEnv` adds: `pass`, more host variables by name (a trailing `*` matches a prefix), and `set`, fixed values that win.
1213
- Without `pass` it is `DEFAULT_SHELL_PASS`, `["GH_TOKEN"]`, so `gh` and a `git push` through `gh auth git-credential` work in the shell; `pass: []` keeps it out.
1214
- Any other secret the host needs (a bot token, a model login, `DATABASE_URL`) stays in the host process; give a shell one only by naming it:
1213
+ Without `pass` it is `DEFAULT_SHELL_PASS`, empty: no host secret reaches the shell, `GH_TOKEN` included.
1214
+ A secret the host needs (a bot token, a model login, `DATABASE_URL`, `GH_TOKEN`) stays in the host process; give a shell one only by naming it, for example a token for `gh` and a `git push` through `gh auth git-credential`, preferably a narrower one than the host's in `set`:
1215
1215
 
1216
1216
  ```ts
1217
1217
  export default {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-roundtable",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "description": "A plugin-driven Pi agent server for one owner, reached through Discord or the web",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -20,8 +20,8 @@ export interface ShellEnvConfig {
20
20
  * What the agents' shell gets of the host's environment besides `SHELL_ENV_NAMES` (the user,
21
21
  * locale, terminal, paths and proxies): host variables to `pass` by name and fixed values to
22
22
  * `set`. Plugins read it as `env.shellEnv` for shells of their own. Default: `pass` is
23
- * `DEFAULT_SHELL_PASS` (GH_TOKEN, so gh and git in the shell keep working); give `pass` to
24
- * replace it, `pass: []` for no host secret in the shell at all.
23
+ * `DEFAULT_SHELL_PASS`, empty, so no host secret reaches the shell; a shell that runs `gh` or
24
+ * `git push` needs a token named, as in `pass: ["GH_TOKEN"]`, or a narrower one in `set`.
25
25
  */
26
26
  shellEnv?: ShellEnv;
27
27
  }
@@ -99,9 +99,7 @@ export function frozenShellEnv(shellEnv: ShellEnv): Readonly<ShellEnv> {
99
99
  }
100
100
 
101
101
  /** The host variables an agent's shell gets beyond `SHELL_ENV_NAMES` when `shellEnv.pass` is not given. */
102
- export const DEFAULT_SHELL_PASS: readonly string[] = Object.freeze([
103
- "GH_TOKEN",
104
- ]);
102
+ export const DEFAULT_SHELL_PASS: readonly string[] = Object.freeze([]);
105
103
 
106
104
  /** The environment of an agent's shell: `childEnv` with `shellEnv`, whose `pass` defaults to `DEFAULT_SHELL_PASS`. */
107
105
  export function shellChildEnv(