Security
Your data mostly never leaves your phone.
Peak Fettle is built local-first. What does travel is encrypted in transit, backups are encrypted with a key only you hold, and payments never touch our servers at all. Here is exactly where everything lives.
Your iPhone
Every workout, set, weight, and health metric is written to a private database inside the app’s sandbox. On the free tier, this is the only copy that exists.
sqlite (on-device)
keys → ios keychain
free tier: 0 personal-data network calls
The wire
Anything that does travel — sign-in, Pro sync, backups — moves only over an encrypted connection. Nothing is ever sent in the clear.
https only
auth endpoints rate-limited
Our servers
Hold your account, Pro-tier sync data, and backups. Backups arrive already encrypted — the server stores them without the ability to read them.
postgres, encrypted at rest
backups: ciphertext only
no card numbers, ever
The key fact: for free users the second and third boxes are almost empty — the app is engineered, and machine-checked on every code change, to make no personal-data requests at all.
The layers
In plain English, and in full.
Local-first by design
Your logs live in a database on your phone, not in a cloud account. There is no server copy to breach unless you choose Pro sync — and our build pipeline automatically fails any code change that would quietly send personal data off-device.
store: on-device sqlite, app-sandboxed
enforcement: ci sweep bans off-device personal-data calls — every commit
free tier: zero personal rest calls
Backups only you can read
Cloud backups are sealed on your phone before upload. The key stays in your device’s Keychain, protected by a recovery code that is shown to you once and never stored anywhere — so not even we can open your backup.
cipher: aes-256-gcm, fresh iv per backup
key: 32-byte data key in ios keychain
recovery: key wrapped by recovery code; code never persisted — server sees ciphertext only
Sign-in done properly
Passwords are stored only as a slow one-way hash — we couldn’t read yours if we tried. Sessions use short-lived tokens kept in the Keychain, and Apple or Google sign-ins are cryptographically verified on the server, not taken on trust.
passwords: bcrypt cost 12, never plaintext
session: jwt access 15 min · refresh 30 d, rotated
oauth: rs256 signature + issuer + audience checked against apple/google jwks
Payments we never see
Subscriptions run through Apple’s App Store. Your card number never reaches Peak Fettle — we only receive a signed “this person is subscribed” signal, and the server refuses to let the app itself claim Pro status.
billing: apple storekit → revenuecat
webhook: shared-secret authorization; unauthenticated traffic rejected
tier: server-authoritative
No tracking baked in
There is no advertising SDK and no analytics harvesting. Even crash reporting ships switched off, and only ever activates if we explicitly configure it — with crash traces, not your training data.
ads / analytics sdks: none
crash reports: opt-in build flag, off by default
The honest fine print
- Pro sync data is readable by the service. If you subscribe and turn on sync, that copy of your training data is processed server-side — that is what makes multi-device sync work. It is encrypted in transit and at rest, but unlike backups it is not end-to-end encrypted. Free-tier users are unaffected: nothing syncs.
- Your account email exists on the server. Signing in requires it. Apple's Hide My Email is supported if you'd rather we never see your real address.
- Your device is part of the model. On-device data is protected by iOS sandboxing and your passcode or Face ID — a strong default, but device security is the one layer only you control.
statements audited against the shipping build · questions: admin@peakfettle.app