Verified by the sovseal team

Bring Your Own Storage

Swap the default Postgres + object store for your own backends.

Overview

sovseal is designed around a decoupled storage architecture. You can swap out the default Supabase/Postgres engine for your own database and object storage backends.

+--------------------------------------------------------+
|                      API Edge                          |
+--------------------------+-----------------------------+
                           |
                           v
+--------------------------+-----------------------------+
|                Storage Driver Interface                |
+------------+-------------+--------------+--------------+
             |             |              |
             v             v              v
         [Postgres]      [S3]      [Cloudflare R2]

The Blind-Ciphertext Contract

Regardless of the storage provider you configure, you must adhere to the blind-ciphertext contract:

[!IMPORTANT] Strict Storage Driver Contract

  • The storage driver MUST NOT attempt to decrypt or examine the payload content.
  • The storage driver processes only encrypted bytes, random initialization vectors (IVs), cryptographic tags, and metadata (hashed IDs, sequences, and timestamps).
  • All encryption/decryption keys reside strictly on client devices.

The Storage Driver Interface

To build a custom storage driver, implement the following four primitive operations:

interface StorageDriver {
  /** Upload an encrypted snapshot payload. */
  put(
    agentId: string,
    sequenceNumber: number,
    payload: EncryptedEnvelope
  ): Promise<void>;

  /** Retrieve an encrypted snapshot by its sequence number. */
  get(
    agentId: string,
    sequenceNumber: number
  ): Promise<EncryptedEnvelope | null>;

  /** List snapshot metadata for an agent (paginated). */
  list(
    agentId: string,
    options: { limit: number; offset: number }
  ): Promise<EnvelopeMetadata[]>;

  /** Delete snapshot record(s) for an agent. */
  delete(
    agentId: string,
    sequenceNumber?: number
  ): Promise<void>;
}

Reference Adapters

1. Amazon S3 / Cloudflare R2 Adapter

You can store the encrypted payloads in any S3-compatible bucket. Since R2 and S3 share the same API schema, the configuration is identical:

vector_store:
  provider: qdrant
storage_provider: s3
storage_config:
  bucket: your-encrypted-snapshots
  region: us-east-1
  endpoint: https://<account-id>.r2.cloudflarestorage.com
  access_key_id: ${S3_ACCESS_KEY}
  secret_access_key: ${S3_SECRET_KEY}

2. External Postgres + pgvector Adapter

If you prefer running a single database stack, you can store both the vector records and the encrypted historical snapshots directly in Postgres:

-- Schema for storing encrypted snapshots
CREATE TABLE public.agent_state_snapshots (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    agent_id VARCHAR(64) NOT NULL,
    sequence_number INT NOT NULL,
    wallet_balances JSONB,
    active_context BYTEA NOT NULL, -- Encrypted ciphertext stored as byte array
    iv VARCHAR(32) NOT NULL,
    tag VARCHAR(32) NOT NULL,
    client_payload_hash VARCHAR(64) NOT NULL,
    timestamp TIMESTAMPTZ NOT NULL,
    created_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (agent_id, sequence_number)
);

CREATE INDEX idx_snapshots_agent_seq ON public.agent_state_snapshots (agent_id, sequence_number DESC);

Configure your environment connection:

vector_store:
  provider: pgvector
  config:
    connection_string: postgresql://postgres:password@localhost:5432/sovseal

On this page