iOS production-readiness: security, localization (RU/FA), parity, polish#1
Open
pavel-shpilev wants to merge 66 commits into
Open
iOS production-readiness: security, localization (RU/FA), parity, polish#1pavel-shpilev wants to merge 66 commits into
pavel-shpilev wants to merge 66 commits into
Conversation
Phase 0 — Swift 6 Concurrency Compliance - Models (VPNConnection, VPNServer, FPTNToken): explicit Sendable conformance - TokenService, ServerSelectionService: converted to actor - VPNService: @mainactor + full async/await pipeline; fixed 3 bugs: * crash on empty server list (guard let servers.first) * dead code in configureAndStartVPN * missing completion handler call after saveToPreferences - NETunnelProviderManager data race: NEManagerBox (@unchecked Sendable) wrapper + MainActor.assumeIsolated (NE callbacks are always main-thread) - Timer closures: wrapped in Task { @mainactor } to access isolated state - SWIFT_STRICT_CONCURRENCY = complete on all 4 build configs - FptnVPNTunnel Swift version bumped 5.0 → 6.0 - @preconcurrency import NetworkExtension Phase 0.5 — Structured Logging (swift-log) - Added swift-log (Logging) to FptnVPN + FptnVPNTunnel targets - FptnVPN/Logging/FptnLogger.swift: AppLogHandler (os_log + file sink) - FptnVPN/Logging/SharedLogSink.swift: rolling App Group log file - FptnVPN/Logging/CredentialRedactor.swift: hideCred() utility - FptnVPNTunnel/Logging/TunnelLogger.swift: mirror handler for tunnel process - FptnVPNTunnel/Logging/SharedLogSink.swift: tunnel-side file sink copy - FptnVPNApp: bootstrapLogging() in init() - All print() replaced with logger.* + hideCred() on credentials - DebugLogView (#if DEBUG): tails shared log file; accessible via long-press - App Group entitlement added to FptnVPN.entitlements (was missing) Phase 1 — MVVM Architecture - Added ViewModels/HomeViewModel, LoginViewModel, ServerListViewModel - HomeView, LoginView, ServerListView: pure rendering surfaces - TokenValidator class removed; logic absorbed into LoginViewModel - Server selection callbacks wired: ServerListView → HomeViewModel → VPNService Build settings / warnings - Removed bogus LD_RUNPATH_SEARCH_PATHS[arch=*] = -lfptn-protocol-lib_static - Fixed framework search path (removed path ending in .framework) - Added UIRequiresFullScreen = YES (portrait-only app) - Prefixed dead _packetBlock/_connectedBlock in WebScoketClientBridge
Token parsing (LoginViewModel): - Support new fptnb: format (base64 of Brotli-compressed JSON, bot commit d1ed549) using Apple's built-in Compression framework — no new dependencies - Fix re-padding corruption when token arrives with existing = signs - Strip backticks that Telegram includes when user copies the full message - Normalize URL-safe base64 chars (- → +, _ → /) - Strip fptnb: prefix before fptn: to prevent partial match corruption VPN service (VPNService): - Replace NEAppProxyProvider stub with NEPacketTunnelProvider that owns the WebSocket and TUN interface inside the extension process - Fix bundle ID mismatch: org.fptn.* → net.mrmidi.* so NE can locate the extension (was causing NEAgentErrorDomain Code=2 / PID 0 crash) - Call startVPNTunnel() after saveToPreferences — the missing call that actually launches the extension and routes device traffic - Reuse existing NETunnelProviderManager instead of creating duplicates - Drive isConnected from NEVPNStatusDidChange observer, not WebSocket start - Remove duplicate app-process WebSocket (extension owns traffic now) Project (project.pbxproj): - Embed fptn_native_lib.framework in FptnVPNTunnel target so dyld can load it when the extension process launches Tooling: - Add token_debug.py: decodes and validates both fptn: and fptnb: tokens, shows server list, md5 fingerprints, and iOS compatibility warnings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- add dSYM generation to CMakeLists - create Info.plist.in to embed in framework - update build script to extract dSYM and add MinimumOSVersion
- update C++ wrapper bridge to accept censorship_strategy - update Swift WebScoketClientBridge classes to send 'SNI' default strategy
- add KeychainHelper to securely persist tokens - integrate AppFilterService and SettingsService - build new SettingsView with proxy routing rules UI - update Home/Login Views to match new models
- track token_debug.py properly - ignore generated fptn.icon folder
- proper conan targets for iOS framework linking - use ntp client master branch zip
- Add .preferredColorScheme(.dark) to root view to fix white text scaling in iOS Light Mode - Make loginToServer and getDNSInfo nonisolated to prevent synchronous C++ networking calls from deadlocking the UI MainActor
…tics - add app-wide semantic adaptive color tokens and keep Color.cian compatibility alias - add persisted appearance preference (system/dark/light) via SettingsService, SettingsViewModel, and SettingsView - update FptnVPNApp to apply preferredColorScheme from stored settings - refactor SettingsView and AppFilterView to remove hardcoded dark-only colors and forced dark toolbar behavior - refactor HomeView and LoginView to use adaptive surfaces/text colors for light-mode readability - add VPN connection state fields (isConnecting, errorMessage) to VPNConnection and expose through HomeViewModel - update VPNService connect flow with user-facing failure messages and manager return-based startup handling - add MetricKitManager service and initialize it on app startup for crash/hang diagnostics logging - remove debug view forced dark scheme to align with selected appearance - add root CHANGELOG.md documenting this release
Introduce a new Tools entry in HomeView and add an SNI Checker workflow for ad-hoc probing of candidate SNI hostnames. Included components: - SNICheckerView UI for server/method selection, SNI list input, progress, filtering, and apply actions. - SNIScannerViewModel state handling for scan lifecycle, buffering, best-result tracking, and SNI apply integration. - ScannerEngine/Prober service layer for sanitization, deduplication, domain validation, concurrent probing, and streamed scan events. - Shared probe models (ProbeConfig, ProbeResult, ProbeStatus, progress/event types). - ToolsView container and HomeView navigation entry to present the checker as a sheet. Also update CHANGELOG.md to document the feature and explicitly mark it as highly experimental and not expected to work reliably in all environments yet (exploratory use).
Implement a production-facing logging workflow tailored to FPTN with a dedicated Home -> Logs entry, Warning as the default level, and app/tunnel synchronization. Included: - New LogLevel model (warning/info/debug) and persisted setting in SettingsService with default Warning. - Settings UI + view model support for selecting log level. - App logger (FptnLogger) reads effective level from settings. - Tunnel logger runtime level store and extension IPC command handling for set_log_level/ping. - VPNService integration to pass logLevel in providerConfiguration and push live updates via sendProviderMessage. - New LogsView + LogsViewModel with severity/source filters, follow/pause, clear, and copy-to-clipboard export. - HomeView bottom navigation now includes a Logs button and sheet. Investigation-driven fixes for observed user confusion: - Added default "Recent only (24h)" filtering so historical errors from previous days do not appear as active failures by default. - Added warning-level tunnel lifecycle markers (start/websocket connected/settings applied) so tunnel activity remains visible at default Warning level. Also updated CHANGELOG.md with feature and fixes.
Add initial macOS host and Network Extension placeholder targets to the Xcode project, including app/extension plist, entitlements, assets, and starter test targets. Also improve iOS home-state correctness by syncing VPN status from system preferences when Home appears and when the app becomes active (Control Center/Settings initiated VPN changes are now reflected in UI). Included functional changes: - VPNService.syncWithSystem() to load existing NETunnelProviderManager and refresh observed status. - HomeViewModel.syncWithSystem() passthrough. - HomeView scene-phase hooks to trigger sync on appear and on active phase.
- Add GitHub Actions workflow to run xcodebuild tests on macOS-26 - Add zsh bootstrap script to generate .env.local and optionally upload secrets - Fix tunnel websocket bridge signature mismatch
- Extend BypassMethod→CensorshipStrategy with 8 browser-specific Reality profiles (Chrome 145/146/147, Firefox 149, Yandex 24/25/26, Safari 26) - Add simpleCases/advancedCases groups, displayName, helpText, isAdvanced - SettingsService: add censorshipStrategy persistence, keep bypassMethod compat - SettingsView: main picker shows simple modes, DisclosureGroup for advanced profiles - SNIProbe: add handshakeLatencyMs, httpCode, strategyRawValue to results - SNIScanner: replace HttpsClient with ApiClientBridge handshake probing; use AsyncStream + TaskGroup for concurrent scanning with cancellation - ServerSelectionService: verify best TCP server via handshake+DNS before auto-select - SNICheckerView: add profile picker for advanced Reality strategies, result detail sheet showing handshake latency and HTTP status
- Reduce kDefaultIdleTimeoutSeconds 300→60 to match server session timeout - Reduce TunnelConfiguration fallback 300→60 - WebSocket bridge: add status reporting (running, started, idle_timeout, last_error, last_disconnect_reason) via websocket_client_bridge_status() - Add WebsocketClientStatus struct (Sendable) in Swift wrappers - Extend TunnelRuntimeSnapshot with DNS addresses, tunnel IPs, IPv6 state, and WebSocket health fields for end-to-end diagnostics - Add wake() health check: if connected but WebSocket isn't running after device wake, triggers transport disconnected → reconnection flow - Clear shared log file on app start - Bump submodule pointer to f964b7b (TCP keepalive + wired idle_timeout)
- Add CFBundleDevelopmentRegion en + CFBundleLocalizations [en, ru] to all app targets - Create iOS Localizable.xcstrings with 95 English→Russian translations - Create macOS Localizable.xcstrings with 13 translations - Create tvOS Localizable.xcstrings with 27 translations - Covers all user-facing UI: login, home, settings, scanner, logs, per-app VPN - String Catalogs (.xcstrings) auto-resolve with SwiftUI Text() — no code changes needed - Language auto-selected from system locale; English is the fallback
- Add Fptn-macOSTests target to project.yml so the Fptn-macOS scheme is configured for the test action (was failing with exit code 66) - Add FRAMEWORK_SEARCH_PATHS to both FptnVPNTests and Fptn-macOSTests so the bridging header can be resolved during dependency scanning (Xcode 26) - Mark CloudTokenSync @mainactor — NSUbiquitousKeyValueStore is main-thread-only; nonisolated on the string constants was redundant and removed - Upgrade actions/cache v4 → v5 and add save-always: true so Conan cache is preserved even when a subsequent step fails Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace deprecated save-always with explicit cache/restore + cache/save steps (if: always()) so Conan cache is saved even when tests fail - Fix @mainactor string keys referenced from @sendable closure in startObserving by capturing as a local Set<String> before the closure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add restore/save steps for .build/DerivedData keyed on Swift sources, project.yml and Package.resolved. restore-keys fallback means partial hits (code changes) still warm the incremental compiler instead of rebuilding cold. Saves ~6m per run once the cache is populated. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement Swift-side tunnel lifecycle state handling with explicit stop intent, generation-checked websocket callbacks, path-aware reconnect scheduling, and app prepare_stop flows for iOS and macOS. Tests: xcodebuild test -project FptnVPN.xcodeproj -scheme FptnVPN -destination 'platform=iOS Simulator,OS=18.5,name=iPhone 16' -skipPackagePluginValidation CODE_SIGNING_ALLOWED=NO
…TCP keepalives - Wire server-assigned dynamic IP addresses from C++ bridge layer down to PacketTunnelProvider across iOS, macOS, and tvOS. - Re-apply network settings on reconnect/reassertion only if server-assigned IP changes to prevent connection disruption. - Resolve Swift 6 strict concurrency warnings (e.g., @unchecked Sendable conformance on providers). - Rebuild all fptn_native_lib.framework targets with Darwin TCP keepalive uncommented. - Add localizations and the l10n_xcstrings.py export/import script.
Replace the Obj-C++/C-pointer bridge layer with direct Swift<->C++ interop across all platforms (iOS, macOS, tvOS). - HTTPS: drop WrapperApiClientBridge in favor of a SwiftApiClient C++ class consumed directly from Swift via std.string. - WebSocket: replace the websocket_client_bridge_* C functions with a WebsocketSwiftBridge C++ class. - Enable C++20 and SWIFT_CXX_INTEROPERABILITY_MODE/objcxx in project.yml. - Update CMake sources and per-target bridging headers accordingly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reflect the current state: XcodeGen-generated project, iOS/macOS/tvOS app+tunnel targets, net.mrmidi bundle prefix, packet-tunnel providers, shared tunnel runtime, and the new Swift/C++ interop bridge layer. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Push notifications can be blocked by censorship whitelists when APNs connects directly. Force APNs traffic through the FPTN tunnel by setting includeAllNetworks=true + excludeAPNs=false on the app-side NETunnelProviderProtocol (the only combination the OS honors for this). Gated behind a new default-ON setting, exposed as a toggle on iOS (Routing section) and macOS (Connection box). On macOS, excludeLocalNetworks is also set so LAN access keeps working (iOS defaults this on). Guarded by iOS 16.4 / macOS 13.3 availability; tvOS unaffected (API unavailable). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Translate the new "Route Push Notifications" toggle and its footer in the iOS catalog, and the macOS toggle string. Restores the Russian translation for the Per-App VPN footer that was orphaned when the push explanation was merged into it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Points the submodule at fdc6150, which fixes the per-reconnect WebsocketClient leak (io_context drain on Stop) that was tripping the network extension's 50MB jetsam limit. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…routing Replace VPNConnection.connectionTime (a foreground-only 1s counter) with connectedAt: Date?, anchored to NETunnelProviderManager.connection.connectedDate. Elapsed time is now computed on display, so the duration stays correct across backgrounding and app relaunch instead of stalling while the foreground timer is paused. HomeViewModel repaints the label every second and catches up after background gaps; the start time is preserved across reasserting/reconnect so a transport blip no longer resets the session timer. Also remove the Per-App VPN navigation entry from Settings (renaming the section to "Routing") and trim the now-stale per-app sentence from the footer string in en/ru.
…oke test Bring the dormant mrmidi iOS codebase to a buildable state on the org repo's mrmidi-base branch (iOS-only scope): - conan profiles: apple-clang 21->17 (conan 2.24 caps at 17 on this toolchain) - conanfile: force zlib/1.3.1 to resolve a transitive version conflict (drift) - add ControlPlaneSmokeTests: drives the real ApiClientBridge (libfptn) to verify TLS/obfuscation/login/DNS against a live server on the simulator; token read from gitignored .build/test-token.txt Verified: native framework + app build & launch on iOS simulator; control plane reaches a live server (handshake ok / login 200 / dns 200). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Was pinned to Aleksandr's team (F6YA6B56LR). Now DEVELOPMENT_TEAM reads from
${FPTN_DEVELOPMENT_TEAM} so simulator builds need no team (CODE_SIGNING_ALLOWED=NO)
and device builds set it via env/CLI once a paid account is available.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move all Apple identifiers off Aleksandr's namespace to the project's own: - bundle IDs net.mrmidi.* -> org.fptn.* (project.yml) - App Group group.net.mrmidi.FptnVPN -> group.org.fptn.FptnVPN (entitlements + shared Swift constants in SharedTunnelRuntime + per-target SharedLogSink) - keychain service net.mrmidi.fptn.credentials -> org.fptn.credentials - keychain access group F6YA6B56LR.group... -> ZX97GS6XNF.group.org.fptn.FptnVPN - provider bundle id used by the app to start the tunnel -> org.fptn.* - logger subsystems / queue labels -> org.fptn.* macOS/tvOS renamed for consistency (not yet building on the new protocol). Verified: iOS app + extension build for the simulator (0 errors). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sh, correctness
Phase 1 — release blockers + security/crash:
- Stop logging the cleartext account password; drop password-length leaks
(TokenService, KeychainHelper)
- Keep the password only in the synchronizable iCloud Keychain — strip it from
UserDefaults and iCloud KVS, migrate+remove the legacy cleartext KVS copy, and
clear it on logout
- Add PrivacyInfo.xcprivacy (app + extension); trim the app NE entitlement to
packet-tunnel-provider only
- Remove the false ITSAppUsesNonExemptEncryption declaration (defer the export
questionnaire to App Store Connect)
- Fix a shared_ptr data race in WrapperWebsocketClientBridge (lock client access
in sendPacket/isStarted)
- Derive the keychain team prefix at runtime (no hardcoded team); env-drive the
bundle-id namespace via ${FPTN_BUNDLE_PREFIX} + generate.sh (canonical org.fptn,
.env.local dev override)
- Make build_fptn_lib.sh honor the Xcode configuration (Release archives are no
longer built Debug)
Phase 2 — correctness bugs:
- Connect re-entrancy guard; getStatus/prepareStop IPC timeout via a single-resume
gate; single-flight guard on the 1Hz speed probe
- Terminate the tunnel when the reconnect budget is exhausted (0 = infinite kept)
- Auto-select verifies candidates concurrently (off the actor), picks the
best-ranked VERIFIED host probed with the resolved connect strategy, and falls
back to best-TCP so it never hard-fails when servers exist
- JSON-encode the login body; delete the orphaned lifecycle FSMs + their tests
Device-verified on iPhone 14 Pro / iOS 26.5: login persistence (keychain runtime
team-prefix), data plane, reconnect churn, memory, clean disconnects, auto-connect.
Also folds in accumulated iOS working-tree work (AppIdentifiers centralization,
real throughput stats, censorship-strategy parity, libfptn convergence shim).
NOTE: FptnLib/fptn points at a local-only ios-converged commit — DO NOT PUSH this
branch until the upstream libfptn PR lands and that commit is public.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… errors - Route dynamic user-facing strings through String(localized:) at the source (VPNService/ServerSelectionService/HomeViewModel/LoginViewModel/HomeView) so the catalog is actually consulted at runtime — previously Text(stringVar) skipped it and ru never displayed. - Map raw connection failures to a small set of localized, user-friendly messages (invalid/expired token for 401/403, connection-blocked-try-another-bypass for TLS/handshake failures, cannot-reach-server for refused/timeout); log raw detail, display localized. - Add Persian (fa) to CFBundleLocalizations + fa (and any missing ru) for all 132 user-visible keys in Localizable.xcstrings (script: scripts/add_fa_localizations.py). Log-only/symbol keys (—, %@, %@ms, %@s) intentionally left untranslated. - Locale-aware speed formatting (NumberFormatter, Gbps tier); CLDR plurals for the SNI-checker/server-scan counts (ru one/few/many/other, fa one/other). fa is a solid first pass — recommend a native-speaker review before release. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…per-app VPN - Bundle global.sni (264) + russia.sni (~59k) into the app Resources and wire them as the SNI-scanner default via a Global/Russia/Custom source picker (default Global; manual paste preserved). Ships in the main app, not the memory-limited extension. (russia.sni is large — may want a curated subset / scan cap later.) - Add a "Connect On Demand" toggle (SettingsService.onDemandEnabled, default off); VPNService sets manager.onDemandRules=[NEOnDemandRuleConnect()] / isOnDemandEnabled accordingly before saveToPreferences — the iOS equivalent of Android always-on. - Remove the non-functional per-app VPN: it needs an MDM/managed entitlement and the UI was only reachable from #Preview while perAppMode/allowedApps were dropped (the tunnel never read them). Deleted AppFilterView/AppFilterService/AppFilter/ PerAppVPNMode and the dead providerConfiguration keys (0 remaining references). - New catalog keys (en/ru/fa): Connect On Demand, Global, Russia, Custom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nStack, About; cleanups - Accessibility: VoiceOver label + live state value on the Connect control, labels on the tab items, and combined download/upload speed elements (decorative arrows folded in). - Server list: NavigationView → NavigationStack; ProgressView during the initial scan; empty-state row with a pull-to-refresh hint. - "Disconnecting…" status while the tunnel tears down (derived isDisconnecting), instead of flipping straight to Disconnected. - About screen (from Settings): app version/build, account service/username (never the password), and the existing Website / Telegram-Bot links (no new URLs invented). - Cleanups: untrack token_debug.py (git rm --cached; still gitignored on disk); strip Headers/PrivateHeaders/Modules from the embedded fptn_native_lib.framework before codesign so ~82 C++ headers no longer ship in the .app. - New catalog keys (en/ru/fa): Disconnecting…, About, Version, Build, Service, Username, Website, Telegram Bot, Connect, Disconnect, Download/Upload speed, loading/empty rows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ork-header strip
macOS/tvOS parity (port of iOS Phase 1/2):
- Retire the legacy cleartext password from iCloud KVS: Fptn-macOS CloudTokenSync +
Fptn-tvOS TvCloudTokenSync now treat the synchronizable iCloud Keychain as
authoritative and remove any residual fptn.cloud.password from KVS once observed.
- Bound reconnect: Fptn-macOS-Tunnel terminates the tunnel when the configured
reconnect budget is exhausted (0 = infinite preserved). (tvOS tunnel has no
reconnect loop, so nothing to bound there.)
- macOS build verified (BUILD SUCCEEDED); tvOS mirrors macOS (tvOS platform not
installed locally to build).
Revert the Phase-5 framework-header strip: strip_framework_headers ran in
build_fptn_lib.sh on the COMPILE-TIME framework copy, but the tunnel bridging headers
#include <fptn_native_lib/...> resolve through that Headers/ dir — so a fresh/archive
build failed ("header not found"). Phase 5's iOS verify only passed because the native
framework was cached (the strip never ran). Removed it; will redo correctly as a
post-embed step on the built .app in a later pass.
Flag (out of scope): MacKeychainStore/TvKeychainStore still hardcode the team prefix
82MYMPMZF6 (iOS derives it at runtime) — follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, throttle diagnostics, post-embed header strip
- Remove the inert IP-assignment callback path (static-tun/internal-NAT means it
never fired; assigned IPs were always nil): dropped the ipAssignedCallback from the
C++ shim (WrapperWebsocketClientBridge.h/.cpp), all bridge wrappers, and the
providers (assigned/applied IP vars, the unreachable ipChanged reassert branch);
applyNetworkSettings now uses the static tun addresses directly. Behavior-preserving
(reasserting never re-applied settings before either; NE retains them).
- Dedup parse_censorship_strategy into FptnLib/src/common/censorship_strategy_parse.*
(both copies were identical); included from SwiftApiClient.cpp + the WS bridge; warns
only on a genuinely unrecognized non-empty strategy ("sni"/empty recognized as kSni).
- Throttle TunnelDiagnosticsStore I/O: O(1) FileHandle append + periodic trim (was a
full O(n) rewrite per event); coalesce heartbeat writes to <=1/s. On-disk format +
read API unchanged (diagnostics-store tests still pass).
- Redo the framework-header strip correctly: strip Headers/PrivateHeaders/Modules from
the EMBEDDED framework in the built .app (project.yml Sign-FptnLib postBuildScript,
pre-codesign), so the compile-time copy keeps headers (fresh builds work) and the
shipped .app omits them.
Verified: fresh native rebuild + iOS-sim build SUCCEEDED; FptnVPNTests 10/10.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…0422a1) The submodule pins the exact device-verified commit e0422a1 (upstream b170630 + the 3 Apple build/keepalive commits). It was local-only; push it to a controlled fork and point .gitmodules there so `git submodule update --init` resolves for anyone fetching this branch — without waiting for the upstream apple-build-support PR (#291) to merge. Converge step (after #291 lands in fptn-project/fptn master): repoint the URL to fptn-project/fptn and bump the pointer to the merged commit. Co-Authored-By: Claude Opus 4.8 (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.
iOS production-readiness — requesting your review
This branch takes the iOS client (plus the macOS/tvOS targets) through a full production-readiness pass on the current protocol. It builds clean (iOS-sim + macOS) and is device-verified on iPhone 14 Pro / iOS 26.5 — login persistence, data plane, reconnect churn, memory (footprint well under the NE ceiling), clean disconnects, and auto-connect all confirmed on device.
What's in it
UserDefaults/iCloud KVS (it now lives only in the synchronizable iCloud Keychain); addedPrivacyInfo.xcprivacy; trimmed the app's NetworkExtension entitlement topacket-tunnel-provideronly; fixed ashared_ptrdata race in the WebSocket bridge; the keychain team prefix is derived at runtime; the bundle-id namespace is env-driven; the native build honors the Release configuration for archives.0still = infinite); auto-select verifies candidates and picks a working server instead of an unverified runner-up; JSON-encoded login body; deleted lifecycle state machines that were never driven in production (false-confidence tests).runever displayed); raw errors map to friendly localized messages; added Persian (fa) with locale-aware speed formatting and CLDR plurals.NavigationStack, and an About screen; the shipped.appno longer carries the C++ framework headers.FptnLib/fptncurrently points at a personal fork (pavel-shpilev/fptn@e0422a1) so this branch resolves on a fresh clone today. That commit is exactly upstream + the 3 Apple build/keepalive commits that are PR #291 (fptn-project/fptn#291).Once #291 merges into
fptn-project/fptnmaster, I'll repoint the submodule back to the canonical repo and bump the pointer to the merged commit — a one-line follow-up commit, no rebase. So please review #291 alongside this; the fork is only a stopgap so reviewers can build the iOS side now.Notes / follow-ups (not blocking)
russia.sni(~59k entries) ships in the app bundle; consider curating to a top-N or capping the scan count.ITSAppUsesNonExemptEncryption=falsewas removed, so the questionnaire gets answered at App Store Connect upload.🤖 Generated with Claude Code