On lab's production the app renders /changelog in about 5 ms (app;dur=5), yet forge-upstream ran 20 ms, 45 ms, 53 ms and then 1321 ms across four requests in a row. forge-route reached 48 ms on an immutable CSS asset. Right now nobody can tell whether that time goes to the socket connect, waiting for the app, or relaying the body. The proxy should measure it, not leave it to guesses.
Done when:
[ ] A proxied answer's server-timing splits the relay into forge-connect (until the socket is open, or 0 when reused), forge-ttfb (until the app's headers arrive) and keeps forge-upstream as their total. Durations only, never a host or a path
[ ] forge-route is split where it spends more than 1 ms (lookup, session, wake check), so its 48 ms spike can be pinned to one part
[ ] A test proxies a stub app that sleeps 30 ms before its headers and proves forge-ttfb is at least 30 and forge-connect is under it. It fails without the change
[ ] The pull quotes ten requests against its own preview with the new phases, so the next issue can name the slow part
Files: src/apps/proxy.ts, src/core/route_timing.ts, test/apps-proxy-timing.test.ts
Risk: server-timing is public. Write only durations under fixed names, as relayPhase does today.
On lab's production the app renders
/changelogin about 5 ms (app;dur=5), yetforge-upstreamran 20 ms, 45 ms, 53 ms and then 1321 ms across four requests in a row.forge-routereached 48 ms on an immutable CSS asset. Right now nobody can tell whether that time goes to the socket connect, waiting for the app, or relaying the body. The proxy should measure it, not leave it to guesses.Done when:
server-timingsplits the relay intoforge-connect(until the socket is open, or 0 when reused),forge-ttfb(until the app's headers arrive) and keepsforge-upstreamas their total. Durations only, never a host or a pathforge-routeis split where it spends more than 1 ms (lookup, session, wake check), so its 48 ms spike can be pinned to one partforge-ttfbis at least 30 andforge-connectis under it. It fails without the changeFiles: src/apps/proxy.ts, src/core/route_timing.ts, test/apps-proxy-timing.test.ts Risk:
server-timingis public. Write only durations under fixed names, asrelayPhasedoes today.