Security and storage

This page describes the current implementation boundaries. The code remains the source of truth.

Authentication boundaries

User-scoped API routes require either:
  • a browser session cookie created by Better Auth
  • a bearer token issued to the CLI device-login flow
Trace reads and mutations are owner scoped. A user can only inspect or mutate their own traces and download their own derived blobs.

Blob storage modes

SellTraces supports three blob-key schemes:
SchemeModeUsed for
s3://Cloudflare R2 through Files SDKproduction-style raw and derived blob storage
db://Postgres fallbackhosted fallback when configured
local://local filesystemfully offline development
R2 mode uses separate raw and derived buckets. Bucket names default to selltraces-raw and selltraces-derived unless overridden by environment variables.

Raw and derived blobs

Ingest writes:
  • raw upload blobs so the background worker can parse queued jobs
  • per-trace raw blobs after insert
  • per-trace derived blobs after server scrub
The trace download API streams the derived scrubbed blob as a private JSON attachment:
GET /api/traces/{id}/download
The response uses cache-control: private, no-store.

What is not implemented

Current code does not implement customer-provided R2 encryption keys or per-trace app-managed encryption keys. Cloudflare R2 provides provider-side encryption at rest, and app access is controlled through private bucket credentials plus user-scoped application auth. Do not describe the current storage model as end-to-end encrypted.

Privacy layers

Local preflight redacts detected PII and secrets before accepted traces leave the machine. Server scrub is a backstop and may still reject traces during ingest.

Testing notes

To verify storage and access behavior:
  • Upload a CLI JSON payload.
  • Run the ingest worker and confirm the uploaded traces appear for the owner.
  • Confirm the trace row has a derived_blob_key.
  • Download the trace through /api/traces/{id}/download while signed in as the owner.
  • Repeat the download with no auth or another user and confirm it does not return the blob.