Files
buzz/desktop
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7andWill Pfleger 26d15944c7 fix(desktop): omission must not wipe team persona_ids/instructions
kind:30176 team events serialized persona_ids with
skip_serializing_if = Vec::is_empty and instructions with
skip_serializing_if = Option::is_none, making 'old/predates-field client
omitted the field' and 'client explicitly emptied it' byte-identical on
the wire. apply_inbound_team blindly overwrote both fields on every
inbound event, so a single empty publisher propagated to every other
device and wiped team membership/instructions fleet-wide (the Sietch
Tabr incident).

- persona_ids: Vec<String> -> Option<Vec<String>>, mirroring the
  agent_pubkeys fix on the unmerged tommy/agents-first-agent-pubkeys-optional
  branch (b91ac88d3). None = publisher predates always-publish (unknown,
  preserve local); Some(vec![]) = explicit clear. New clients always
  publish Some, even when empty.
- instructions: Option<String> -> Option<Option<String>> (double-Option,
  via the existing crate::util::double_option helper) for the same
  reason, using the tri-state absent/null/value shape: absent = preserve
  local, null = explicit clear, string = set.
- apply_inbound_team overwrites local only on Some; None preserves
  local. Fresh inserts unwrap_or_default().

persona_ids is wrapped even though the prior-art commit argued the
unwrapped field's omission always means genuinely empty: that reasoning
does not hold on main because skip_serializing_if = Vec::is_empty makes
every shipped client also omit it when empty, so omission is
structurally ambiguous. The Sietch Tabr wipe is the field evidence.

Always-publishing changes the serialized projection, so every team
re-publishes once via retention content-hash mismatch on next save.
Benign — same tradeoff the agent_pubkeys prior art accepted.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-07-16 13:50:23 -05:00
..
2026-06-11 15:06:24 +00:00

Buzz

Desktop chat shell with:

  • Tauri + React + TypeScript + Vite
  • Tailwind CSS
  • shadcn/ui-ready shared components
  • Biome (lint/format/check)
  • Feature-driven frontend structure

Scripts

  • pnpm dev - run the web frontend
  • pnpm tauri dev - run the desktop app
  • pnpm build - typecheck and build frontend
  • pnpm typecheck - TypeScript checks
  • pnpm lint - Biome lint
  • pnpm format - Biome format (write)
  • pnpm check - Biome check

Structure

  • src/shared - reusable app-wide code (ui, lib, styles)
  • src/features - feature modules (vertical slices)
  • src/app - top-level app composition