Skip to content

feat(stability): Phase 6 — edge cases and cleanup - #4

Open
dariusvorster wants to merge 13 commits into
mainfrom
stability/phase6-edge-cases-cleanup
Open

feat(stability): Phase 6 — edge cases and cleanup#4
dariusvorster wants to merge 13 commits into
mainfrom
stability/phase6-edge-cases-cleanup

Conversation

@dariusvorster

Copy link
Copy Markdown
Owner

Summary

  • 6A: Add routes.testUpstream tRPC procedure that probes upstream addresses and returns typed error categories (dns, connection_refused, timeout, tls, http_5xx, http_4xx, slow, ok). Add Test/Retest button in route detail panel showing distinct badge + message per error type — not a generic "fetch failed"
  • 6B: Document browser compatibility matrix (Chrome/Edge/Firefox/Safari latest 2), tested common paths, known limitations (iOS Safari cookie over HTTP, Firefox self-signed TLS), and IPv6/proxy/VPN notes
  • 6C: Upgrade CaddyClient.doRequest() retry from linear (delay*attempt) to exponential (delay*2^attempt, capped at 10s). Avoids thundering-herd on brief Caddy admin outages
  • 6D: Remove dormant trustUpstreamHeaders UI toggle from route edit and view panels. The field is stored in DB and accepted by API but config.ts (locked) never consumes it — the toggle was purely cosmetic. DB field stays for forward compat
  • 6E: Federation exponential backoff was already implemented in packages/federation/src/client.ts. User traffic pass-through is Caddy's default. Health check max_fails would require changes to locked config.ts — noted as future work
  • 6F: Add optional limit/offset to routes.list (backward-compatible; all 14 existing callers unaffected). Add routes.count for total pagination. Routes page uses PAGE_SIZE=50 with Prev/Next controls and "1–50 of N routes" label
  • Fix pre-existing TS2322 in apply-docker-dns.ts (missing handler in spread return type)
  • Fix pre-existing TS2532 in db/index.ts (possibly undefined indexed access)

Test Plan

  • pnpm --filter @proxyos/caddy test — 59 passed, 0 failed
  • pnpm --filter @proxyos/api exec tsc --noEmit — 0 errors
  • Routes page: Test/Retest button appears in route detail Upstream section; each upstream shows its error category
  • Routes page: Prev/Next pagination appears when more than 50 routes; page resets on site change
  • Caddy admin retry: exponential backoff (500ms → 1s → 2s) instead of linear (500ms → 1s → 1.5s)

Blocked / Not done

  • 6E health check max_fails: wiring healthCheckMaxFails into Caddy's health_checks.active.max_fails requires editing locked packages/caddy/src/config.ts — deferred
  • 6F analytics OOM / log unbounded growth: no analytics collector or log rotation changes — these require deeper investigation of the analytics pipeline

🤖 Generated with Claude Code

Darius Vorster and others added 13 commits April 22, 2026 11:55
…oxy transports (4A)

Adds applyDockerDns() wrapper that injects resolvers: ['127.0.0.11'] and
dial_timeout: '3s' into every reverse_proxy handler's transport block,
ensuring Caddy re-resolves container names on each dial instead of caching
the IP at config load time. Applied in bootstrap and all three buildCaddyRoute
call sites in routes.ts (syncRouteToCaddy, create, expose).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…yDockerDns

- apply-docker-dns.ts: use (route.handle ?? []).map(...) to prevent throw when handle is undefined
- bootstrap.ts: always wrap opts.buildRoute with applyDockerDns so Docker DNS resolvers are never skipped when a caller provides a custom build function

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ty check (4D)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends the existing Cloudflare tunnel deployment doc with a new section
covering how to survive ProxyOS container rebuilds: user-defined Docker
network, container-name upstreams in cloudflared config, removal of
healthcheck (distroless incompatibility), sidecar alternative, and a note
on how Task 4A's 127.0.0.11 resolver makes ProxyOS's own upstreams
rebuild-resilient when using container names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… is lost (4C)

Replace the generic enrollment error with a structured message that names
the missing identity file path and provides two concrete recovery paths
(volume restore or re-enrollment via PROXYOS_AGENT_TOKEN). Update the
instrumentation.node.ts catch block to surface the identity-lost message
directly rather than wrapping it in a generic failure log.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace :latest tags with ghcr.io/proxyos/proxyos:1.0.0 and
cloudflare/cloudflared:2025.4.1 in all three docs files, and add an
upgrade-path note in each file.
Verifies ProxyOS survives ProxyOS container recreation and upstream
container recreation, including DNS re-resolution detection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single-container architecture uses s6-overlay for intra-container
ordering: caddy starts first, proxyos polls the admin API before
exec-ing node, and bootstrapProxyOs() runs migrations then
waitForCaddyReady() before pushing routes. docker-compose depends_on
is not applicable — one service, no inter-container ordering needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… smoke test (4G)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y; remove dormant trustUpstreamHeaders UI toggle

6C: upgrade CaddyClient.doRequest() retry from linear (delay*attempt) to
exponential (delay*2^attempt, capped at 10s). Avoids thundering-herd on
brief Caddy admin outages.

6D: remove Trust Upstream Headers toggle from route edit and view panels.
The trustUpstreamHeaders field is stored in the DB and accepted by the API
but the Caddy config builder (locked config.ts) never consumes it, so the
toggle was purely cosmetic. Caddy's native trusted_proxies (buildTrustedProxies)
already handles the correct behaviour. Field stays in DB schema for forward
compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nection probe

Add routes.testUpstream tRPC procedure that probes an upstream address and
returns a typed error category:
  dns             ENOTFOUND / EAI_* — unknown hostname
  connection_refused  ECONNREFUSED — port closed / service down
  timeout         ETIMEDOUT / ECONNRESET — partition or firewall
  tls             cert errors / ERR_TLS_* — handshake failure
  http_5xx        upstream returned 5xx
  http_4xx        upstream returned 4xx (reachable, auth/path issue)
  slow            no response within 5s timeout
  ok              2xx/3xx, reachable

Add UpstreamProbeBadge component that maps each category to a
distinct badge tone and explanatory detail string.

Add Test / Retest button in the route detail Upstream section that
probes each configured upstream and shows a per-upstream result row.
Each result uses a distinct colour and label — not a generic "fetch failed".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-existing type errors

6F: add optional limit/offset params to routes.list (backward-compatible;
all existing callers continue to work without changes). Add routes.count
procedure for total row count. Routes page now uses PAGE_SIZE=50 with
Prev/Next controls and "1-50 of N routes" label. Page resets to 0 when
siteId changes.

Fix pre-existing TS2322 in apply-docker-dns.ts: map returns
Record<string,unknown> spread which loses the handler property from
CaddyHandler's perspective — add as unknown as CaddyHandler cast.

Fix pre-existing TS2532 in db/index.ts: integrityResult[0] is possibly
undefined per TS noUncheckedIndexedAccess — extract to integrityRow with
optional chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Document tested browser matrix (Chrome/Edge/Firefox/Safari latest 2),
tested common paths, known limitations (iOS Safari cookie over HTTP,
Firefox self-signed TLS warning), APIs used (no exotic ones), and
notes on proxy/VPN, non-standard port, and IPv6 support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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