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