Privacy Policy

Last updated: 12 July 2026

What stays on your device

Dha keeps your practice history, recorded takes, tuning defaults, and app settings on your device. There are no accounts and no sign-in. If you turn on "Record this take," the audio is saved only on your device and is never uploaded.

Using "Delete all local data" removes the app's on-device practice sessions, course and guided-review progress, saved patterns, recordings, preferences, Coach consent, and random installation identifier. Local deletion does not erase Apple purchase history or server records already created for purchase verification, abuse and quota enforcement, notification idempotency, or a consented Coach request. Apple's account controls govern Apple's records; the automatic retention periods below and our support contact govern Dha server records and deletion requests.

Purchases

StoreKit purchases are processed by Apple. To recognise Pro for the live coach, the app sends Apple's signed StoreKit transaction and a random installation identifier to our backend on Amazon Web Services. We verify the certificate chain and transaction claims, but we do not store the signed JWS.

Apple also sends signed App Store Server Notifications when subscription state changes, including while the app is closed. We verify the signed notification and independently verify its nested transaction, renewal, or app-transaction information when present. We do not store the signed transaction, renewal, app-transaction, or notification JWS.

For each subscription we retain one canonical entitlement record containing: product identifier; active, expired, billing-retry, grace-unavailable, upgraded, or revoked status; expiry; StoreKit transaction and original transaction identifiers; Production or Sandbox environment; the nested transaction's Apple-signed timestamp; the notification or device event's Apple-signed timestamp; our last-updated timestamp; and a deletion timestamp. Separate alias records contain only the random installation or StoreKit app-account alias, a pointer to that canonical subscription, environment, original transaction identifier, event and update timestamps, and deletion timestamp. We use these fields only to recognise current Pro access, share the 30-drill limit across aliases of one subscription, handle restores and Family Sharing, and prevent stale, expired, revoked, upgraded, or unverified records from authorising live coach.

Entitlement and alias records are marked for automatic deletion 90 days after the latest of the subscription expiry, the latest verified entitlement event applied to that record, or our processing/update time. To process notifications once, we retain for at least 200 days after the later of Apple's signed event time or the time our processing begins: a one-way SHA-256 hash of the Production-or-Sandbox environment and Apple's notification UUID; processing or done state; Apple's signed event timestamp; processing/update/completion timestamps; a temporary random lease token and lease expiry while processing; and a deletion timestamp. These idempotency records contain no signed JWS. DynamoDB deletion can occur after a deletion timestamp rather than at the exact second.

On-device coach

Current versions build coaching drills privately on the device from the numeric timing, sam, relative-spacing, and tempo estimates already shown to you. No audio or practice metrics leave the device for coaching. A deterministic offline drill is used when the on-device coach is unavailable.

Older compatible versions may explicitly send a numeric timing estimate, sam estimate when available, relative-spacing estimate, hit/miss counts, tempo drift, taal, and tempo together with a random installation identifier to this backend. Their bounded legacy text processor receives only the taal, focus label, and suggested and current tempos — never audio, practice history, detailed scores, installation identifiers, StoreKit identifiers, or IP addresses. Those versions ask before the first send.

Abuse prevention and retention

Live coach is available only after an active verified Pro entitlement. For each request, our backend creates separate keyed HMAC-SHA-256 daily identifiers from a scope label, the current UTC day, and the installation identifier, original StoreKit transaction identifier, or request IP address. The HMAC secret stays in the backend environment. We store only each derived identifier, its request count, and its deletion timestamp — not the raw IP address in the rate-limit table. Changing the UTC day changes the derived identifier. These records are marked to expire two days after creation. The installation and original-transaction identifiers each enforce the 30-live-drill daily allowance. The IP identifier is a higher 180-request abuse ceiling so unrelated subscribers on a shared household, school, carrier, or VPN address do not normally consume one another's allowance.

We do not use entitlement, practice, or rate-limit information for advertising or cross-app tracking.

Contact

Questions or privacy requests: nora@playsoloist.com.

Back to Dha