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.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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)