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 308-redirected to HTTPS by Cloudflare and Fly.io's edge 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. Daily snapshots are encrypted. 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
Cancellation runs through Stripe's customer portal. We never hold subscriptions hostage — one click cancels, no email-back-and-forth, no retention pop-ups.
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 + Microsoft Entra are supported as alternatives 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 — privacy-preserving CAPTCHA, no third-party tracking.
Cloudflare edge
Bot Fight Mode is enabled at Cloudflare's edge (free tier). Most low-effort scraping attempts are blocked before they reach our origin.
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, app.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, Stripe customer ID, IP address (for rate-limit + audit logs only — not associated to user records). Plus standard server logs (timestamp, path, status code) for 30 days.
What we don't
No browsing history outside Tapeline. No third-party trackers. No advertising pixels. Plausible analytics (when enabled) is cookie-free and doesn't fingerprint.
Export + deletion
Email privacy@tapeline.io with the subject “Data export” or “Account deletion” and we respond within 30 days (UK/EU GDPR + California CCPA timelines). Account deletion is hard-delete, not soft-delete — your row is removed from the production DB and next-day backup rotation removes it from snapshots within 7 days.
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 runs on Fly.io (Sydney region). Database is managed Postgres in AWS Sydney. Frontend is on Vercel's global edge network. All infrastructure is multi-zone within the region.
Last verified 2026-05-04. Re-verified quarterly. Spot something out of date? security@tapeline.io.