Security
How we handle your data.
Tapeline is a financial-data product. Trust matters more than features. We'd rather over-explain how the security works than make you guess. If anything below changes, the changelog records it.
Encryption
In transit
Every page and every API call runs over HTTPS with HSTS preload (2-year max-age, includeSubDomains). HTTP requests are redirected to HTTPS before they reach our application. The HSTS header is verifiable: curl -sI https://tapeline.io | grep -i strict-transport.
At rest
The production database (managed Postgres) is encrypted at rest via AES-256. Neon also encrypts its backups. Application secrets (API keys, webhook signing keys, JWT signing keys) are stored as Fly.io secrets — encrypted at rest, never in source, never in logs.
Passwords
bcrypt with cost factor 12. We never see your plaintext password — bcrypt-hashed at the moment of signup before the row hits the DB. Password reset uses signed single-use tokens with a 1-hour TTL.
Payment data
We don't store card numbers
All payment processing runs through Stripe — your card details go directly from your browser to Stripe's PCI-DSS Level 1 vault, not through our servers. We store only Stripe's tokenised customer ID and subscription metadata (tier, status, renewal date).
Stripe webhook integrity
Every Stripe webhook event is signature-verified server-side using Stripe's webhook secret. Replay attacks are prevented by an event-ID idempotency check (we log every processed event ID and skip duplicates).
Cancel any time
Cancel online any time, from your billing page or Stripe's customer portal. We never hold subscriptions hostage: no email back-and-forth, and no survey required. The cancel screen also offers a pause or a discount, but 'Just cancel my subscription' is on that same first screen.
Account access
Cookie-based sessions
JWT in an HttpOnly + Secure + SameSite=Lax cookie. JavaScript on the page can't read it (mitigates XSS). The cookie is scoped to tapeline.io so it works across the marketing site and the app.
OAuth providers
Google sign-in is supported as an alternative to email + password. We receive the standard OIDC profile claims (email, name, sub) and nothing else — no contact list, no calendar, no Drive.
Rate limiting
Auth endpoints (/api/auth/*) are capped at 10 attempts per IP per minute. The general /api/* limit is 120 req/min per IP. Both are enforced in-process before any DB work — brute-force attempts get 429ed cheaply.
Bot + abuse defence
Three layers on signup
(1) Honeypot field — invisible to humans, filled by bots, returns a fake-success that creates no account. (2) Disposable-email block list of ~62 throwaway providers. (3) Cloudflare Turnstile — a privacy-friendly bot check that does not track you across sites.
Cloudflare
Cloudflare runs our DNS and the Turnstile bot check on signup.
Vulnerability disclosure
Found something?
Email security@tapeline.io with a description and reproduction steps. We acknowledge within 24 hours and target a fix within 7 days for high-severity issues. We don't have a paid bounty programme yet (small team) but we credit researchers who want public credit.
What's in scope
tapeline.io, api.tapeline.io. Authenticated bypasses, IDOR, XSS, SSRF, RCE, sensitive-data exposure, broken auth — all in scope.
What's out of scope
Self-XSS, missing security headers on third-party domains we don't control, social engineering of staff, denial of service via volume. The /api/health endpoint intentionally has no rate limit (it's the Fly health probe target).
Data rights
What we collect
Email, password hash, name (optional), tier, watchlist contents, alert rules, scan history and Stripe customer ID. Your IP address is used in server memory for rate limits and bot checks, and some server log lines record it (see the privacy policy). If ad measurement is allowed for you, we also keep the IP address and browser of your latest signup, Google sign-in or checkout on your account, for the Meta ad events described below. A log of website visits (pages viewed, device, time zone, time on site — see the privacy policy). Plus server logs, which Fly.io keeps for 7 days. They hold the time, the web address requested (which can include a search you typed) and the status code, and some lines also hold an IP address, an email address or a browser user agent (see the privacy policy).
What we don't
No browsing history outside Tapeline: we don't see what you do on other websites. We have never sold personal data.
Analytics and advertising
Running on this site: Google Analytics 4, Google Ads conversion measurement and Meta (Facebook & Instagram) advertising measurement. Not enabled (the code is there, but it has no key): PostHog, Microsoft Clarity and Plausible. Google’s tags count visits, measure our ads and set cookies in your browser. In the EEA, the UK and Switzerland they wait until you press Accept on our cookie banner. With the Meta (Facebook) pixel on, when you sign up, start a trial or pay, and ad measurement is allowed for you, our servers also send Meta a scrambled (hashed) copy of your email plus the IP address and browser of your latest signup, Google sign-in or checkout. Scrambling is not the same as anonymous: Meta can match it to its own records. What each one receives is listed in the privacy policy.
Your data + deletion
Email privacy@tapeline.io with the subject “Copy of my data” or “Account deletion” and we reply within 7 days and complete the request within 30 days (UK/EU GDPR + California CCPA timelines). We send a copy of your data by email. Account deletion is a hard delete, not a soft delete: when an account is deleted, its data is removed from the live database, not marked as deleted. Deleted data can stay in the backups kept by our database host, Neon, until those backups are removed. The privacy policy lists the few records kept after deletion and how long logs and error reports are kept.
Operational
System status
Live at /status — refreshes every 30 seconds. Shows API health, worker tick recency, database reachability, and per-vendor configured-ness. Same data exposed as JSON at
api.tapeline.io/api/status for uptime monitors.Incident response
Backend errors are logged to Fly + (when enabled) Sentry. Client-side React errors ship to
/api/log-client-error so they land in the same log stream. Major incidents get an email to subscribers within 24 hours.Hosting + region
Backend and frontend both run on Fly.io in the Sydney region. The database is Neon managed Postgres, hosted on AWS ap-southeast-2 (Sydney).
Last verified 2026-10-04. Spot something out of date? security@tapeline.io.
Ready to look for yourself?
An account takes an email and a password.
Check our work:Data sourcesLimitationsSystem statusChangelog