How your data flows
1 — Capture. Your screen and audio are recorded locally by the macOS app and written to ~/Documents/Focuscap/ as an MP4. Nothing has left your Mac yet.
2 — Upload. The file is uploaded over HTTPS to Cloudflare R2 using a pre-signed URL that expires in 1 hour.
3 — Transcription (only if you turn it on). Transcription is off by default. When you turn it on — in Settings on the web, or in the Mac app — the audio track is sent to OpenAI’s transcription API. While it is off, no audio leaves your machine.
4 — Storage. The video lives in Cloudflare R2. Metadata and transcripts live in an AWS RDS PostgreSQL database in US-East-1 (Virginia). Credentials live in AWS Secrets Manager. Your session tokens live in the macOS Keychain.
5 — Access. Sharing produces a unique, unindexed link. Playback is served through short-lived signed URLs — 4 hours for you as the owner, 30 minutes for anonymous viewers. You can add a password or revoke the link at any time.
6 — Deletion. Deleting a recording takes it out of your gallery straight away, and 7 days later it is purged with every file it points at. Deleting your account starts a 24-hour grace period, after which everything is purged. See Deletion and retention for exactly what “everything” covers, and what it does not.
Encryption
| Layer | What we use |
|---|---|
| Database at rest | AES-256 via AWS RDS storage encryption, using the AWS-managed KMS key for RDS. Automated backups inherit the same encryption. The instance is not publicly reachable. |
| File storage at rest | AES-256-GCM. Cloudflare R2 encrypts every object and its metadata automatically, with Cloudflare-managed keys. It cannot be turned off. |
| In transit | TLS 1.3 is supported and negotiated by current browsers. TLS 1.2 is still accepted for compatibility; TLS 1.0 and 1.1 are not. |
| Database connections | Database connections require TLS: the database refuses an unencrypted one, and our clients verify its certificate rather than trusting whatever answers. |
| Server credentials | Database passwords, the OpenAI key and Stripe keys are stored in AWS Secrets Manager, not in environment variables or source. |
| Share passwords | Hashed with bcrypt. Plaintext is never stored, and a stored value that is not a bcrypt hash is treated as a failed match rather than compared directly. |
Session tokens. Auth tokens are stored in the macOS Keychain with kSecAttrAccessibleAfterFirstUnlock, and are not marked synchronizable, so they are never copied to iCloud Keychain. They are not excluded from local device backups: a token can exist inside an encrypted backup of your own Mac. Signing out removes it.
Network and edge
API requests are throttled at the gateway, with tighter limits on the sign-in, billing and admin routes than on the rest.
Every response carries:
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(self), geolocation=()
Content-Security-Policy: default-src 'self'; …explicit allowlists per directive
The marketing site is stricter still: script-src 'none'. The page you are reading runs no JavaScript at all.
Authentication
FocusCap uses AWS Cognito for identity.
- Sign-in: email and password, Google OAuth via PKCE, and email one-time codes.
- Passwords: a 12-character minimum, and deliberately no character-class requirements — a long passphrase beats a short one with a symbol bolted on. The same minimum is set on the identity pool and enforced in our own code from a single place, so sign-up, reset and the pool cannot drift apart.
- Two-factor: TOTP can be enabled from web Settings, using any authenticator app — Google Authenticator, 1Password, Authy. Once you turn it on it applies to every sign-in path, including passwordless email codes: an enrolled account is not signed in by a code alone, it is sent to the password flow where the second factor is asked for. Enrolment stays optional — no tier requires it.
- Session: access tokens are short-lived and refreshed automatically; signing out clears tokens on the device.
Authorization. Recordings are scoped to their owner, and every query filters by user. Workspaces use role-based access — owner, admin, member — with membership checked server-side. Admin endpoints authenticate separately and write to an audit trail.
Audit logging. We keep an append-only log of privileged administrative actions. To be precise about scope: this records what we do as operators. It is not a per-user activity log, and we do not claim one.
AI processing — and exactly who sees what
This is the section most worth reading closely, because it is the only point at which your content reaches a company other than us.
Where your audio goes
Transcription. Transcription is off unless you turn it on. When it is on, the audio track of a recording is uploaded to OpenAI in the United States, transcribed, and sent back. It is not used to train models — model training, evaluation sharing and API call logging are all disabled on our OpenAI account. OpenAI may still retain it briefly for abuse monitoring; we do not have a zero-retention agreement, and we say so rather than implying one.
English Voice Dub is built on the transcript, so it sends the same audio to the same place. Turning transcription off turns it off too.
The switch is on your account, not on one computer. You can see and change it in Settings on the web as well as in the Mac app, and the server refuses to send the audio when it is off — so an older copy of the app cannot override you. Every change is recorded with the date and the wording you were shown, and you can download that record with the rest of your data.
What our OpenAI account is configured to do
- Training and evaluation sharing is disabled at the organization level, for all three settings OpenAI exposes. Your audio is not used to train or improve models.
- API call logging is disabled on our organization.
- A Data Processing Addendum with OpenAI is applied for and awaiting countersignature — confirmed . This one is a status rather than a property of the system, so it carries the date we last checked it.
What we do not yet have, and will not pretend to: OpenAI’s Zero Data Retention agreement. Without it, OpenAI may retain API inputs for a limited period for abuse monitoring — currently documented as up to 30 days. ZDR is granted by OpenAI on approval rather than switched on by us. Until it is in place, the honest statement is: your audio is not used for training, and may be briefly retained by OpenAI for abuse monitoring.
What is processed on our own infrastructure
These features do not send your content to any third party:
- Speaker diarization runs
pyannote.audioinside our own AWS Lambda, on CPU. We hold a HuggingFace token, but it is used only to fetch model weights — no audio is sent to HuggingFace. - Filler-word removal, silence removal, trimming, stitching and GIF generation are media operations performed in our own compute.
Deletion and retention
Deletion. Deleting a recording moves it to your Trash, where you can restore it for 7 days. After that it is purged: the row and every stored file it points at — the video, the audio, any trimmed original and any dubbed track — are deleted. A link somebody opened just before you deleted it can keep playing for up to 30 more minutes, until the address their player holds expires; deleting stops new viewers, not a stream already running.
Deleting your account starts a 24-hour grace period; after it, your account, recordings, transcripts, files, subscription and support records are erased from our live systems in a single transaction.
The job that does it runs every day at 03:30 UTC. It also deletes your recording and thumbnail objects from R2, your Cognito user and your Stripe customer record. Failed runs retry, land in a dead-letter queue and raise an alarm; they do not fail silently. It carries a hard batch cap that aborts rather than proceed if the candidate set is unexpectedly large.
One thing we want to be straight about:
Backups. Our database keeps encrypted automated backups for 7 days, for disaster recovery. For up to those 7 days after erasure, deleted rows still exist inside those snapshots. Nobody reads them: they are used only to restore the database after a failure, and after any restore we re-run the erasure job before the system serves a single request, so anyone who asked to be forgotten stays forgotten. After 7 days the snapshots containing them are gone.
We would rather tell you this than claim an instant erasure no database can honestly promise.
Where your data lives
| Provider | What they hold | Region |
|---|---|---|
| Amazon Web Services | Accounts, metadata, transcripts, compute, secrets | US-East-1 (Virginia) |
| Cloudflare | Recording and thumbnail files (R2), web hosting, CDN, DDoS protection | Global edge |
| OpenAI | Audio and text, only when transcription or voice dub is used | United States |
| Stripe | Payment details and subscription state. PCI-DSS Level 1. | Global |
| Resend | Email addresses, for transactional mail only | United States |
| Sentry | Error diagnostics | United States |
| Small Chat | Support conversations, only if you accept the support-chat cookie | United States |
We do not sell your data, and we do not share it for advertising or third-party analytics.
Sentry specifically: error reporting runs with personally identifiable information disabled. Session Replay — which records screen interactions — is not loaded unless you explicitly grant it, and it masks all text and blocks all media when it is.
Cookies and consent
Consent is stored per purpose, not as a single yes/no: analytics, session replay and support chat are separate choices, each recorded with a timestamp and the version of the policy it was given against. When the policy changes materially, we ask again — consent to old terms is not consent to new ones. You can change or withdraw any of it at any time, as easily as you gave it.
Your rights
- Access and portability — Settings → Export My Data produces a JSON export of your data.
- Rectification — edit your profile in Settings.
- Erasure — Settings → Delete Account, as described above.
- Withdraw consent — turn transcription off in Settings, on the web or in the Mac app; change cookie choices at any time.
- Object or restrict — email privacy@focuscap.co.
Making a request. If you have an account, the fastest route is Settings → Your Data Rights: choose what you want — a copy, a correction, deletion, portability, or an objection — and we record the request with a timestamp and show you the date we will reply by. We answer within 30 days.
You can also email privacy@focuscap.co. The form is better only because it cannot be mistyped, and because you can see where your request stands.
We handle EEA users’ data on a GDPR basis, including documented retention periods and erasure on request. The full Privacy Policy & Terms of Service sets out the legal basis for each purpose.
Monitoring and incident response
Infrastructure alarms page an on-call address through SNS, and application errors are captured in Sentry.
If we suffer a breach affecting your data, our commitment is: contain and revoke first, determine scope second, and notify affected users within 72 hours of becoming aware — telling you what happened, what data was involved, and what to do. We will follow with a technical write-up rather than a statement.
Reporting a vulnerability. security@focuscap.co, or read /.well-known/security.txt, which names the same address in the format security tooling reads automatically. We will not pursue anyone acting in good faith.
What we have not done yet
A security page that lists only strengths is a marketing page. These are open:
- No SOC 2 report. We are not certified and no audit is underway. We build toward those controls; we have not been audited against them.
- No third-party penetration test has been performed.
- No Zero Data Retention agreement with OpenAI (see above).
- Two-factor authentication is optional. It protects every sign-in path once you turn it on, but no tier requires it.
If any of these is a blocker for your organization, tell us at security@focuscap.co — knowing what customers actually need decides what we build next.