Security
Files, Privacy, and the Sanity Media Boundary
The upload, encryption, proxy, authorization, quarantine, retention, and incident rules for EPS evidence.
First created Last updated
Non-negotiable storage rule
All EPS upload bytes go to the Sanity media bucket through the authenticated API. Supabase remains the operational Postgres database and stores metadata and opaque canonical Sanity asset IDs only. Supabase Storage is never used.
No Sanity API or CDN URL may reach browser HTML, JSON, redirects, exports, notifications, webhooks, logs, or client-visible errors. Public media uses an API proxy URL. Protected artifacts use an opaque authenticated content endpoint that authorizes every download.
Why proxying is not encryption
A proxy can enforce authorization, rate limits, audit, and stable application URLs, but a proxy does not make upstream plaintext private if the upstream asset itself is public. For confidential and restricted artifacts, the API generates an artifact key, encrypts bytes with AES-256-GCM before upload, wraps the key with the configured encryption key, and stores ciphertext in Sanity. The Worker authorizes, retrieves, decrypts, and streams content without redirecting to Sanity.
Upload lifecycle
- The authenticated user selects classification and file.
- The API validates size/type, hashes the plaintext, and encrypts protected classifications.
- Bytes upload to Sanity; Postgres records only opaque asset identity, checksum, size, classification, encryption scheme, scan state, retention, and owner.
- A file remains blocked while
pendingorquarantined. - An authorized review marks it
cleanorquarantinedwith audit evidence. - Downloads re-check project access and never disclose the upstream locator.
The current Preview includes the quarantine state and manual authorized review endpoint. Production General Availability requires a deployed malware-scanning integration, file-type allowlist and size certification, retention jobs, legal-hold testing, access-history reporting, key rotation/recovery drills, and leak regression tests.
Classification
public: may use an application media proxy, never a Sanity URL.internal: authenticated organizer access; do not assume upstream secrecy solely from proxying.confidential: ciphertext-only upstream storage and authorized decryption.restricted: confidential controls plus the narrowest project capability and explicit handling policy.
Incident response
Stop access, quarantine the artifact, preserve audit records, revoke exposed links or credentials, rotate affected keys, assess external caches/messages, notify the privacy/security owner, and document recovery. Never paste the Sanity locator into the incident ticket.
Completion check
Inspecting browser HTML, JSON, redirects, exported files, and notification payloads reveals only API proxy URLs or opaque artifact IDs—never a Sanity project, dataset, API, or CDN URL.