`, so the same policy
language reads `role_in: [reader, viewer]` or `replicas_lte: 10` as easily as `amount_lte`, and
[nine domains](#the-same-shape-in-nine-domains) below have one policy each.
-[Protect your first action](https://ctrlrun.dev/docs/get-started/quickstart) walks the same path
+[Protect your first action](https://docs.ctrlrun.dev/get-started/quickstart) walks the same path
with every output explained ·
-[Policy YAML reference](https://ctrlrun.dev/docs/reference/policy-yaml) ·
-[Cookbook](https://ctrlrun.dev/docs/cookbook/index): refunds, deploys, IAM, deletions, email, MCP.
+[Policy YAML reference](https://docs.ctrlrun.dev/reference/policy-yaml) ·
+[Cookbook](https://docs.ctrlrun.dev/cookbook/index): refunds, deploys, IAM, deletions, email, MCP.
## Three ways to use it
@@ -294,7 +294,7 @@ that reaches its tools over MCP, in any language.
Cursor, Codex, OpenAI Agents: any AI agent you have. CTRLRun checks the action, not the
agent, so if the agent acts through a tool server or an API you run, the action is checked, and
the agent is not rebuilt, redeployed or told.
-[Agents you can't modify](https://ctrlrun.dev/docs/agents-you-cant-modify) says where the
+[Agents you can't modify](https://docs.ctrlrun.dev/agents-you-cant-modify) says where the
boundary goes for each kind.
An adapter exists for one reason: to route an `approve` decision through the framework's own
@@ -351,7 +351,7 @@ same write, so a thousand refunds that each pass `amount_lte` cannot add up to m
grant allows. An `AMBIGUOUS` effect holds its budget until it is resolved, because otherwise an
agent that can manufacture ambiguity could manufacture authority. A budget bounds what the next
reservation may do; it cannot recall an action already in flight.
-[Authority](https://ctrlrun.dev/docs/authority) has the whole model.
+[Authority](https://docs.ctrlrun.dev/authority) has the whole model.
State lives in SQLite by default, a file with no server and no ops, and the reservation holds
across processes rather than merely across threads. Point it at Postgres when more than one
@@ -372,9 +372,6 @@ grades the transport classifier.
| **Receipts** — Every executed action leaves a portable JSON receipt of who, what and outcome. | yes | yes | yes |
-[Follow one action through every check](https://ctrlrun.dev/execution-boundary), interactively,
-with nothing installed.
-
## The same shape in nine domains
Nothing in CTRLRun knows what a refund is. An action is a **name**, **canonical arguments**, an
@@ -410,33 +407,18 @@ about your domain gets written down; CTRLRun is what makes it hold.
## Documentation
-**[ctrlrun.dev](https://ctrlrun.dev)** is the documentation: concepts, guides, a cookbook, the
+**[docs.ctrlrun.dev](https://docs.ctrlrun.dev/)** is the documentation: concepts, guides, a cookbook, the
full reference, and a browser demo that runs with no install.
| | |
|---|---|
-| Start here | [Why](https://ctrlrun.dev/docs/why) · [Protect your first action](https://ctrlrun.dev/docs/get-started/quickstart) · [Try it in your browser](https://ctrlrun.dev/docs/try-it) · [The execution boundary](https://ctrlrun.dev/execution-boundary), one action through every check |
-| The ideas, and doing something with them | [Concepts](https://ctrlrun.dev/docs/concepts/outcomes-and-ambiguous) · [Guides](https://ctrlrun.dev/docs/guides/protect-a-function) · [Cookbook](https://ctrlrun.dev/docs/cookbook/index) |
-| Agents and MCP | [Agents you can't modify](https://ctrlrun.dev/docs/agents-you-cant-modify) · [MCP overview](https://ctrlrun.dev/docs/mcp/overview) · [The gateway in five minutes](https://ctrlrun.dev/docs/mcp/gateway-in-5-minutes) |
-| Running it for real | [Production](https://ctrlrun.dev/docs/production/index) · [Postgres](https://ctrlrun.dev/docs/production/postgres) · [Recovery](https://ctrlrun.dev/docs/production/recovery) · [Operations](https://ctrlrun.dev/docs/production/operations) |
-| Every key, flag and error | [Reference](https://ctrlrun.dev/docs/reference/policy-yaml) · [FAQ](https://ctrlrun.dev/docs/faq) |
-| Compared with | [Idempotency keys](https://ctrlrun.dev/docs/compare/idempotency-keys) · [Framework human-in-the-loop](https://ctrlrun.dev/docs/compare/framework-hitl) · [Guardrail libraries](https://ctrlrun.dev/docs/compare/guardrail-libraries) · [Durable workflows](https://ctrlrun.dev/docs/compare/durable-workflows) · [Governance toolkits](https://ctrlrun.dev/docs/compare/governance-toolkits) |
-| What holds, and what does not | [Threat model](https://ctrlrun.dev/docs/THREAT_MODEL) · [What `verify` proves](https://ctrlrun.dev/docs/verify) · [`CLAIMS.md`](https://ctrlrun.dev/docs/CLAIMS), every sentence mapped to its test · [How this is built](https://ctrlrun.dev/docs/how-this-is-built) |
-
-## Open source, Pro, Enterprise
-
-The boundary is the same in every tier. What differs is who runs it.
-
-- **ctrlrun Open Source: free, run it yourself.** The boundary itself, at no cost. No account,
- no card, no call with us. Every rule that decides is code you can read, and every action
- leaves a receipt you keep. Free to use and free to change, under the Apache-2.0 licence.
-- **ctrlrun Pro, in development: the boundary, run for you.** Connect your agents and workflows
- and see what each connection covers. Search every action, decision and outcome across your
- agents. Manage policies and approvals from one place, test a rule in observe mode, then turn
- enforcement on. [Request early access](https://ctrlrun.dev/#pro-and-enterprise).
-- **ctrlrun Enterprise, engagements open: the boundary, shaped to you.** Everything in Pro, with
- CTRLRun engineers who design, integrate and maintain the controls your business needs.
- [Keep your stack, add the boundary](https://ctrlrun.dev/protect-my-agent).
+| Start here | [Why](https://docs.ctrlrun.dev/why) · [Protect your first action](https://docs.ctrlrun.dev/get-started/quickstart) · [Try it in your browser](https://docs.ctrlrun.dev/try-it) |
+| The ideas, and doing something with them | [Concepts](https://docs.ctrlrun.dev/concepts/outcomes-and-ambiguous) · [Guides](https://docs.ctrlrun.dev/guides/protect-a-function) · [Cookbook](https://docs.ctrlrun.dev/cookbook/index) |
+| Agents and MCP | [Agents you can't modify](https://docs.ctrlrun.dev/agents-you-cant-modify) · [MCP overview](https://docs.ctrlrun.dev/mcp/overview) · [The gateway in five minutes](https://docs.ctrlrun.dev/mcp/gateway-in-5-minutes) |
+| Running it for real | [Production](https://docs.ctrlrun.dev/production/index) · [Postgres](https://docs.ctrlrun.dev/production/postgres) · [Recovery](https://docs.ctrlrun.dev/production/recovery) · [Operations](https://docs.ctrlrun.dev/production/operations) |
+| Every key, flag and error | [Reference](https://docs.ctrlrun.dev/reference/policy-yaml) · [FAQ](https://docs.ctrlrun.dev/faq) |
+| Compared with | [Idempotency keys](https://docs.ctrlrun.dev/compare/idempotency-keys) · [Framework human-in-the-loop](https://docs.ctrlrun.dev/compare/framework-hitl) · [Guardrail libraries](https://docs.ctrlrun.dev/compare/guardrail-libraries) · [Durable workflows](https://docs.ctrlrun.dev/compare/durable-workflows) · [Governance toolkits](https://docs.ctrlrun.dev/compare/governance-toolkits) |
+| What holds, and what does not | [Threat model](https://docs.ctrlrun.dev/THREAT_MODEL) · [What `verify` proves](https://docs.ctrlrun.dev/verify) · [`CLAIMS.md`](https://docs.ctrlrun.dev/CLAIMS), every sentence mapped to its test · [How this is built](https://docs.ctrlrun.dev/how-this-is-built) |
## Contributing
@@ -448,13 +430,9 @@ working agreement, and
vulnerability. Every claim in this file has a test behind it, so a change to the prose usually
means a change to the suite.
[`CHANGELOG.md`](https://github.com/CTRLRun/ctrlrun/blob/main/CHANGELOG.md) and
-[`https://ctrlrun.dev/docs/ROADMAP`](https://ctrlrun.dev/docs/ROADMAP) say
+[`https://docs.ctrlrun.dev/ROADMAP`](https://docs.ctrlrun.dev/ROADMAP) say
where it is going. Releases carry PyPI provenance attestations from GitHub Actions.
## License
Apache-2.0. The enforcement kernel is and will remain fully open source.
-
-
- Let agents act. Keep the consequences yours to decide.
-
diff --git a/tests/test_readme_assets.py b/tests/test_readme_assets.py
index e1d39432..99786259 100644
--- a/tests/test_readme_assets.py
+++ b/tests/test_readme_assets.py
@@ -249,8 +249,10 @@ def test_the_social_preview_is_1280_by_640_and_rendered_from_its_svg():
#: What ctrlrun.dev's homepage says first, and therefore what the README says first. The site
#: is the marketing surface and the README is the GitHub and PyPI one, and until 2026-09-14
-#: they led with different sentences. `CTRLRun/ctrlrun-docs` asserts the same strings against
-#: `index.mdx`, so a change to either surface fails on the other.
+#: they led with different sentences. The pitch is shared; nothing commercial is, and the
+#: README's documentation links go to docs.ctrlrun.dev rather than to the site.
+#: `CTRLRun/ctrlrun-docs` asserts the same strings against `index.mdx`, so a change to either
+#: surface fails on the other.
HOMEPAGE_H1 = (
"CTRLRun stops AI agents from taking wrong, restricted, or malicious actions in your workflows."
)
@@ -258,7 +260,6 @@ def test_the_social_preview_is_1280_by_640_and_rendered_from_its_svg():
"Every action is checked against your rules before it runs. Allowed actions go through. "
"Sensitive ones wait for a person. Forbidden ones are blocked."
)
-HOMEPAGE_CLOSE = "Let agents act. Keep the consequences yours to decide."
def _prose(html: str) -> str:
@@ -298,10 +299,8 @@ def test_the_header_carries_the_fixed_copy_and_the_five_badges():
"receipt." in head
)
assert "When the outcome is unknown, CTRLRun says so instead of guessing." in head
- # The homepage's example heading opens the first section, and its closing line closes
- # the file.
+ # The homepage's example heading opens the first section.
assert "**The model guesses. CTRLRun does not.**" in text
- assert HOMEPAGE_CLOSE in _prose(text.rsplit("## License", 1)[1])
# The row was cut from thirteen to ten on 2026-09-11: `pypi/pyversions` is metadata rather
# than a claim, and `ruff` and `mypy --strict` say how the library is written, which is not
# what a stranger is deciding on the first screen. `scripts/check.sh` still runs all three
diff --git a/tests/test_repository_signals.py b/tests/test_repository_signals.py
index b4af94ea..ba630200 100644
--- a/tests/test_repository_signals.py
+++ b/tests/test_repository_signals.py
@@ -338,7 +338,7 @@ def test_how_this_is_built_states_the_review_gap_and_the_tooling_once():
provenance sentence appears in both the README and `SECURITY.md`.
"""
readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8")
- assert "https://ctrlrun.dev/docs/how-this-is-built" in readme
+ assert "https://docs.ctrlrun.dev/how-this-is-built" in readme
assert "Releases carry PyPI provenance attestations from GitHub Actions" in readme
assert "Releases carry PyPI provenance attestations from GitHub Actions" in (
REPO_ROOT / "SECURITY.md"
diff --git a/tests/test_verify_action.py b/tests/test_verify_action.py
index 1b9df362..4e25bc8c 100644
--- a/tests/test_verify_action.py
+++ b/tests/test_verify_action.py
@@ -363,13 +363,13 @@ def test_the_readme_carries_the_badge_and_links_it_to_what_it_means():
assert "img.shields.io/endpoint" in readme
assert "verify-badge.json" in readme
- assert "https://ctrlrun.dev/docs/verify#what-the-badge-means" in readme
+ assert "https://docs.ctrlrun.dev/verify#what-the-badge-means" in readme
def test_the_readme_documentation_table_links_the_verify_page():
readme = _repository_file(README)
- assert "https://ctrlrun.dev/docs/verify" in readme
+ assert "https://docs.ctrlrun.dev/verify" in readme
assert "declared guarantees pass" in readme