|
1 | 1 | # CLAUDE.md — nostrkey.app.ios.src |
2 | 2 |
|
3 | 3 | ## What This Is |
4 | | -NostrKey iOS app — native wrapper that runs the full NostrKey browser extension UI on iOS with native platform integrations (QR scanner, clipboard, lock screen npub display). |
| 4 | +NostrKey iOS app — a native SwiftUI Nostr identity authenticator. QR scanner as primary interface, Secure Enclave key storage, NIP-46 remote signing, Apple Wallet integration, and deep link relay management. |
| 5 | + |
| 6 | +## Architecture (v2 — March 2026 Rebuild) |
| 7 | +Complete rewrite from WebView-wrapper to native SwiftUI. No more bundled browser extension. The app is a standalone authenticator that holds keys and signs on behalf of any Nostr client. |
| 8 | + |
| 9 | +### Source: `NostrKey-v2/` |
| 10 | +``` |
| 11 | +NostrKey-v2/ |
| 12 | +├── App/ # SwiftUI app entry, AppState, ContentView, DeepLinkHandler |
| 13 | +├── Scanner/ # AVFoundation QR camera view |
| 14 | +├── Identity/ # KeyManager (Secure Enclave), NostrProfile, ProfileManager |
| 15 | +├── Relay/ # RelayManager, RelayInfo, NIP-11 metadata |
| 16 | +├── NIP46/ # NIP-46 remote signing session management |
| 17 | +├── Crypto/ # Bech32, NostrCrypto (nsec/npub encoding), event hashing |
| 18 | +├── UI/ # IdentityCardView, RelayListView, SettingsView |
| 19 | +├── Info.plist # App config (camera + Face ID permissions, deep link schemes) |
| 20 | +└── NostrKey.entitlements # App Groups + Keychain sharing |
| 21 | +``` |
| 22 | + |
| 23 | +### Legacy Source: `NostrKey/` |
| 24 | +The original WebView-wrapper app (v1.x) is preserved in `NostrKey/` for reference. The v2 project.yml points to `NostrKey-v2/` sources but still uses `NostrKey/Assets.xcassets` for icons. |
5 | 25 |
|
6 | 26 | ## Ecosystem Position |
7 | | -Mobile surface for NostrKey — the key management layer. Same role as the browser extension but on iOS. Uses dual-WKWebView architecture with IOSBridge.swift bridging JS to native APIs. |
| 27 | +The authenticator for Nostr. Holds keys in Secure Enclave, signs via NIP-46 for any client. Shares keys with the Safari extension via App Group Keychain (`group.com.nostrkey`). |
8 | 28 |
|
9 | 29 | ## Current Version |
10 | | -v1.1.1 — Bundled extension v1.5.5 — App Store submission in progress |
| 30 | +v2.0.0 (Build 1) — Native SwiftUI rebuild |
11 | 31 |
|
12 | 32 | ## Tech Stack |
13 | | -- Swift 5.9, Xcode 15.0+ |
14 | | -- Dual-WKWebView (background + UI) |
15 | | -- IOSBridge.swift (`WKScriptMessageHandler`) |
16 | | -- ios-polyfill.js maps `chrome.storage`/`chrome.runtime` to bridge calls |
17 | | -- UserDefaults for storage |
18 | | -- AVFoundation for QR scanning |
19 | | -- xcodegen for project generation |
| 33 | +- Swift 5.9, SwiftUI, Xcode 16.0+, iOS 17.0+ |
| 34 | +- AVFoundation (QR camera) |
| 35 | +- Security framework + CryptoKit (Keychain with Secure Enclave protection) |
| 36 | +- LocalAuthentication (Face ID / Touch ID) |
| 37 | +- CoreImage (QR code generation) |
| 38 | +- URLSessionWebSocketTask (NIP-46 relay communication) |
| 39 | +- XcodeGen for project generation |
20 | 40 |
|
21 | 41 | ## Build |
22 | 42 | ```bash |
23 | 43 | xcodegen generate |
24 | 44 | open NostrKey.xcodeproj |
25 | | -# Build & Run in Xcode |
| 45 | +# Build & Run in Xcode (requires physical device for camera + Secure Enclave) |
26 | 46 | ``` |
27 | 47 |
|
28 | | -## Key Differences from Browser Extension |
29 | | -- Storage: UserDefaults (not `chrome.storage`) |
30 | | -- QR scanning: AVFoundation (native) |
31 | | -- No `window.nostr` injection |
32 | | -- No cross-device sync yet |
33 | | -- Lock screen QR code + npub display (iOS-only features) |
| 48 | +## Key Architecture Decisions |
| 49 | +- **SwiftUI-only** — no UIKit except for AVCaptureSession (camera requires UIKit) |
| 50 | +- **Secure Enclave via Keychain** — secp256k1 keys stored with biometric access policy |
| 51 | +- **App Group sharing** — `group.com.nostrkey` shared Keychain + UserDefaults |
| 52 | +- **NIP-46 over WebSocket** — remote signing without key exposure |
| 53 | +- **Deep links** — `nostrkey://add-relay`, `nostrkey://connect`, `nostrconnect://` |
| 54 | +- **No web views** — pure native UI, no embedded browser extension |
| 55 | + |
| 56 | +## TODO: Before Shipping |
| 57 | +- [ ] Integrate swift-secp256k1 package for real key derivation + Schnorr signing |
| 58 | +- [ ] Complete NIP-46 message parsing and encrypted response flow |
| 59 | +- [ ] Apple Wallet pass generation (PassKit + server-side signing) |
| 60 | +- [ ] Pass update push notification service |
| 61 | +- [ ] NIP-49 (ncryptsec) encrypted relay backup |
| 62 | +- [ ] App Store screenshots for authenticator flow |
34 | 63 |
|
35 | | -## Planned |
36 | | -- App Store listing |
37 | | -- App Groups (share profiles between iOS app ↔ Safari extension) |
38 | | -- Biometric unlock (Face ID / Touch ID) |
39 | | -- Deep links (`nostr:` URIs) |
| 64 | +## Deep Link Schemes |
| 65 | +- `nostrkey://add-relay?url=wss://...&name=...&paid=true` |
| 66 | +- `nostrkey://connect?pubkey=...&relay=wss://...` |
| 67 | +- `nostrkey://import-keys?nsec=nsec1...` |
| 68 | +- `nostrkey://wallet-pass?npub=npub1...` |
| 69 | +- `nostrconnect://pubkey?relay=wss://...&secret=...` |
40 | 70 |
|
41 | 71 | ## Related Repos |
42 | | -- `nostrkey.browser.plugin.src` — core extension code (bundled here as web assets) |
| 72 | +- `nostrkey.browser.plugin.src` — Safari/Chrome extension (NIP-07) |
43 | 73 | - `nostrkey.app.android.src` — Android equivalent |
44 | | -- `nostrkey.bizdocs.src` — business strategy |
| 74 | +- `nostrkey.bizdocs.src` — business strategy (see NostrKey-App-Architecture.md) |
0 commit comments