DEV Community

Isaiah Kim
Isaiah Kim

Posted on

The early return that shipped a false all-clear

I typed the word "construction" into my own lookup tool and it answered:

All 200 qualifying contracts under null have an approved Affidavit of Wages Paid on file.

Two things wrong in one sentence, and the more interesting one is that nothing had been checked against the affidavit file at all. The route had returned before it got there.

The product is HeldBack, a free retainage blocker check I'm building under Kynth. You give it a company name or a 9-digit UBI, and it reads two of Washington's published Socrata files live: the Statements of Intent a contractor files before a public works job, and the Affidavits of Wages Paid filed after. A job with an intent and no matching approved affidavit is a job whose retainage, capped at 5% under RCW 60.28.011, is likely still sitting with the awarding agency.

The floors are most of the logic

The naive version of this is a set difference: intents minus affidavits. That version is wrong in a way that destroys the product's credibility on first contact, because a job that started six months ago has no affidavit for the boring reason that the work isn't finished. Report that as frozen money and you've told a contractor something they know to be false about a job they remember clearly.

So src/app/api/lookup/route.ts filters before it compares:

const MIN_CONTRACT = 5000;
const MIN_AGE_MONTHS = 24;

const priced = intents.filter(
  (r) => Number(r.cntrct_amt) >= MIN_CONTRACT && !tooRecentOrUndated(r.expected_start_dt),
);
Enter fullscreen mode Exit fullscreen mode

At or under $5,000 the affidavit is folded into the combined intent form and never appears separately, so those rows are false positives by construction. Undated rows can't be aged at all, so tooRecentOrUndated returns true for them and they drop out too.

Both floors are correct. The bug was what happens when they eat everything.

The early return that shipped a false all-clear — code

The return that skipped the comparison

if (priced.length === 0) {
  return NextResponse.json({ term, company: null, rows: [], searched: intents.length });
}
Enter fullscreen mode Exit fullscreen mode

searched is the number the UI prints back. Everywhere else in the file it means "contracts we actually compared against the affidavit file". Here it meant "rows the first query returned", because at the moment I wrote the line those felt like the same quantity.

They're the same quantity right up until a search term is generic. The intents query is capped at $limit: '200', and a common word matches far more than 200 filings across the whole state, none of them one company. Nearly all of them fail the $5,000 floor or the 24-month floor. priced comes back empty, the route returns here, and the client is handed searched: 200 with an empty rows array. The panel reads that as 200 contracts checked and zero blocked.

The null in the sentence has the same root. Company name is resolved as priced[0]?.companyname, and on this path priced is empty.

The fix splits the count into two:

if (priced.length === 0) {
  /* `searched` IS THE QUALIFYING COUNT, NOT THE FILING COUNT, and this line used to return
   * `intents.length` for it. [...] `found` is the honest count for this case: filings
   * located, none of them judgeable. */
  return {
    payload: {
      term,
      company: intents[0]?.companyname ?? null,
      rows: [],
      searched: 0,
      found: intents.length,
      cleared: 0,
      totalHeld: 0,
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

searched: 0 is now literally true. Nothing was searched against the affidavit file.

The early return that shipped a false all-clear — architecture

Two branches for three outcomes

The other half was in src/components/HeroLookup.tsx, which had an empty state and a clear state and nothing else. Any result with rows.length === 0 fell into "nothing appears to be blocked". There was no way to express "we found filings and none of them can be judged yet", so that case borrowed the reassuring one.

{(result.found ?? 0) === 0
  ? 'No public works contracts found under that name.'
  : result.searched === 0
    ? 'Nothing here can be judged yet.'
    : 'Nothing appears to be blocked.'}
Enter fullscreen mode Exit fullscreen mode

The middle branch explains itself in the body copy: every match is under $5,000 or started inside the last 24 months, a job that recent has no affidavit because the work is not finished, and search the exact legal entity name or the UBI to narrow it. That last part matters more than the correction does. The person who typed a generic term wanted an answer about a company, and now the panel tells them how to get one.

heldback — live

The same short-circuit, one component away

The wait panel streams NDJSON and fires a stage as each of the route's four real pieces of work finishes, with the measured elapsed printed per stage. On a real company that reads 587ms, 587ms, 756ms, 757ms, and the third line says "53 of 74 have an approved Affidavit on file". Two of the four stages are live network calls, which is where the seconds go.

The orb at the head of that panel spun forever on the short-circuit path, because it asked whether all four stages were done. On an early return two of them never fire, so the answer is permanently no, and the orb kept spinning next to a finished answer.

const running = steps.some((s) => s.state === "running");
const phase = idle ? "idle" : failed ? "failed" : running ? "running" : "done";
Enter fullscreen mode Exit fullscreen mode

What the orb reports is whether anything is still happening, not whether every stage reported.

Neither of these turned up in reading. I found both by typing a word into the live thing and looking at the sentence it gave back, which is also the exact sentence a first-time visitor would be most likely to see, since a generic term is what you type before you know what the tool wants.

Top comments (0)