Skip to content

fix(leads): three failures that only showed up against real businesses - #155

Merged
ralyodio merged 1 commit into
masterfrom
fix/prod-regressions
Jul 28, 2026
Merged

ralyodio merged 1 commit into
masterfrom
fix/prod-regressions

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

All three were invisible until campaigns ran against companies nobody would have picked as a test case. Found by reading the production run log:

builtinla.com: new row violates check constraint
               "outreach_prospects_contact_source_check"
4cornerresources.com: states "4", which the campaign never mentions
summary: 0 discovered … 11 people, credits_spent: 0

1. A guessed address made the prospect unsaveable

CHECK (contact_source = ANY (ARRAY['mailto','text','manual']))

Those were the only ways to find an address when the table was written. A search fallback and a guessed role address have been added since — neither was storable. The failure was total, not cosmetic: the whole row was rejected, so a business was discovered, crawled, searched for, then dropped on the floor.

'guess' is worth keeping distinguishable rather than folding into 'text' — a constructed address bounces far more often, and bounces are charged to the sender's reputation.

2. You couldn't write to a company called "4 Corner Resources"

The guard checks every number in a draft against everything the operator wrote — and the operator cannot write the recipient's name, because it differs per prospect. So naming the company read as inventing a number.

Naming who you're writing to isn't a claim about them. The recipient's host, domain and self-description now ground the check. An invented credential is still caught — pinned by a test, since that's the guard's entire job:

"We have 30 years of experience and 500 clients."  → still rejected
"I came across 4 Corner Resources"                 → now allowed

3. Eleven CTOs, billed as nothing

!result.discovered && !result.researched && !result.drafted && !result.sent

Every kind of output except the one a people-directory actually produces. Rendering, paginating and parsing a directory is the expensive part of the run — and it was being refunded in full, every time.

Checks

  • tsc --noEmit clean · 1,042 tests pass (6 new) · build compiles
  • Constraint migration applied to prod

🤖 Generated with Claude Code

Every one of these was invisible until campaigns ran against companies
nobody had picked as a test case.

A prospect whose address had to be guessed could not be saved at all.
contact_source was constrained to the three ways an address could be
found when the table was written; a search fallback and a guessed role
address have been added since, and neither was storable. The failure was
total rather than cosmetic — the whole row was rejected, so a business was
discovered, crawled, searched for and then dropped with a constraint error
in the run log. builtinla.com is in that log twice.

The grounding guard rejected every draft to 4 Corner Resources for
stating "4", which the campaign had indeed never mentioned. The guard
checks numbers in the draft against everything the operator wrote, and
the operator cannot write the recipient's name — it differs per prospect.
Naming who you are writing to is not a claim about them, so the
recipient's own host, domain and self-description now ground the check.
An invented credential is still caught; that is the whole point of it.

And a run that named eleven CTOs was refunded as though it had produced
nothing. The produced-something test listed prospects, research, drafts
and sends — every kind of output except the one a people-directory
actually yields. Rendering, paginating and parsing a directory is the
expensive part of the run, and it was being given away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit 53cceba into master Jul 28, 2026
8 checks passed
@ralyodio
ralyodio deleted the fix/prod-regressions branch July 28, 2026 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant