Encryption
- In transit: every connection between your browser, mobile app, or extension and our backend is HTTPS only (TLS 1.2+). We have no plain-HTTP endpoints.
- At rest: bookmark data, notes, and screenshots are stored on our self-hosted Convex backend with disk-level encryption.
- Email: outbound mail uses standard TLS negotiation via Cloudflare Email Service. Inbound bounces terminate at Cloudflare; we don’t run a customer- facing inbound mail server.
Authentication
- Sign in with Google OAuth via Convex Auth. Sessions are signed JWTs in httpOnly cookies; CSRF-safe by construction.
- Sessions expire after extended inactivity and rotate on every password change / OAuth re-authorization.
- The browser extension authenticates via per-account API keys you generate yourself in Settings → Extensions. Revoke a key and the extension instance is locked out immediately.
Payment security
- All card data is handled by Stripe. We are PCI scope SAQ A: we never see, store, or transmit primary account numbers.
- Stripe webhooks are verified with HMAC-SHA256 against the signing secret on every request; replay attempts older than 5 minutes are rejected.
- Webhook events are deduped by event ID before they touch account state.
Infrastructure
- Backend: self-hosted Convex in a European datacenter. Your data stays in the EU; not shared multi-tenant infrastructure.
- Backups: Convex’s built-in continuous snapshots plus host-level volume backups. Retention 30 days.
- Secrets: stored as Convex environment variables and pushed via the admin CLI; never committed to version control.
- Code: open repo, signed commits, branch-protected main with required reviews.
What we log
- HTTP request metadata (method, path, status, latency) for performance and abuse detection.
- Authentication events (sign-in, sign-out, API-key generation / revocation) for audit.
- Errors and stack traces.
We do not log bookmark contents, note contents, screenshot bytes, or AI prompts. Logs roll off after 30 days.
Data isolation
Every Convex query and mutation gates access on either the owning userId or shared-board membership (see requireBoardAccess / requireBoardOwner in our backend). Cross-account data leakage requires a code bug, not a configuration bug.
Reporting a vulnerability
Found something? Email [email protected] with:
- A description of the issue
- Steps to reproduce
- Affected URL or endpoint
- Any artifacts you’d like to share (screenshots, PoC)
We’ll acknowledge within 3 business days and aim to triage within a week. Please do not publicly disclose until we’ve had a reasonable chance to fix: industry-standard 90 days.
We don’t run a paid bug bounty yet, but we maintain a hall of fame with credit for responsible disclosures.
Out of scope
- Self-XSS / clickjacking on legacy browsers without a clear attack vector
- Reports based on automated scanner output without a PoC
- Missing rate limits on non-state-changing endpoints
- Issues in third-party services (Stripe, Convex, Cloudflare): report those directly to the vendor
- Social-engineering attacks against our team
Incident response
If we detect a security incident affecting customer data, we’ll:
- Notify affected accounts within 72 hours of confirmation
- Publish a post-mortem after the fix has shipped
- Cooperate with relevant authorities where breach notification is legally required