From 63adb218e6bca4d15eb982925f7d8be6144659ba Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Fri, 29 May 2026 22:23:13 +0000 Subject: [PATCH] chore(coder): untrack live coder-providers.json, ship example The live config is read AND written by the coder (UI provider toggles PATCH it), so tracking it churned `git status`. Untrack it (now gitignored under data/*), add a tracked data/coder-providers.example.json reference, and update the .gitignore exception + CLAUDE.md/BOOCODER.md docs. Loader already falls back to {providers:{}} (built-ins only) when the live file is absent. + CHANGELOG v2.5.15. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 2 +- BOOCODER.md | 2 +- CHANGELOG.md | 4 ++++ CLAUDE.md | 2 +- data/coder-providers.example.json | 12 ++++++++++++ data/coder-providers.json | 3 --- 6 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 data/coder-providers.example.json delete mode 100644 data/coder-providers.json diff --git a/.gitignore b/.gitignore index 5f8ebd3..bb3c3ba 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,5 @@ data/* !data/AGENTS.md !data/skills/ !data/mcp.json -!data/coder-providers.json +!data/coder-providers.example.json codecontext/fork.tar.gz diff --git a/BOOCODER.md b/BOOCODER.md index 960e094..8e87d85 100644 --- a/BOOCODER.md +++ b/BOOCODER.md @@ -44,7 +44,7 @@ BooCoder's coding agents are a **config-backed registry**: built-ins live in `pr ### Config file: `data/coder-providers.json` -Resolved from `CODER_PROVIDERS_PATH` (default `/data/coder-providers.json`; dev/host path `/opt/boocode/data/coder-providers.json`). It is **tracked in git** via a `.gitignore` exception (the rest of `data/*` is ignored). A missing file, invalid JSON, or a schema mismatch all fall back to built-ins-only — loading never throws at startup. +Resolved from `CODER_PROVIDERS_PATH` (default `/data/coder-providers.json`; dev/host path `/opt/boocode/data/coder-providers.json`). It is **gitignored** — it's live runtime config that the coder reads *and writes* (UI toggles `PATCH` it), so tracking it would churn `git status`. The tracked reference is `data/coder-providers.example.json`; copy it to `coder-providers.json` to seed overrides. A missing file, invalid JSON, or a schema mismatch all fall back to built-ins-only — loading never throws at startup. ```json { diff --git a/CHANGELOG.md b/CHANGELOG.md index 62c0508..02af5fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes per release tag. Most recent on top, ordered by tag creation date (which matches the git history). Tag names follow `vMAJOR.MINOR.PATCH-slug` — the slug describes what shipped, so the tag name alone is enough to recall the batch. +## v2.5.15-acp-path-guard — 2026-05-29 + +Security fix + repo hygiene. Fixes a path-traversal in the ACP filesystem bridge (`acp-client-fs.ts`, flagged by the automated push security review): the worktree guard used an unbounded `startsWith(resolve(worktreePath))`, so a sibling path sharing the worktree as a string prefix (`-evil/…`) escaped the scope — and `writeWorktreeTextFile` writes to disk directly (no `pending_changes` gate), so a confused/buggy ACP agent could write outside its worktree. Now uses a separator-bounded check matching `write_guard.ts` (`resolve()` + `startsWith(root + sep)` / `=== root`) via a shared `resolveInWorktree`, with a regression test covering `../` traversal and the sibling-prefix bug. Symlink-swap/`O_NOFOLLOW` hardening was intentionally skipped — consistent with `write_guard`'s no-realpath stance, and the agent already runs with host FS access so this is a containment guard, not a trust boundary. Separately, stops tracking the live `data/coder-providers.json` (it's runtime config the UI reads *and writes* on provider toggles, which churned `git status`) — it's now gitignored with a tracked `data/coder-providers.example.json` reference; the loader falls back to built-ins-only when the live file is absent. The provider-type duplication (coder ↔ web) stays guarded by the existing text-identity `provider-types-parity.test.ts` — a shared package was considered and declined (drift is already prevented; not worth the Docker/build-order risk at solo scale). + ## v2.5.14-claude-md — 2026-05-29 Docs-only — CLAUDE.md session-learnings update, no code. Adds gotchas surfaced while shipping the v2.3 provider-lifecycle batch: the host `boocoder.service` keeps running the old process after `pnpm -C apps/coder build` (stale-process tell = new routes 404 while old routes 200, restart don't re-debug); the `boocode` container `build: .` deploys the working tree, so web edits are live on the Vite dev server but not production until `docker compose up --build -d boocode`; `PATCH /api/providers/config` replaces a provider's override wholesale (send `{...existing, enabled}` or a custom ACP entry's command is wiped) and `data/coder-providers.json` is live config not to be committed as code; external agents dispatch one-shot with no context/token tracking (only native `boocode` tracks ctx; OpenCode-as-server is the unshipped `v2-6-persistent-agent-sessions` plan); the `ui/` primitive inventory with `button role=switch` / Dialog fallbacks for the absent switch/sheet; and the mobile Dialog-with-list scroll-containment recipe. Also backfills previously-uncommitted doc bullets for the `v2.5.7`–`v2.5.11` coder work (provider-type parity test, async ACP command discovery, AgentComposerBar `installed` filter, provider-registry path disambiguation). diff --git a/CLAUDE.md b/CLAUDE.md index 9225eee..4df7497 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -88,7 +88,7 @@ Route registration: all routes registered in `index.ts` via `register*Routes(app - Frontend: NOT a separate SPA. BooCoder is a `'coder'` pane type within BooChat's SPA (`apps/web/`). `CoderPane.tsx` in `apps/web/src/components/panes/`. API requests go through `/api/coder/*` proxy (Vite dev + Fastify production) which rewrites to the boocoder host service (`BOOCODER_URL` env var, default `http://100.114.205.53:9502`). WS connects directly to `:9502`. - `apps/coder/web/` is a STANDALONE fallback SPA served at `:9502` directly. The PRIMARY BooCoder frontend is the `CoderPane` in BooChat's SPA (`apps/web/src/components/panes/CoderPane.tsx`), accessible via the "Coder" pane in the workspace at `code.indifferentketchup.com`. Both exist; the pane is what Sam uses. - **Provider snapshot lifecycle** (`apps/coder/src/services/`): `provider-config.ts` (Zod config, never-throws on bad input) → `provider-config-registry.ts` (`buildResolvedRegistry`, singleton) → `provider-snapshot.ts` (two-tier probe: tier-1 fast presence, tier-2 cold ACP probe skipped unless force / stale `PROVIDER_PROBE_TTL_MS` 24h / dbEmpty; cached). Verify live: `curl http://100.114.205.53:9502/api/providers/snapshot` — returns providers + models + commands, the exact shape `AgentComposerBar` renders. -- `PATCH /api/providers/config` replaces a provider id's override object **wholesale** (per-id shallow merge) — to flip one field send `{...existing, enabled}`, or a custom ACP entry's `command`/`label` is wiped and it drops out of the resolved registry. `data/coder-providers.json` is the live config (tracked via a `.gitignore` exception, bind-mounted); UI toggles mutate it on disk → working-tree drift, don't commit it as a code change. +- `PATCH /api/providers/config` replaces a provider id's override object **wholesale** (per-id shallow merge) — to flip one field send `{...existing, enabled}`, or a custom ACP entry's `command`/`label` is wiped and it drops out of the resolved registry. `data/coder-providers.json` is **gitignored** (it's live runtime config — the coder reads AND writes it on UI toggles); the tracked reference is `data/coder-providers.example.json`. The loader falls back to `{providers:{}}` (built-ins only) when the live file is absent, so a fresh checkout needs no copy. - External agents dispatch **one-shot** (`opencode acp` / `goose acp` / `qwen --acp`) and report no context-window/token usage; only native `boocode` (llama-swap engine) tracks ctx. OpenCode-as-HTTP-server (warm process + `@opencode-ai/sdk`, the source of a real context bar) is the **planned, unshipped** `openspec/changes/v2-6-persistent-agent-sessions` batch; Paseo's per-provider native clients (design §12) were deliberately not ported. ### Frontend (`apps/web/src/`) diff --git a/data/coder-providers.example.json b/data/coder-providers.example.json new file mode 100644 index 0000000..8295c9e --- /dev/null +++ b/data/coder-providers.example.json @@ -0,0 +1,12 @@ +{ + "providers": { + "goose": { "enabled": false }, + "amp-acp": { + "extends": "acp", + "label": "Amp", + "description": "ACP wrapper for Amp", + "command": ["amp-acp"], + "enabled": true + } + } +} diff --git a/data/coder-providers.json b/data/coder-providers.json deleted file mode 100644 index 87b07bc..0000000 --- a/data/coder-providers.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "providers": {} -}