feat(stability): Phase 2 — eliminate silent failures - #1
Open
dariusvorster wants to merge 16 commits into
Open
Conversation
- New package @proxyos/logger: createLogger(subsystem) returns pino logger
with pretty-print in dev, JSON in production
- Replaced all console.log/warn/error in packages/caddy/src/bootstrap.ts,
packages/api/src/{auth,crypto,loader,bootstrap}.ts,
packages/api/src/routers/{routes,automation}.ts,
packages/api/src/automation/{drift-detector,network-join}.ts,
packages/api/src/security/exit-node-blocker.ts,
packages/alerts/src/evaluator.ts,
apps/web/src/instrumentation.node.ts
- Locked files (trpc.ts, users.ts, config.ts, verify.ts, regenerate-routes.ts) untouched
- 59 caddy vitest tests still pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move pino-pretty from dependencies to devDependencies in packages/logger - Update createLogger to use transport:undefined in production so pino-pretty is never resolved at runtime - Add @proxyos/logger workspace dep to packages/db Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hes (2A)
Move pino-pretty from devDependencies to dependencies so staging/dev
containers that skip devDep installs don't crash. Pass { err } as the
first arg in all four bootstrap.ts catch blocks so pino serialises the
error stack in structured output.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- docker-discovery: add HTTP status check + descriptive errors to fetchContainers; log (not swallow) sync failures via pino - network-join: split dockerRequest into dockerRequestOnce + retry wrapper with 3 attempts at 1s/2s/4s for transient errors (ECONNRESET, ETIMEDOUT, etc); permanent 404/403 errors skip retry - ddns.ts + ddns-updater.ts: add response.ok checks on Cloudflare zones and records API calls before .json(); wrap fetch with .catch for network failures - routes.ts: wrap all three insert(routes) sites with UNIQUE constraint catch → TRPCError CONFLICT Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…perations (2C) - Export Result<T, E = Error> from @proxyos/types - detectPublicIp (ddns-updater): was Promise<string|null>, now Result<string,Error> — caller reads ipResult.ok - fetchFromLockBox (lockboxos): was Promise<string|null>, now Result<string,Error> — caller in integrations.ts updated - updateCloudflare (routers/ddns): was Promise<string|null> (inverted: string=error, null=ok), now Result<void,Error> — triggerUpdate procedure updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- routes.ts: add messages to bare NOT_FOUND throws (get, update); wrap bare `throw err` re-throws after DB insert as INTERNAL_SERVER_ERROR with [db] prefix - trafficReplay.ts: add messages to NOT_FOUND throws (record, replay) - ddns.ts: add messages to NOT_FOUND throws (update, triggerUpdate); convert bare throw new Error in updateCloudflare .catch() chains to TRPCError via toCaddyFetchError helper - caddy.ts: convert throw new Error(status) in rootCA to TRPCError with descriptive [caddy] message - integrations.ts: convert throw new Error in testLockBoxRef to NOT_FOUND / BAD_REQUEST TRPCError; add TRPCError import - organizations.ts: convert throw new Error in get to NOT_FOUND TRPCError; add TRPCError import - sites.ts: convert throw new Error in get to NOT_FOUND TRPCError; add TRPCError import - templates.ts: convert throw new Error for built-in delete guard to CONFLICT TRPCError with template ID; add TRPCError import - automation.ts: convert throw new Error in toggleComposeWatcher to NOT_FOUND TRPCError; add TRPCError import Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Every useMutation in the web app now has onError: handleError wired from useErrorHandler, ensuring mutation errors surface to the user rather than failing silently. Covers all routes, settings, security, scanner, shell sidebar, and TOTP sub-components. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add in-memory ring buffer (1000 entries) to @proxyos/logger with getRecentLogs/clearLogs; pino.multistream feeds both stdout and the buffer - Add system.getLogs adminProcedure filtering by subsystem and level - Add Pino logs tab to /logs page with 5s polling, level/subsystem filters, and Download button - Add GET /api/logs/download route returning NDJSON attachment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add checkDatabase/checkCaddy/checkDocker/checkAuth/checkDisk helpers to packages/api/src/routers/system.ts - Add getDetailedHealth adminProcedure to systemRouter - Add ./health-checks subpath export to packages/api/package.json - Create apps/web/src/app/api/health/detailed/route.ts (admin-only REST wrapper) - Create apps/web/src/app/system-health/page.tsx (30s auto-refresh UI) - Add System health link to Tools nav in shell.tsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- /api/auth/diagnose returns structured {authenticated, reason, action, details} alongside legacy status/hint fields for backward compat
- Login page shows "Not sure why? Run diagnosis" link on credential failures; expands inline panel with hint from diagnose endpoint
- useErrorHandler UNAUTHORIZED message now suggests logging out and back in
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
console.*replaced across packagesResult<T, E>discriminated union in@proxyos/types; applied to DDNS/LockBox operationsTRPCErrorwith correct codes (NOT_FOUND,CONFLICT,PRECONDITION_FAILED, etc.) and actionable messagesuseErrorHandlerhook; everyuseMutationin the web app hasonError/api/health/detailed+ System Health UI page (30s refresh, per-component status)/api/auth/diagnoseendpoint + login page diagnosis link + improved UNAUTHORIZED messageTest Plan
cd packages/caddy && npx vitest run)catch {}patterns without comments in packages/api and packages/caddyuseMutationcalls haveonError(grep useMutation apps/web/src | grep -v onErrorreturns nothing)/api/health/detailedreturns component-level JSON when authenticated as admin/logs(Pino logs tab present)/system-health/logsrequires admin auth (401 if not authenticated)🤖 Generated with Claude Code