← back to Costa Rica
cycle 11 docs: YOLO_NOTES ledger — systemic async-error hardening, real-router proof, 11-cycle summary
47088ae948c0c5939d27f318df3c1b8f5fd3b501 · 2026-09-23 21:10:14 -0700 · Steve
Records the harden()/global-error-handler fix closing the request-hang gap,
Cody's required real-router test, the free double-next() documentation, and
the honest webhooks-is-a-no-op note. Summarizes 11 cycles of provider-agnostic
hardening now complete.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TouFkmUGKHtwqpZwgReVic
Files touched
Diff
commit 47088ae948c0c5939d27f318df3c1b8f5fd3b501
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Sep 23 21:10:14 2026 -0700
cycle 11 docs: YOLO_NOTES ledger — systemic async-error hardening, real-router proof, 11-cycle summary
Records the harden()/global-error-handler fix closing the request-hang gap,
Cody's required real-router test, the free double-next() documentation, and
the honest webhooks-is-a-no-op note. Summarizes 11 cycles of provider-agnostic
hardening now complete.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TouFkmUGKHtwqpZwgReVic
---
YOLO_NOTES.md | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/YOLO_NOTES.md b/YOLO_NOTES.md
index a5bb718..c4facaf 100644
--- a/YOLO_NOTES.md
+++ b/YOLO_NOTES.md
@@ -277,3 +277,23 @@ Canonical apply order now: `004_marketplace → 005_apple → 006_contacts → 0
**Cost:** $0 (local tests + one Cody pass — Cody found 2 holes inside my own diff's blast radius that I'd have shipped as "done").
**Backlog / NEXT CYCLE (scheduled):** the SYSTEMIC fix — wrap all ~23 async routes in an asyncHandler that forwards to a global Express error handler, so an uncaught throw returns a clean 500 AND the request doesn't hang (the unhandledRejection net keeps the server up but the offending request still never responds). This is a review-worthy, Cody-gated change of its own. Plus: the approval-enforcement decision still on Steve's desk; provider-honored idempotency key still live-only.
+
+## /yoloforever CYCLE 11 (2026-09-23, yf-costa) — the systemic async-error fix (closes the request-hang gap)
+
+**Shipped the change scheduled at the end of cycle 10.** Express 4 doesn't forward a rejected promise to error middleware — cycle 10's `process.on('unhandledRejection')` net stopped an uncaught throw from crashing the server; it did NOT stop the offending request from hanging forever (no response ever sent). This closes that.
+
+**New `lib/async-harden.js`:** `harden(router)` wraps every ordinary route handler in a router's stack so a thrown/rejected handler calls `next(err)`. A handler with its own try/catch never rejects, so it's an unaffected pass-through. Idempotent.
+
+**Wired into `server.js`:** all 5 sub-router mounts (webhooks, `/api/app`, `/api/admin`, `/api/build`, `/api/logo-agent`) go through `harden()`; a global 4-arg error handler mounted last, reusing the existing `serverError()` pattern (generic client message, full detail logged). The ~20 inline server.js routes already had their own try/catch — untouched, that gap didn't exist there.
+
+**Cody gate — clears the bar, one required follow-up + one free fix, both done:**
+- **REQUIRED:** the first 8 tests proved the mechanism against a throwaway router built inline in the test — never against the real `routes/app.js`. Cody: *"'verified against the actual repo' was a claim the test suite doesn't back up."* Added `async-harden-real-router.test.js` — mounts the ACTUAL router through the REAL `harden()`, drives the genuinely-uncaught `GET /listings/:slug` (verified via direct read: no try/catch) through a rejecting `pool.query`, proves the full real chain resolves to a clean 500 in <5s (not a hang).
+- **FREE:** documented (inert today, checked every handler across all 5 routers) the latent next()-then-later-throw double-`next()` limitation shared with upstream `express-async-handler`.
+- **NOTED, not a defect:** `harden(webhooks router)` is a no-op — its handlers already self-catch. The fix's value is entirely in app/admin/build/logo-agent.
+- **Bonus (Cody found, pre-existing):** `server.js`'s `/sitemap.xml` `next(err)` call now lands on the new clean handler instead of Express's default (which would've leaked a stack trace in dev).
+
+**Tests (+10, suite 160 → 170):** `async-harden.test.js` (8: mechanism + E2E) + `async-harden-real-router.test.js` (2: the required real-router proof).
+
+**Cost:** $0 (local tests + one Cody pass — hand-traced the real chain, then required the test suite actually prove what was claimed).
+
+**Backlog:** approval-enforcement decision still on Steve's desk (`REQUIRE_HOST_APPROVAL` flag pre-written). Provider-honored idempotency key still live-only. Safe local reversible work across 11 cycles has now covered: full payment-provider timeout/idempotency hardening, admin.js + host-listing auth/race audit, Plaid bank-linking hardening, and the systemic async-error fix. Next cycle: continue the coverage sweep (`routes/webhooks.js` full signature/replay audit, `routes/build.js`, `lib/apple.js`) or pivot to a fresh area if those are clean.
← 16c0a2b costa-rica: wrap all sub-router async routes in an error-for
·
back to Costa Rica
·
costa-rica: webhook idempotency-marker release on failure + ce0a607 →