Extensions can only do what you've declared.
Every architectural choice starts from one principle: an extension built for one of your customers cannot reach another customer's data, escape its sandbox, or call a tool you didn't declare. Here's how that's enforced — and what we haven't earned yet.
One extension, one namespace, one customer
Every approved extension runs in its own sandboxed namespace. Secrets, state, configs, triggers, and tokens are scoped to that namespace. No shared globals, no cross-extension reads, no cross-customer leakage. An extension built for one of your customers can't see anything belonging to another.
Extension code can't escape its namespace
Runtime extension code executes inside a sandbox. It can't reach the host file system, can't open arbitrary network sockets, can't import unbounded native modules. It can call its own scoped secrets, run its scheduled triggers, and make outbound HTTP — that's it.
Agents can only call what you've declared
The build-time agent uses the tools you expose via your MCP, OpenAPI, or GraphQL source — and nothing else. Capabilities are validated at build time before an extension can ship. The agent can't reference a tool that doesn't exist in your registry.
Runtime extensions don't invoke capabilities
Capabilities are design-time only — used by the build-time agent while writing extensions, never by runtime extension code. Once shipped, an extension talks to your APIs over plain HTTP using namespace-scoped secrets. The blast radius of a compromised runtime is bounded by what those secrets allow.
Each build session is scoped to one customer
When one of your customers starts a build session, you mint a short-lived token (atk_*) with an explicit permission set. The build-time agent uses that token and can only build or manage extensions for that one customer. Tokens expire; they can be revoked.
Forge never holds your customers' credentials
When the build-time agent calls one of your tools, Forge signs the dispatch with HMAC using your workspace signing secret (cws_*) and includes the subject in a signed header. Your handler verifies the signature; the per-customer authorization stays on your side. Forge holds no per-subject host credentials, ever.
Nothing runs until your customer approves
Every generated extension lands in pending_approval. Your product renders the review screen — what triggers it subscribes to, what tools it called at build time, what secrets it needs — and your customer approves, edits, or rejects. Activation is explicit, auditable, and reversible.
Multi-tenant Forge, no cross-workspace access
Workspaces are the multi-tenancy boundary inside Forge. Namespaces are workspace-prefixed; one host's data, customers, sources, and event types are not visible to another. Workspace API keys (cwa_*) and signing secrets (cws_*) scope every server-to-server call.
TLS everywhere, encrypted at rest
All traffic is over TLS. Workspace credentials, signing secrets, and namespace secrets are encrypted at rest. Audit records persist what was created, approved, edited, and dispatched.
What we prevent matters as much as what we permit.
- × Reach data belonging to a different extension or customer.
- × Call host APIs you didn't expose via a source or capability.
- × Be activated without an explicit approval from your customer.
- × Persist changes outside its own scoped namespace state.
- × Issue requests Forge can't sign or attribute to a subject.
Forge is in private pilot. We don't have a SOC 2 report, an ISO 27001 certificate, or a third-party penetration test. We won't claim any of those until they're real.
What we do have is an architecture designed around isolation from the start — every guarantee above is enforced by the runtime, not by policy.