Skip to content

fix(runtime): serve hardening — guard/reset auth, os NameError, wrist kwarg#237

Open
rylinjames wants to merge 2 commits into
mainfrom
fix/runtime-serve-hardening
Open

fix(runtime): serve hardening — guard/reset auth, os NameError, wrist kwarg#237
rylinjames wants to merge 2 commits into
mainfrom
fix/runtime-serve-hardening

Conversation

@rylinjames

Copy link
Copy Markdown
Collaborator

Audit §3.2 — three independent runtime bugs in server.py.

# Bug Fix
1 /guard/reset unauthenticated — anyone reachable could clear a tripped safety guard (while /act//config need the key) added Depends(_require_api_key)
2 NameError: os in the create_app lifespan — fn imports os as _os but the curate block read bare os.environ → swallowed NameError when a user opted into curate uploads os._os.; verified none remain
3 image_wrist_b64 kwarg TypeError — /act passes it but the TetherServer base class didn't accept it → every wrist-camera request to a single-cam model 500'd added the param to the base class; single-cam base drops it with a debug log (multi-cam VLAs route to Pi05DecomposedServer which consumes it)

Tests: tests/test_runtime_serve_hardening.py (9) — guard_reset auth via route introspection + TestClient 401/200; no-bare-os scan + compile; wrist-kwarg signature + live-call + cross-class checks. All pass.

Implemented by a Sonnet subagent against a verified spec; reviewed, and the wrist-drop debug log added on review (no silent fallback).

🤖 Generated with Claude Code

rylinjames and others added 2 commits June 10, 2026 21:54
… kwarg

Audit §3.2. Three independent runtime bugs in server.py:

1. /guard/reset was unauthenticated — anyone reachable could clear a tripped
   safety guard, while /act and /config require the api key. Added the same
   `_auth: None = Depends(_require_api_key)` dependency.

2. NameError: os in create_app's lifespan — the function imports `os as _os`,
   but the curate block read `os.environ.get("TETHER_CURATE_DRY_RUN")` (bare
   os), raising NameError (swallowed) whenever a user opted into curate
   uploads. Fixed to _os.environ. Verified no bare `os.` remains in the fn.

3. image_wrist_b64 kwarg TypeError — the /act path calls
   server.predict_from_base64_async(image_wrist_b64=...), but the TetherServer
   base class only accepted (image_b64, instruction, state), so every
   wrist-camera request to a single-camera model raised TypeError.
   Pi05DecomposedServer already accepts + uses it. Added the param to the base
   class's predict_from_base64[_async]; the single-camera base drops the wrist
   image with a debug log (not silently) — multi-camera VLAs route to the
   decomposed server that consumes it.

Tests: tests/test_runtime_serve_hardening.py (9) — guard_reset auth via route
introspection + TestClient 401/200; no-bare-os scan + compile; wrist-kwarg
signature + live-call + cross-class checks. All pass.

Implemented by a Sonnet subagent against a verified spec; reviewed + the
wrist-drop debug log added on review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The runtime serve hardening test suite used an absolute macOS checkout path for server.py, which made GitHub CI fail on Linux runners. Resolve server.py relative to the test file instead and clean up the test imports so the new test file is ruff-clean.

Tests: PYTHONPATH=src /Users/romirjain/Desktop/building\ projects/fastcrest/tether/.venv/bin/python -m pytest tests/test_runtime_serve_hardening.py -p no:cacheprovider

Lint: PYTHONPATH=src /Users/romirjain/Desktop/building\ projects/fastcrest/tether/.venv/bin/ruff check tests/test_runtime_serve_hardening.py

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant