Audio Monster treats the native client as the owner of the user's narrated-document collection. The native Kokoro engine produces an artifact and a recommended filename; the app decides where to save it. For a user who has iCloud Drive available, the default is the Documents directory inside Audio Monster's ubiquity container. This makes the files available through iCloud Drive to other Apple devices signed into the same account.
This design uses iCloud Documents rather than CloudKit because the current data is a collection of user-visible audio files. CloudKit may be appropriate later for structured job history, indexes, or service state. Apple distinguishes these services in Configuring iCloud services.
The client resolves the recommended location in this order:
- A custom folder previously selected in Settings remains active through its security-scoped bookmark.
- Otherwise, the app calls
FileManager.url(forUbiquityContainerIdentifier: nil)on a background task. Apple notes that resolving a ubiquity container can take time and should not run on the main thread. The API returnsnilwhen the container is unavailable. Seeurl(forUbiquityContainerIdentifier:). - When resolution succeeds, the destination is the container's
Documentsdirectory. The app'sNSUbiquitousContainersconfiguration makes this document directory visible in iCloud Drive; Apple's iCloud fundamentals describesDocumentsas the public part of a ubiquity container. - When resolution returns
nil, the client falls back to~/Library/Application Support/Audio Monster/Library. This covers a user without iCloud Drive, an offline or signed-out account, and a development build without working iCloud entitlements. The folder remains available through Settings and Finder, but does not pretend to be a provisioned iCloud container.
Settings displays whether the active destination is iCloud Drive, the local fallback, or a custom folder. Choosing “Use Recommended Location” clears the custom override and repeats iCloud resolution.
While the menu-bar app is running, it observes NSUbiquityIdentityDidChange and resolves the recommended location again after an iCloud sign-in, sign-out, or Documents-sync setting change. A custom folder remains authoritative across those account changes.
Every completed download is first staged on local storage and collision-checked before final placement. The client then uses a destination-specific path:
- For the app-owned iCloud Documents container, it calls
FileManager.setUbiquitous(_:itemAt:destinationURL:)on a background task to move the staged file into iCloud. Apple documents that this operation may take time, should not run on the main thread, and performs file coordination internally. It must not be wrapped in a separateNSFileCoordinatoroperation. SeesetUbiquitous(_:itemAt:destinationURL:). - For the Application Support fallback or a custom security-scoped folder, it copies the staged file through
NSFileCoordinator. This preserves coordinated local/document-provider access without applying the iCloud-specific transfer API to destinations the app does not own.
Apple's broader document guidance explains coordinated access for iCloud documents and document-based clients; see Designing Documents in iCloud and NSFileCoordinator.
The source URL remains embedded in the audio tags and in macOS “Where from” metadata regardless of which location is active.
The current identifiers are:
- macOS bundle:
org.audiomonster.AudioMonster - iCloud container:
iCloud.org.audiomonster.AudioMonster
The Apple Developer team now has the bundle identifier and iCloud container registered, with iCloud Documents enabled and the container assigned. The repository keeps those stable identifiers in source but never stores private keys or provisioning profiles.
For a signed build:
- Keep the
NSUbiquitousContainersentry in the productionInfo.plist, including the public-document setting and display name. - Download the
Audio Monster Developer IDprovisioning profile and keep it outside the repository. - Set
AUDIO_MONSTER_SIGNING_IDENTITYto the matching Developer ID Application identity andAUDIO_MONSTER_PROVISIONING_PROFILEto the downloaded profile, then runbundle exec fastlane mac signed. - Test signed-in, signed-out, offline, first-launch, and conflict scenarios on real devices before notarization or broader distribution.
The signed build embeds the profile and uses
apps/macos/Resources/AudioMonster.entitlements. The current Developer ID
profile was issued in Apple's “Compatible with Xcode 5” iCloud Documents mode,
so its allow-list uses the team-qualified
com.apple.developer.ubiquity-container-identifiers form:
<Team ID>.iCloud.org.audiomonster.AudioMonster. The source entitlement uses
Apple's $(TeamIdentifierPrefix) placeholder, and the signed-build script
resolves it from the selected profile rather than committing a contributor's
Team ID. Do not add the newer
com.apple.developer.icloud-services or
com.apple.developer.icloud-container-identifiers keys to this build unless a
replacement profile explicitly authorizes them; macOS rejects an app at launch
when its restricted entitlements exceed the embedded profile. Apple's legacy
iCloud entitlement reference
documents the team-qualified ubiquity-container form.
The default .app remains ad-hoc signed so contributors can build without Apple credentials. Ad-hoc signing does not provision the registered iCloud container, so its normal behavior is to receive no ubiquity URL and use the Application Support fallback. The bundle exec fastlane mac signed lane produces the provisioned Developer ID variant that can resolve the app-owned iCloud Documents folder. The mac release lane notarizes and staples that build for distribution.
A future iOS or iPadOS target can access the same files by using the same registered iCloud container under the same Apple Developer team and including that container in its entitlements. Sharing the container should be an explicit product decision: both apps then operate on the same user-visible document library and must use coordinated, conflict-aware file access.
Only completed audio artifacts live in the shared document container today. Menu settings and temporary synthesis files do not sync through iCloud. A future mobile client can use the same shared Swift domain and storage conventions while choosing either on-device synthesis or a future hosted API.
A hosted backend does not receive access to a user's personal iCloud Drive container. If a hosted conversion service is added later, the native app remains responsible for downloading its artifact and placing it in iCloud Documents. A future web frontend can offer browser downloads, but it cannot write into this FileManager ubiquity container directly.
If product requirements later include server-visible libraries, web/mobile history synchronization, or server-side sharing, model that as a separate authenticated storage system or a deliberate CloudKit design. Do not expose a local iCloud path to a future service API: that service should return bytes and a filename while each Apple client owns persistence.