195 lines
8.2 KiB
Markdown
195 lines
8.2 KiB
Markdown
# Known Issues & Future Work
|
||
|
||
---
|
||
|
||
## Medium
|
||
|
||
### 1. Cascade Correlation Is Heuristic
|
||
|
||
**File:** `src/mitm/intercept.rs` — `extract_cascade_hint()`
|
||
|
||
The MITM proxy matches intercepted API traffic to cascade IDs by scanning for `metadata.user_id` or `workspace_id` in the request body. If neither is found, it stores under `_latest`. Since `take_usage()` no longer falls back to `_latest`, unidentified requests will have **no MITM usage data at all**.
|
||
|
||
**Fix:** Investigate the actual request body format the LS sends for better correlation keys. Alternatively, use timing-based correlation (match MITM capture timestamp to cascade polling window).
|
||
|
||
---
|
||
|
||
### 2. Domain Certificate Cache Is Unbounded
|
||
|
||
**File:** `src/mitm/ca.rs` — `domain_cache`
|
||
|
||
The `domain_cache` (`HashMap<String, Arc<ServerConfig>>`) grows without bound. Each unique domain gets a cached entry containing a full `ServerConfig` with an RSA key pair. In practice, only ~5–10 domains are intercepted so this is unlikely to matter, but there's no eviction.
|
||
|
||
**Fix:** Set a max cache size (e.g., 100 entries) with LRU eviction, or use a TTL since leaf certs are generated with a 1-year validity.
|
||
|
||
---
|
||
|
||
### 3. Request Modification Not Implemented
|
||
|
||
**File:** `src/mitm/proxy.rs` — `modify_requests: false`
|
||
|
||
The `MitmConfig.modify_requests` flag exists and is plumbed through, but no actual modification logic is implemented. The flag is hardcoded to `false`.
|
||
|
||
**Fix:** When needed, implement request body mutation in `handle_http_over_tls()` — parse JSON, modify, reserialize, update `Content-Length`.
|
||
|
||
---
|
||
|
||
### 4. `total_cost_usd` Is Dead
|
||
|
||
**File:** `src/mitm/store.rs` (line 28)
|
||
|
||
`ApiUsage.total_cost_usd` is `Option<f64>` but is **always `None`** — set to `None` in all 4 construction sites (`h2_handler.rs` ×2, `intercept.rs` ×2). Neither Anthropic nor Google include cost in API responses.
|
||
|
||
**Fix:** Either remove the field (simpler), or populate it via a pricing table lookup (model → $/1K tokens) at `record_usage()` time.
|
||
|
||
---
|
||
|
||
## 🟢 Low
|
||
|
||
### 5. Wrapper Script Fallback Paths May Be Stale
|
||
|
||
**File:** `scripts/mitm-wrapper.sh` — `LS_FALLBACK_DIRS`
|
||
|
||
The fallback glob patterns (e.g., `~/.cursor/extensions/antigravity.antigravity-*/...`) assume a specific extension naming convention. These are only used when no running LS process is found via `/proc` scanning (Method 1), which is the primary and robust discovery mechanism.
|
||
|
||
**Impact:** Only affects `install` when the LS isn't running. Low priority.
|
||
|
||
---
|
||
|
||
### 6. No Integration Tests for MITM Module
|
||
|
||
The MITM module has unit tests for protobuf decoding and intercept parsing, but no integration tests that verify:
|
||
|
||
- TLS interception end-to-end with the generated CA
|
||
- Full HTTP/1.1 request/response cycle through the proxy
|
||
- gRPC (HTTP/2) request/response cycle through `h2_handler`
|
||
- Store recording and retrieval under concurrency
|
||
- Wrapper script install/uninstall lifecycle
|
||
|
||
---
|
||
|
||
## 🔍 Investigation
|
||
|
||
### 7. LS Exposes Credit/Quota Data via `GetUserStatus`
|
||
|
||
**Confirmed via live probing.** The LS's `GetUserStatus` RPC already returns structured cost/quota data:
|
||
|
||
```json
|
||
"planStatus": {
|
||
"planInfo": {
|
||
"planName": "Pro",
|
||
"monthlyPromptCredits": 50000,
|
||
"monthlyFlowCredits": 150000,
|
||
"monthlyFlexCreditPurchaseAmount": 25000,
|
||
"canBuyMoreCredits": true
|
||
},
|
||
"availablePromptCredits": 500,
|
||
"availableFlowCredits": 100
|
||
}
|
||
```
|
||
|
||
Each model also includes **per-model quota info**:
|
||
|
||
```json
|
||
"quotaInfo": {
|
||
"remainingFraction": 0.2,
|
||
"resetTime": "2026-02-14T07:41:37Z"
|
||
}
|
||
```
|
||
|
||
**Key findings:**
|
||
|
||
- `GetUserStatus` is the single source for credit/quota data (exposed via `LanguageServerService`)
|
||
- `SeatManagementService` methods (`GetPlanStatus`, `GetTeamCreditEntries`, `GetCascadeAnalytics`, `GetUserSubscription`) are **not routed through the LS** — they're backend-only
|
||
- `PredictionService/RetrieveUserQuota` is also backend-only (not proxied by LS)
|
||
- `GetUserAnalyticsSummary` returns empty `{}` (may not be implemented or requires different context)
|
||
- `GetModelStatuses` returns empty `{}` (separate from the model configs in `GetUserStatus`)
|
||
- `userTier` field shows subscription level: `{"id": "g1-ultra-tier", "name": "Google AI Ultra"}`
|
||
|
||
**Potential use:** We could poll `GetUserStatus` periodically and expose `availablePromptCredits`, `availableFlowCredits`, and per-model `remainingFraction` via the `/v1/usage` endpoint — giving users real-time credit burn visibility without needing MITM token counting.
|
||
|
||
---
|
||
|
||
## 🔴 Blockers
|
||
|
||
### 8. LS Go LLM Client Ignores System TLS Trust Store
|
||
|
||
**File:** `docs/mitm-interception-status.md`
|
||
|
||
The LS binary is a Go program whose HTTP client for LLM API calls uses a custom `tls.Config` that does **not** trust system CAs or honor `SSL_CERT_FILE`. This means our MITM proxy's generated CA cert is rejected even when properly installed system-wide.
|
||
|
||
The extension patch (`detectAndUseProxy=1`) only makes the LS honor `HTTPS_PROXY` for routing — it doesn't fix CA trust. Without this, the MITM proxy can route but not decrypt LLM traffic.
|
||
|
||
**Potential fixes:**
|
||
|
||
- Binary patching the Go TLS verification (hard, breaks on updates)
|
||
- Full standalone LS control (in progress, see issue #9)
|
||
- Network namespace + iptables redirect (eliminates HTTPS_PROXY need but doesn't fix TLS trust)
|
||
- eBPF/ptrace to inject certs at runtime (complex)
|
||
|
||
**See:** `docs/mitm-interception-status.md` for full analysis
|
||
|
||
---
|
||
|
||
### 9. Standalone LS Cascades Silently Fail
|
||
|
||
**File:** `docs/standalone-ls-todo.md`
|
||
|
||
When running a standalone LS instance (outside of Antigravity), cascades start but produce no output. The LS accepts `StartCascade` RPCs without error, but the cascade never progresses.
|
||
|
||
**Suspected blockers:**
|
||
|
||
- Missing auth context (OAuth token not properly propagated)
|
||
- Unleash feature flags differ between main and standalone instances (`GetUnleashData` returns different flags)
|
||
- `LoadCodeAssist` / `OnboardUser` initialization steps may be required
|
||
- Extension server callbacks (`WriteCascadeEdit`, `ExecuteCommand`, etc.) have no handler
|
||
|
||
**See:** `docs/standalone-ls-todo.md` for investigation plan
|
||
|
||
---
|
||
|
||
## Medium
|
||
|
||
### 10. Extension Patch Fragility
|
||
|
||
**File:** `scripts/mitm-wrapper.sh`, GEMINI.md
|
||
|
||
The `sed` patch that sets `detectAndUseProxy=1` in `extension.js` must be **re-applied after every Antigravity update**. The search pattern (`detectAndUseProxy=pe.UNSPECIFIED`) is brittle — if the minified variable name changes from `pe` to something else, the patch silently fails.
|
||
|
||
**Fix:** Use a regex-based patch (`detectAndUseProxy=[^;]*` → `detectAndUseProxy=1`) or patch via AST manipulation. Add a post-update hook or version check to warn when the patch is stale.
|
||
|
||
---
|
||
|
||
### 11. Polling-Based Cascade Updates vs Streaming RPC
|
||
|
||
**File:** `src/api/polling.rs`
|
||
|
||
We poll `GetCascadeTrajectorySteps` on a timer to check for new cascade output. The LS has a `StreamCascadeReactiveUpdates` streaming gRPC method that pushes updates in real-time. Our polling approach works but adds latency and unnecessary requests.
|
||
|
||
**Impact:** Functional but suboptimal. The streaming approach would give lower latency and less LS load, but requires maintaining a long-lived gRPC stream and handling reconnection.
|
||
|
||
**See:** `docs/ls-binary-analysis.md` → gRPC Services → LanguageServerService
|
||
|
||
---
|
||
|
||
### 12. No BYOK Model Routing
|
||
|
||
**File:** `src/api/models.rs`
|
||
|
||
The LS supports BYOK (Bring Your Own Key) variants for Claude and OpenAI models (e.g., `MODEL_CLAUDE_4_SONNET_BYOK`, `MODEL_OPENAI_COMPATIBLE`). Our proxy only exposes the 5 built-in placeholder models. Users with BYOK keys can't use them through the proxy.
|
||
|
||
**Fix:** Add a mechanism to register BYOK models at runtime (e.g., via a config file or API endpoint). The BYOK model IDs and their proto enum numbers are documented in `docs/ls-binary-analysis.md`.
|
||
|
||
---
|
||
|
||
### 13. `total_cost_usd` Could Use Pricing Table
|
||
|
||
(Extends issue #4)
|
||
|
||
Now that we have the full model catalog with proto enum numbers (`docs/ls-binary-analysis.md`), we could build a pricing table mapping model → cost per token. The MITM captures input/output token counts, so cost calculation is just a lookup + multiply.
|
||
|
||
Known models that could have pricing:
|
||
|
||
- Claude Opus 4.6 (M26/1026), Opus 4.5 (M12/1012)
|
||
- Gemini 3 Pro High (M8/1008), Pro Low (M7/1007), Flash (M18/1018)
|