[object Object]

← back to Costa Rica

cycle 14 docs: YOLO_NOTES ledger + GO-LIVE processorFee prerequisite

9afa84bb738206669f99960d523ff78c48d91935 · 2026-09-23 22:44:57 -0700 · Steve

Records the money-math/invariant review: MAX_BOOKING_NIGHTS cap, the per-column
int4-overflow guard (Cody caught the fees column overflows before total), the
min_nights lockout guard, and the deferred processorFee/CHECK gap now landed as
a go-live prerequisite in docs/GO-LIVE.md §6.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TouFkmUGKHtwqpZwgReVic

Files touched

Diff

commit 9afa84bb738206669f99960d523ff78c48d91935
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Sep 23 22:44:57 2026 -0700

    cycle 14 docs: YOLO_NOTES ledger + GO-LIVE processorFee prerequisite
    
    Records the money-math/invariant review: MAX_BOOKING_NIGHTS cap, the per-column
    int4-overflow guard (Cody caught the fees column overflows before total), the
    min_nights lockout guard, and the deferred processorFee/CHECK gap now landed as
    a go-live prerequisite in docs/GO-LIVE.md §6.
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01TouFkmUGKHtwqpZwgReVic
---
 YOLO_NOTES.md   | 21 +++++++++++++++++++++
 docs/GO-LIVE.md |  4 +++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/YOLO_NOTES.md b/YOLO_NOTES.md
index c59a24d..e65e842 100644
--- a/YOLO_NOTES.md
+++ b/YOLO_NOTES.md
@@ -335,3 +335,24 @@ Canonical apply order now: `004_marketplace → 005_apple → 006_contacts → 0
 **Cost:** $0 (local tests + two focused Cody passes).
 
 **Backlog:** ALL live provider fetches now bounded; provider-agnostic timeout hardening is fully complete across every integration. Remaining: approval-enforcement decision on Steve's desk; provider-honored idempotency key (live-only); the per-event webhook-auto-reply try/catch follow-up; live-only sig-encoding verification. Next cycle: a fresh Cody-driven codebase audit for a NEW issue class (the fetch-timeout + async-error + fail-closed classes are now saturated), or deeper money-invariant / SQL-correctness review.
+
+## /yoloforever CYCLE 14 (2026-09-23, yf-costa) — money-math / invariant review (new class)
+
+**Pivoted** off the saturated fetch/async/fail-closed classes to money-math + invariants + IDOR.
+
+**IDOR: clean** — every booking/payment/thread read + cancel is scoped by `traveler_id = req.user.sub` (GET /bookings, GET /bookings/:code, cancel, GET /payments/:id, threads). No cross-user access. (The one authz gap — host-claim approval — was already found + gated in cycle 9.)
+
+**Money-math finds + fixes (routes/app.js POST /bookings):** the bookings money columns are all INTEGER (int4, max 2,147,483,647) with NO cap on the date range or computed amounts.
+1. **Unbounded date range** → `subtotal = base_price * n` overflows int4 (a 500), and even below overflow lets a client create a multi-decade booking that **squats the listing's availability** (the overlap guard then blocks every real booking for years). Fix: `MAX_BOOKING_NIGHTS` cap (default 365, env-configurable) → clean 400 before the overlap query.
+2. **Per-column overflow guard** on ALL stored amounts (subtotal, fees, platform_fee, total, host_payout).
+3. **min_nights > MAX_BOOKING_NIGHTS** self-lockout (a listing that can never be booked) → rejected at /host/listings write time.
+
+**Cody gate — caught my first attempt guarded the WRONG column, proven by executing computeSplit:** `fees = cleaningFee + platformFee` reaches ~2x total, so a huge host-set `cleaning_fee` (uncapped by any DB CHECK) overflows the `fees` int4 column at the **DEFAULT 10% fee** while `total` is still under int4 max — a `total`-only guard would still 500 the INSERT. Verified repro: `cleaningFee=1_999_999_000` → `total=1,999,999,001` (under) but `fees=2,199,998,900` (over). Fixed to guard EVERY stored column. Cody also required the **negative test** (TK-11431 doctrine — a check ships with a test proving it goes red on the injected fault; the prior tests only drove subtotal, never fees). Cody cleared: slot branch funnels through the same guard; `Number.isSafeInteger` is needed (a huge host-set `max_guests` can push subtotal past `MAX_SAFE_INTEGER`).
+
+**Deferred (documented, dead code today):** `computeSplit` supports `processorFeeBps>0` and subtracts processorFee from hostPayout, but `bookings` has no `processor_fee` column and the CHECK is `total = platform_fee + host_payout` — enabling a processor fee would 500 every booking. The route never passes it (inert). Recorded as a go-live prerequisite in `docs/GO-LIVE.md §6` (add the column + fix the CHECK before enabling one).
+
+**Tests (+4, suite 181 → 185):** over-long stay → 400 (before overlap query); subtotal-overflow → 400; **FEES-overflow with total-under-int4 → 400** (the negative test for the column my first guard missed); min_nights>cap → 400.
+
+**Cost:** $0 (local tests + one Cody pass — which executed computeSplit to prove the guard checked the wrong column).
+
+**Backlog:** approval-enforcement decision on Steve's desk; provider-honored idempotency key + sig-encoding (live-only); per-event webhook-auto-reply try/catch; processorFee schema prerequisite (documented). Next cycle: SQL-correctness (missing hot-path indexes, admin-stats JOIN miscounts) or another fresh Cody-driven audit.
diff --git a/docs/GO-LIVE.md b/docs/GO-LIVE.md
index 28fc821..dbf9147 100644
--- a/docs/GO-LIVE.md
+++ b/docs/GO-LIVE.md
@@ -64,7 +64,9 @@ These closed in the /yoloforever cycles; they need no creds and are already live
 4. **Verify with a $1 real charge + refund** before opening bookings.
 
 ## 6. Verify money math
-`total = platform_fee + host_payout` (10% platform fee; `fees` is display-only). Enforced by DB CHECK `bookings_total_reconciles` + `test/money.test.js`.
+`total = platform_fee + host_payout` (10% platform fee; `fees` is display-only). Enforced by DB CHECK `bookings_total_reconciles` + `test/money.test.js`. Booking amounts are capped: stays > `MAX_BOOKING_NIGHTS` (default 365) and any amount that would overflow the INTEGER (int4) money columns are rejected with a 400 at `POST /bookings` (cycle-14 guards).
+
+**PREREQUISITE before enabling a processor fee (`processorFeeBps > 0`):** `lib/money.js computeSplit` supports a processor fee and subtracts it from `hostPayout`, but the `bookings` table has NO `processor_fee` column and the CHECK is `total = platform_fee + host_payout` — so `platform_fee + host_payout = total - processorFee ≠ total` would 500 EVERY booking. The `/bookings` route never passes `processorFeeBps` today (inert), but before turning one on you MUST: add a `processor_fee` INTEGER column to `bookings`, update `bookings_total_reconciles` to `total = platform_fee + host_payout + processor_fee`, and have the route pass + store `split.processorFee`. (Cody gate, cycle 14.)
 
 ## 7. App Store
 ASC app 6799240433; build #13 on TestFlight. Remaining: attach build + `store/listing.md` desc + 5 screenshots + export-compliance in the ASC console, then Submit for Review (your Apple login).

← faf2ab6 costa-rica: bound booking money amounts against int4 overflo  ·  back to Costa Rica  ·  auto-data-snapshot: 2026-09-23T23:13:08 (1 data files) — scr 3de6348 →