mirror of
https://github.com/block/buzz.git
synced 2026-10-30 22:11:36 +00:00
F1: outcomeLabel now derives the verb from the positional allow contract (optionIds[0] = allow_once, optionIds[1] = reject_once, fixed by sentinel_option_fields, pinned by the cross-language fixture) rather than the mutable display label. A reject option named "Allow file access" now correctly renders "Denied: Allow file access", not "Approved: Allow file access". F2: Pending and resolved sentinels now carry a description field sourced from params.subject of the session/request_permission message. Producer-side: truncated at a UTF-8 char boundary to SENTINEL_STRING_MAX_BYTES (same as the labels precedent). Parser-side: absent/null accepted (optional field); over-limit or non-string rejected. Card renders description above the buttons/controls on both pending and resolved cards. Cross-language fixture regenerated with description: "read a file". NIP-AO D6 table updated. computePermissionRequest correlation check excludes description (display-only annotation, not a cryptographic correlation key). F3: MessageRow now uses isTrustedPermissionRequestSentinel (new helper in permissionRequestAuthPubkey.ts) instead of shape-only isPermissionRequestSentinel. The helper gates suppression on getPermissionRequestAgentPubkey succeeding — a forged sentinel (valid JSON shape, wrong signer) no longer produces a blank row; it falls through to markdown prose rendering. MessageRow.tsx stays at exactly 999 lines (net zero: import swap + comment collapse). Tests: Rust — description present/null/truncated/multibyte-truncated; TS — F1 distinct verb component tests, F2 parser-level description validation + hostile/overlong/absent, F3 isTrustedPermissionRequestSentinel unit tests (forged signer returns false, unknown agent returns false, trusted returns true), F2 card render tests (description appears, absent description safe). Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>