Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/OWASP-AGENTIC-TOP10.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ The half that makes the table above credible. One honest sentence each; nothing
| `ASI04:2026` | Agentic Supply Chain Vulnerabilities | Out of scope. CTRLRun never inspects a package, a model, a tool registry or an MCP server's provenance; it decides actions, and a poisoned dependency reaches it as an ordinary caller. |
| `ASI05:2026` | Unexpected Code Execution | Out of scope. Nothing here sandboxes an interpreter or constrains what a process may run. CTRLRun sits between an agent and one remote effect, not between an agent and its own runtime. |
| `ASI06:2026` | Memory & Context Poisoning | Out of scope, and deliberately so: CTRLRun never reads a model's memory, its context or its prompt. It sees a proposed action and its arguments, which is the point at which a poisoned context has already become a concrete request. |
| `ASI07:2026` | Insecure Inter-Agent Communication | Not yet. Authority does not propagate across agent hops in this release — a grant is evaluated where the action is proposed, and there is no A2A model. `docs/docs/ROADMAP.md` puts that in v0.7; until then, an agent handing work to another agent is outside what these guarantees say anything about. |
| `ASI07:2026` | Insecure Inter-Agent Communication | Not yet. Authority does not propagate across agent hops in this release — a grant is evaluated where the action is proposed, and there is no A2A model. `docs/docs/ROADMAP.md` puts that in v0.8; until then, an agent handing work to another agent is outside what these guarantees say anything about. |

And the two entries where the mapping above is **partial**, with the part that is not covered
stated here rather than left implied:
Expand Down
20 changes: 18 additions & 2 deletions docs/docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,30 @@ among and contradicted by.

Standards: none new.

## v0.7 — Multi-agent
## v0.7 — Execution boundary

Every guarantee shipped so far is a guarantee about what happens *inside* CTRLRun. But the kernel does not decide whether the remote side acted — an executor does, by raising `NotExecuted` or not. It does not own the clock its leases are measured against, once the store is on another host. It does not know whether the world still looks the way it did when a human said yes. v0.7 asks what the kernel owes at each of those edges.

- **A transport classifier in core.** `FAILED` versus `AMBIGUOUS` is the one decision this project exists to get right, and the kernel does not make it — the user's executor does. The correct rule is already written and already implemented, in the gateway's `outcome.py`: the connection was never established, or the peer said in band and before dispatch that it rejected the request; everything after the first byte is `AMBIGUOUS`. It is reachable today only by installing `ctrlrun[gateway]`, while `@protect` — the surface the README leads with — gets a docstring. One rule, one implementation, reachable from core.
- **Clock-skew detection.** v0.6 moved the store to another host so several hosts could share it; lease liveness stayed on the application clock. Skew is fail-closed and therefore quiet — a host running ahead marks a live reservation `AMBIGUOUS` while its real holder is mid-flight and about to succeed, and nothing names the cause. This makes divergence observable. It does not change how a lease is evaluated.
- **A provider idempotency token**, derived from the effect key *and the attempt number*. Derived from the effect key alone it would be stable across v0.1 §5.4's renewal, and a provider would replay its cached failure for the one retry the kernel permits precisely because the executor proved nothing happened. Its main value is a deterministic handle for reconciliation to observe with — not a licence for anything to act twice.
- **A ceiling on renewal after `FAILED`.** There is none today: one human approval plus an executor that always reports "nothing happened" is unlimited dispatches, each recorded as an ordinary retry. An operator-set policy key, and an amendment to §5.4 written as an amendment.
- **Precondition fingerprints.** An approval binds to an action hash and an expiry, and to nothing about the world it was granted against. A human approves a deletion when the balance is zero; thirty minutes later it is not, and the action hash has not moved. The operator supplies a fingerprint, it is hashed through the canonicalizer so raw resource state never reaches a receipt, and it is rechecked before the reservation. **It narrows the window between decision and execution; it does not close it** — the recheck cannot run inside the atomic reservation write, so a residual gap remains, and that sentence appears wherever the feature does.

Exit: a classifier that observes rather than infers, with a test that writes a byte, kills the peer and asserts `AMBIGUOUS`; a skew detector with a positive control that stays silent when the clocks agree; a token that provably changes across a renewal; and the precondition recheck documented as narrowing everywhere it is described.

**A2A moved from v0.7 to v0.8 on 2026-09-08, and the reason is recorded here rather than made silently**, on the rule this file already follows for the v0.6 receipt-integrity line and the soak criterion. Multi-agent authority propagation builds on a kernel whose executor boundary is sound. Three of the five items above are weaknesses in guarantees the project already sells — the classifier most of all — and shipping a hop-counting authority model on top of an outcome mapping the primary surface leaves undefended would be building the next floor before the joists. Nothing about A2A changed; only its position.

Standards: none new.

## v0.8 — Multi-agent

- A2A integration: task-bound delegated authority with limits, expiry, and depth.
- Authority propagation across agent hops.

Standards: none new.

## v0.8–0.9 — Hardening
## v0.9 — Hardening

Fuzzing, property tests, concurrency stress, failure injection, benchmarks, external security review, upgrade testing, compatibility guarantees, CodeQL/SAST/SBOM/signed artifacts.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/THREAT_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ they entitled to?* Everything above still holds; these are the threats the secon
- **A `HeaderIdentityProvider` behind a proxy that does not overwrite the header.** It is worth exactly what the thing setting it is worth, and RFC 7239 §8.1 says the same of the header it standardizes. If the agent can set the header, the agent chooses its own authority. It warns at construction and it is still the operator's call.
- **A revoked token before its `exp`.** There is no revocation channel: a verified token is valid until it expires, which is why one with no `exp` is refused. Shared-signals mechanisms exist and v0.3 implements none of them. Short lifetimes are the whole of the story.
- **A tenant-templated issuer.** `issuer` is matched as an exact string, so a multi-tenant endpoint cannot be configured correctly here. Pointing it at one without pinning the tenant makes every tenant on that platform a valid issuer — stated because the fail-open is inviting.
- **Authority across an agent-to-agent hop.** A grant covers the principal CTRLRun resolved for *this* call. Propagating attenuated authority across hops is v0.7.
- **Authority across an agent-to-agent hop.** A grant covers the principal CTRLRun resolved for *this* call. Propagating attenuated authority across hops is v0.8.
- **Approving an authority change.** `ctrlrun delegate --as` is an assertion typed at a shell, not an authentication; the record keeps `created_via` so a reader can tell an act from an assertion. Authenticating the *approver* remains out of scope, as in v0.1.

## Known v0.4 limitations — what `ctrlrun verify` does not see
Expand Down