Sloe Laboratory · SLOE Labs Inc. · Last updated: 3 August 2026
Written for a technical reviewer doing due diligence. Every claim is cited to a file in the codebase or to our internal audit at docs/security-audit.md, so you can verify rather than trust. For the plain-English version, see trust-summary.md.
1. Architecture#
Two deployable components:
- Studio (
sloelabs.com) — where a customer designs an operating system. Vite SPA plus serverless functions. - Tenant runtime (
<slug>.sloelabs.com) — where a provisioned system runs. A long-lived Node process serving both the API and the application.
Every provisioned operating system is the same application rendering a customer-specific JSON schema, not bespoke deployed code. This matters for security: there is one codebase to patch and one attack surface to reason about, rather than N forks drifting apart.
2. Tenant isolation#
Two independent layers.
Database layer. Every customer-data table enforces row ownership in PostgreSQL itself. As at the 2026-05-22 audit: 31 of 31 tables have row-level security enabled — zero tables run with RLS off — across 47 policies. Rows are scoped either directly (owner_id = auth.uid()) or by join to the owning operating system, whose owner_id is checked. There is no table where a cross-tenant read is expressible.
Application layer. The tenant server validates the session cookie, resolves the user, and verifies owner_id / os_id ownership per request before returning data. Row-level security sits beneath this as defence in depth rather than as the sole control.
Elevated credential use is inventoried. The tenant server holds a service-role database credential that bypasses RLS. Every use — 45 sites as at the audit — is enumerated with a justification in docs/security-audit.md Section 2 and annotated inline in source with a matching // CP5 audit: comment. The credential is server-side only and never reaches the browser.
3. Secrets and key handling#
No AI provider credential ever reaches the browser. All model calls proxy server-side through /api/llm-gateway. The convention is load-bearing and documented as an invariant in AGENTS.md: only VITE_-prefixed variables are inlined into the client bundle, and provider keys are prohibited from carrying that prefix. vite.config.ts carries an explicit comment forbidding reintroduction of a define: that previously leaked a key into the production bundle.
Supabase URL and anon key are browser-exposed by design; RLS is what enforces access, which is why section 2's coverage matters.
4. Connector credentials#
Who holds the grant matters more than how it is encrypted. For most integrations — Gmail, Slack, Notion and the rest of the Composio toolkit catalogue — the OAuth grant is held by Composio, established via connectedAccounts.link(userId, authConfigId) (apps/tenant/server/connectors/composio.ts). This platform stores a connection reference in os_mcp_connections, not the credential. A reviewer assessing credential risk should assess Composio, and we say so rather than implying a narrower blast radius than exists.
The native Google OAuth connector was removed (2c37180); Google is now resolved as a Composio toolkit. Any /api/oauth/google/* routes described in docs/security-audit.md (dated 2026-05-22) no longer exist — that audit predates the change.
Where this platform does hold a credential directly — currently the RESO data connector (apps/tenant/server/connectors/reso/connection.ts, the only encryptToken() call site) — it is encrypted at rest.
- AES-256-GCM, authenticated encryption — tampering or truncation fails decryption rather than yielding altered plaintext.
- Purpose-scoped key derivation. One master secret (
TOKEN_ENCRYPTION_KEY, minimum 32 characters) derives per-purpose 32-byte sub-keys assha256(master ‖ "|" ‖ purpose), so the token-encryption key and the OAuth state HMAC key are cryptographically distinct. - Fresh random 12-byte IV per encryption, never reused. Output is
base64(iv ‖ ciphertext ‖ authTag). - The process refuses to start with a missing or short master secret.
Source: apps/tenant/server/connectors/crypto.ts, apps/tenant/server/connectors/state.ts.
5. Least-privilege integrations#
Connector scopes are the minimum a feature requires, and the customer approves them at the provider's own consent screen. Because integrations are brokered through Composio (section 4), the exact scope set for a given toolkit is determined by that toolkit's auth configuration rather than by a scope list this platform maintains. Customers revoke access from settings at any time.
6. Agent action controls#
The distinguishing risk of an agentic system is action, not storage. Controls:
- Audit log. Every action against a connected service is written to
os_actions, attributable to the operating system and actor. - Independent verification. A verifier audits the agent's claims about actions taken against the actual tool responses, so "I sent that" is corroborated rather than trusted. Results are written to a service-role-only table.
- Email send gating. Outbound mail sends only from a domain the customer has verified, never from a model-chosen from-address, and is gated behind an explicit approve-to-send confirmation. Both the proposal and the confirmation are recorded in the audit trail.
- Scoped tool exposure. Tools are declared per connected app and bucketed read / create / update / destructive; destructive tools are the first to be truncated under a token budget rather than the last.
7. Authentication#
Supabase Auth. Passwords are stored as salted hashes and never in plaintext. Sessions are cookie-based and validated server-side on every request. OAuth state is HMAC-protected with a key distinct from the token-encryption key (section 4).
8. Data handling and AI providers#
Customer content is sent to third-party AI providers for inference. SLOE Labs does not train models on customer content, does not use it to build features or benchmarks for other customers, and does not use it for advertising.
We procure AI processing on commercial terms under which the provider may not train on submitted content and may not subject it to human review, except as strictly necessary for security or legal compliance. The per-provider position is published at https://sloelabs.com/subprocessors and kept current.
The complete sub-processor list is at https://sloelabs.com/subprocessors.
9. Memory#
The agent maintains long-term memory as pgvector embeddings (os_memory_embeddings, 768-dimension) plus a pattern cache. Retrieval is a weighted ranking — similarity × importance × recency decay — not naive cosine. Both tables are RLS-protected and scoped to the owning operating system. Memory is derived from customer content and is deleted with it.
10. Monitoring and resilience#
Application error and performance monitoring with alerting; health checks covering dependent services (/api/health?deep=true); backups on a rolling cycle with restoration capability.
11. Where we are today#
Here is the current state of our security program, so you don't have to pull it out of us on a call.
Certifications — Not SOC 2 Type II or ISO 27001 certified. No independent audit has been performed. You can have the internal audit cited throughout this document and a completed security questionnaire — SIG Lite, CAIQ, or your own — usually within a day.
Penetration testing — No independent test of the current architecture yet. If your review needs one, tell us early and we'll scope it with you.
Uptime — No contractual SLA on standard plans. We monitor continuously and will show you the real numbers. Formal SLA with service credits is available on annual contracts.
Data controls — Keys are managed by us and our infrastructure providers. Tenants share infrastructure with logical isolation, enforced by row-level security in the database and again in the application. Customer-managed keys, data residency, and single-tenant deployment are on the roadmap, not available today.
Bug bounty — No programme. We accept good-faith reports under AUP section 5.
12. Reporting a vulnerability#
security@sloelabs.com — see AUP section 5 for our safe-harbour commitment.