docs: describe the system as of 2026-10-02 (ax plane, AI decision engine, PHP, v3)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-10-02 07:08:44 +02:00
co-authored by Claude Opus 5.5
parent 7b17eacd44
commit 32a2cb8bcf
11 changed files with 715 additions and 405 deletions
+28 -21
View File
@@ -5,18 +5,23 @@ it does not, and the controls that keep a scan safe to run in CI and safe to sha
## Trust boundaries
- **Scanned code is untrusted input, never executed.** Quick and standard modes read
source as text (regex rules, evidence ladder, optional LLM review). They never import,
build, or run the target. Only `deep` mode would execute target-derived code, and only
inside the sandbox below — and deep mode is not yet implemented (it exits with a clear
message rather than running anything).
- **Scanned code is untrusted input.** Quick and standard modes never import, build or run
the target: quick reads source as text, and standard additionally parses it into a code
property graph with Joern (`joern-parse`, a parser, not a build) and may send code excerpts
to the configured model. Only `deep` mode executes target-derived code: its REGRESS stage
loads promoted candidates inside the Docker sandbox below, and it runs only when `docker
info` succeeds (otherwise the stage is skipped and recorded as `sandbox_unavailable`).
- **The ruleset and CWE policy are trusted, governed data.** They change only through
reviewed commits or the bounded self-improvement loop (`ousast improve`), which can
flip rule *status* and tune score constants but can never edit pattern text or the
authoritative 0–5 severity. See the self-improving cycle in the README.
- **Provider credentials are the operator's.** The zero-dependency core makes no network
calls. A local scan calls a model only for the optional `[models] hunter` tool hunter
in standard mode. Agentic work runs on the plane (`ousast plane run`): `ousast` reads
authoritative 0–5 severity. See [architecture.md](architecture.md#self-improvement).
- **Provider credentials are the operator's.** The core install (PyYAML only) makes no
network calls on its own. A local scan calls a model only in standard or deep mode, and
only when a key is available: the model layer asks the residual question the graph cannot
settle, and `[models] hunter` enables the tool hunter. LLM calls go to DeepSeek
(`DEEPSEEK_API_KEY`); OpenRouter (`OPENROUTER_API_KEY`) serves embeddings. Keys come from
the environment or a gitignored `.env`, which never overrides an exported variable. The
pre-push check calls a model only with an explicit `--model-config`. Agentic work runs on the plane (`ousast plane run`): `ousast` reads
the variable a task's Model names (`secretKey.key`) from the operator's environment or
`.env` and sends the key only in that task's start request, through Agent Substrate's
router to that task's actor. It is not baked into an image or task template, and it is
@@ -54,7 +59,7 @@ LLM/embedding calls retry transient failures (HTTP 429/5xx, connection errors, t
with exponential backoff; non-transient errors (e.g. 4xx, malformed JSON) fail fast.
### Visible degradation & determinism
When an optional capability is missing (the extra, a model, a provider key), the scan
When an optional capability is missing (Joern, Docker, a model, a provider key), the scan
falls back to its deterministic equivalent and records a `degradations` entry in the
manifest — it is never silently downgraded. Runs are reproducible: fixed config,
artifact manifests, prompt hashes, and model identifiers are recorded.
@@ -63,18 +68,20 @@ artifact manifests, prompt hashes, and model identifiers are recorded.
`ousast mcp` exposes only the ten narrow project tools. No tool runs arbitrary shell,
Docker, or internal hunter tools, and no tool accepts a free-form command argument.
## Sandbox limits (deep mode, when implemented)
## Sandbox (deep mode)
Dynamic analysis runs under the bounds in `[sandbox]` (`config.SandboxConfig`):
The REGRESS stage (`regress/`, `sandbox/runner.py`) runs each snippet with `docker run`
and never mounts the host Docker socket:
| Control | Default |
| Control | Setting |
|---|---|
| network | disabled (`network = false`) |
| workspace | read-only (`workspace_readonly = true`) |
| memory | 2048 MB (`memory_mb`) |
| pids | 512 (`pids_limit`) |
| timeout | 300 s (`timeout_seconds`) |
| network | `--network none`, always; a host-network argument is refused |
| source | the target bind-mounted read-only at `/workspace`; root filesystem `--read-only` |
| scratch | a tmpfs at `/scratch` for the snippet |
| user | non-root `65534:65534`, `--cap-drop ALL`, `no-new-privileges` |
| memory | `[sandbox] memory_mb`, default 2048 MB |
| pids | `[sandbox] pids_limit`, default 512 |
| timeout | `[sandbox] timeout_seconds`, default 300 s |
Dynamic probes additionally declare their network scope, log commands, and capture
artifacts; a hardened runtime (e.g. gVisor) is used when available. Until deep mode
ships, no target code is executed at all.
Before anything runs, a structural deny-list (`regress/safety.py`) rejects a snippet that
mentions sockets, curl, host networking or writes under `/workspace`.