Repository navigation
feat(workflow): add owner-only agent mentions for workflow messages - #9227
Merged
Merged
Conversation
Record what caused each workflow run and, when BUZZ_SECURE_WORKFLOWS is on, stamp buzz:workflow-mention only on messages from runs that the owner or a timer caused and whose definitions use only send_message and delay steps. Signed-off-by: Will Pfleger <[email protected]> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
… resume Signed-off-by: Will Pfleger <[email protected]> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Co-authored-by: Will Pfleger <[email protected]> Signed-off-by: Will Pfleger <[email protected]>
…e-mode * origin/main: (36 commits) feat(relay): let an operator mint invites for a community owner or admin (#9265) fix: inline ARM64 atomics in Sprig image build (#9291) fix(mobile): show observed thread replies in Activity (#9286) Enable mobile huddles with Codex agents (#9269) fix(mobile): read mentions taller than the screen (#9243) test(relay): give every media e2e upload its own blob hash (#9272) Add invite preview video and fallback poster (#9282) NEXUS-4336: Wait for desktop-provider socket ownership proof (#9270) fix: unblock image audit with patched MCP SDK (#9287) feat(ci): allow admin dispatch of desktop candidate validation (#9288) feat(mobile): tag the reacted-to message author on reactions (#9141) fix(mobile): steady New DM picker rows and animate picks (#9249) perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158) fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235) fix(mobile): read only shown events from filtered Activity rows (#9215) fix(mobile): show the channel name as the notification subtitle (#9173) fix(mobile): keep Home's header clean under sheets (#9152) fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150) mobile: add follow and remind actions to inbox row menu (#9142) fix(mobile): start no threads in Solo chats (#9123) ... Signed-off-by: Will Pfleger <[email protected]>
…and NIP-11 field
BUZZ_SECURE_WORKFLOWS=true|false becomes BUZZ_WORKFLOW_AGENT_MENTIONS=any|owner.
A send_message step that withholds buzz:workflow-mention tags records
agent_mentions {withheld, reasons} in its trace output, logs at info and
counts buzz_workflow_agent_mentions_withheld_total by reason. The NIP-11
document always advertises workflow_agent_mentions.
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Signed-off-by: Will Pfleger <[email protected]>
…e-mode * origin/main: ci(docker): skip relay image publishes for main pushes outside the build context (#9310) Add manual-only relay image publishing (#9303) fix(mobile): bump Flutter to 3.47.9 for Android TLS fix (#9309) Serve video and poster previews for invite links (#9306) docs: point the README to Buzz 1.0 in block/buzz-app (#9296) fix(db): give the replica-fence probe its own pool and instrument it (#9297) fix(relay): never close connections when cross-node fan-out falls behind (#9302) test: fix timing-dependent unit tests in buzz-cli, buzz-agent and buzz-admin (#9273) fix(ci): classify hermit retry timeouts by watchdog kill, not whole seconds (#9274) test(ios): wait for a key, foreground-active window before presenting in RunnerTests (#9275) test(desktop): wait on real readiness signals in audience and community-rail specs (#9277) Signed-off-by: Will Pfleger <[email protected]>
The sink now returns whether it left off any buzz:workflow-mention tag, and the executor records the trace key, log and counter only then. Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> Signed-off-by: Will Pfleger <[email protected]>
wpfleger96
force-pushed
the
duncan/workflow-secure-mode
branch
from
November 10, 2026 01:20
2a12e7e to
a9f0559
Compare
…ource Co-authored-by: Will Pfleger <[email protected]> Signed-off-by: Will Pfleger <[email protected]>
Co-authored-by: Will Pfleger <[email protected]> Signed-off-by: Will Pfleger <[email protected]>
wpfleger96
marked this pull request as ready for review
November 12, 2026 18:18
🔐 Codex Security Review
Review SummaryOverall Risk: NONE
FindingsNo concrete security, correctness, or reliability findings were identified. Notes
Generated by Codex Security Review | |
brow
approved these changes
Nov 12, 2026
TheSentinel454
added a commit
that referenced
this pull request
Nov 12, 2026
…04 (#9418) ## Summary Two separate CI breaks are hitting every PR right now. Each one blocks a required check, and neither fix can go green on its own, so this PR fixes both. **1. Rust test targets stopped compiling on main at fc8c802.** #9227 added a required `RunCause` argument to `create_workflow_run` and a `may_direct_agents` flag to `ActionSink::send_message`. Two tests that merged around the same time still used the old signatures: - `attach_rejects_run_from_another_workflow` in `crates/buzz-db/src/store/workflow.rs` (from #8317) - the agent-DM refusal test in `crates/buzz-relay/src/workflow_sink.rs` (from #9371) Each PR passed CI on its own base. Together they break Rust Lint, Unit Tests, Windows Rust and the Desktop E2E Relay artifact build (main CI run 43291564834). The fix passes `RunCause::Schedule` and `true`, matching the neighbouring tests. Neither test is about run cause or agent mentions, so neither assertion changes. **2. Desktop E2E Integration fails on GitHub's new Ubuntu 26.04 runners.** `ubuntu-latest` is rolling to 26.04, and Playwright 1.60 (our lockfile) fails with `Playwright does not support chromium on ubuntu26.04-x64`. Playwright 1.61 is the first release that knows ubuntu26.04. This PR bumps `@playwright/test` to `^1.65.0` in `desktop/`, `web/` and `admin-web/` and regenerates `pnpm-lock.yaml`. It also pins every `ubuntu-latest` job in `ci.yml` and `_ci-*.yml` to `ubuntu-26.04`, so the next runner image change arrives in a reviewed diff. macOS and Windows jobs are unchanged. The newer Chromium bundled with Playwright 1.65 changed two smoke specs. It reports Tailwind's `items-end` as `align-items: flow-end` (`doctor-states` now accepts `flex-end` or `flow-end`), and it draws the textarea resize grip differently, so the `workflow-template-variable-autocomplete` baseline is refreshed from the ubuntu-26.04 CI output. It also exposed a timing race in `profile.spec.ts` "owned agent profile stays in parity": when the Message click lands while the profile panel is still settling, Playwright's scroll-into-view retry scrolls the profile body, which hides the owned-agent action row (aria-hidden + inert) for good. The test now pins the body to the top and waits for the row before clicking (12/12 repeats plus the full profile spec pass on Linux). ## Verification - `cargo clippy -p buzz-db -p buzz-relay --tests -- -D warnings` is clean on fc8c802 with commit 1 applied. - `pnpm install --frozen-lockfile` succeeds with the new lockfile, and `playwright --version` reports 1.65.0. - `tsc --noEmit` passes for `desktop`, `web` and `admin-web`. - This PR's CI is the E2E check on 26.04. ## Notes - Workflows that don't run on PRs (release, helm charts, sprig, image builds, codex-security-review) still use `ubuntu-latest`. This PR can't exercise them, so they're left for a follow-up. - The hermit-pinned actionlint (1.7.12) doesn't know the `ubuntu-26.04` label yet. CI only actionlints `codex-security-review.yml`, which this PR doesn't touch. ## Simpler No production code changes. The runner pin swaps an implicit moving target for an explicit one. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Luke Tornquist <[email protected]> Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
TheSentinel454
added a commit
that referenced
this pull request
Nov 12, 2026
Rebasing onto main picked up #9227, which made `RunCause` a required argument to `create_workflow_run`. Pass `RunCause::Schedule` in the new reference and delete-race tests, matching the existing callers. Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Luke Tornquist <[email protected]>
ravarora2
added a commit
that referenced
this pull request
Nov 12, 2026
…small * origin/main: feat(workflow): add owner-only agent mentions for workflow messages (#9227) Adapt iPhone Duo layouts, rail navigation, and native sheets (#8568) End last-human agent Huddles and preserve mobile transcript access (#9375) Signed-off-by: Ravneet Arora <[email protected]>
matt2e
added a commit
that referenced
this pull request
Nov 14, 2026
… closes (#9440) ## Summary `desktop/src/features/terminal/TerminalSubstrate.test.mjs` can pass every test and then run the Desktop JS job out of memory several minutes later. This moves the React Testing Library unmount from `beforeEach` to `afterEach`, so no tree is still mounted when the jsdom window closes. Only the test file changes (6 insertions, 2 deletions). Commit (cherry-picked unchanged from a local flake-fix series): - `test(desktop): unmount every TerminalSubstrate tree before the window closes` ### CI sighting One sighting was found in the CI runs from 7 to 12 November 2026 that were searched: - 9 November 2026, "Desktop Domain / Desktop JS", run 42706004493 attempt 1 (on #9227; the rerun passed): - https://github.com/block/buzz/actions/runs/42706004493/job/129463488242 In that job the suite reported 6,950 of 6,951 passing. The log shows `An update to TerminalSubstrate inside a test was not wrapped in act(...)` at 21:54:33Z, then `FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory` at 22:02:17Z, and the file is reported as failed at file level (`test at src/features/terminal/TerminalSubstrate.test.mjs:1:1`) after 504.6 s. ### Root cause The file called `cleanup()` only in `beforeEach`, so the last test's tree was still mounted when `after(() => dom.window.close())` ran. If ThemeProvider's asynchronous palette update landed after that close, it re-rendered the substrate, the splash effect's palette guard passed, and `requestAnimationFrame` on the closed window started a fresh jsdom interval that nothing cleared. That 60 Hz loop repainted the banner into the test's recording `getContext` stub indefinitely, and `paintLog` grew until the heap limit. No individual test hangs, so a per-test timeout would not catch it. ### Fix `afterEach(() => cleanup?.())` unmounts every tree, including the last, before `after()` closes the window. The `beforeEach` call became redundant and is removed. No assertions change, and no timeouts, retries or sleeps are added. ### Related issue N/A (flake fix). No existing issue or PR for this failure was found. Three open PRs touch the same test file (#5057, #5485, #7777); none of them changes where `cleanup` runs. ### Testing Human testing is still required. This PR does not carry `buzz-review-completed`; the author has not yet run this test themselves on this branch. #### Verification of the fix (before this branch was split out) - The test file, 5 consecutive runs: 25 of 25 tests passed each time in about 6.8 s, with no `act` warning. - The CI out-of-memory failure was not reproduced with the real test file. Its mechanism was reproduced in a scratch harness with the same stubs: without cleanup before the window close, 3 of 3 runs left the palette unresolved at close, added 11,556 `paintLog` entries per 100 ms, kept one live timer, and never exited. With cleanup before the close, 3 of 3 runs added no entries, left no timers, and exited on their own. #### Local checks on this branch The push ran the repository's full pre-push hook set from a checkout of this branch's head (`7f4117340`), with no lanes excluded and without `--no-verify`. The branch is one commit behind `main`; that commit changes only mobile and docs files, none of them touched here. Ran and passed: - `branch-skew`, `push-head-scope` and `file-size-check` - `desktop-check` (`pnpm check`) - `desktop-typecheck` (`pnpm typecheck`) - `desktop-test` (`pnpm test`, the full desktop unit suite, which includes `TerminalSubstrate.test.mjs`) Did not run: - `rust-tests`, `desktop-tauri-checks` and `mobile-checks`. The hook selects lanes by changed path, and this branch changes no Rust, Tauri or mobile file. - Desktop builds and the Playwright E2E suites, which are CI-only. - `just ci`. - The 5-run repetition and the scratch harness above were not repeated on this branch. A green run does not prove the flake is gone: the failure needs the palette update to land after the window closes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: mtoohey <[email protected]> Signed-off-by: Matt Toohey <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]>
wpfleger96
added a commit
that referenced
this pull request
Nov 14, 2026
#9500) …er (#9371)" This reverts commit a09b84d, resolved against current main (#9227 changed the neighboring workflow_sink tests). Supersedes #9393 Signed-off-by: Joah Gerstenberg <[email protected]> Co-authored-by: Joah Gerstenberg <[email protected]> Co-authored-by: Hertz <c6741012416ef5c49a865db79682113385c5fb998e8c890234fb442b59e22748@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds owner-only agent mentions, a relay setting,
BUZZ_WORKFLOW_AGENT_MENTIONS. Its values areany, the default and today's behaviour, andowner. Any other value fails startup. Withowner, a workflow message can direct an agent only if the run's cause and definition allow it. The setting is relay-wide.Recording what caused each run.
workflow_runsgetscause_sourceandcause_pubkeycolumns. Migration0087adds them with named checks markedNOT VALID, so it does not scan existing rows under its lock;0088validates the checks separately.create_workflow_runnow takes a requiredRunCause, so every place that creates a run has to set one:Rows written before this change have no cause. A stored source without the pubkey it requires, or with one it forbids, is read as no cause.
Deciding eligibility. A run's messages may direct agents only when all of these hold:
send_messageordelay. This is an allowlist, so any other action, including one added later, makes the definition ineligible, even when anif:skips that step;Webhook runs and runs with no recorded cause are never eligible. The executor decides this from
WorkflowConfig::agent_mentions, and passesActionSink::send_messagethe owner's stored step text with amay_direct_agentsflag. The sink addsbuzz:workflow-mentiontags only when the flag is set, and returnsSentMessage { event_id, agent_mentions_withheld }, which is true only when it left out a tag that a member named in both the stored and rendered text would otherwise have received. Webhook and manual runs start throughexecute_run, soexecute_from_stepis used only to resume after an approval.The gate. With
owner, the relay addsbuzz:workflow-mentiononly to messages from eligible runs. Messages from other runs still post with their plainptags and still notify people. Withany, mention tags are added exactly as before.Making it visible. When a
send_messagestep leaves the tags out:"agent_mentions": {"withheld": true, "reasons": [...]}, listing each reason that applies:cause(not started by the owner or a timer),steps(a step other thansend_messageordelay),resumed(resumed after an approval). The key is absent when nothing was withheld. The trace is what the app's run history shows;buzz_relay::workflow_agent_mentionstarget (visible under the default filter) with the community, workflow, run, step and reasons;buzz_workflow_agent_mentions_withheld_totalincreases once per reason, labelledreason.Discovery. The NIP-11 document always carries
"workflow_agent_mentions": "any" | "owner", so a missing field means an older relay.NOSTR.mdnow specifiesbuzz:workflow-mentionfor clients: what the tag means, the checks an agent makes before acting, that a relay may leave it out under a policy, and the NIP-11workflow_agent_mentionsfield. The relay policy itself is in the new operator guide,docs/operator-workflow-agent-mentions.md: the setting and its values, what counts as a run's cause for each trigger, which steps are allowed, the trace key, the log and metric, the NIP-11 field, when to useowner, rollout across pods, and what it doesn't cover. TheTESTING.mdand.env.exampleentries link to it.