fix(ui): allow Universal Clipboard for bunker URI copy#8
Merged
Conversation
Drops `.localOnly: true` from the bunker URI copy path while keeping the 120s expiration. Nsec export in ExportKeySheet.swift stays locked (raw private key, non-negotiable). Audit finding A10.2 originally applied `localOnly: true` to both nsec and bunker URI to prevent Universal Clipboard from syncing either to nearby Apple-ID devices. For the bunker URI, that turned out to defeat the primary cross-device pairing flow: users copy their bunker URI on iPhone to paste into a Mac browser client (Coracle, noStrudel, etc.), and Universal Clipboard is how that works without friction. Without this change, users fall back to AirDrop or manual retype. The 120s expiration still auto-clears the clipboard on both devices, so the window of secret exposure is bounded. Scope note recorded in security-audits/2026-04-17-pre-external-testflight.md.
8 tasks
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
.localOnly: truefrom the bunker URI copy inConnectSheet.swift(keeps the 120s expiration).ExportKeySheet.swiftstayslocalOnly: true(raw private key, non-negotiable).Why
Audit finding A10.2 originally locked both nsec and bunker URI to
localOnly: trueto prevent Universal Clipboard leakage. For the bunker URI that turned out to defeat the main cross-device pairing flow — users resort to AirDrop or manual retype, or silently fail (clipboard shows stale content on Mac).Expiration behavior (important caveat)
The 120s
.expirationDatefires on iPhone only. Universal Clipboard does not propagate expiration metadata to Mac-side NSPasteboard, so the Mac clipboard stays populated until the user next copies something on any UC-connected device. Apple provides no cross-device expiration API.Residual exposure on the Mac is bounded by
SharedStorage.rotateBunkerSecret()firing on successful pair — once any client pairs with the secret, any stale clipboard copies become dead weight (the secret is single-use). Audit note at~/hq/clave/security-audits/2026-04-17-pre-external-testflight.mdA10.2 updated to reflect this.Test plan
Related
🤖 Generated with Claude Code