The Accountless Design
Verity has no user accounts. No email. No password. No personal information collected. This is not a missing feature—it's a core architectural decision.
When we analyzed what user accounts would provide versus what they would cost, the costs far outweighed the benefits:
| What Accounts Would Provide | Business Value |
|---|---|
| Session history across devices | Low — users typically use one phone |
| User-level rate limiting | Medium — achievable via device ID |
| Abuse prevention (ban users) | Medium — achievable via device ID |
| What Accounts Would Cost | Impact |
|---|---|
| User database | ~$10-20/month + complexity |
| PII storage liability | Legal exposure |
| Subpoena response surface | Email addresses, metadata |
| GDPR/CCPA compliance burden | Legal + development time |
What We Don't Store
- Video content — Your recordings never touch our persistent storage
- Storage credentials — Your AWS keys, Backblaze keys, etc. are never stored
- Email addresses — We don't collect them
- Names — We don't collect them
- Location data — If you enable location tagging, it goes only to your storage
- Device identifiers — Used only for rate limiting, auto-deleted after 24 hours
- IP addresses — Hashed and auto-deleted after 24 hours
What We Do Store
The only persistent data we store is attestation records:
- Session ID — Random UUID, not tied to any user
- Sequence number — Which chunk in the session
- Content hash — SHA-256 of chunk content (not the content itself)
- Previous hash — Link to previous chunk for chain integrity
- Timestamps — When we received the chunk
- Relay signature — Our cryptographic signature
Key Point
Attestation records contain only cryptographic hashes, not video content. A hash is a one-way mathematical fingerprint—it is impossible to reconstruct video content from a hash.
Data Flow Architecture
When you record with Verity, here's how data flows:
- Video is captured and encoded on your device
- Each chunk is hashed (SHA-256) before transmission
- Chunk + encrypted credentials sent to our relay
- Relay decrypts credentials in volatile memory only
- Relay uploads chunk to your storage destinations
- Memory is cleared immediately after upload
- Attestation record (hash only) stored in database
Video and credentials exist on our systems only in volatile memory (RAM) for the brief moments needed to process the upload. They are never written to disk, database, or logs.
What We Log
We use Cloudflare's built-in observability to monitor errors, debug failures, and keep the relay healthy. Transparency means being explicit about what our logs contain—and what they don't.
Logged (operational data only)
- Session IDs — Random UUIDs, not tied to any person
- Chunk sequence numbers — Which chunk in a session (e.g., chunk 3 of 42)
- Destination type — The kind of storage (e.g., "s3", "b2") but never the bucket name or path
- Error codes — Categorized failure reasons (e.g., "auth_denied", "network_error"), not raw error messages
- HTTP status codes — Standard status codes (403, 500, etc.)
- Timing and latency — How long uploads take in milliseconds
- Content hashes — SHA-256 hashes for integrity verification (not video content)
- Aggregate counts — Destinations succeeded vs. total, chunks per session
Never logged
- Device IDs — If we need to correlate logs, we use a truncated, non-reversible hash that cannot be traced back to a device
- Video content — Not in logs, not on disk, not anywhere
- Storage credentials — AWS keys, OAuth tokens, and other secrets never appear in logs
- Session tokens (JWTs) — Authentication tokens are excluded from all logging
- Bucket names or storage paths — Your storage infrastructure details are stripped from error messages before logging
- IP addresses — Only a salted hash is used for rate limiting; raw IPs are never logged
- Push notification tokens — Device notification identifiers are never logged
- Request or response bodies — Cloudflare's automatic request body logging is disabled
Error Message Sanitization
Cloud providers (AWS, Backblaze, Google Cloud) often include bucket names, file paths, or credential details in their error messages. Before any error message reaches our logs, it passes through a sanitization layer that strips URLs, ARNs, storage paths, and endpoint names. We log the error category, not the error content.
Log retention
Operational logs are retained for the minimum period needed to debug production issues. Crash reports are retained for 90 days. We do not use third-party analytics services—our telemetry is first-party only, processed on Cloudflare's infrastructure.
Rate Limiting Without Identity
Instead of user accounts, we use device IDs for rate limiting:
- App-generated UUID — This is NOT a hardware identifier (like IMEI or IDFA). It's a random UUID generated by the Verity app on first launch.
- Resets on reinstall — If you uninstall and reinstall the app, a new UUID is generated. There's no persistent tracking across app installations.
- Stored securely in your device's keychain (iOS) or EncryptedSharedPreferences (Android)
- Used only to count sessions and chunks for rate limiting
- Rate limit counters auto-expire after 24 hours
- Cannot be linked to a person without physical device access
App Store Compliance
Our device ID approach complies with both Apple App Store and Google Play Store privacy guidelines. We never use hardware identifiers, advertising IDs, or device fingerprinting techniques. The UUID is purely app-scoped and ephemeral.
Subpoena Resistance
If we receive a legal request for user data, we can only provide:
- Attestation records (hashes and timestamps) for a specific session ID, if known
- Aggregate statistics
We cannot provide:
- User identities (we don't know them)
- Video content (we don't have it)
- Storage credentials (we don't have them)
- Historical IP addresses (hashed and auto-deleted)
- Email addresses (never collected)
This is not defiance—it's architecture. We designed a system where the data simply doesn't exist.