Status: implemented locally behind rollout gates, 2026-09-11. Working tree: HEAD 98553fae plus preserved existing changes, build 1.3 (63). Implementation is authorized; no deployment or submission has occurred. Existing Android work is separate.
LocalVoiceProfileStore saves profiles.json plus reference audio in Application Support/LocalQwenVoiceProfiles. Profiles include name, primary/additional recordings, exact transcripts, preferred reference and per-model-family generation settings. These are conditioning references, not independently trained model weights. There is no account owner in LocalVoiceProfile and the directory is installation-wide. Sign-out keeps profiles; another signed-in account on the same installation can see them. Files use Complete protection and backup exclusion. There is no local-profile cloud-save or cross-device restore flow.
Hosted ElevenLabs clones use a different path: voice-clone-create records user_id, provider and voice_id in user_cloned_voices; voices-list selects owned IDs for the authenticated user. The architecture supports account-linked hosted clones across clients, subject to provider availability/access, but no fresh two-device test was performed. A hosted voice ID cannot replace local model reference audio.
Implemented first scope: explicit Save to account and Download to this device, not automatic continuous synchronization. Local-only remains the default. Support all reference recordings, transcripts, profile name, preferred reference and family settings. Exclude generated clips/history, model downloads and transient embeddings. Default voice selection stays device-local initially; unavailable models/settings are preserved but not applied.
Use Supabase private Storage for audio and account-owned metadata tables for profiles/references. Reuse authenticated backend boundaries, with owner checks plus RLS and owner-scoped object paths. Never use a public bucket or embed service credentials in clients. Short-lived access must be issued only after authorization. Validate actual file format, duration/size, checksum and schema; set bounded profile/reference/storage quotas before rollout.
Account isolation precedes cloud sync. New account-owned profiles/cache use owner-specific directories. Existing installation-wide profiles remain visible as legacy On this device; explicitly choose which to import into an account. Do not silently claim or upload them for the current account. Account-owned cache must become inaccessible on sign-out/account switch, including active playback and pending downloads. Preserve deliberate local-only data with clear shared-device copy.
Upload metadata and recordings into a pending revision, then publish only after all files validate; retry idempotently and clean abandoned uploads. Use revision checks to prevent lost updates; preserve conflicting edits as a separate copy rather than last-write-wins. Download into staging, verify all checksums, then atomically activate. An interrupted transfer must leave an existing working profile usable.
UI states: On this device, Saved to account, Available to download, Uploading/Downloading, Changes not saved, Failed. Offer distinct Remove from this device and Delete from account actions. Cloud deletion must not unexpectedly remove independent local copies; explain retained copies. Define account-deletion cleanup for metadata, audio, pending objects and cached account data, with tombstones preventing queued uploads from resurrecting deletions.
Explicit opt-in explains that reference audio and transcript will be uploaded to SpeakTrue storage and downloaded on other signed-in devices; it is separate from ElevenLabs consent. Update privacy/retention copy before enabling. Do not describe this as end-to-end encryption unless client-side keys and recovery are actually implemented. Proposed v1 uses private authenticated service storage; encryption design, quotas and any cost/plan restrictions must be settled before implementation rollout.
A1-A4 fixes -> A5 TestFlight evidence -> public release decision. Cloud saving is a separate feature milestone and need not delay the initial TestFlight.
Cloud B1: backend schema/storage/policy/cleanup contracts and negative cross-account tests. B2: iOS owner scoping, legacy import and transfer states. B3: two-device save/restore, offline generation after download, interruption/conflict/deletion/account-switch tests. B4: Android client integration against the same schema, coordinated with its existing local TTS work. No cross-platform completion claim until both clients are tested. Backend rollout requires reviewed migrations and explicit deployment authorization.
Completion requires no cross-account reads, correct references/settings on the second device, clean offline generation with a supported downloaded model, preserved local-only profiles, and verified deletion semantics. TestFlight is the appropriate place to establish this evidence before public availability.
App privacy manifest declares UserDefaults (CA92.1), elapsed-time measurement (35F9.1) and app-file timestamps (C617.1). Hosted consent now gates request boundaries, including captured account-operation authorization for TTS/STT/STS and direct ElevenLabs calls; local navigation stays available. Qwen new/reset defaults use top-k 50/repetition 1.05, preserving saved overrides and other family defaults. OmniVoice requires explicit Boolean LocalTTSOmniVoiceBetaEnabled; production default false.
Optional cloud profile code is implemented with SPEAKTRUE_CLOUD_VOICE_PROFILES_ENABLED=false in Info.plist. Backend LOCAL_VOICE_PROFILES_ENABLED defaults off. Follow backend/supabase/functions/local-voice-profiles/README.md for schema, limits, cleanup endpoint and rollout requirements. Configure SPEAKTRUE_CLOUD_VOICE_STORAGE_ORIGIN to the actual HTTPS Storage origin if different from the API origin. Enable iOS only after backend and cleanup deployment plus real storage/two-device acceptance. The uploader normalizes reference audio to mono PCM16 WAV. Retry revision identity is retained for the current app session; app termination can leave pending reservations that expire after 24h. Account-bound downloads and new profiles are hidden after sign-out; legacy profiles remain unclaimed. Generated history is still installation-scoped and excluded from this feature.
New cloud limits: 50 active/reserved profiles, eight references/profile, 10 MiB/reference, 1–60 seconds mono 8–48 kHz, 512 MiB/account, ten pending revisions and 500 lifetime cloud IDs including tombstones. These are initial fixed limits, not a billing promise.
OpenCode2 preflight returned an empty catalog, so requested GLM/DeepSeek were not dispatched; native agents implemented bounded slices and Codex reviewed/integrated them. No external source disclosure occurred. No merge, push, migration deployment or app upload. Android client cloud integration remains a separate follow-on against the tested contract; existing Android local TTS work was preserved.
Build 63 focused simulator suite passed 72 tests: 52 local-Qwen, eight cloud-profile, eight hosted-consent/operation and four release-settings tests. Backend passed 17 tests and both entrypoint type checks. A disposable PostgreSQL instance independently passed migration, owner isolation, permission denial, idempotency, revision conflict, tombstone and account-deletion cleanup checks. Android/iOS parity passed 12 surfaces/24 gates. These checks do not establish physical-device inference quality or live Supabase Storage behavior.
The full Android CI-equivalent gate remains required before any commit/push involving the release guard or shared account-delete contract; existing Android changes were preserved. Remaining rollout evidence: real backend/Storage deployment with scheduled cleanup, configured Storage origin, two-device profile round trip and deletion, supported-device generation/upgrade/offline checks, and App Store Connect privacy/license/review metadata plus submission validation.
Signed Release archive succeeded at /private/tmp/SpeakTrue-1.3-63.xcarchive. Archive Info.plist verifies version 1.3/build 63 with cloud profiles and OmniVoice beta flags false; the app-root privacy manifest includes the three intended required-reason declarations. codesign --verify --deep --strict passed with macOS trust-store access. App Store Connect validation and upload were not performed.
The complete bash scripts/verify_android_ci_local.sh gate passed before the iOS release commit: 797 Android unit tests, lint, signed release bundle verification, parity and local readiness checks. External Play/live-provider evidence remains outside the local gate. Standard Xcode clean and incremental signed iPhone builds also succeeded for 1.3 (63); the incremental build emitted no warnings. Full compilation still reports four upstream MLX Metal extension warnings. Existing Android planning edits are excluded from this iOS commit. Cloud rollout and device acceptance gates above remain pending.
App Store Connect rejected 1.3 (63) with errors 90062 and 90186 because the approved 1.3 train is closed. iOS Debug and Release now use marketing version 1.4 and build 64. Android stays at 1.3 (25); its iOS release assertions reflect the independent iOS version. A fresh archive must be created from this configuration; the previous 1.3 archive cannot be resubmitted as 1.4. No upload or App Store acceptance is claimed.