You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Local HEAD before this audit: v2.0.135 (`17a8b4a`), working tree clean.
8
+
- VPS was already running v2.0.135 and `/health` reported the commit after the prior deployment fix.
9
+
- Open issue clusters: upstream provider deadline around 236-243s, tool-call stability, WebSearch/WebFetch protocol work, SWE-1.6 special-agent routing, and dashboard large-list performance.
10
+
- One security subagent failed with a remote 429, so security findings here are from the main-thread read-through plus the successful protocol/performance/release subagents.
11
+
12
+
## Findings
13
+
14
+
### High: release metadata was not injected into GHCR images
15
+
16
+
`Dockerfile` accepts `BUILD_VERSION`, `BUILD_COMMIT`, `BUILD_COMMIT_MESSAGE`, `BUILD_COMMIT_DATE`, and `BUILD_BRANCH`, and `/health` reads the exported `WINDSURFAPI_BUILD_*` env. The tag release workflow did not pass those build args. Because `.dockerignore` excludes `.git`, release containers had no reliable source for `/health.commit`; Docker labels could still contain a revision, but `/health` could not read labels.
17
+
18
+
Status in this audit: blocked by the current GitHub token, which has `repo` but not `workflow` scope. GitHub rejects any push that modifies `.github/workflows/release.yml` without `workflow` scope. Keep this as the first follow-up once a workflow-scoped token is available.
19
+
20
+
### High: WebFetch/Read native bridge is still lab-only
21
+
22
+
Confirmed facts:
23
+
24
+
- Native bridge defaults remain narrow. Read/WebFetch/WebSearch are mapped but not in the default mature native set.
25
+
- WebFetch direct API that returns URL content has not been found. The observed official path is LS `HandleCascadeUserInteraction` for `read_url_content` permission approval, followed by trajectory steps.
26
+
-`read_url_content` completed output should come from `web_document` field 2. The top-level field 5 fallback was historical and is not confirmed for current official protocol.
27
+
- Read wrapper `type=14 field=19` remains partially reversed. v2.0.131 stopped prompt text from being promoted as a path, but that does not make Read production-ready.
28
+
29
+
Fix in this audit: WebFetch auto-approve now canonicalizes URL/origin and only accepts http(s) URLs without embedded credentials. `read_url_content` top-level field 5 fallback is now behind `WINDSURFAPI_NATIVE_TOOL_BRIDGE_READ_URL_LEGACY_SUMMARY=1`; default parsing only trusts `web_document`.
30
+
31
+
Still not fixed by design: do not production-open Read/WebSearch/WebFetch by default. Continue gated canaries only.
32
+
33
+
### Medium: oversized HTTP bodies were misclassified
34
+
35
+
`readBody()` detected bodies over 10 MB, but route-level JSON parse catches returned `400 Invalid JSON` for chat/responses/messages. That misled clients and operators.
36
+
37
+
Fix in this audit: `readBody()` now preserves a 413-class error and routes return protocol-shaped 413 payloads.
38
+
39
+
### Medium: atomic JSON temp files could race across processes
40
+
41
+
Several JSON persisters used one fixed sibling temp path such as `accounts.json.tmp` or `config.json.tmp`. Concurrent writers in separate processes could collide on the same temp file; on Windows, replacing the final target can also briefly fail while another test/process has the file open.
42
+
43
+
Fix in this audit: atomic JSON writers now use unique sibling temp names and retry short-lived `EPERM`/`EBUSY` rename failures before surfacing the error.
44
+
45
+
### Medium: dashboard account pages do full heavy-list rendering
46
+
47
+
`GET /dashboard/api/accounts` returns all accounts with heavy fields such as capabilities, credits, available models, tier models, user status, and LS admission. The front end renders all account rows at once; the anomaly page also full-renders and polls every 30 seconds. This matches issue #168.
48
+
49
+
Not fixed in this audit: this needs a separate dashboard pagination/summary endpoint slice. It is larger than the release/protocol hardening changes and should not be mixed into the same patch.
50
+
51
+
### Medium: stream and cache memory pressure remain bounded by count, not bytes
52
+
53
+
Conversation pool and response cache have item limits and TTLs. Response cache does not have a byte cap, and streaming accumulates text for downstream usage/cache logic. SSE writes do not wait for `drain` on slow clients.
54
+
55
+
Not fixed in this audit: recommended follow-up is byte caps plus backpressure-aware SSE writes.
56
+
57
+
## Non-Bugs / External Limits
58
+
59
+
- The 236-243s `context deadline exceeded` issue is a Windsurf upstream provider/Cascade stream window. Local `CASCADE_MAX_WAIT_MS` is not the limiting factor.
60
+
- SWE-1.6 should not be treated as a normal catalog or entitlement bug. It should continue through the Devin/ACP special-agent POC path.
61
+
- Trial/free rate limits, entitlement misses, and IP-level cooldowns are upstream capacity controls; local routing can surface them clearly but cannot create upstream quota.
62
+
63
+
## Next Execution Plan
64
+
65
+
1. Release and deploy the current hardening patch, then smoke VPS.
66
+
2. With a token that has `workflow` scope, apply the release workflow metadata/test-gate fix.
67
+
3. Next patch: dashboard account pagination/lightweight summary endpoint for #168.
68
+
4. Next protocol work: continue raw-child traces for `type=14 field=19` Read wrapper and WebSearch/WebFetch traces, but keep production native defaults narrow.
- Oversized HTTP request bodies now return protocol-shaped `413 Request body too large` errors instead of being misclassified as `Invalid JSON`.
6
+
- WebFetch lab auto-approve now canonicalizes URL/origin allowlist entries and rejects non-http(s), malformed, or credential-bearing URLs.
7
+
-`read_url_content` no longer trusts the unconfirmed top-level field 5 summary by default; legacy fallback requires `WINDSURFAPI_NATIVE_TOOL_BRIDGE_READ_URL_LEGACY_SUMMARY=1`.
8
+
- Atomic JSON writes now use unique temporary filenames and retry short-lived Windows rename locks, including `accounts.json`.
9
+
- Added `docs/audits/AUDIT_2026-06-06.md` with the audit baseline, findings, fixed items, and remaining follow-ups.
10
+
11
+
## Notes
12
+
13
+
- Read/WebSearch/WebFetch remain lab-only native bridge surfaces. This release tightens canary behavior; it does not production-open those tools.
14
+
- Release workflow metadata/test-gate hardening is documented in the audit, but was not included in this release because the current GitHub token lacks `workflow` scope.
15
+
- Dashboard account pagination for #168 is the next recommended implementation slice.
Copy file name to clipboardExpand all lines: package.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
{
2
2
"name": "windsurf-api",
3
-
"version": "2.0.135",
3
+
"version": "2.0.136",
4
4
"description": "Windsurf to OpenAI + Anthropic compatible API proxy. Turns Windsurf's 107 AI models (Claude, GPT, Gemini, DeepSeek, Grok, Qwen, Kimi, GLM, SWE) into dual-protocol API endpoints. Zero npm deps.",
0 commit comments