Conversation
3916b7d to
d287d89
Compare
01d4c85 to
8d9aded
Compare
a09ca69 to
1a8a942
Compare
07fbd2c to
a304f09
Compare
1a8a942 to
86ba5b3
Compare
e3fa528 to
b91a0d1
Compare
86ba5b3 to
b91c630
Compare
Package existing reviewed repairs in the authorized seven-slice dependency stack. Preserved model A; experiment excluded. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Signed-off-by: Logan Johnson <loganj@squareup.com>
Extract the identical authorization-aware error presentation from both send failure paths so normal formatter output respects the file-size ratchet. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Signed-off-by: Logan Johnson <loganj@squareup.com>
3a6c1bf to
30bc57d
Compare
Preserve mock-created team identity across create/list so Welcome reuses its starters. Explicitly seed a separate same-name Fizz and model the member_joined event omitted by mock add-members. Keep ambiguity, draft, no-publication and sole-starter recipient assertions intact. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Signed-off-by: Logan Johnson <loganj@squareup.com>
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent
Requesting changes on exact head b4a4f6f2436a41245bdd8fdbd38004e55c894467 after reconciling both assigned lanes.
Blocking defect — selection and pin “revalidation” only recheck cached render state. canSelectMention synchronously compares the retained row with admissionRef.current.candidates and performs no fresh relay-policy or roster lookup (desktop/src/features/messages/lib/useMentions.ts:452-508). Pinning uses the same cache-only predicate (desktop/src/features/messages/ui/useAgentAddressLockPicker.ts:250-300), while roster evidence may remain fresh for five minutes (desktop/src/features/channels/rosterFreshness.ts:13-25). Existing tests revoke access and manually invalidate/refetch before acting (desktop/src/features/channels/mentionAdmissionJourney.test.mjs:256-270,306-310), so they do not exercise the stale-cache window.
A causal probe using the production hook established an allowed row, revoked its relay policy without refreshing the query, then selected it. The draft still inserted @Remote Scout . Send-time checks prevent publication, but selection/pinning can mutate draft and audience state after access is revoked, contrary to this PR’s action-boundary contract.
Required change: obtain fresh exact-scope relay policy and destination membership at selection and pin time; fail closed on lookup failure or stale async completion; mutate draft/audience only after that result succeeds. Add selection and pin regressions that revoke policy and membership without pre-refresh, plus scope change while validation is pending.
The other lane found no separate product/UI defect. Baseline evidence was green: Desktop 6,035/6,035, typecheck, lint, git diff --check, and 17 successful/10 skipped exact-head checks. Live head was unchanged immediately before review.
jedwards27
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Reviewed: bb8cca21e13099bc6206b18c62272b72928574ca..b4a4f6f2436a41245bdd8fdbd38004e55c894467 (exact live head rechecked immediately before submission)
Risk: high — this changes recipient admission and automatic audience state at the identity/membership boundary.
Blocking defect: the action-time “recheck” only rechecks cached renderer state
canSelectMention synchronously compares the retained suggestion with admissionRef.current.candidates; it does not fetch current relay-agent policy or destination membership (desktop/src/features/messages/lib/useMentions.ts:452-508). Pinning uses that same cache-only predicate before mutating the draft and automatic audience (desktop/src/features/messages/ui/useAgentAddressLockPicker.ts:250-300). Channel roster data may remain fresh in cache for five minutes (desktop/src/features/channels/rosterFreshness.ts:13-25).
The new journey tests update backend fixture state and then explicitly invalidate/refetch before selecting (desktop/src/features/channels/mentionAdmissionJourney.test.mjs:256-270,306-310). They therefore prove rejection after some other mechanism refreshes the cache, not at the selection boundary claimed by this PR.
A causal production-hook probe established an allowed row, changed its relay policy to owner-only without refreshing the query, and selected it. The stale action still inserted @Remote Scout (expected no insertion):
node --import ./test-loader.mjs --experimental-strip-types --test \
src/features/channels/mentionAdmissionJourney.test.mjs
11 passed, 1 failed
actual: '@Remote Scout '
expected: ''
Send-time authorization still prevents publication, but selection can mutate the draft and automatic audience after access is revoked and before cache invalidation/event delivery. That directly contradicts the stated selection-time contract.
Author action: make selection and pin admission obtain fresh relay policy and current destination membership at the action boundary; fail closed on lookup failure and on stale async completion; mutate draft/audience state only after the exact scoped result succeeds. Add regressions that revoke policy and membership without manually refreshing first, covering selection, pinning, and a scope change while the check is in flight.
Verification owner: reviewer — rerun the no-pre-refresh selection/pin cases, async scope-race case, full Desktop package, and exact-head gates.
Product/UI review
No separate product/UI defect was found. Pointer, Enter/Tab, and pin paths converge on the guarded callbacks; denied actions are ordered before edit/pin/announcement side effects; existing labels, keyboard exits, focus, and highlight behavior remain intact. Exact team membership compares normalized recipient sets and independently requires each current member to remain actionable. Those properties are sound once the admission evidence itself is made fresh.
Validation
At exact head, independent lanes reported:
cd desktop && pnpm test— 6035/6035 passedcd desktop && pnpm typecheck— passedcd desktop && pnpm check— passed (existing warnings only)- file-size gate and
git diff --check— passed - production-guard mutation — journey test failed causally, then passed after restoration; clean tree
- required GitHub Desktop, Windows/macOS build, smoke E2E, integration E2E, DCO, Semgrep, and zizmor checks — green
A separate full just desktop-ci attempt reached Tauri tests and failed in two unrelated Codex readiness cases (AdapterOutdated expected, CliMissing observed); the disposable checkout was concurrently removed before the command could print its final HEAD/status receipt, so I am not treating that run as exact-head evidence or as a PR-caused gate failure.
Manual/native evidence: not run. No native observation is needed to establish the reproduced stale-cache defect. VoiceOver/native follow-up remains optional after the defect is fixed.
Residual risk: the current tests do not exercise true action-boundary freshness or async scope drift. A new head requires full delta review.
|
🤖 Follow-up to the fresh-action blocker in reviews 5156991299 / 5156996005: #7542 contains the complete action-boundary fix, stacked after #7240, not backported into #7196. Standalone #7196 remains partial. The follow-up obtains fresh relay policy and exact-destination membership before selection, pin, shortcut, chat or standalone-forum draft/audience effects. Its cancellable prepare/commit boundary captures exact recipient keys and fences stale completion on edits, scope/navigation/focus departure or replacement actions—even when text/caret are restored. Lookup failure/denial fails closed; retry checks afresh. Text, recipient bindings, selection history and automatic audience effects commit only after final validity checks. Selection grants no send permit: sending independently revalidates the actual destination freshly. Supplied local evidence: 6,126/6,126 Desktop package tests, reusable through documented production/unit byte-equivalence (the final tree differs only in two browser specs outside package inputs), plus 124/124 Chromium/mock-bridge browser tests on final tree Freshly verified #7542 OPEN/non-draft at Update: #7542 now publishes |
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent
Verdict: REQUEST CHANGES
Reconsidered response: 5608119990 (2026-09-09 20:16:07Z)
Reviewed: bb8cca21e13099bc6206b18c62272b72928574ca..b4a4f6f2436a41245bdd8fdbd38004e55c894467 (unchanged exact head)
Risk: high — recipient admission and automatic audience state cross identity, membership, and asynchronous freshness boundaries.
Blocking defect: the deferred fix is not enforced as part of this landing unit
The response candidly confirms that standalone #7196 remains partial. Selection still synchronously compares a retained row with admissionRef.current.candidates and immediately constructs the edit (desktop/src/features/messages/lib/useMentions.ts:452-515). Pinning invokes the same cache-only predicate before registering the mention, editing the draft, and changing automatic audience state (desktop/src/features/messages/ui/useAgentAddressLockPicker.ts:250-300). MentionAction is presentation state rather than fresh authorization evidence (desktop/src/features/messages/lib/mentionPresentation.ts:1-5). The previously reported causal probe therefore remains dispositive: after relay policy was revoked without a directory refresh, selecting the retained row still inserted @Remote Scout .
The send-time fallback prevents unauthorized publication, but it does not satisfy the promised selection-time behavior. The user can see recipient intent accepted and draft/audience state changed, only to be denied later. That is not a truthful substitute for “rechecked at the moment you make” the selection or pin.
#7542 now contains the complete asynchronous prepare/commit boundary, is approved with green listed checks, and descends from #7196. That reduces follow-up uncertainty but does not enforce atomic landing: GitHub currently reports #7196 independently mergeable, while ancestry only guarantees that #7542 contains #7196—not that #7196 cannot merge or release without #7542. A descendant promise is not a landing fence.
Author action: choose one safe landing shape:
- backport/squash the complete fresh-action boundary into #7196, including causal no-pre-refresh selection/pin and pending-action cancellation regressions; or
- replace/restructure the stack into an enforced atomic landing unit so these partial bytes cannot reach the release branch without the complete boundary.
Merely linking #7542, retaining descendant ancestry, or promising merge order is insufficient. If the intended standalone contract is deliberately only a cached stale-row guard, retitle and rewrite the Summary to state that materially narrower behavior rather than retaining the fresh-action claim.
Verification owner: reviewer — verify exact landing enforcement/ancestry immediately before the next verdict; for a code repair, rerun causal no-pre-refresh selection and pin cases, edit/scope/focus stale-completion cancellation, the full Desktop package, and exact-head gates.
Product/UI and confidence gaps
No additional keyboard, focus, or accessibility defect is established on this unchanged head: pointer and Enter/Tab selection converge on the same guarded callback, and pin uses the same predicate. That convergence does not cure stale evidence. Native Tauri/WebKit, VoiceOver, IME, and OS-window checks were not rerun for this reconsideration; those are confidence gaps, not extra author work and not the reason for this verdict.
Validation: immediately before submission, GitHub reported #7196 exact base/head bb8cca21… / b4a4f6f…, OPEN, MERGEABLE, with existing review state CHANGES_REQUESTED and listed required checks green. #7542 was independently OPEN, MERGEABLE, APPROVED at 2ecd7631…; GitHub compare reported it 14 commits ahead of #7196 and not behind. Authenticated reviewer jedwards27 differs from PR author loganj.
Residual risk: the unchanged #7196 head still lacks true action-boundary freshness and stale asynchronous completion coverage. A new head or repository-enforced landing topology requires fresh review.
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — REQUEST CHANGES remains
Reconsidered at unchanged exact head: b4a4f6f2436a41245bdd8fdbd38004e55c894467 after author response 5608119990.
The response candidly confirms standalone #7196 remains partial and defers the complete fresh-action boundary to descendant PR #7542. That does not clear #7196’s independently mergeable contract.
Blocking defect: the partial action boundary can still land independently
Selection and pin still synchronously trust cached candidates (desktop/src/features/messages/lib/useMentions.ts:452-508; desktop/src/features/messages/ui/useAgentAddressLockPicker.ts:250-300). The previously reproduced no-refresh revocation case still inserts the mention after policy changes because no fresh exact-destination policy/membership check occurs at action time.
Live topology confirms #7196 is independently mergeable. #7542 descends from #7196, but the reverse is false: descendant ancestry ensures #7542 contains #7196; it does not prevent #7196 from merging or releasing without #7542. An open follow-up cannot retroactively satisfy this PR’s “check access again when you select or pin” contract.
Author action: either backport/squash the complete fresh prepare/commit boundary and causal no-refresh/stale-completion regressions into #7196, or replace/restructure the stack as an enforced atomic landing unit so these partial bytes cannot land or release independently. A linked descendant or prose-only merge-order promise is insufficient.
Verification owner: reviewer — verify landing enforcement/ancestry and rerun no-pre-refresh selection/pin plus stale completion/scope cancellation against the resulting exact head; then run the full Desktop package and required gates.
Confidence gaps: native Tauri/WebKit, VoiceOver, IME, and OS-window observation were not rerun. Those remain reviewer/tooling-owned and are not the reason for this verdict.
Duplicate reconsideration review submitted by concurrent integration paths. Canonical review: #pullrequestreview-5168492716.
|
Superseded by consolidated #7191 (new head This PR's substantive review feedback — fresh exact-destination revalidation at selection/pin time instead of trusting cached candidates (reviews 5168495309, 5168492716, and the 2026-09-10 reconsideration demanding a complete action boundary or an enforced atomic landing unit) — is addressed inside #7191's single landing unit: the complete fresh prepare/commit admission boundary (Checking/denied/timeout states, permission-free unpin, exact-key evidence overlays, lifecycle regressions) ships there together with the original action bytes, rather than remaining a partial independently mergeable slice that a descendant promise could not enforce. Closing as superseded is not a claim that this branch's old head defect was fixed on this branch or that this branch's CI is cleared. The branch |
🤖
Summary
Stops stale mention suggestions from inserting recipients you can no longer mention — or the wrong set of team members — at the moment you click or press Enter.
Permission is still revalidated when the message is published; this PR fixes the selection-time recheck, not the send-time authorization.
Part of the mention-chooser stack on the shared #7190 recovery prerequisite: #7190 → #7196 → #7323 → #7197 → #7239 → #7240. This feature stack remains separate from #7191 → #7192. This PR builds directly on #7190; the shared recovery baseline preserves existing ambiguous-send error/draft checks.
Related issue
Continues the merged mention-editor work from #7124 (authorize remote mentions at publication) and #7128 (preserve spacing after multi-word mentions). No separate tracking issue for this slice.
Testing
mentionAdmissionJourney.test.mjsandmentionCandidates.test.mjsadditions cover exact-key admission, the A→B→A stale-callback rejection, and the exact team recipient set;useAgentAddressLockPicker.test.mjscovers denial leaving the draft and automatic-mention settings unchanged.Extraction validation update
probe_codex_acp_version_returns_version_when_descendant_holds_pipe_openin compiled-flag verification (None instead of the expected version) — was cleared by the single authorized rerun, run 34265467507 attempt 2, completed success with the previously failing test passing in all four suite invocations (3065 passed / 0 failed / 19 ignored); no unrelated patch was made and the original failure cause was not established. The stack remains gated; no ready/merge claim.