Skip to content

fix(desktop): propagate respond_to changes from persona to linked agent instances - #6039

Open
BradGroux wants to merge 2 commits into
block:mainfrom
BradGroux:fix/respond-to-propagation
Open

fix(desktop): propagate respond_to changes from persona to linked agent instances#6039
BradGroux wants to merge 2 commits into
block:mainfrom
BradGroux:fix/respond-to-propagation

Conversation

@BradGroux

Copy link
Copy Markdown
Contributor

What users saw

Changing an agent's inbound author gate (e.g. "Only me" → "Allowlist") in the Desktop persona edit dialog saved the definition fields (definition_respond_to, definition_respond_to_allowlist) but never reached the runtime fields (respond_to, respond_to_allowlist) that build_respond_to_env reads at spawn. The agent kept booting with the stale gate (e.g. owner-only) across restarts while the UI showed the updated value (allowlist). No error was surfaced.

The issue was security-relevant in one direction: a user who widened access saw the wider setting in the UI, but the agent silently kept the narrower gate and dropped messages from allowlisted identities.

Why it happened

The persona edit command (update_persona_with in desktop/src-tauri/src/commands/personas/update.rs) saves the definition via apply_persona_behavior, then propagates changes to linked agent instances. But the propagation block only fired when avatar_changed || name_changed — behavioral changes (respond_to mode + allowlist) were not in the trigger condition, so a respond_to-only edit saved the definition and skipped the runtime record entirely.

The runtime record's respond_to / respond_to_allowlist fields are the ones build_respond_to_env reads at spawn (desktop/src-tauri/src/managed_agents/runtime.rs:769). The definition_* fields are stored on the record for catalog/publish purposes but are never consulted at spawn time.

What changed

Added behavior-change detection in update_persona_with: before apply_persona_behavior runs, the pre-edit respond_to and respond_to_allowlist are captured. After the apply, a behavior_changed flag compares old vs. new. When the flag is set, the propagation block (which already loads linked agent records for avatar/name changes) also copies the definition's respond_to onto each linked instance's runtime respond_to / respond_to_allowlist fields.

The persona stores respond_to in wire shape (Option<String>); the fix parses it to the typed RespondTo enum via RespondTo::parse_wire. An absent value falls back to OwnerOnly (the default). When the mode is not Allowlist, the allowlist is cleared (stale entries must not survive a mode toggle).

This does not change apply_persona_snapshot, which intentionally preserves instance-level overrides during re-snapshot at start/restore. The fix is scoped to the persona edit path only, matching the existing pattern for avatar and name propagation.

Testing

  • Full buzz-desktop lib suite: 2,440 passed, 0 failed, 15 ignored
  • cargo fmt clean
  • cargo clippy clean (no warnings)

The existing test resnapshot_does_not_clobber_record_quad_with_definition_absent_quad (which verifies that apply_persona_snapshot does NOT overwrite instance-level respond_to with definition defaults) still passes — confirming the fix respects instance-level overrides outside the persona edit path.

Closes #6026

@BradGroux
BradGroux requested a review from a team as a code owner August 16, 2026 12:52

@themiguelamador themiguelamador left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found three issues with the propagation approach:

  • P1 — A persona-template edit overwrote every linked instance's explicit access policy. Instance respond_to values can be deliberate overrides; the codebase preserves those overrides during resnapshot and surfaces persona drift separately. With this patch, changing a persona from owner-only to anyone silently widens even an instance intentionally pinned owner-only. That is the security-sensitive direction the fix must not introduce.
  • P2 — Invalid definition modes were silently converted to owner-only. RespondTo::parse_wire(wire).ok().unwrap_or_default() discards the parse error even though the type's documented invariant is to fail loudly rather than launch with a different audience.
  • P2 — The changed persistence behavior had no regression test. The cited existing resnapshot test exercises a different path and cannot catch either the broad overwrite or the original profile-edit omission.

The reported flow already has the correct scope boundary: after saving the persona, personaManagedAgentUpdate builds a patch for the single linked agent whose profile the user edited. I fixed #6026 there in commit a49142662 on review/pr-6039-fix, including null-definition → owner-only handling and exact allowlist synchronization, and removed the unsafe global backend propagation.

Verification: full Desktop frontend suite (4,956 passed); pnpm typecheck; pnpm check (clean for changed files; four pre-existing advisory diagnostics remain elsewhere); focused mapping regressions; git diff --check.

@BradGroux
BradGroux force-pushed the fix/respond-to-propagation branch from a072331 to 84a4707 Compare August 17, 2026 05:16
@BradGroux

Copy link
Copy Markdown
Contributor Author

Thanks @themiguelamador — the security-sensitive direction was the key insight.

Your fixes are folded into this branch (commit e671f5c0c):

  • Unsafe global backend propagation removed. The Rust-side behavior_changed logic that overwrote every linked instance's respond_to is gone. Changing a persona from owner-only to anyone no longer silently widens an instance intentionally pinned owner-only.
  • Fix moved to frontend personaManagedAgentUpdate. The patch now builds for the single linked agent whose profile the user edited, preserving instance-level overrides elsewhere. Null-definition → owner-only handling and exact allowlist synchronization are included.
  • Regression tests added. Four tests cover mode sync, allowlist sync, allowlist clearing on mode switch, and null → owner-only default. All 14 tests pass, tsc clean.

dm-builder and others added 2 commits August 17, 2026 14:59
…nt instances

When an agent's inbound author gate (respond_to) was changed via the
persona edit dialog, the definition fields (definition_respond_to,
definition_respond_to_allowlist) were saved correctly, but the runtime
fields (respond_to, respond_to_allowlist) that build_respond_to_env
reads at spawn were never updated. The propagation block in
update_persona_with only fired on avatar or display_name changes —
behavioral changes were silently dropped.

The agent kept booting with the stale gate (e.g. owner-only) across
restarts while the Desktop UI showed the updated value (e.g. allowlist).
No error was surfaced. The issue was security-relevant: a user who
widened access saw the wider setting in the UI but the agent silently
kept the narrower gate.

The fix detects behavior group changes (mode or allowlist) and
propagates the definition's respond_to onto each linked instance's
runtime fields in the same record-load-and-save cycle that already
handles avatar and name propagation. The persona's wire-shape
Option<String> is parsed to the typed RespondTo enum; an absent value
falls back to OwnerOnly (the default).

This does not change apply_persona_snapshot, which intentionally
preserves instance-level overrides during re-snapshot at start/restore.
The fix is scoped to the persona edit path only.

Closes block#6026

Co-authored-by: Brad Groux <brad@digitalmeld.communities.buzz.xyz>
Signed-off-by: Brad Groux <brad@digitalmeld.communities.buzz.xyz>
Signed-off-by: dm-builder <f01486f036641ccb52c11bb1e0ff2346ea89a8b4e3b49cd772249948f6fcbae6@digitalmeld.communities.buzz.xyz>
The Rust-side propagation overwrote every linked instance's respond_to
when the persona was edited, including instances with deliberate
per-instance overrides. The security-sensitive direction (widening
owner-only to anyone) was silently applied to all linked agents.

The correct scope is the frontend's personaManagedAgentUpdate, which
builds a patch for the single linked agent whose profile the user
edited. Add respondTo and respondToAllowlist fields to the update
function: sync the persona's mode (null defaults to owner-only) and
sync the allowlist only when mode is allowlist (clear otherwise).

Remove the behavior_changed block from the Rust update_persona_with
loop entirely — the frontend handles it for the one linked agent.

Add regression tests for mode sync, allowlist sync, allowlist clearing,
and null-to-owner-only fallback.

Addresses themiguelamador's review feedback.

Co-authored-by: Brad Groux <brad@digitalmeld.communities.buzz.xyz>
Signed-off-by: Brad Groux <brad@digitalmeld.communities.buzz.xyz>
@BradGroux
BradGroux force-pushed the fix/respond-to-propagation branch from e671f5c to a141446 Compare August 17, 2026 20:08
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased on latest main (a282e06). Resolved a conflict in UserProfilePanelUtils.ts — main's #6086 added a simpler respond_to sync that only propagated when persona.respondTo != null, while this PR's version also defaults to "owner-only" when the persona has no explicit policy and clears the instance's allowlist when switching away from "allowlist" mode. Kept this PR's more complete version since the allowlist-clearing behavior prevents stale entries from surviving a mode switch back to "allowlist".

tsc --noEmit passes.

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.

Bug: respond_to change saved in Desktop UI never propagates to the runtime record

2 participants