Skip to content

Proxy storage: flows table, bodies in blobs.sqlite, settings - #751

Merged
gschier merged 2 commits into
mainfrom
t3code/proxy-flow-storage
Oct 14, 2026
Merged

gschier merged 2 commits into
mainfrom
t3code/proxy-flow-storage

Conversation

@gschier

@gschier gschier commented Oct 14, 2026

Copy link
Copy Markdown
Member

Flows move to a flows table with the engine's metadata and no body columns; bodies go to the proxy's blobs.sqlite as <flow id>.request and <flow id>.response through a chunk writer now shared with the client's request-body capture. Also: resolve_data_dir in yaak-common, a standalone blob-store opener in yaak-models, WAL and a single writer for proxy.db, and settings.json (port, system proxy, capture limit) feeding ProxyConfig.

Tests: chunk writer (grouping, empty body); a flow end to end through ProxyCtx (row, both blobs, gzip decode on read, truncated body over the cap); the migration on an old-schema DB; settings defaults, missing keys, round trip, invalid JSON.

@greptile-apps

greptile-apps Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 3/5

[Critical impact] Database schema migration and storage restructuring for proxy flows.

The PR should not merge while upgrading deletes saved traffic and systemProxy has no effect.

Findings

  1. P1 Upgrade deletes saved traffic ▶
  2. P1 System proxy setting does nothing ▶
  3. P2 Window shows the wrong port ▶
  4. P2 Early responses save wrong totals ▶
  5. P2 Decoded bodies have no cap ▶

Summary

The PR moves captured traffic metadata into flows and stores request and response bodies separately in blobs.sqlite.

  • The proxy records each exchange as a flow with detailed metadata.
  • Proxy request and response bodies are saved as readable chunks.
  • Proxy database reads and writes use separate pools with WAL enabled.
  • The proxy starts with settings from its data folder.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    Settings[settings.json] --> Engine[Proxy engine]
    Engine --> Events[Request and response events]
    Events --> Capture[ProxyCtx event loop]
    Capture --> Writer[BodyChunkWriter]
    Writer --> Blobs[(blobs.sqlite)]
    Capture --> Flows[(proxy.db: flows)]
    Flows --> Models[model_write]
    Models --> UI[Traffic table and sidebar]
Loading

Reviews (2) · Last reviewed commit: "Count request bytes per chunk so early r..." · Reviewed by Greptile

@@ -0,0 +1,27 @@
DROP TABLE http_exchanges;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Upgrade deletes saved traffic

Opening an existing proxy.db runs DROP TABLE http_exchanges before any history is copied. This permanently deletes every saved exchange, including both inline bodies. Copy the old rows into flows and move their bodies into blobs.sqlite before dropping the table.

Knowledge Base Used:

Comment on lines +65 to +67
let mut config = ProxyConfig::new(settings.port, Arc::new(ca));
config.capture_body_limit = settings.capture_body_limit;
let mut proxy_handle = yaak_proxy::start_proxy(config)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 System proxy setting does nothing

Setting systemProxy to true in settings.json has no effect. start() reads only port and capture_body_limit, and neither lifecycle method changes the operating system's proxy settings. Desktop traffic therefore stays outside the proxy. Apply the requested setting on start and restore the previous setting on stop.

let settings = ProxySettings::load(&self.settings_path())?;
let ca = CaStore::load_or_create(&self.data_dir.join("ca"))
.map_err(|e| format!("Failed to load proxy CA: {e}"))?;
let mut config = ProxyConfig::new(settings.port, Arc::new(ca));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Window shows the wrong port

With {"port":8080} in settings.json, the engine listens on 8080 but ProxyLayout still says Running :9090. Users following that label can configure their clients with the wrong port. Return the actual bound port through the proxy-state response and display it instead of the fixed label. This also covers port: 0.

Comment on lines +255 to +256
ProxyEvent::ResponseBodyComplete { id, size, truncated, elapsed_ms, error } => {
if let Some(mut f) = in_flight.remove(&id) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Early responses save wrong totals

request_size and request_truncated are set only by RequestBodyComplete, but a response can finish before an upload does, particularly with HTTP/2. Removing the flow on ResponseBodyComplete discards the later request completion. The saved row can report zero request bytes and no truncation despite already having captured request bytes. Keep request counts current from chunk events and retain enough state to save the final request totals.

Knowledge Base Used: Local proxy service

Comment on lines +31 to +32
let mut decoded = Vec::new();
match streaming_decoder(Cursor::new(raw), encoding).read_to_end(&mut decoded).await {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Decoded bodies have no cap

read_body() puts no limit on decoded output. A compressed body below the capture limit can expand far beyond it when read_to_end() fills decoded. There is no production caller yet, so this is hardening rather than a current exposed failure. Add a decoded-byte limit and a test with highly compressible input before this helper is used for body inspection.

@gschier

gschier commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

@greptileai

@gschier
gschier merged commit b5508e6 into main Oct 14, 2026
6 checks passed
@gschier
gschier deleted the t3code/proxy-flow-storage branch October 14, 2026 20:50
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.

1 participant