Rivvl · report pipeline

It was not one PR. We stacked four faults and blamed the last merge.

Reports worked around PR 61. Then Free compares looked paid, the navbar 500'd, Inngest printed invalid status code: 500 on item_kind=start, and progress sat on Queued. Those are four different bugs. The last four GitHub PRs barely touch the worker. The damage is older, and some of it never had a PR number.

Same week, four products

If you treat this as one regression you will keep "fixing" the wrong file

What you sawWhat it actually wasRoot
Free card selected, banner says YOUR CURRENT PLAN: STANDARD Compare UI still advertised the account tier. Profile load overwrote the click. Leftover bundle credits still spent on a $0 run. PR 62 incomplete
column profiles.admin_role does not exist on GET /api/admin/access Staff lookup selects is_admin, admin_role. PostgREST 500s until migration v19. The home worker calls the same lookup at the start of runHomeReportGeneration, so the job dies before listing fetch. b7395aa, not a PR
Inngest invalid status code: 500 on start, listings still scraping The function ran the whole scrape in one HTTP request. Redfin failover Firecrawl to Jina to Scrape.do takes minutes. Inngest times out start, retries, 500s. The first run is still alive. Latent since Aug 10
Progress stuck on Queued / waiting for the worker to claim PR 56 made 429 a dead end, failed young rows with no event id, and left claimed starting jobs alone for 20 minutes. Later reconnect attached the UI to those zombies. PR 56

A healthy generate this week, bc525b08-…, proved the scrape path still works. Listings completed, geocode, risk profiles, Free gate isFullReport: false, AI ~45s, save. The FEMA/EPA stacks are failovers. Two POST compare 429 lines in that log are React Strict Mode remounts, not a dead queue.

GitHub vs what actually landed

The last four PRs are the wrong suspects

"Working 3 to 4 PRs back" lands on PR 61, merged 25 Aug, dark-mode CSS on home report pages. It did not touch Inngest, compare plan resolution, or queue recovery. Everything after that on GitHub is naming, lint, knowledge tracking, and an incomplete Free honor.

ChangeWhenPipeline?What we actually did
PR 56 Fix Inngest report dispatch recovery 21 Aug Yes resolveGenerationStart throws on any 429. getQueuedGenerationAction immediately fails if inngest_event_id is null. Recovery only looks at queued. Claimed starting waits 20 minutes. Functions still did not pass step.run.
PRs 57 / 58 / 59 21 Aug No Upgrade-claim, revert, reopen. Billing circus. Not the worker.
PR 60 SEO 21 Aug No Metadata and ticket copy. Touched Inngest files only for ticket references.
b7395aa Refactor admin role management 25 Aug 13:12 IST Yes Pankaj commit on main between #60 and #61. No GitHub PR. Selects admin_role. Home worker and navbar share that lookup. v19 was not applied everywhere. Throw became Inngest 500 on start.
PR 61 Dark mode 25 Aug No CSS and report page colors. Last "it worked" merge. RBAC was already on main. If v19 was applied locally, reports still ran.
PR 62 Knowledge + honor free + report chrome 27 Aug Plan UI only Did not touch Inngest functions or listing scrape. Stopped admin default to home_pro10 when planType was omitted. Left the banner on account tier, profile load clobbering Free, and shouldUseBundleCredits spending whenever credits > 0.
PR 63 Fixed rivvl naming 27 Aug No Copy. Merge from bhudev.
PR 64 Next.js lint 27 Aug No Deleted unused symbols in requireAdmin and a report page. Not the worker.
PR 66 Coverage + recovery, open 27 Aug Fixing the pile Chat coverage plus commit 3c17e09: fail-closed admin lookup, reconnect 429 with generation id, do not fail young rows with no event id, redispatch dead starting after 30s, wire step.run, concurrency 1 per generation, keep explicit Free off leftover credits.

How we kept making it louder

Each "fix" treated a symptom as the whole bug

  1. 10 Aug. Credit-settlement work added stepRun hooks inside processHomeReportGeneration. The Inngest wrappers kept calling the processor with no step. Fine while Firecrawl was fast.
  2. 20 Aug. The earlier briefing already named the 429-as-success path. Progress treated a conflict as a new run and sat on a queued orphan for 20 minutes.
  3. 21 Aug. PR 56 flipped that. 429 became a hard error. Missing event id failed the row immediately, racing the original dispatch. starting was ignored. The worker still ran as one HTTP request.
  4. 25 Aug. RBAC landed on main as a naked commit. Code required admin_role. Migration v19 was a separate human step. Until it ran, staff lookup 500'd. The worker throws before scrape. Inngest retries. You see start 500 while nothing is "stuck" in the listing code.
  5. 27 Aug. PR 62 stuffed a Free-plan API change into a knowledge PR and stopped at the resolver. The banner still lied. Credits still drained. Same week the worker 500s showed up, so 62 ate the blame.
  6. Same week, this chat. Reconnecting 429 onto a claimed-then-dead starting row made the hang visible. Redispatching live starting after 30s could start a second scrape on a Redfin job that was still going. That is why it kept "breaking again" after each patch.

The Inngest hole was always there

Before 3c17e09 the function was async ({ event }) => processHomeReportGeneration({ generationId, userId }). No step.run. One request owns listing fetch, geocode, risk, AI, save. Inngest's start timeout is shorter than a Redfin failover. Retries look like 500s. The first invocation keeps writing listings. That is the log you already saw: dca11265-… then bc525b08-… scraping while start failed.

v19 is not optional for this code

loadProfileStaffFields selects is_admin, admin_role. isAdminForUserId runs at the top of the home runner. A missing column is a PostgREST 500, not a false. Until the retry-on-missing-column path in PR 66, that throw killed the job. Navbar access used the same select, which is why the admin 500 and the worker 500 arrived together.

On PR 66, not merged

What 3c17e09 already changed

FaultPatch on 66Still true
Free banner / leftover credits userChosePlan, banner from selection, shouldUseBundleCredits skips explicit free Needs a click-through on homes and vehicles compare, not only unit tests
Missing admin_role Retry is_admin only. isAdminForUserId catch returns false. Fail closed on privileges, not the job v19 should still be applied. The retry is a belt, not a substitute for the column
Start timeout / duplicate scrape step.run wired. Concurrency 1 per event.data.generationId A Redfin listing can still take minutes. That is expected. Start 500s should stop being the default
Sticky queued / 429 dead-end Reconnect 429 when it carries generationId. Do not fail young rows with no event id. Redispatch dead starting after 30s. Leave live fetching / analysis alone. Dev skips compare rate limit Do not redispatch a live scrape. Status must use the actual row status so stuck starting can clear

PR 66 is still titled as chat coverage. The recovery commit is on that head. Updating the PR is a push to Absterrg0:main. It is not a merge to upstream/main.