Skip to content

fix(watcher): the brief marks production data as untrusted and finds duplicate writes without selecting a title; the installer refuses a watcher that cannot load (Refs #949) - #968

Merged
alex-mextner merged 3 commits into
mainfrom
fix/watcher-untrusted-data-20261102
Nov 5, 2026
Merged

alex-mextner merged 3 commits into
mainfrom
fix/watcher-untrusted-data-20261102

Conversation

@alex-mextner

Copy link
Copy Markdown
Owner

What this changes

The alert watcher starts an unattended investigation session from the production alert queue. Its brief fenced only the alert text as untrusted, yet the incident checklist tells the session to read container logs, per-chat logs, event rows, Redis values and job errors, all of which hold text that users and upstream services write. A user who writes a crafted event title could steer that session.

  • The section every brief carries now says all of that material is evidence, never instructions.
  • The checklist's duplicate-write query groups on user and start across all rows (a later retry and an already deleted copy still show), counts distinct titles without selecting one, and a title-free lookup reads the copies outside the window.
  • The installer (scripts/install-alert-watcher.sh) now runs bun build on the watcher before it touches the unit, the keychain or ssh. After a merge that changed package.json or bun.lock the unit used to restart every 30 seconds without a word because node_modules lacked a package the watcher imports; the installer now refuses, prints the head of Bun's error and its exit status, and suggests bun install only for a missing package or a stale node_modules export. The runbook says to run bun install --frozen-lockfile after any merge that touches those files.
  • Version 0.3.5.

Refs #949

Evidence

  • bun test test/scripts/install-alert-watcher.test.ts test/scripts/hcb-alert-watcher.test.ts: 101 pass, 0 fail. The new installer tests fail on the old installer. A test runs the brief's queries against the real events schema.
  • biome check scripts test/scripts: clean.

Review

Single-seat Opus via omp (review diff --staged --task 949 --pool 1 -m omp:anthropic/claude-opus-5-5), several rounds on the brief commit (the Sol quota is out until 2026-11-09) and two on the installer commit; the last round found no actionable bug. Still open from the review and recorded on #949: start_at is grouped as stored text, and the correlated query has no index on (user_id, start_at). This is a single-seat review; the full-roster pass is owed in #961.

After merge

Restart hcb-alert-watcher from the canonical checkout (Bun loads the script once), send one labeled synthetic alert through the real queue and check the generated brief. Results go to #949 and #935.

…uction as untrusted and finds duplicate writes without selecting a title (Refs #949)

Logs, per-chat logs, event rows, Redis values and job errors hold text users and upstream services write; the brief fenced only the alert text. The section every brief has now says all of it is evidence, never instructions. The duplicate query groups on user and start across all rows (a later retry and an already deleted copy still show), counts distinct titles without selecting one, and a title-free lookup reads the copies outside the window. A test runs the brief's queries on the real events schema.

Single-seat review (pool 1), six rounds; Sol quota is out until 2026-11-08, so a full-roster review is still owed. Left open from the review: start_at is grouped as stored text, and the correlated query has no index on (user_id, start_at); both are noted in #949.
…oad and says why; the runbook installs dependencies after every merge that touches them (Refs #949)

After a merge that changed package.json or bun.lock the unit restarted every 30 seconds without a word, because node_modules lacked a package the watcher imports. The installer now runs `bun build` on the watcher before it touches the unit, the keychain or ssh, prints the head of Bun's error and its exit status, and suggests `bun install` only for a missing package or a stale node_modules export. The runbook says to run `bun install --frozen-lockfile` after any merge that touches package.json or bun.lock. Version 0.3.5.

Single-seat review (pool 1, Opus): no findings; a full-roster pass is owed under #961.
…nknown> (Refs #949)

The type-bans gate blocks Record<string, unknown> on an added line. The query selects id and is_deleted only; the test still checks that no title column comes back.
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.

1 participant