Drop our 797-LoC manual GraphQL ``ProxyManager`` and the in-container
sandbox dispatch. Caido goes host-side via the official async Python
SDK. The Caido CLI still runs as a sidecar in the container — only the
control-plane moves.
Bootstrap moves host-side:
- New ``strix/sandbox/caido_bootstrap.py``: ``loginAsGuest`` via
aiohttp (5 retries), then ``client.project.create(temporary=True)``
+ ``client.project.select(...)``, then return the connected
``caido_sdk_client.Client``. Drop the equivalent bash from
``docker-entrypoint.sh`` (~60 lines of curl + jq).
- ``entry.py`` calls ``bootstrap_caido_client`` after the
``wait_for_tcp_ready`` healthcheck, stashes the client in the bundle
and threads it through ``make_agent_context(caido_client=...)``.
``agents_graph.create_agent`` propagates the same client to children.
- ``session_manager.cleanup`` ``await``s ``client.aclose()`` before
tearing down the container.
- Drop ``CAIDO_PORT`` from the manifest env (only the in-container
ProxyManager read it) and ``CAIDO_API_TOKEN`` from the entrypoint's
``/etc/profile.d/proxy.sh`` + ``/etc/environment`` heredocs.
Tools (``strix/tools/proxy/tools.py``):
- ``list_requests`` → ``client.request.list().filter().first().after()``
with ascending/descending order. **Pagination changes from
start_page/end_page (1-indexed) to first/after cursors** matching the
SDK's native shape; response includes ``page_info.end_cursor`` for
the model to thread.
- ``view_request`` → ``client.request.get(id, RequestGetOptions(...))``;
decode raw bytes locally; existing regex-search and line-pagination
modes preserved.
- ``send_request`` → synthesize raw HTTP bytes, parse URL into
``ConnectionInfoInput(host, port, is_tls)``, create a replay session
via ``client.replay.sessions.create(CreateReplaySessionFromRaw(...))``,
then ``client.replay.send(session_id, ReplaySendOptions(...))``.
- ``repeat_request`` → ``client.request.get(id, request_raw=True)`` →
port the existing parse/_apply_modifications/build helpers verbatim →
send via the same replay flow as ``send_request``.
- ``scope_rules`` → direct mapping to ``client.scope.{list, get, create,
update, delete}``.
- **Drop ``list_sitemap`` + ``view_sitemap_entry``** — the official SDK
has no sitemap module. The model uses HTTPQL filters
(``req.host.eq:"X" AND req.path.cont:"/api/"``) for the same
drill-down workflow.
Deletions:
- ``strix/tools/proxy/proxy_manager.py`` (797 LoC)
- ``strix/tools/proxy/proxy_actions.py`` (113 LoC)
- The 6-line proxy_actions pre-import in ``python_instance.py``
(broken once proxy_actions is gone; that file is queued for deletion
in commit 2 anyway).
Deps:
- Add ``caido-sdk-client>=0.2.0`` and ``aiohttp>=3.10.0`` to runtime
``[project] dependencies``.
- Drop ``gql[requests]>=3.5.3`` from ``[project.optional-dependencies]
sandbox`` — only the in-container ProxyManager used the sync transport
variant; the SDK pulls in ``gql[aiohttp]`` transitively for us.
- ``[[tool.mypy.overrides]]``: add ``caido_sdk_client.*`` and
``aiohttp.*`` to the missing-imports list with
``disable_error_code=["import-untyped"]`` (neither ships ``py.typed``).
- ``[tool.ruff.lint.per-file-ignores]``: bump the proxy/tools.py
ignore to also include ``PLR0911`` (the scope_rules action dispatcher
has many short-circuit returns).
ruff drops from 21 → 12 errors; mypy moves from 82 → 84 (the +2 are in
already-flaky files unrelated to this change). All touched files mypy
clean.
Users can now access the Caido web UI from their browser to inspect traffic,
replay requests, and perform manual testing alongside the automated scan.
- Map Caido port (48080) to a random host port in DockerRuntime
- Add caido_port to SandboxInfo and track across container lifecycle
- Display Caido URL in TUI sidebar stats panel with selectable text
- Bind Caido to 0.0.0.0 in entrypoint (requires image rebuild)
- Bump sandbox image to 0.1.12
- Restore discord link in exit screen
- Move tool server startup from Python to entrypoint script
- Hardcode Caido port (48080) in entrypoint, remove from Python
- Use /app/venv/bin/python directly instead of poetry run
- Fix env var passing through sudo with sudo -E and explicit vars
- Add Caido process monitoring and logging during startup
- Add retry logic with exponential backoff for token fetch
- Add tool server process validation before declaring ready
- Simplify docker_runtime.py (489 -> 310 lines)
- DRY up container state recovery into _recover_container_state()
- Add container creation retry logic (3 attempts)
- Fix GraphQL health check URL (/graphql/ with trailing slash)