CubeLedger

Security

Built to hold customer books.

CubeLedger will hold bank tokens and wallet addresses. The v1 controls below are in the product. A SOC 2 audit is not. The readiness path is in docs/soc2-readiness.md in the repository.

Tenant isolation

Financial tables use Postgres row-level security. The web app connects as a role that does not own the tables and does not bypass RLS. A test signs in as that role and proves one tenant cannot read another.

Authentication

Email and password, TOTP authenticator codes, and passkeys. Session cookies are httpOnly. Login attempts are rate limited.

Connector secrets

Access tokens are envelope-encrypted: a random data key encrypts the secret, and the key-encryption key wraps the data key. Errors strip URLs so a SimpleFIN access URL is not logged.

Read-only by construction

The connector interface has no write or trade method. Plaid is limited to the transactions product. QuickBooks is specified as the read-only accounting scope. Nothing in v1 requests a transfer or payment scope.

Audit log

Sign-in, imports, syncs, entity changes, and billing events are appended. The application role cannot update or delete audit rows.

Jobs

Syncs run through a Postgres-backed queue with retries, backoff, idempotency keys, and per-source rate limits. Imports dedupe on an external id.

Reports

A finalized report is hashed with SHA-256. Anchoring writes only that hash into an XRPL memo. It does not publish balances.

Before production data

  1. Run the app role, not the table owner, in every deployed environment.
  2. Put the key-encryption key in a managed secret store and rotate it with a re-encryption job.
  3. Turn on managed Postgres backups, point-in-time recovery, and private networking.
  4. Complete a SOC 2 Type I readiness review, then a Type II observation window, plus a penetration test before production Plaid.
  5. Keep trading, payment, and write scopes out of every connector review.