feat: MITM interception for standalone LS with UID isolation

- Spawn standalone LS as dedicated 'antigravity-ls' user via sudo
- UID-scoped iptables redirect (port 443 → MITM proxy) via mitm-redirect.sh
- Combined CA bundle (system CAs + MITM CA) for Go TLS trust
- Transparent TLS interception with chunked response detection
- Google SSE parser for streamGenerateContent usage extraction
- Timeouts on all MITM operations (TLS handshake, upstream, idle)
- Forward response data immediately (no buffering)
- Per-model token usage capture (input, output, thinking)
- Update docs and known issues to reflect resolved TLS blocker
This commit is contained in:
Nikketryhard
2026-02-14 17:50:12 -06:00
parent 6842bfeaa5
commit d4de436856
10 changed files with 1156 additions and 478 deletions

View File

@@ -83,6 +83,34 @@ impl Backend {
})
}
/// Create a Backend with known connection details (for standalone LS).
///
/// Skips auto-discovery — the caller provides the port, CSRF, and OAuth token.
pub fn new_with_config(
port: u16,
csrf: String,
oauth_token: String,
) -> Result<Self, String> {
let inner = BackendInner {
pid: "standalone".to_string(),
csrf,
https_port: port.to_string(),
oauth_token,
};
let client = wreq::Client::builder()
.emulation(wreq_util::Emulation::Chrome142)
.cert_verification(false)
.verify_hostname(false)
.build()
.map_err(|e| format!("wreq client build failed: {e}"))?;
Ok(Self {
inner: RwLock::new(inner),
client,
})
}
/// Re-discover language server connection details.
/// Runs blocking I/O on a spawn_blocking thread to avoid starving tokio.
pub async fn refresh(&self) -> Result<(), String> {