Skip to main content

BUILT TO SURVIVE AN AUDIT.

Not a compliance checklist bolted on after the fact. The design constraint from day one was: prove it to an auditor. Every call traced, every secret isolated, every action enforced.

Air-Gapped Deployment

systemprompt.io ships as a single Rust binary that is its own token issuer and validator. It runs on your infrastructure against a local Postgres database. The binary includes the web server, API layer, job scheduler, AI orchestration, and admin dashboard in one process.

This is not a SaaS product with an "on-prem option." The runtime depends on Postgres and nothing else. The health endpoint validates connectivity by running SELECT 1 against the local database, with no callbacks to a vendor service. Outbound traffic only leaves the process when an operator explicitly configures an AI provider, and the route is whatever proxy you point it at.

Plug your existing IdP in and the binary handles the rest. JWTs are minted by JwtService using HS256 and validated locally by AuthValidationService, so every action is tied back to the authenticated subject without a round trip to an external auth server.

  • Single Binary, Own Token Issuer — JwtService generates HS256 tokens with SessionGenerator managing per-user sessions. No external auth service required. Plug your IdP in and go.
  • No Implicit Outbound Calls — Health, discovery, and auth code paths talk only to the local Postgres. AI provider connections are opt-in through profile config and route through whatever proxy you specify.
  • Cryptographic User Tracing — Tokens are embedded in data ingestion. Every action is cryptographically tied to the authenticated user across the entire system.

Secrets Never Touch Inference

With agents calling tools, secrets end up flowing through inference endpoints. API keys, database credentials, and tokens sitting in plain text in prompts. Every credential that enters a prompt is one prompt-injection away from exfiltration.

systemprompt.io abstracts secrets through MCP services. The agent calls the tool, McpToolHandler injects the credential server-side from the request context, and the model never sees it. PluginVariableDef marks each variable with a secret: bool flag so secret-flagged values are filtered out of anything the model can read.

Secret material is held in Secrets with provider isolation and a minimum 32-byte JWT secret enforced by Secrets::validate(). Source resolution is configurable via SecretsConfig (file or environment) and SecretsValidationMode (Strict, Warn, Skip). Master values stay in environment variables, never in the database.

  • Server-Side Credential Injection — McpToolHandler executes with RequestContext server-side. PluginVariableDef marks secrets with secret: bool. The LLM never sees API keys, database passwords, or tokens.
  • Provider-Isolated Secret Material — Secrets holds per-provider credentials in distinct fields with custom_env_vars() resolution. A leak in one provider context cannot exfiltrate another.
  • Validated at Load — Secrets::validate() enforces JWT_SECRET_MIN_LENGTH of 32 bytes. SecretsConfig selects file or env source, SecretsValidationMode picks Strict, Warn, or Skip behavior at boot.

Identity-Bound, Replayable Audit Trails

Every tool call in the audit trail is tied to the authenticated user, timestamped, and replayable. This is non-negotiable. When an auditor asks "who accessed what, and when," the answer is a database query, not a guess.

Tokens issued by the binary are embedded in the data ingestion layer. This means every action, every tool invocation, every secret access is cryptographically traceable to the authenticated user throughout the entire system.

Records are written to the logs table defined in crates/infra/logging/schema/log.sql. TraceQueryService exposes 25+ query methods for the admin dashboard and SIEM export. Retention is policy-driven through RetentionConfig, with tiered cleanup from one day at debug to ninety days at error.

  • Identity-Bound Tool Calls — LogEntry carries user_id, session_id, trace_id, and context_id on every record. JwtClaims embed sub, jti, and scope. No anonymous actions, no shared service accounts hiding who did what.
  • Replayable Events — TraceQueryService.get_all_trace_data() returns log events, AI requests, MCP executions, and execution steps in a single query. Full replay context for every action.
  • Queryable and Exportable — 25+ query methods on TraceQueryService: search_logs, list_tool_executions, count_logs_by_level, find_ai_request_for_audit. Export to CSV or JSON for your SIEM.

Policy-as-Code on PreToolUseHooks

Every tool invocation is a policy decision point, not an afterthought. HookEvent::PreToolUse fires before McpToolHandler::handle ever reaches inference. A denying hook short-circuits the call. Security teams ship rules without coordinating a product release.

Hooks are loaded from DiskHookConfig as YAML, with matcher patterns, category (System or Custom), and visible_to scoping. HookAction dispatches to a Command, a Prompt, or a sub-Agent with a configurable timeout. Block unauthorized data access, enforce data classification boundaries, require approval for sensitive operations.

Policies are code, not configuration toggles. Version them, review them, test them, deploy them through your existing CI/CD pipeline. When the CISO asks "how do we prevent agents from accessing production databases," the answer is a PreToolUse hook that runs before every tool call.

  • Pre-Execution Enforcement — HookEvent::PreToolUse fires before tool execution. HookAction supports Command, Prompt, and Agent types with configurable timeout. Abort before anything hits inference.
  • Independent Security Rules — DiskHookConfig loads from YAML with matcher patterns, category (System/Custom), and visible_to scoping. Security teams ship policy rules independently of product releases.
  • Hooks Wired Per Plugin — PluginConfig.hooks embeds a HookEventsConfig per plugin and runs validate() at load. Policy attaches to the plugins it is meant to govern, not as a global afterthought.

Data-Domain Scoping

Skills, plugins, and MCP servers are scoped by role and department. Finance sees finance tools. Engineering sees engineering tools. Down to which MCP servers are even visible to a given user.

This is not just RBAC at the API level. The entire tool surface changes based on who is authenticated. A finance-analyst sees a completely different set of capabilities than an engineering-lead. The tools that do not apply to your role do not exist in your session.

Access control is enforced in middleware on every request. A user cannot access another user's secrets, modify another user's skills, or view another user's analytics, regardless of how the request is constructed. Entity ownership is enforced at the database query level.

  • Role + Department Scoping — Permission.implies() enforces hierarchy: Admin(100), User(50), Service(40), A2a(30), Mcp(20), Anonymous(10). PluginComponentRef scopes skills with include/exclude lists per role.
  • Invisible by Default — enforce_rbac_from_registry checks OAuth scopes per MCP server before tool listing. Tools outside your scope do not exist in your session. Reduced attack surface by design.
  • Middleware Enforcement — validate_scopes_for_permissions runs in RBAC middleware before any application code. BaseRoles.anonymous() grants only users.read. No bypass, no exceptions.

Full Data-Plane Control

Every call enters through the API layer and is evaluated before reaching application code. RateLimitsConfig defines 11 per-endpoint base rates (oauth 10/s, contexts 100/s, MCP 200/s) with six TierMultipliers keyed off the authenticated user's role. AuthValidationService decodes the token, checks issuer and audience, and rejects anything that does not match before a handler runs.

The codebase is Rust. The compiler rejects buffer overflows, use-after-free, double-free, data races, and null pointer dereferences before the binary links. These are not classes you mitigate at runtime with sanitizers; they fail to build.

The build artifact is a single statically linked binary pinned by Cargo.lock. The same source produces the same binary. ScannerDetector is compiled in, blocking known scanner paths and 20+ malicious user-agents at the edge of the request lifecycle. What you audit is what you deploy.

  • Policy Engine on Every Call — RateLimitsConfig defines 11 per-endpoint base rates (oauth 10/s, contexts 100/s, MCP 200/s) with six TierMultipliers. Every call evaluated structurally, not retroactively.
  • Rust Memory Safety — The compiler prevents buffer overflows, use-after-free, data races, and null dereferences at compile time. Not with sanitizers. At compile time.
  • Cargo Audit and Reproducible Builds — ScannerDetector blocks known attack paths (.env, .git, .sql, wp-admin) and 20+ scanner user-agents. Cargo.lock pins every version. The same source always produces the same binary.

Compliance Framework Compatibility

systemprompt.io's architecture provides technical controls that map to requirements in major compliance frameworks. The library does not certify your organization, but it gives auditors concrete evidence of control implementation.

SOC 2: Air-gapped deployment supports CC6.1 (logical access controls). Secrets isolation maps to CC6.7 (data classification and protection). Identity-bound audit trails support CC7.2 (system monitoring). RBAC addresses CC6.3 (role-based access).

ISO 27001: Secrets management maps to A.10 (cryptography). Data-domain scoping addresses A.9 (access control policy). Audit trails support A.12.4 (logging and monitoring). Data retention aligns with A.18 (compliance with legal requirements).

HIPAA: Server-side credential injection supports the encryption addressable specification under the Security Rule. Data-domain scoping maps to the access control standard. Identity-bound audit trails support the audit controls standard.

OWASP Top 10 for Agentic Applications: The architecture is informed by OWASP's agentic AI risk taxonomy. RBAC with department scoping enforces least-privilege access. Secret scanning prevents credential leakage through inference. Identity-bound audit trails provide traceability for incident response. Some risks (hallucination detection, RAG poisoning) are outside the current scope and are documented transparently in our OWASP implementation guide.

  • SOC 2 Type II — Technical controls for logical access, data protection, system monitoring, and role-based access. Map directly to Trust Services Criteria.
  • ISO 27001 — Controls aligned with Annex A requirements for cryptography, access control, logging, monitoring, and legal compliance.
  • HIPAA — Secrets isolation, access control, audit trails, and data retention address Security Rule addressable specifications.
  • OWASP Top 10 for Agentic Applications — Governance pipeline addresses excessive agency, privilege escalation, credential leakage, and lack of traceability. These are the top risks identified by OWASP for agentic AI systems.

Founder-led. Self-service first.

No sales team. No demo theatre. The template is free to evaluate — if it solves your problem, we talk.

Who we are

One founder, one binary, full IP ownership. Every line of Rust, every governance rule, every MCP integration — written in-house. Two years of building AI governance infrastructure from first principles. No venture capital dictating roadmap. No advisory board approving features.

How to engage

Ready to build?

Get started with systemprompt.io in minutes.