Threat model
The assets worth protecting, what could go wrong, and the control that holds — designed so the failure mode is safe rather than open.
| Asset / surface | Threat | Control |
|---|---|---|
| Tenant data | One org's request reads or writes another org's rows | Every query is scoped to the caller's org and enforced at the data layer with Postgres row-level security; an unscoped query returns nothing rather than everything (fails closed). |
| Learner PII | Personal data exposed at rest or in logs | Sensitive fields encrypted with AES-256-GCM; access is consent-gated and written to an append-only access log. |
| Assessment integrity | The tutor is talked into revealing an answer during a graded task | Output is buffered and passes a fail-closed leak audit before display; a demand for the answer is declined, not obeyed. The release gate is zero answer leaks. |
| Agent actions | An autonomous agent takes an irreversible or high-impact action | The model only selects a registered action id; money / tenancy / legal actions are on a permanent human-approval never-list that no prompt can bypass. |
| Prompt injection | Instructions hidden in user text hijack the model ("ignore your rules") | Injected text is treated as data, never authority. A dedicated red-team eval category asserts the gate holds against fake system overrides on every release. |
| Secrets | API keys or tokens leak through source or logs | All credentials are injected from the environment, never committed; the public evidence repo is scanned to confirm zero secrets ship. |
| Cost / abuse | Runaway spend from a loop or a hostile user | Per-user daily token budgets are enforced in one place (the model router), with bounded provider timeouts and retries so a stalled call fails fast. |
| Model regression | A prompt or model change quietly degrades safety or quality | A 61-scenario CI evaluation gates every merge that touches the tutor; below threshold, it does not ship. |
AI-specific safety gates
The controls that exist because a model is in the loop. Each is a design decision recorded as an ADR and shipped in the public evidence repository.
Fail-closed leak audit
In any gated context the draft is buffered and audited — a deterministic heuristic, then a fast-tier model check — before a single token is shown. If the auditor errors or is unavailable, the draft is treated as a leak and blocked. Safety does not depend on the auditor being healthy.
Permanent human-approval list
High-impact actions (price, lease terms, eviction, legal notices, refunds) are on a never-automate list the gate consults instead of the model's confidence. There is deliberately no "force" path.
Buffer-and-audit on risk
Low-risk turns stream normally; risky turns give up streaming, get audited, and are released only after they pass — so the zero-leak guarantee survives streaming.
Adversarial evaluation
Twelve red-team scenarios plus crisis and sycophancy categories run on every release, scored by mechanical assertions and a reasoning-tier judge. Prompt-injection resistance is a tested property, not a hope.
How the controls work
Three diagrams for the load-bearing paths — how every model call is routed, how an agent’s action is constrained, and how output is gated before it reaches a person.
Data & platform security
| Authentication | Clerk-managed identity, with a native Apple / Google token bridge on iOS. |
| Tenant isolation | Org-scoped access enforced with Postgres row-level security; unscoped access fails closed. |
| Encryption | AES-256-GCM for sensitive fields at rest; TLS in transit. |
| Consent & audit | Consent-gated access to personal data, recorded in an append-only access log. |
| Secrets | Provider keys injected from the environment; never in source, never in the repo. |
| Least privilege | The model reaches only a registered action surface — no raw database or query access. |
Release & deployment playbook
How a change reaches production, and how it comes back if it shouldn't have.
- Gate. A change that touches the tutor runs the 61-scenario evaluation in CI. The gate is absolute on leaks (zero) and has a pass-rate floor; below either, the merge is blocked.
- Freeze provenance. Every evaluation report freezes the exact model ids, judge version, scenario-set hash, commit, and cost — so a green run is reproducible and a number on this site maps back to it.
- Deploy atomically. Releases are atomic: a deploy either fully replaces the site or it doesn't, so there is no half-updated state. The build is verified against its published file digests before it is considered live.
- Roll back fast. Because deploys are immutable and versioned, rollback is re-pointing to the previous known-good deploy — not a hotfix under pressure.
- Observe. Usage, cost, latency, errors, and an audit trail are captured, with before/after snapshots on meaningful changes.
The portfolio you're reading is itself deployed this way — atomic publishes, digests verified against the live manifest after every deploy.
Responsible disclosure
If you find a security issue in any SoloStack system, please email hello@solo-stack.ai with the details and steps to reproduce. I'll acknowledge it and work the fix. Please don't publicly disclose until it's resolved.
The controls above are described honestly: where something is a design principle rather than a fully external-audited control, the evidence index says so, and the reference implementations ship in the public repository.