Security & Data Protection
This document describes how DSFrog protects client data. We've kept it specific and honest on purpose — it reflects the actual implementation, not what we wish we had. See /privacy for the legal policy and /dpa for the Data Processing Agreement template.
1. Where your data lives
| Layer | Provider | Region | Purpose |
|---|---|---|---|
| Web server & application | DigitalOcean Droplet | fra1 (Frankfurt, EU) | Hosts dashboard |
| Database | SQLite via Prisma | Same server | Stores all client data |
| Daily backups | DigitalOcean Spaces (SSE) | sfo3 (US) | 30-day rolling encrypted backups |
| Email delivery | Resend | United States | Password reset codes, alerts |
| CDN / TLS / WAF | Cloudflare | Global edges | TLS termination, DDoS shield, Bot Fight, WAF |
| DNS | DigitalOcean DNS + Namecheap | Global | Domain routing |
| AI assistant (if enabled) | Anthropic API | United States | See section 9 |
Primary application data currently lives in DigitalOcean fra1 (Frankfurt); backups in DigitalOcean Spaces sfo3 (US). For US-based clients we can host the application in a US region (nyc / sfo / tor) on request — DigitalOcean operates in 14 datacenters worldwide. If your compliance requires data residency in a specific jurisdiction, tell us before go-live and we'll provision in that region.
2. Encryption
In transit (network)
- Browser ↔ dashboard: HTTPS only. TLS termination at Cloudflare with Full (Strict) mode — Cloudflare verifies the origin certificate (Let's Encrypt, auto-renewed).
- HSTS enabled with 6-month max-age. Minimum TLS 1.2. HTTP requests auto-redirect to HTTPS at the edge.
- Origin server is reachable only via Cloudflare IP ranges (origin lockdown at the firewall layer) — direct-to-IP attacks are blocked.
- All third-party API calls (DigitalOcean Spaces, Resend, Anthropic, etc.) are HTTPS.
At rest (disk)
- The application server runs on a DigitalOcean Droplet. DigitalOcean encrypts the underlying block storage at the infrastructure level.
- S3-compatible backups in DigitalOcean Spaces use server-side encryption (SSE) with provider-managed keys.
Application secrets
- User passwords: bcrypt with cost factor 12 (~250ms per hash) — defeats GPU brute-force for any reasonable password.
- Session tokens: JWT signed with HMAC-SHA256, secret stored in
.envon the server only (file mode600, root-only). - Two-factor (TOTP) shared secrets are generated at first enrollment and stored only on the server.
- API keys for third-party services (DigitalOcean Spaces, Resend, Telegram bot, Anthropic when enabled) live only in the server's environment file. Never sent to the browser, never embedded in JavaScript, never committed to source control.
- Per-client integration secrets are stored in isolated, restricted-access files on the server (file mode
600) — one file per client, never co-mingled. - JWT secret rotation is the "kill all sessions" mechanism (rotating it invalidates every existing session globally). We rotate on suspicion of compromise; otherwise on a planned cadence (at least annually).
3. Authentication & access control
For your team
- Each user has an individual account tied to their email. No shared passwords.
- First-time login uses a 6-digit verification code sent to the user's email — proves they control that inbox before any password is set.
- "Forgot password" uses the same email-verification flow.
- Passwords: minimum 10 characters, bcrypt-hashed (cost 12), never logged.
- Two-factor authentication (TOTP) is required for every account. On the next login after enrollment is rolled out, every user is guided through a setup flow that prompts them to scan a QR code with Google Authenticator (or Authy / 1Password / any TOTP-compatible app).
- Sessions are JWT-based, valid for 7 days from issue, signed with HMAC-SHA256.
- Session cookie flags:
httpOnly,Secure,SameSite=Strict— mitigates XSS theft and cross-site request forgery. - Logout immediately clears the session cookie on the user's device. For "kill all sessions everywhere" we rotate the JWT secret (admin operation).
For us (DSFrog)
- Server access is restricted to SSH keypair authentication only (Ed25519). Password-based SSH login is disabled in
sshd_config. - Administrator access is granted on a least-privilege basis with individual keys, and every administrative action is captured in the audit trail.
- Every administrative action against client data goes through the dashboard (which is logged) or via the admin CLI (which signs a JWT and uses the same audited HTTP endpoints).
Anti-abuse
- Login endpoint rate-limited per-IP (5 attempts / 15 min, then a 30-minute block).
- Password reset has three rate-limit layers: per-IP, per-email (3 send-codes / hour), and a global ceiling (30 codes / minute).
fail2banwatches authentication logs at two levels: SSH (3 failed logins per hour → ban) and HTTP login (8 failed POSTs to/api/auth*per 10 min → ban). Bans are enforced via the firewall.- Critical: nginx is configured to log the real client IP from Cloudflare's
CF-Connecting-IPheader — fail2ban bans the actual attacker, not Cloudflare edge servers. - Email enumeration is prevented: the "forgot password" endpoint returns the same response regardless of whether the email exists, with randomized timing.
4. Multi-tenancy isolation
Each client's data is logically separated:
- Every dashboard data row carries a client identifier and is partitioned by it at the database layer.
- Each user account is bound at issue-time to a single dashboard scope, encoded in the session token.
- The HTTP middleware enforces that a non-admin session can only reach its own dashboard — any cross-account access attempt returns a redirect to login. This is verified end-to-end by automated test scenarios on every change.
- Server-rendered dashboards load data scoped to the session's assigned client; cross-client queries are not generated by the application.
- Every login attempt is recorded in an audit log (login, IP, user-agent, success/failure, reason). Reviewable by admins.
5. Network & infrastructure protection
- Firewall (ufw): SSH (22) open globally (key-only); HTTP/HTTPS (80/443) open only from Cloudflare IP ranges (origin lockdown). Direct-to-IP probes are dropped — verified by external test (8s connection timeout).
- Cloudflare in front of the application: TLS termination (Full Strict), DDoS protection, Bot Fight Mode, WAF managed ruleset, automatic HTTPS rewrites, HSTS 6-month max-age.
- Operating system receives automated security updates via
unattended-upgrades. - Application dependencies are scanned with
npm audit; high-severity vulnerabilities trigger an immediate patch cycle. Lower-severity ones are reviewed for actual exploitability before triage. - The Node.js process currently runs as root for operational simplicity (PM2 single-server setup). When we move to managed orchestration, this will move to an unprivileged service user.
6. Backups & disaster recovery
- Daily automated backups at 03:00 UTC. The script takes a consistent SQLite snapshot (via
.backup, not a copy of the live file) plus thedata/directory (per-client secrets, configuration) plus the.envfile. Packaged as a tar.gz, uploaded to DigitalOcean Spaces with server-side encryption, then verified viahead-object. - Retention: 30 rolling days, enforced by an S3 bucket lifecycle policy.
- Backup failures trigger an automatic email alert via Resend within minutes.
- Restore procedure is documented but is not yet automatically tested on a schedule. Manual restore drills are performed when significant changes are made to backup tooling.
- Recovery target: with 24-hour worst-case data loss (one full daily cycle), we can restore service within several hours given a healthy server. We are not yet running formal RTO/RPO measurement.
- If you cancel your account, we retain backups for the standard 30-day window, after which they are automatically purged by the lifecycle policy.
7. Monitoring, audit logs & incident response
Audit log
- Every authentication event (success, failure, 2FA challenge, 2FA enrollment, rate-limit, etc.) is recorded with timestamp, login attempted, real client IP, user-agent, and reason.
- Stored in the application database. Reviewable by admins through the dashboard.
- Backed up daily (covered by the standard backup process). Retained indefinitely for security analysis; deleted on account closure on request.
Health monitoring
- An automated health check runs every 5 minutes: confirms the public site responds (HTTP 200 via Cloudflare), the database is reachable (sqlite query succeeds), and the most recent backup in DO Spaces is fresh (under 26 hours old).
- Any failure triggers a Telegram alert to the on-call admin within minutes. Alerts are de-duplicated (one alert per problem, not one per check) and a recovery message is sent when the issue clears.
Incident response
If we discover a security incident affecting your data:
- We isolate the affected component as soon as possible after detection (rotate JWT secret to invalidate all sessions, block compromised IPs, take service offline if needed).
- We notify you in writing within 24 hours of confirmation, including: what happened, what data was potentially affected, and what we're doing.
- We provide a written post-incident report within 7 days.
- If the incident triggers GDPR Art. 33 notification thresholds, we coordinate with the relevant supervisory authority.
8. Your rights — portability and deletion
- Export: full export of your dashboard data as JSON or CSV on request, typically within 7 days.
- Delete: request account deletion in writing; live database records are deleted within 7 days, and backup copies are purged within the standard 30-day backup retention window.
- Audit log access: we can provide a record of authentication and admin actions affecting your account on request.
- We never sell, share, or use your data for any purpose other than running your dashboard (and, when you explicitly opt in, the optional AI assistant — see section 9).
9. AI assistant (optional)
If you enable a natural-language assistant feature in your dashboard, the following applies.
Architecture
- The user's question goes to our server.
- Our server fetches only your data, scoped to your account, into a request payload.
- That payload is sent to the Anthropic Claude API over HTTPS.
- The model's response is returned to your dashboard.
- Anthropic never has direct access to our database; it only sees what we explicitly include in each API request.
- The Anthropic API key lives only on our server.
Anthropic's commitments
- API data is not used to train Anthropic models — guaranteed under their Commercial Terms.
- Requests are retained by Anthropic for up to 30 days for safety/abuse review and then deleted. Zero Data Retention is available on enterprise contracts if your compliance requires it.
- Anthropic is SOC 2 Type II certified. Their DPA is available on request.
Boundaries
- The AI cannot run code or queries against the database.
- The AI cannot read files, send emails, or call external services.
- The AI cannot see other clients' data — every request is scoped at the application layer before it leaves our server.
- You can disable the AI assistant at any time. The dashboard continues to function without it.
10. Compliance & legal
- GDPR: We act as a data Processor for client data and as a Controller for our website-visitor and direct-account data. We sign a DPA before go-live with EU-based clients.
- CCPA / state privacy acts: We support the consumer-rights regime — access, deletion, opt-out of sale (we don't sell data anyway). We treat all customers the same regardless of jurisdiction.
- HIPAA: We do not currently support PHI (Protected Health Information). If your dashboard would contain PHI, we'd need a Business Associate Agreement (BAA) and additional infrastructure controls — talk to us first.
- Sub-processor list: see Privacy Policy section 6. We notify clients in writing 30 days before adding a new sub-processor.
- Data Processing Agreement: standard template at /dpa; signed before go-live.
11. What we are honest about
We're a small focused team running a well-maintained single server, not a Fortune 500 cloud platform. We promise:
- Industry-standard practices, applied consistently and visibly (this page describes the actual implementation).
- Transparency — including disclosure of every sub-processor and prompt notification of any incident.
- Honesty about limits — we tell you "no" if your compliance requires more than we can deliver, instead of pretending we can.
We do not promise:
- Bank-grade infrastructure or "unhackable" systems.
- 99.99% SLA — single-server architecture realistically delivers ~99.5% uptime.
- SOC 2 / ISO 27001 / HIPAA certification — not currently certified.
- Independent third-party penetration testing — not yet on a regular schedule.
- Zero-data-loss guarantees — daily backups mean up to 24 hours of data could be lost in the worst case.
Questions, custom requirements, or your legal team needs specific clauses? Email hello@ds-frog.com — we respond within 1 business day.