Legal
Privacy policy
Last updated 15 August 2026.
This page describes the data paths in the application and its Cloudflare Worker. It distinguishes data that stays local, ciphertext stored for sync, and readable data relayed for a bank connection. Those are different things.
The short version
Manual records and imported statements. With optional sync off, records you type and statement files you import stay on your device. Typing or importing a record does not itself make a network request. If you enable sync, Garden sends an encrypted copy of the whole vault, including those records, to its Worker.
Licence checks. Licence verification is genuinely offline. Garden verifies the Ed25519 signature on your key against a public key committed in the application. The verification path makes no network request.
Connected banks. A bank connection is not local-only. SimpleFIN and Plaid receive data under their own policies, and readable credentials and financial data cross the network as described below. Garden's Worker relays the SimpleFIN claim and every SimpleFIN refresh, and brokers Plaid API tokens and refresh data. It does not persist or deliberately log credentials or financial response bodies. It does keep the short-lived rate-limit counters described below.
Other requests. The desktop app checks for updates when its main shell opens; opening Settings → Maintenance mounts a second update-checking component and can repeat the request. Garden also makes a Plaid availability check when Accounts or the connection settings open. Encrypted sync and usage counts make requests only if you enable them. Purchase and key recovery happen through the website and purchase services, not through licence verification.
Manual data and generated documents
Without sync or a bank connection, Garden stores your financial vault on your device. Its statement parsers, categorisation, calculations, and document generation run there. Generated documents are not uploaded to Garden. The app may load a blank form bundled with the web or desktop build, but it does not send the values used to fill that form with the request.
If sync is on, the encrypted vault copy can include all of the following: transactions, balances, account names and numbers, imported statement contents, document-profile details such as a name and address, and connected-bank data. The Worker receives that copy only as ciphertext; it does not receive the vault passphrase or decryption key.
Optional sync
Sync is off until you enable it. When enabled:
AES-256-GCM before upload.
client-encrypted blob. The server stores the blob, a revision number, and an update timestamp in Cloudflare KV.
the passphrase or vault key, and the Worker has no code or key that can decrypt it.
It is not a Garden account, but anyone who obtains it can request the encrypted blob and attempt to guess the passphrase offline. Keep it private and use a strong passphrase.
- Garden builds an export of the whole vault and encrypts it on the device with
- The request to
/api/sync/:syncIdcarries a pairing code in the URL and a - The blob contains an encryption salt, IV, and ciphertext. It does not contain
- The pairing code is an unguessable bearer identifier generated on the device.
Turning sync off removes the local sync configuration. It does not delete the already-uploaded blob, and the current app and Worker expose no deletion endpoint. Email support@garden.khushin.com with the pairing code to request manual removal.
SimpleFIN
SimpleFIN is a third party. You buy and manage a SimpleFIN Bridge directly from SimpleFIN; Garden does not collect that payment. SimpleFIN receives the bank credentials you give it and can receive account identifiers, names, balances, and transaction history. It handles that information under SimpleFIN's privacy policy, not this one.
The connection has two stages:
The Worker decodes it, requires an HTTPS claim URL, and sends the claim to the bridge. It also requires the returned access URL to use HTTPS and contain HTTP Basic credentials before returning it to your device. Garden stores that access URL as the connection secret inside your encrypted vault.
cursor to Garden's Worker. The Worker uses the access URL to call the bridge, reads the returned account, balance, and transaction data, and sends it back to your device.
- You paste a one-time setup token into Garden. Garden sends it to its Worker.
- The first import and every later refresh send the access URL and refresh
The Worker therefore sees the setup token, claim URL, SimpleFIN access credential, and financial response data in readable form while relaying them. The relay code does not write them to KV, a database, or an application log. It returns the credential or financial response directly to the app. It does store an approximate rate-limit counter keyed by IP address in Cloudflare KV, with an expiry of no more than two minutes. If sync is enabled, the resulting local records are included in the encrypted sync blob.
Disconnecting SimpleFIN deletes the access URL from Garden's vault and leaves the imported accounts and transactions as manual records. It does not cancel or change the SimpleFIN Bridge you purchased.
Plaid
Plaid is a third party. Garden opens Plaid's hosted Link page, and you enter bank credentials there. Those credentials go to Plaid and the financial institution, not to Garden. Plaid can receive credentials, device and connection information, account identifiers and names, balances, and transaction history. Plaid handles that data under its End User Privacy Policy.
Before showing the connection as available, Garden pings its Worker to see whether Plaid is configured. That request carries no licence key or ledger data. Starting Link sends Plaid the Garden client name, the Transactions product, country and language settings, and a pseudonymous client id derived from the local vault generation. It does not send your name from the Garden profile.
Garden's Worker creates and polls the Link token, exchanges Plaid's public token for an access token, and relays account, balance, institution, and transaction data. The access token is stored inside your encrypted Garden vault. On later refreshes the app sends it to the Worker, which sends it to Plaid. The Worker does not persist or deliberately log Plaid tokens or financial response bodies.
The Worker does keep a short-lived Plaid rate-limit counter keyed by IP address. Its expiry is set to no more than two minutes. Disconnecting in Garden removes the token from the local vault, but the current app does not call Plaid's item removal endpoint. Use Plaid's own controls if you also want Plaid to disconnect the institution or delete data it holds.
Both SimpleFIN and Plaid require an encrypted vault before Garden will start the connection. Later bank refreshes also check for an unlocked encrypted vault before the Worker request is made.
Optional usage counts
Usage counts are off until you explicitly allow them. The complete application event allowlist is:
| Event | Payload |
|---|
| --- | --- |
|---|
onboardingbeatreached | One of seed, plant, grow, or bloom |
|---|
onboarding_completed | A boolean saying whether setup used demo data |
|---|
section_opened | One of Overview, Transactions, Plan, Documents, or Learn |
|---|
The client rejects any other event or property before sending, and the Worker validates the same allowlist again. The payload accepts no arbitrary string or number, so it cannot carry a merchant, account name, note, balance, or dollar amount.
An accepted event is written to Cloudflare Workers Logs with the event name, its listed property, and a server timestamp. The application payload has no Garden user id, device fingerprint, or session id. Like any request to the Worker, it still exposes ordinary connection metadata such as an IP address and user agent to Cloudflare. You can turn usage counts off again in Settings.
Buying Garden and recovering a key
Lemon Squeezy is the merchant of record. It collects the contact, payment, billing, and tax information needed for the purchase under its own privacy policy. Garden does not receive your card number.
Lemon Squeezy sends Garden's Worker a signed order webhook. The Worker reads the order id, purchase email, product and variant identifiers, payment status, and test-mode status needed to validate the order. It mints a licence key and stores:
purchase email, the licence key, issue date, and order id.
- the order id and licence key; and
- a separate recovery record containing a salted one-way hash of the normalized
Garden does not store the purchase email itself. The Worker sends the email address and licence key to Resend for delivery, so Resend receives both under its own privacy policy.
For recovery, the email address you type is sent to Garden's Worker in readable form. The Worker normalizes and hashes it for lookup rather than storing it. It stores rate-limit counters for the raw request IP and the salted email hash for up to one hour. If a recovery record matches, the Worker sends the typed address and stored licence key to Resend.
Offline licence checks and desktop updates
The licence key is a signed payload containing a random licence id, issue date, update-through date, and edition. Garden stores the pasted key in local browser storage and verifies its Ed25519 signature on the device against the public key built into the app. There is no fetch, activation server, device registration, or revocation check in that verification path. A compatible installed copy can verify the key and run without internet access.
Separately, Garden checks for updates when the desktop application launches. The main shell performs that check, and opening Settings → Maintenance can perform it again because the About section mounts the same update hook. Each request goes to Garden's public update feed on its Cloudflare Worker. It does not include the Garden licence key, ledger, balances, transactions, or vault encryption key. Cloudflare receives ordinary request metadata such as IP address and user agent.
The update check, Plaid availability check, connected-bank traffic, encrypted sync, and optional usage counts do not create a Garden user account. There is no application account login or online licence activation.
Infrastructure and third parties
Garden's web application, update feed, relays, sync storage, licence records, and telemetry logs run on Cloudflare. Cloudflare processes requests and ordinary connection metadata under its privacy policy.
The application has no advertising network, session recorder, or third-party analytics SDK. Garden does not sell your financial data. The third parties used for the paths above are Cloudflare, Plaid, SimpleFIN, Lemon Squeezy, and Resend; each service's own policy governs what that service receives.
Access, export, and deletion
removes its financial records from that device.
with the pairing code to request manual deletion; there is no self-service deletion endpoint.
recovery record. Removing it means the site can no longer recover the key by email.
credential. Requests concerning data held by the provider must go to that provider under its policy.
- Local records: Garden can export the vault as JSON. Erasing the vault
- Sync: turning sync off does not delete the server blob. Contact support
- Purchase recovery: contact support to request removal of the hashed-email
- Plaid and SimpleFIN: deleting a connection from Garden removes the local
Children
Garden is not directed at children under 13. If you believe a child has provided purchase or other information to Garden, contact us.
Changes
If this policy changes, the date at the top changes. Tests cover specific claims about licence verification, sync, provider relays, telemetry payloads, and generated-document disclaimers, but tests are not a substitute for reviewing the whole application and its deployed infrastructure.