278df25fd7f28112e0e5fae249a415ffa31b69b6
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f5d3810f5f |
feat(ios,macos): Apple privacy manifest (PrivacyInfo.xcprivacy)
Apple has enforced a `PrivacyInfo.xcprivacy` privacy manifest at App
Store submission since May 2024 for iOS / iPadOS / visionOS /
watchOS, and rolled the requirement out to macOS in late 2024.
Without the file, App Store Connect rejects archive uploads with
"missing required privacy manifest". This commit adds the manifest
for both iOS and macOS Runner targets.
apps/chanora_flutter/ios/Runner/PrivacyInfo.xcprivacy
apps/chanora_flutter/macos/Runner/PrivacyInfo.xcprivacy
Identical content. Declarations:
NSPrivacyCollectedDataTypes:
NSPrivacyCollectedDataTypeAudioData
Microphone audio transmitted to the user's chosen voice
server while connected and unmuted. Not linked to user
identity (no Apple ID / IDFA tied), not used for tracking.
Purpose: AppFunctionality (communications).
NSPrivacyTracking: false
NSPrivacyTrackingDomains: []
Chanora performs no cross-app / cross-website tracking.
NSPrivacyAccessedAPITypes:
FileTimestamp (C617.1)
tokio + rusqlite file I/O for identity.tskey, chanora.db,
audio_meta.json, chanora.log inside the app container.
UserDefaults (CA92.1)
Indirect via path_provider Flutter plugin querying for
Application Support / Documents directories.
SystemBootTime (35F9.1)
tracing-subscriber timestamps log records relative to boot.
DiskSpace (85F4.1)
rusqlite checks before sqlite page writes.
All four "required reason" API categories use Apple's published
allow-list reason codes; no fingerprinting / analytics usage.
apps/chanora_flutter/ios/Runner.xcodeproj/project.pbxproj
apps/chanora_flutter/macos/Runner.xcodeproj/project.pbxproj
Added PrivacyInfo.xcprivacy to the Runner group and to the
Runner target's "Copy Bundle Resources" build phase via the
xcodeproj Ruby gem (via a one-shot script). With this, the file
is placed at Runner.app/PrivacyInfo.xcprivacy where Apple's
validator looks for it — `find Runner.app -name
PrivacyInfo.xcprivacy` shows our manifest at the bundle root
alongside Flutter's and connectivity_plus's.
Verified on the M1 Mac (coder@100.118.130.73):
flutter build ios --release --no-codesign 4.0 s
-> Runner.app/PrivacyInfo.xcprivacy present
flutter build ipa --release --no-codesign 28.4 s
-> Runner.xcarchive built (171.4 MB)
-> archive's Runner.app/PrivacyInfo.xcprivacy present
-> archive's Runner.app/Frameworks/chanora_bridge.framework
built fresh via the chanora_bridge.podspec prepare_command
under xcodebuild's sandbox (no PATH / env weirdness).
P1 follow-ups noted by xcodebuild's validator (not blockers for
this commit but for App Store submission):
* Real app icon (currently default placeholder)
* Real launch image (currently default placeholder)
* Paid Apple Developer Program account, registered App ID, and
Distribution provisioning profile (Personal Team sideloads
still work as today).
|
||
|
|
1f729284b3 |
feat(flutter,ios): vendor chanora_bridge as a CocoaPods framework
iOS rejects loose .dylib loads (`dlopen` of any path outside the
app bundle is sandboxed), so a Flutter-Rust bridge has to ship
inside the .app as an Embed-and-Sign framework that
flutter_rust_bridge's runtime loader can dlopen via its default
`chanora_bridge.framework/chanora_bridge` lookup path.
This commit wires the bridge into the iOS build via a CocoaPods
podspec. Same role Cargokit plays for other Flutter+Rust setups,
done by hand against this repo's layout to avoid the Cargokit
vendoring footprint that was previously dropped.
apps/chanora_flutter/ios/chanora_bridge.podspec
New file. `prepare_command` invokes
`cargo build --release --target aarch64-apple-ios -p chanora_bridge`
with IPHONEOS_DEPLOYMENT_TARGET=13.0 +
CMAKE_POLICY_VERSION_MINIMUM=3.5 (satisfies audiopus_sys's
cmake invocation on modern CMake 4.x), then wraps the
produced libchanora_bridge.dylib into
chanora_bridge.framework with an Info.plist that declares
iPhoneOS / MinimumOSVersion=13.0, and rewrites LC_ID_DYLIB
to @rpath/chanora_bridge.framework/chanora_bridge.
`vendored_frameworks` exposes the result to CocoaPods, which
integrates it into Runner.xcodeproj with Embed & Sign
automatically. No Xcode UI edits required.
apps/chanora_flutter/ios/Podfile
Add `pod 'chanora_bridge', :path => '.'` to the Runner
target.
apps/chanora_flutter/ios/Podfile.lock
Generated by `pod install` after the pod was added. Pins
chanora_bridge 1.0.0 + checksum so iOS builds on other
developer machines pull the same framework version.
.gitignore
Add `/apps/chanora_flutter/ios/Frameworks/` so the
~13 MB built framework (regenerated on every pod install) is
not committed.
Verified end-to-end on the M1 Mac (coder@100.118.130.73):
pod install ok
chanora_bridge.framework generated at
apps/chanora_flutter/ios/Frameworks/chanora_bridge.framework
Install name: @rpath/chanora_bridge.framework/chanora_bridge
flutter build ios --release --no-codesign 12.7 s
-> Runner.app 29.9 MB (was 16.9 MB without the bridge)
-> Runner.app/Frameworks/chanora_bridge.framework present
alongside Flutter.framework, App.framework,
connectivity_plus.framework, objective_c.framework.
DEC-025: iOS / iPad officially in scope for P0.
Notes for owners installing on physical iOS devices:
The Personal Apple Team in Xcode requires a unique
PRODUCT_BUNDLE_IDENTIFIER (the default 'app.chanora.chanoraFlutter'
may already be claimed in the App Store registry). Set this
locally in Xcode -> Runner target -> Signing & Capabilities ->
Bundle Identifier (e.g. yourname.chanora.chanoraFlutter); do
NOT commit that change back since it is user-specific.
|
||
|
|
f0ddb160a0 |
fix(protocol,audio,ios): native-tls instead of rustls+aws-lc-rs
Building the bridge for `aarch64-apple-ios` failed in two ways with
the previous TLS stack:
1. `aws-lc-sys` (transitive: rustls -> aws-lc-rs -> aws-lc-sys)
does not cross-compile cleanly to iOS — the build produced
undefined symbols for architecture arm64 (mldsa44, ec_GFp_mont,
etc).
2. `audiopus_sys` linked against the wrong iOS runtime version,
missing `___chkstk_darwin`.
Following the rustls-platform-verifier docs and the standard Rust+
iOS+TLS pattern used by 1Password / Signal / rustup / Bitwarden,
this commit swaps the TLS provider to **native-tls** so each
platform picks its own:
* macOS + iOS -> Security.framework (no external C deps)
* Windows -> SChannel
* Linux/BSD -> system OpenSSL
Changes:
crates/chanora_protocol/Cargo.toml
crates/chanora_audio/Cargo.toml
* Drop `default-tls` from tsclientlib's features. The remaining
`audio` feature is what we actually use; default-tls was a
reqwest convenience that picked rustls+aws-lc-rs.
* Add a direct `reqwest` dep with `default-features = false,
features = ["charset", "http2", "native-tls"]`. Cargo's
workspace feature unification carries this through the
transitive `tsclientlib -> reqwest` chain.
apps/chanora_flutter/ios/Podfile
* Uncomment `platform :ios, '13.0'` so CocoaPods stops emitting
the implicit-platform warning and Xcode's iOS deployment-
target check is honored.
apps/chanora_flutter/ios/Podfile.lock
* Generated by `pod install` after the platform pin. Committed so
iOS builds on other developer machines pull the exact same Pod
versions.
apps/chanora_flutter/ios/Runner.xcodeproj/project.pbxproj
apps/chanora_flutter/ios/Runner.xcworkspace/contents.xcworkspacedata
* CocoaPods auto-integration: adds Pods_Runner.framework +
Pods_RunnerTests.framework references and the Pods xcconfig
file references. Standard `pod install` output; reviewing the
diff shows only Pod-bookkeeping additions, no signing or
target-config drift.
Verified end-to-end on the M1 Mac (coder@100.118.130.73):
cargo build --release -p chanora_bridge 29.09 s
cargo build --release --target aarch64-apple-ios 24.32 s
(with IPHONEOS_DEPLOYMENT_TARGET=13.0 and
CMAKE_POLICY_VERSION_MINIMUM=3.5 in the env to satisfy the
audiopus_sys cmake invocation; documented as a P1 build-glue
follow-up.)
flutter build ios --release --no-codesign ok
Built build/ios/iphoneos/Runner.app (16.9 MB)
Xcode GUI build of Runner.xcworkspace ok
(after the user opened Runner.xcworkspace, NOT
Runner.xcodeproj, and Clean Build Folder.)
Tests on macOS unchanged: chanora_audio 34 / 0 / 0.
DEC-025: iOS + macOS officially in scope for P0.
|
||
|
|
f3320715ea |
feat(audio,ios): AVAudioSession PlayAndRecord+voiceChat in AppDelegate
iOS AVAudioSession must be configured BEFORE Flutter starts its
audio pipeline; the canonical place is application(_:didFinishLaunching\
WithOptions:) in AppDelegate.swift. This commit:
apps/chanora_flutter/ios/Runner/AppDelegate.swift:
* import AVFoundation
* In application(_:didFinishLaunchingWithOptions:), call
AVAudioSession.sharedInstance().setCategory(.playAndRecord,
mode: .voiceChat,
options: [.defaultToSpeaker, .allowBluetooth, .allowBluetoothA2DP])
followed by setActive(true). Failures are NSLogged but do not
block app launch — cpal's CoreAudio backend will still come up
against the default iOS routing.
This shape:
* routes the receiver/speaker like a phone call (.playAndRecord +
.voiceChat),
* engages on-device AEC / NS where supported,
* defaults to speaker so users don't have to hold the phone to
their ear,
* permits Bluetooth headsets (AirPods et al. just work).
crates/chanora_audio/src/engine.rs:
* Replace the iOS engine-start placeholder log line ('binding
pending — Chanora iOS audio is documented-only for Beta') with
an honest acknowledgment that the AVAudioSession configuration
lives Swift-side. The Rust engine acknowledges the request, then
cpal opens its CoreAudio streams against the session.
iOS-only Rust code is #[cfg(target_os = "ios")]-gated so this commit
is no-op on every other platform.
SRS-197: iOS/macOS audio routing contract. DEC-025: iOS officially
in scope for P0 (Focused PTT only — Apple's sandbox model has no
global PTT analogue).
|
||
|
|
e3d7017dd9 |
feat(macos,ios): entitlements + permission strings + bundle-glue script
macOS:
* Runner/DebugProfile.entitlements + Release.entitlements: add
com.apple.security.network.client (outbound TS3 server connect)
and com.apple.security.device.audio-input (microphone capture).
Debug keeps com.apple.security.network.server + cs.allow-jit
(Flutter hot-reload needs both); Release drops them.
* Runner/Info.plist: add NSMicrophoneUsageDescription and
NSInputMonitoringUsageDescription so the macOS system prompts
show a sensible explanation when Chanora first needs mic or
Input Monitoring access. Input Monitoring is required by
CGEventTapCreate (SDD-085).
* Runner.xcodeproj/project.pbxproj: switch Debug/Release/Profile
code-signing from Automatic + Apple Development to Manual +
"Sign to Run Locally" (CODE_SIGN_IDENTITY = -). This lets
`flutter build macos --release` work over SSH where the login
keychain is locked. The owner re-enables the personal team
locally in Xcode for physical-device iOS testing later.
iOS:
* Runner/Info.plist: add NSMicrophoneUsageDescription and the
UIBackgroundModes = ['audio'] entry so voice traffic continues
when the app is backgrounded (TS3 servers drop clients on idle
audio streams).
tools/macos-postbuild.sh: new script. flutter build macos --release
emits build/macos/Build/Products/Release/chanora_flutter.app but
does NOT bundle libchanora_bridge.dylib. FRB on macOS dlopen()s the
bridge as chanora_bridge.framework/chanora_bridge, not a plain
dylib. This script:
1. Wraps target/release/libchanora_bridge.dylib in a proper
chanora_bridge.framework (Versions/A layout, Info.plist,
Resources, symlinks).
2. Rewrites LC_ID_DYLIB to
@rpath/chanora_bridge.framework/chanora_bridge.
3. Ad-hoc codesigns the framework and the .app bundle.
4. Verifies with codesign --verify --deep --strict.
macOS analogue of buildit.cmd on Windows. Auto-integration into
Xcode build phases via cargokit / corrosion is a P1 carryover.
Verified end-to-end on the M1 Mac:
cargo build --release -p chanora_bridge 11.76 s
flutter build macos --release ok (59.2 MB)
tools/macos-postbuild.sh Release ok
chanora_flutter.app launch via SSH bridge initialised,
identity + bookmark
store initialised
(~5 s smoke).
~/Library/Logs/app.chanora.chanora_flutter/chanora.log captures
the boot sequence cleanly.
DEC-025 reference: macOS desktop is officially in scope.
|
||
|
|
4d57d189c9 |
feat(flutter,macos,ios): scaffold platform Xcode projects via flutter create
Ran `flutter create --platforms=macos,ios --project-name=chanora_flutter
--org=app.chanora .` on the M1 Mac to generate the standard Flutter
platform-specific scaffolding (Runner.xcodeproj, Podfile, AppDelegate,
entitlements, etc.) for both macOS and iOS.
The cross-platform Dart source (lib/) and Rust workspace (crates/,
core/) carry the actual application logic; these scaffolds are
required only so flutter build macos / ios can resolve their Xcode
projects. No application code added.
macOS smoke-launch from the M1 Mac verified the bridge dylib load
path: after manually wrapping libchanora_bridge.dylib into a proper
chanora_bridge.framework bundle (FRB on macOS expects a framework,
not a plain dylib) and codesigning ad-hoc, the runner starts cleanly
through 'bridge initialised', 'identity store initialised', 'bookmark
store initialised' just like the Linux runner.
Following commits will:
* Wire the framework-bundling step into build glue (currently manual
install_name_tool + codesign).
* Replace the macOS PTT backend stub (crates/chanora_audio/src/
ptt_backends/macos.rs) with live IOHIDCheckAccess +
CGEventTapCreate so the descriptor advertises real L2/L3 capability
on a permission-granted box (SDD-085).
* Add the iOS AVAudioSession PlayAndRecord+voiceChat wiring.
* Add docs/verification/macos-p0-acceptance.md and ios-p0-acceptance.md.
|