| 1 | # Default server, Sign in, guest joining, server setting — 2026-09-24 |
| 2 | |
| 3 | Branch `feat/default-server` off `f91de82`. The signed-out home names the |
| 4 | server (calls.oficina.works by default) with one **Sign in** and a secondary |
| 5 | **Join a call as a guest**; the server is a setting (Mac Settings scene, |
| 6 | iPhone gear sheet). M1 Max, macOS 27. |
| 7 | |
| 8 | | Check | Result | |
| 9 | | --- | --- | |
| 10 | | `build-bridge.sh` | Rebuilt; RNNoise and DeepFilter cache hits at their pins | |
| 11 | | `swift test` | 133 tests, 0 failures, 1 skipped (keychain); adds `DefaultServerTests` (17) | |
| 12 | | `GOTOOLCHAIN=go1.26.5 make ci`, `make native-test` | Passed with `GOFLAGS=-count=1` | |
| 13 | | `make native-mac` | Built; launched and stayed up | |
| 14 | | `make iphone` | Simulator build succeeded | |
| 15 | | `CGO_ENABLED=0 make browser` | 33 of 34 in the full run while an Xcode build shared the machine; `mutualshare` (a frame-flow window stalled) passed alone on an idle machine. No web code changed | |
| 16 | | `make native-browser` | Passed; `TestNativeBrowserAuthentication` gains a `server` case (Sign in's instance-root handoff) | |
| 17 | | iPhone UI tests | `testSignedOutHomeIsSignInAndGuest`, `testInvalidGuestLink` passed on the simulator | |
| 18 | | `TestIPhoneSafariAuthentication` | Member (Sign in, `-CallsServer`) and guest (guest screen) passed. The guest case was already failing on main: the web's guest screen needs its "sign in" link followed, and Safari's autofill bubble could take the tap on the submit button | |
| 19 | | Snapshots | `CallsInterop --lobby-snapshots` renders the new states (see DESIGN.md) | |
| 20 | |
| 21 | # Per-call device routing on LiveKit's module — 2026-09-23 |
| 22 | |
| 23 | Branch `merge/native-call-devices`: `native-call-devices` (`410ddcb`, the |
| 24 | source of Calls 0.2.1 build 3) merged into `origin/main` at `1ab8a2e`. The |
| 25 | Mac stays on LiveKit's AVAudioEngine module with DeepFilterNet 3; build 3's |
| 26 | CoreAudio HAL device (`CallsAudio`) was dropped, because WebRTC's |
| 27 | custom-audio-device constructor takes no audio processing module. Its routing |
| 28 | rules were carried onto the module (`AudioRoutes`), and its camera discovery, |
| 29 | refresh and restore-on-refusal kept. M1 Max, macOS 27. |
| 30 | |
| 31 | | Check | Result | |
| 32 | | --- | --- | |
| 33 | | `build-bridge.sh`, `build-rnnoise.sh`, `build-deepfilter.sh` | Built fresh in a new worktree (no cache) | |
| 34 | | `deepfilter-notices.py` after that build | Regenerates `LICENSE.deepfilternet-crates` byte for byte (90 crates) | |
| 35 | | `swift test` | 116 tests, 0 failures, 1 skipped (keychain test, as before); includes the seven `CallAudioSelectionTests` and a non-default choice on the real module | |
| 36 | | `GOTOOLCHAIN=go1.26.5 make ci`, `make race`, `make native-test` | Passed with `GOFLAGS=-count=1` (no cached results) | |
| 37 | | `make native-mac` | Built; signature verifies; bundle carries LiveKitWebRTC, the DeepFilterNet model, all five notices and `PATENTS.webrtc`; launched and stayed up | |
| 38 | | `make iphone` | Simulator build succeeded | |
| 39 | | `CGO_ENABLED=0 make browser` | 34 of 34 scenarios passed | |
| 40 | | `make native-browser` | Passed (auth, member, guest, chat); CallsInterop rebuilt by the target; the new per-call audio step ran and passed, DeepFilterNet 3 processed the synthetic microphone | |
| 41 | |
| 42 | Found while porting: LiveKit's engine module (M150) never reports which device |
| 43 | it is on (`inputDevice`/`outputDevice` read back nil — confirmed on this |
| 44 | machine), and `trySetInputDevice`/`trySetOutputDevice` return YES when the |
| 45 | native call fails (read in the source). Main's pickers read the device back, |
| 46 | so a non-default choice would have been reported as refused; the choice is |
| 47 | now kept by `AudioRoutes`. |
| 48 | |
| 49 | Not verified here: this Mac lists only the default microphone and speaker, |
| 50 | so switching between two real devices, unplugging a chosen one, and the |
| 51 | module following a new system default or sample rate need a hands-on pass |
| 52 | with a USB or Bluetooth device. |
| 53 | |
| 54 | --- |
| 55 | |
| 56 | # LiveKit WebRTC and neural noise reduction — 2026-09-23 |
| 57 | |
| 58 | Branch: `feat/livekit-webrtc-audio`, based on `origin/main` at `3846ca4`. Not |
| 59 | merged, not deployed. Machine: M1 Max, macOS 27, Xcode 26.6. |
| 60 | |
| 61 | | Check | Result | |
| 62 | | --- | --- | |
| 63 | | `./native/scripts/build-bridge.sh` | Passed | |
| 64 | | `native/scripts/build-rnnoise.sh`, `build-deepfilter.sh` | Built both xcframeworks from their pins (DeepFilter: Rust 1.92.0 via rustup, cbindgen 0.29.2) | |
| 65 | | `swift test` (native/apple) | 48 tests, 0 failures, including the suppressor fixture tests | |
| 66 | | `make native-test` (uncached, `GOFLAGS=-count=1`) | Passed | |
| 67 | | `make native-mac` | Built; ad hoc signature verifies; bundle carries LiveKitWebRTC.framework, the DeepFilterNet model and the RNNoise/DeepFilterNet notices; app launches | |
| 68 | | `make iphone` + `build-for-testing` (simulator) | Build and test build succeeded; RNNoise linked, DeepFilter not | |
| 69 | | `make native-browser` | Passed (member, guest, chat); asserts DeepFilterNet 3 processed the synthetic microphone and WebRTC reports its suppressor and gain off, echo cancellation on | |
| 70 | | `CGO_ENABLED=0 make browser` | 33 of 34 passed; `switching` (web camera switch) failed once under load from a concurrent simulator run and passed alone. This branch does not touch the web client | |
| 71 | | `make iphone-browser` | Failed, and fails identically on a clean `origin/main` worktree (both peers stuck `reconnecting`, 0 frames); the Safari UI test flaked differently on each run. Environmental, not this branch; the first run's media test did pass on this branch | |
| 72 | | `GOTOOLCHAIN=go1.26.5 make ci` | Passed | |
| 73 | |
| 74 | Fixture (synthesised speech at -23 dBFS with seeded hiss and key clicks, each |
| 75 | suppressor alone): RNNoise takes the noise-only lead-in from -41 to -71 dBFS |
| 76 | and DeepFilterNet 3 to -69 dBFS (both at their 30 dB limit); speech holds at |
| 77 | -24.5 → -24.6 dBFS; 99% of voiced frames kept by each. Per 10 ms frame: |
| 78 | RNNoise 0.69–0.81 ms, DeepFilterNet 1.16–1.23 ms (about 7–8% and 12% of one |
| 79 | core). DeepFilterNet's model loads in 0.26–0.35 s. In the native/browser |
| 80 | gate, as wall-clock share of the audio thread with Chromium on the same |
| 81 | machine: DeepFilterNet median 15.1–15.3% (13–27%), RNNoise median 12.9%. |
| 82 | |
| 83 | Needs a real call or device: echo with speakers (software AEC3 on Mac, now on |
| 84 | the AVAudioEngine module), typing, wind and room echo against both models; |
| 85 | that SpeechGain lifts a quiet talker without audible pumping; switching Mac |
| 86 | microphone and speaker mid-call (only one of each on the test machine); |
| 87 | Bluetooth at 16 kHz handing back to WebRTC's suppressor; Voice Isolation on |
| 88 | iPhone standing ours aside; whether iPhone accepts the platform-mode options |
| 89 | (the readout says if not); DeepFilterNet's cost on an iPhone. The Mac audio |
| 90 | bug (growling) is not addressed and the module change may move it either way. |
| 91 | A test process cannot get microphone permission, so Apple voice processing's |
| 92 | live state on Mac and the Mic Mode menu could not be observed. |
| 93 | |
| 94 | --- |
| 95 | |
| 96 | # Per-call device routing — 2026-09-21 |
| 97 | |
| 98 | Superseded for audio when this branch was merged into main on 2026-09-23: |
| 99 | the CoreAudio HAL device (`CallsAudio`) it describes was not kept, and its |
| 100 | routing rules now run on LiveKit's audio device module (see the README). |
| 101 | |
| 102 | Worktree: `meet-call-devices`, branch `native-call-devices`, based on fetched |
| 103 | `origin/main` at `3846ca4`. Calls 0.2.1 (build 3) is signed with Team Tito Limited, notarized, and published. |
| 104 | Download: https://raw.amadan.net/oficina/native-releases/deb0bac4cdf6ef23a8edca9094f41260fc02143d/calls/releases/net.amadan.oficina.calls-3.zip |
| 105 | |
| 106 | Independent release review: GPT-6 Astra (`release_review`), approved with the |
| 107 | physical-device acceptance limitations below. The extracted, notarized app also |
| 108 | passed Gatekeeper and a relocated launch smoke test. |
| 109 | |
| 110 | - Mac app builds and its development signature verifies; iPhone simulator builds. |
| 111 | - All 29 Swift tests pass, including independent per-call selections, reset on |
| 112 | leave, refused changes, disconnection fallback, following system defaults, |
| 113 | and reopening devices after sample-rate changes. |
| 114 | - Native/browser member and guest calls pass with the new HAL audio path. |
| 115 | Reopening both audio routes and refusing a missing microphone preserve |
| 116 | increasing audio counters and the peer connection. Camera switching, queued |
| 117 | camera changes, refusal, stream renewal and leaving also pass. |
| 118 | - Native/browser chat passes. The shipping DevicePanel was rendered and visually |
| 119 | inspected in `native/build/call-devices.png`. |
| 120 | - `GOTOOLCHAIN=go1.26.5 make browser` passes all 34 Chromium scenarios. |
| 121 | - `GOTOOLCHAIN=go1.26.5 make ci` passes. The repository pins this Go version for |
| 122 | its dependency-notice inventory. |
| 123 | |
| 124 | The live gate uses the system's audio route and a synthetic camera. Audio packet |
| 125 | counters establish transport continuity, not audible quality. Physically changing |
| 126 | between USB/Bluetooth devices, unplugging them, and checking echo cancellation |
| 127 | remain hands-on acceptance checks; unit tests cover the routing policy. |
| 128 | |
| 129 | --- |
| 130 | |
| 131 | # Native completion verification — 2026-09-12 |
| 132 | |
| 133 | Branch: `codex/iphone-and-mirrored-preview`, based on `86ed9f3`. |
| 134 | |
| 135 | - Final `make ci`, server race gate, and shared-core race gate pass. |
| 136 | - Full Chromium call gate passes (539 seconds) for this web snapshot. |
| 137 | - Final native/browser gate passes (81 seconds), including member/guest media, |
| 138 | browser authorization, and bidirectional chat. |
| 139 | - iPhone Safari member/guest authorization and native peer media tests pass |
| 140 | on iOS 26.5 Simulator (154 seconds). Peers retain media through stream renewal |
| 141 | and leave cleanly. Simulator media uses synthetic video and disables audio. |
| 142 | - Mac app builds, its ad hoc signature verifies, and it is installed and |
| 143 | relaunched at `/Applications/Calls.app` with the approved icon and license. |
| 144 | - iPhone development build signs successfully with the personal development |
| 145 | team and is installed on Paul's iPhone 16 Pro. Initial launch was blocked by |
| 146 | the phone's lock screen; physical launch/permissions and audible audio await |
| 147 | an unlocked-device acceptance pass. |
| 148 | - Independent GPT-6 Astra source review approved the local-build milestone |
| 149 | after fixing cancellation outcomes for queued chat and obsolete join/leave |
| 150 | operations. A regression test verifies all accepted queued chat gets an |
| 151 | explicit failure on re-registration; it passes under the race detector. |
| 152 | |
| 153 | The server update includes member-only repeat sharing of encrypted invitations |
| 154 | and its additive migration. Older invitations remain valid. Native credentials |
| 155 | remain in memory; calls are foreground-only on iPhone. Developer ID notarization, |
| 156 | TestFlight, physical audio/device routing, background calling and native screen |
| 157 | sharing remain outside this local-install milestone. |
| 158 | |
| 159 | The earlier milestone record follows for historical context. |
| 160 | |
| 161 | --- |
| 162 | |
| 163 | # Mac milestone verification — 2026-09-11 |
| 164 | |
| 165 | Base: fetched `origin/main` at `a283c53`, then fast-forwarded the working branch |
| 166 | to the newer `origin/integrate/home-sso-release` at `eee686a`. Working branch: |
| 167 | `codex/native-mac-milestone`. No production deployment was performed. |
| 168 | |
| 169 | | Check | Result | |
| 170 | | --- | --- | |
| 171 | | `CGO_ENABLED=0 make ci` | Passed: vet, formatting, all Go tests and migration agreement | |
| 172 | | `make race` | Passed across `internal/...` | |
| 173 | | `CGO_ENABLED=0 make browser` | Passed all 31 Chromium scenarios; 541 seconds for the browser suite | |
| 174 | | `make native-test` | Passed shared core, bridge and core race tests | |
| 175 | | `make native-mac` | Built the local Mac app with a macOS 14 deployment target | |
| 176 | | `codesign --verify --deep --strict native/build/Calls.app` | Passed for the ad hoc development signature | |
| 177 | | `TestNativeMacCallsBrowser` | Passed member and guest cases; final run 26.49 seconds | |
| 178 | | App launch and opening-window inspection | Passed | |
| 179 | |
| 180 | The native/browser test observed video decoded in both directions, audio bytes |
| 181 | received in both directions, no incoming guest media before admission, increasing |
| 182 | media counters after repeated three-second stream renewals, preservation of the |
| 183 | native participation ID, and removal of the browser's remote tile after the |
| 184 | native client left. It uses a synthetic native camera implemented only in the |
| 185 | separate `CallsInterop` executable, Chromium's fake media device, and real |
| 186 | magic-link sessions on an isolated local Calls server. Audio traffic counters do |
| 187 | not prove audible microphone/speaker quality. |
| 188 | |
| 189 | `TestNativeCoreUsesHomeSessionAndResumesCall` separately runs the shared Go |
| 190 | client through the real Home assertion/linking fixture, stream renewal and |
| 191 | meeting end. `TestNativeCoreCannotUseAgentBearerAsHumanSession` rejects agent |
| 192 | credentials for calls. Metadata isolation tests cover an actual second meeting |
| 193 | the guest cannot access. Unit tests exercise SSE bounds and framing, redirect |
| 194 | refusal, retry sequence preservation, duplicate delivery and stale native |
| 195 | callbacks after a pair generation changes. |
| 196 | |
| 197 | Unverified physical-device acceptance: camera/microphone permission prompts, |
| 198 | audio-device changes, sleep/wake, and a live Home passkey ceremony. |
| 199 | Distribution signing/notarization, |
| 200 | iOS, screen sharing and full long-call TURN renewal parity remain outside this |
| 201 | first milestone. The result is a local development app, not a public release. |
| 202 | |
| 203 | |
| 204 | The webview sign-in implementation was replaced with system-browser approval. |
| 205 | `TestNativeBrowserAuthentication` covers member and guest sign-in in a fresh |
| 206 | Chromium context with JavaScript disabled: the email opens in a separate tab, |
| 207 | approval hands a session to the shared Go client, and that session can read the |
| 208 | meeting metadata. Server tests cover Home identity/authentication-time |
| 209 | preservation, distinct session tokens, explicit POST approval, CSRF rejection, |
| 210 | wrong proof, replay, expiration, revoked source sessions, and unsafe targets. |
| 211 | |
| 212 | Handoff revision checks (2026-09-11): CI and migration agreement passed; core |
| 213 | and bridge tests passed with the core race detector; server authentication race |
| 214 | tests passed; member/guest browser handoff and code comparison passed (65.13 s); |
| 215 | native/browser media and departure checks passed (84.33 s). The rebuilt app's |
| 216 | ad hoc signature verified, and the app was reopened locally. Production sign-in |
| 217 | requires deployment of the new server routes; no deployment was performed. |
| 218 | |
| 219 | The full `CGO_ENABLED=0 make browser` gate also passed all 31 scenarios |
| 220 | after the handoff change (797.94 s for Chromium). |
| 221 | |