1. Architecture
The web app runs on Vercel; the API is a Python service on Vercel Functions; authentication, PostgreSQL and private object storage are Supabase; release regions still require verification. Authenticated API calls use a server-verified session or an explicitly scoped API token; a browser-supplied user ID grants no access.
2. Tenant isolation
Every workspace table uses PostgreSQL row-level security keyed on membership. The API derives your workspace from that membership, never from the request body, and a foreign workspace is indistinguishable from a missing one (“Workspace unavailable”). Local isolation tests exercise cross-tenant reads and writes. Remote CI and release-environment isolation still require verification.
3. Connected-account tokens
- OAuth with PKCE and per-transaction state; the public callback never exchanges codes — the signed-in app completes the exchange.
- Tokens are encrypted at the application layer (Fernet) with a server-held key before they reach the database; the key id is stored with each ciphertext so a rotation is detectable and forces re-authorisation rather than failing silently.
- Tokens are decrypted only inside server-side provider operations and are never returned by any API, logged, or written to audit rows.
- Minimum scopes per capability; the connection card shows exactly which were granted.
- Disconnect wipes the ciphertext and revokes remotely where the platform supports it.
4. Nothing publishes without you
A review freezes text, media hashes, account, capability and time into a manifest with a digest. Only an approval of that exact digest creates a job. Jobs use manifest idempotency plus reconciliation-before-retry so an uncertain provider response never becomes a duplicate post. Every approval, publication and cancellation is recorded content-free in the audit log.
5. Sessions and step-up
You can see and revoke every session from Profile. Disconnecting a channel, changing members, revoking sessions and deleting the account require a sign-in from the last 10 minutes. Sign-in and invitation acceptance are rate-limited per address and per account.
6. Money and limits
Card details go to Stripe only. Billing webhooks are signature-verified, replay-safe and out-of-order safe. Usage is metered in an append-only ledger with a reserve-then-settle model and hard stop-lines per workspace and globally, which refuse new paid work when the approved budget cannot cover its reservation. Uncertain provider usage remains reserved until reconciled.
7. What we do not do
- We do not store passwords (Supabase Auth handles sign-in).
- We do not train models on your content.
- We do not publish, reply or moderate automatically.
- We do not put post bodies, prompts, tokens or files in logs.
- We do not present a capability as “Direct” before the provider has approved it.
8. Responsible disclosure
Found a vulnerability? Email privacy@postriff.app with the subject “Security”. The support mailbox, response commitment and disclosure policy are pending release review; no response-time guarantee is active yet. Avoid other customers’ data and service disruption when reporting a concern.
Related: Privacy Policy · Data deletion