Skip to content

feat: add crust doctor, ACP stdio proxy, and security hardening#30

Merged
chen-zichen merged 6 commits intomainfrom
fix/doctor-bugs
Feb 26, 2026
Merged

feat: add crust doctor, ACP stdio proxy, and security hardening#30
chen-zichen merged 6 commits intomainfrom
fix/doctor-bugs

Conversation

@cyyever
Copy link
Collaborator

@cyyever cyyever commented Feb 26, 2026

Summary

  • crust doctor — new diagnostic command that probes all provider endpoints (builtin + user-configured)
    using the same URL-joining logic as the proxy, catching path bugs (404), auth issues (401/403), and
    connectivity errors before they hit production. Supports --timeout, --retries, --report (privacy-safe
    markdown for GitHub issues).
  • ACP stdio proxy (crust wrap) — wraps IDE agent subprocesses (e.g. VS Code Copilot) over stdin/stdout,
    applying the same security rules as the HTTP proxy. Includes mock agent for testing.
  • URL path duplication fixpathHasVersion now handles v1beta-style segments, preventing
    /v1beta/openai/v1/chat/completions double-pathing for Gemini and similar providers.
  • Dashboard cleanup — removed misleading "total tool calls" metric and block rate bar. TotalToolCalls
    only counts events reaching RecordEvent, so safe text-only responses were excluded, making "N total, N
    blocked (100%)" incorrect. Now shows blocked count only.
  • Security hardening — regression tests for rules engine, prefilter, security manager, and telemetry; SSE
    buffering fixes; engine edge-case handling.

Test plan

  • go build ./... passes
  • go test -race ./... passes
  • Tested manually (describe below)

Security checklist

  • No new path traversal or glob bypass vectors
  • No secrets or credentials in code

Providers like Zhipu AI (GLM) use versioned base URLs such as
/api/paas/v4. When the client sends /v1/chat/completions, the naive
path join produced /api/paas/v4/v1/chat/completions (404).

Add pathHasVersion/stripLeadingVersion helpers that detect version
segments in provider URLs and strip the client's redundant /vN prefix.
Also add GLM as a builtin provider.
pathHasVersion now matches any segment starting with "v" + digit
(e.g. v1beta, v2alpha1), not just pure vN. This fixes Gemini's
/v1beta/openai path being treated as unversioned, which caused
client /v1 to be prepended and produce 404s.

Updates the Gemini builtin URL to the correct OpenAI-compatible
endpoint at /v1beta/openai, removes unused isDigits helper, and
uses maps.Copy in BuiltinProviders accessor.
Fix HTTP client connection leak (defer CloseIdleConnections),
send minimal JSON body for Anthropic POST probes instead of nil,
and move markdown heading outside code fence in --report output.
…lignment

- Add defer client.CloseIdleConnections() to prevent transport leak
- Send minimal JSON body for Anthropic POST probes instead of nil
- Move markdown heading outside code fence in --report output
- Pad raw provider name before ANSI styling for correct column alignment
- Run provider checks concurrently with sync.WaitGroup (~2s vs ~20s)
- Add http.ProxyFromEnvironment to Transport (fixes CONN timeouts
  behind proxies)
- Broaden HTTP 400 handling to all providers (Gemini returns 400
  for unauthenticated GET /models)
- Respect --retries 0 instead of forcing minimum 1
- Use tagged switch for staticcheck QF1002
TotalToolCalls only counts events reaching RecordEvent — safe calls
with text-only LLM responses skip evaluation entirely, making "N total,
N blocked (100%)" misleading. Show only blocked count instead.

Also add doctor command documentation to cli.md and README.
@chen-zichen chen-zichen merged commit 282853c into main Feb 26, 2026
5 checks passed
@chen-zichen chen-zichen deleted the fix/doctor-bugs branch February 26, 2026 07:06
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.

2 participants