This page is generated directly from the app's data inventory, which is kept in the source repository and updated in the same commit as any change to how the app handles data. What follows is that inventory, unedited.
Status: no data collected, no data shared. That statement is literally true, not a marketing position. There is no server to collect anything to.
Nothing, unless you deliberately export a file — a printable PDF, or an encrypted backup — and choose where to send it. Both are described below.
Puzzlebind has no backend, no account system, no login, no sync and no analytics. The app makes no network requests of its own — not at launch, not while you build a book, not while it generates puzzles or renders a PDF. All puzzle generation and all PDF layout happen on the device, offline.
The only outbound traffic the binary is capable of comes from the platform purchase SDK (RevenueCat), which talks to RevenueCat and the platform store to answer one question: has this install bought the one-time unlock. It is given an anonymous store-generated identifier and none of your content — no book titles, no word lists, no clues, no email, no device identifier we set.
| Item | Where | Encrypted | Leaves device |
|---|---|---|---|
| Books (titles, subtitles, author line, page size, structure) | App private storage, one file | AES-256-GCM | Never |
| Puzzle sections and word lists, including your crossword clues | Same file | AES-256-GCM | Never |
| App settings | Same file | AES-256-GCM | Never |
| Document encryption key | iOS Keychain / Android Keystore | Protected by the OS | Never |
| Exported PDF | App cache, written only when you tap Export | No — it is a PDF for you to print | Only where you send it |
| Encrypted backup file | App cache, written only when you tap Create backup | AES-256-GCM under a key derived from your passphrase by scrypt | Only where you send it |
| Backup passphrase | Not stored anywhere | n/a | Never |
| Purchase entitlement | Not stored by us; held by the App Store / Play Store receipt | n/a | n/a |
The whole library is serialised to JSON and sealed as a single document. The 256-bit key is generated on the device on first launch, held in expo-secure-store under the alias puzzlebind.vault.key.v1 with WHEN_UNLOCKED_THIS_DEVICE_ONLY, and never transmitted. Every write draws a fresh random 96-bit nonce, because reusing a nonce under one AES-GCM key would destroy the guarantee entirely.
The envelope header (format magic, version, nonce length) is passed to AES-GCM as additional authenticated data, so it is covered by the authentication tag and cannot be rewritten. If the stored file is modified by anything other than the app, decryption fails the tag check and Puzzlebind refuses to open it and tells you — it will not show you silently corrupted books.
Two things can leave the device, both only when you choose:
.puzzlebind), protected by a passphrase you set. The passphrase is stretched with scrypt (N=215, r=8, p=1) and the library is sealed under the derived key with AES-256-GCM, with a fresh random salt and nonce every time. It is handed to the share sheet like the PDF. We never see the passphrase and hold no copy of the file, and we cannot open it — losing the passphrase means losing the backup.The backup's header, including the scrypt cost parameters, is authenticated as part of the encryption. A file whose work factor has been edited downwards to make it cheap to attack is rejected rather than opened.
There is no photo import, no document import, no audio, and no camera roll access in this app, so there is nothing else that could be attached to a book. Restoring a backup uses the system file picker, which grants the app access to the one file you choose and nothing else.
Verified against the generated AndroidManifest.xml, not just the config. Only these two are present in a build:
| Permission | Why | User-facing |
|---|---|---|
INTERNET | The purchase SDK asking the store whether this install has bought the unlock, and the purchase and restore flows themselves. Nothing else makes a network request. | No prompt; not shown by Android |
com.android.vending.BILLING | The one-time in-app purchase | No prompt |
Explicitly stripped via blockedPermissions, because the libraries we depend on would otherwise add them by default:
ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, CAMERA, RECORD_AUDIO, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, SYSTEM_ALERT_WINDOW, VIBRATE
Every one of those was present in the generated manifest before it was blocked, contributed by transitive dependencies rather than by anything Puzzlebind does. The app has no feature that uses any of them, so each is removed at manifest-merge time rather than left in place unused. SYSTEM_ALERT_WINDOW — draw over other apps — is worth calling out specifically: an offline puzzle-book maker has no business holding it.
A few normal-level permissions arrive from transitive Android libraries rather than from our configuration, such as ACCESS_NETWORK_STATE and the biometric pair USE_BIOMETRIC / USE_FINGERPRINT that comes with the OS keystore integration behind expo-secure-store. None is a runtime-prompted permission, none grants access to personal data, and none is used to collect anything.
No location, no microphone, no contacts, no photo library, no camera, no background access, no notifications, no draw-over-other-apps.
On iOS, no permission usage strings are declared at all, because the app asks for nothing. The expo-secure-store config plugin would otherwise add NSFaceIDUsageDescription, so it is explicitly disabled (faceIDPermission: false), which deletes the key rather than leaving a prompt the app would never show. The keystore entry is not gated behind biometrics. The app ships a PrivacyInfo.xcprivacy declaring no tracking, no tracking domains and no collected data types, with required-reason declarations only for file timestamp, user defaults and disk space.
An app update replaces the code, never the stored data. The key alias (puzzlebind.vault.key.v1) and the filename (puzzlebind.vault) are fixed, the envelope format is versioned, and nothing in the startup path deletes anything — erasing is reachable only from you tapping "Erase everything on this device" in Settings.
What DOES lose your books, by design:
WHEN_UNLOCKED_THIS_DEVICE_ONLY, so it is deliberately excluded from iCloud and iTunes backups and never leaves the device. A restored copy of the encrypted file has no key to open it. The same holds on Android: the expo-secure-store backup rules keep the keystore entry out of auto-backup.That is the honest cost of the privacy promise: because we hold no copy and the key never leaves the device, there is no way for us to recover your books. The encrypted backup described above is the only way to carry a library to a new phone, and it is the only thing that survives any of the three events above. Make one before you change devices.
Puzzlebind is free to build with. A single one-time purchase unlocks full-book PDF export. There is no subscription and no recurring charge.
Because there is no account, your purchase is tied to your Apple ID or Google account rather than to anything we hold — which is exactly why "Restore purchases" works on a new device and why there is nothing for you to sign in to. If the purchase SDK is not configured in a given build, it is never initialised, and that build makes no network requests whatsoever.
Puzzlebind is rated for ages 18+ on both stores and is not directed at children. It collects no data from anyone, of any age.
If the way the app handles data ever changes, this page changes in the same commit, and the date at the top moves. Previous versions remain in the public git history.
Questions about this policy: gapfound.apps@gmail.com