Security, Safety & Operations

How these systems are secured, gated, and run.

A production AI system fails in two directions: the ordinary application ways (a tenant sees another tenant's data, a secret leaks) and the model-specific ways (a prompt injection, an answer leak, an unsafe autonomous action). This page states the threats plainly and names the control for each — the same controls the case studies and the evidence index point to in code. Everything here describes my own systems, Lumenor and DoorOps.

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 / surfaceThreatControl
Tenant dataOne org's request reads or writes another org's rowsEvery 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 PIIPersonal data exposed at rest or in logsSensitive fields encrypted with AES-256-GCM; access is consent-gated and written to an append-only access log.
Assessment integrityThe tutor is talked into revealing an answer during a graded taskOutput 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 actionsAn autonomous agent takes an irreversible or high-impact actionThe 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 injectionInstructions 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.
SecretsAPI keys or tokens leak through source or logsAll credentials are injected from the environment, never committed; the public evidence repo is scanned to confirm zero secrets ship.
Cost / abuseRunaway spend from a loop or a hostile userPer-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 regressionA prompt or model change quietly degrades safety or qualityA 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.

Capability-tier ModelRouter — providers swappable behind one interface Every LLM call ModelRouter one interface · names a tier, never a model reasoning compiles · judging tutor Socratic turns fast classify · safety Provider implementation Anthropic Claude ⇄ OpenAI GPT-5.6 — swapped at one seam (anthropic.ts / openai.ts)
Capability-tier routing. Features name a tier, never a model, so switching providers is one change at the root — the exact swap that produces the cross-provider evaluation. Per-user budgets are enforced here, in one place.
Constrained action gate — model selects; deterministic code executes; high-impact is human-approved Model picks action id + params Validate params (zod) Resolve to registry Deterministic guards Policy decides Rejected fail closed — nothing runs Execute (deterministic) Audit log Human approval invalid fails auto high-impact
Constrained action gate. The model only selects a registered action id and parameters; deterministic code validates (zod), resolves, guards, and executes, writing one audit record. High-impact actions require a human. Any failed check rejects — it fails closed, nothing runs.
Fail-closed leak audit — buffered draft, two-stage audit, blocks on any doubt Draft response (buffered) Heuristic check Fast-tier model audit Leak? Show to learner Blocked auditor errors → treat as leak Regenerate once Safe fallback message clean no explicit auditor down leak still leaks
Fail-closed leak audit. In a gated context the draft is buffered and audited — a heuristic, then a fast-tier model check. If the auditor errors or is unavailable, the draft is treated as a leak. A leak is regenerated once with a do-not-answer directive, then falls back to a safe message rather than show an unaudited draft.

Data & platform security

AuthenticationClerk-managed identity, with a native Apple / Google token bridge on iOS.
Tenant isolationOrg-scoped access enforced with Postgres row-level security; unscoped access fails closed.
EncryptionAES-256-GCM for sensitive fields at rest; TLS in transit.
Consent & auditConsent-gated access to personal data, recorded in an append-only access log.
SecretsProvider keys injected from the environment; never in source, never in the repo.
Least privilegeThe 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.

  1. 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.
  2. 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.
  3. 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.
  4. Roll back fast. Because deploys are immutable and versioned, rollback is re-pointing to the previous known-good deploy — not a hotfix under pressure.
  5. 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.