Build 22: response-delivery fixes (push-embed + pending relay-URL)#10
Merged
Conversation
Avoids the NSE ephemeral-fetch race when the relay drops kind:24133 between proxy dispatch and NSE wake. Oversized events fall through to the existing fetch path (no regression). Part of build 22 response-delivery hotfix. See ~/hq/clave/specs/2026-04-20-response-delivery-fixes-design.md
NSE and AppDelegate foreground-push handler now check userInfo["event"] first; fall through to LightRelay.fetchEvents only if absent. Closes the ephemeral-fetch race for ≤3500B events. Oversized events fall through as today. Part of build 22 response-delivery hotfix.
Spec Risk #1 mitigation: when userInfo["event"] is present but not a dict, log a warning so proxy payload-shape regressions are visible in production triage. Unchanged: behavior on happy path + missing-key path.
PendingRequest gains relayUrl: String? captured at queue-time from the incoming responseRelayUrl. approvePendingRequest threads it back into LightSigner.handleRequest, so signed responses for protected kinds publish to the relay the client is actually subscribed on — not the powr.build fallback. Bug was latent since PR #7 (switch_relays → null) — nostr-tools clients stopped migrating to powr.build, so the fallback stopped matching. Bunker flow unaffected because Clave's bunker URIs are already pinned to powr.build. Codable's default synthesis handles missing keys on Optional fields, so pre-build-22 pending rows decode as nil → fall back to powr.build (unchanged broken behavior for pre-upgrade stragglers). Part of build 22 response-delivery hotfix.
Matches the parameter name on LightSigner.handleRequest so the call site reads `responseRelayUrl: request.responseRelayUrl` instead of `responseRelayUrl: request.relayUrl` — self-documenting round trip. Also corrects "forward" → "backward" compatibility in the field's doc comment (new code reading pre-upgrade rows is backward compat, not forward).
DocNR
added a commit
that referenced
this pull request
May 2, 2026
Brainstorm review of design-system.md against shipped code surfaced 9 inconsistencies + 1 anti-pattern still present. Fixed everything in one batch so the next TestFlight archive carries it all. Code: - HomeView: drop .padding(.bottom, 8) on SlimIdentityBar invocation — slim banner owns its outer bottom padding (12pt); stacking another 8pt on top was double-counting (review #4) - HomeView: drop .padding(.bottom, 8) inside statsRow — listSectionSpacing(0) carries the gap to Connected Clients; the residual padding kept the visible gap excessive after polish round 2 (review #2) - AccountDetailView: avatarLarge letter fallback opacity 0.25 → 0.22 to align with SlimIdentityBar's 0.22 (review #3) - ConnectSheet: add .presentationBackground(Color(.systemGroupedBackground)) — was the last sheet still defaulting to translucent (review #9) - ApprovalSheet: rename @State capExceeded → showConnectionCapAlert for naming convention parity with HomeView (review #7) design-system.md: - New "Cross-platform applicability" section at the top — clarifies what carries directly to clave.casa web companion (color tokens, displayLabel rule, identity-vs-functional zone philosophy, avatar treatments, copy patterns, anti-patterns) vs what's iOS-only (SwiftUI modifiers, haptics, sheet/toolbar conventions) - §3 Typography: corrected initial-letter font scale — AvatarView uses size*0.35 mono (pubkey) or size*0.4 proportional (name); was wrongly documented as a single 0.37 (review #1) - §4 Avatars: added Treatment Selection Rule table (B on neutral bg, C on saturated theme gradient) + clarified 1-vs-2 letter behavior (review #5, #6) - §4 Sizing scale: expanded table to include initial font + border thickness per slot, with the ~5% border scaling rule (review #8) - §5 Spacing: explicit "single source of truth" note on slim banner bottom padding; new "Stats row" subsection capturing the ultraThinMaterial-on-small-cards-OK rule (review gap #10, #4) - §6 HomeView gradient: documented palette[0] defensive fallback when currentAccount is nil (review #13) - §7 Patterns: new "State variable naming" subsection with the showCapAlert / showAccountCapAlert / showConnectionCapAlert convention (review #7 doc side) - §11 Anti-patterns: audit-point note that ConnectSheet was the last surface to acquire .presentationBackground (review #9 doc side) Build green on iOS Simulator 26.4. pbxproj still 41 — assumes user hasn't yet archived 41; bump to 42 if needed before re-archive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two bug fixes bundled for build 22 — both on the "response delivery reliability" surface surfaced by build 21 matrix testing:
PendingRequestnow stores the origin relay URL (responseRelayUrl: String?), so approve-later publishes land on the relay the client is actually subscribed on instead of therelay.powr.buildfallback. Latent bug since PR fix(signer): switch_relays returns null (NIP-46 responder-only) #7 (switch_relays → null) — nostr-tools-family clients stopped migrating to powr.build, so the fallback stopped matching. Bunker flow was unaffected because Clave's bunker URIs are pinned to powr.build.Design doc: `
/hq/clave/specs/2026-04-20-response-delivery-fixes-design.md`/hq/clave/plans/2026-04-20-response-delivery-fixes.md`Plan: `
Changes
~30 lines of net diff across 6 files. 5 commits (2 of which are small quality-review follow-ups).
Backward-compatible in both skew directions (build 21 app + build 22 proxy, build 22 app + build 21 proxy). Pre-build-22 pending rows decode with `responseRelayUrl: nil` and fall back to powr.build — unchanged broken behavior for pre-upgrade stragglers, accepted per spec as one-time degradation.
No new unit tests — manual matrix verification only for build 22 per sprint decision. Backlogged: `push-payload.test.js` (proxy) and `NotificationServiceTests` (iOS). Local Node 18 dev env has a pre-existing `nip98.test.js` failure (ESM `require` incompat with `@noble/curves@2.2.0` — Dell runs Node 20+ where this passes); not introduced by this PR.
Test plan
🤖 Generated with Claude Code