mirror of
https://github.com/block/buzz.git
synced 2026-10-31 06:21:34 +00:00
Implements the desktop side of issue #4938: a kind-9 sentinel published by buzz-acp is parsed and displayed as an interactive card in the thread view. Parser (permissionRequest.ts): - Discriminated union PermissionRequestPending | PermissionRequestResolved aligned to the frozen schema (event b31c716e): requestNonce, sessionId, turnId, optionIds[], labels{}, hasDurableRule, durableRuleNote, outcome, chosenOptionId, originalEventId. - All untrusted display strings capped at 200 chars; optionIds bounded to 10. - extractPermissionRequest() and stripPermissionRequestSentinel() are render-safe (never throw). Compute helper (computePermissionRequest.ts): - D1 signer gate: kind-9 must be signed by the channel's known agent pubkey. - Edit authenticity: resolved state accepted only from kind-40003 signed by the original agent (not owner, not attacker). - selectProseOrPermission() mirrors selectProseOrNudge() from configNudge. Card (permission-request-card.tsx): - Pending: renders option buttons from optionIds + labels[optionId]. Deny-style button heuristic uses label text (opaque optionIds carry no semantic). ExpiryCountdown ticks down to expiresAt; expired cards show 'Timed out'. D5 durable-rule disclosure (durableRuleNote) shown below buttons when hasDurableRule is true. - Resolved: shows outcome label derived from outcome + chosenOptionId. - Actionable buttons gated: isOwner && state === 'pending' only. - sendPermissionDecision() is fire-and-forget; button disables on click with 'Decision sent'; re-enables on relay error so the user can retry. Integration (MessageRow.tsx, formatTimelineMessages.ts, types.ts): - editSignerPubkey threaded from formatTimelineMessages through TimelineMessage so the edit authenticity gate has the raw event signer without re-querying. - PermissionRequestCardBlock wraps useIdentityQuery to resolve the current viewer, computes isOwner, and renders the card when a trusted sentinel is present. React.memo with custom comparator keeps MessageRow re-render budget clean. Auth helper (permissionRequestAuthPubkey.ts): - getPermissionRequestAgentPubkey() returns the agent pubkey only for known-agent-signed kind-9 events, mirroring getConfigNudgeAuthorPubkey. Tests: 33 named tests covering all 6 frozen fixtures verbatim plus rejection cases (bad version, unknown state, size bounds, malformed JSON, field invariants) and the full signer/edit-authenticity gate matrix. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
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 frontendpnpm tauri dev- run the desktop apppnpm build- typecheck and build frontendpnpm typecheck- TypeScript checkspnpm lint- Biome lintpnpm 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