Closes#255. Without timeouts, a hung upstream during the access-hook
or git http-backend CGI call (git_http_backend.py) and a stalled Gitea
API during deploy-key provisioning (contrib/gitea/deploy_key_provisioner.py)
could wedge a sidecar indefinitely. Adds GIT_HTTP_BACKEND_TIMEOUT_SECS
(30s) to both subprocess.run calls in the HTTP backend, mirroring the
existing GIT_GATE_DAEMON_TIMEOUT_SECS on the daemon path. Adds
_API_TIMEOUT_SECS (30s) and _KEYGEN_TIMEOUT_SECS (10s) to the Gitea
provisioner's urlopen and ssh-keygen calls. Tests verify the timeout
values are forwarded in all four call sites.
Main code fixes:
- Remove unused Iterator import from local_registry.py
- Fix signal handler signature in pty_resize.py (correct parameters for signal.signal)
- Add type annotations for screen parameters in tui.py (use Any for curses types)
- Fix missing tty_fd type annotation in tui.py
- Remove unused old_term variable in tui.py
- Fix tty_fd FileIO wrapping for TextIOWrapper initialization
- Add type: ignore for curses._CursesWindow attributes in supervise.py
- Add type: ignore for BaseServer attributes in git_http_backend.py
- Fix HTTPRequestHandler.log_message parameter name mismatch
- Cast _agent_prompt_mode to PromptMode in bottle.py files
- Fix Popen[bytes] generic type annotations in sidecar_init.py
- Add type: ignore for dynamic prompt_file attribute access in agent_provider.py
Configuration:
- pyrightconfig.json now suppresses third-party library unknowns
- Remaining test errors are mostly in test suites
Fixes 23 errors in main code, reduces total from 985 → 240 (75% reduction from initial ~1,200)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Previously when the access-hook returned non-zero, git-http would pipe
the hook's stderr into the 403 body sent back to the agent's git
client but never log it locally, so docker logs just showed
`"GET ... 403 -"` with no explanation. Operators had to shell into
the sidecar and re-run the hook by hand to find out why a clone was
being refused (e.g. upstream SSH unreachable, missing credentials).
Route the hook's stderr/stdout through the existing log_message
channel before sending the 403, one log line per output line so the
default request-log format stays readable. When the hook exits
non-zero with no output, log the exit code so the line is still
informative.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both remote-addr and peer-addr args to the access hook are the same
TCP peer in this non-proxied stack. Extract a `peer` variable so the
intentional repetition is visible. Closes#148.
Before this change, int() on a non-numeric Content-Length raised an
unhandled ValueError, crashing the request handler. There was also no
upper bound on how much memory a POST body could consume.
After this change:
- Non-numeric or missing Content-Length returns HTTP 400.
- Negative Content-Length returns HTTP 400.
- Bodies declared larger than 1 MiB (_MAX_BODY_BYTES) return HTTP 413,
matching the cap already in supervise_server.py.
Closes#138