Skip to content

Job posts: postings by URL or keyword, and the real people behind each one - #107

Merged
ralyodio merged 3 commits into
mainfrom
worktree-job-urls
Oct 2, 2026
Merged

ralyodio merged 3 commits into
mainfrom
worktree-job-urls

Conversation

@ralyodio

@ralyodio ralyodio commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

What

A CRUD list of job postings (pasted URLs, or a ValueSERP keyword search across Workable / Greenhouse / Lever / Ashby) and, for each, the real people behind it: founders, engineering leaders and recruiters found on LinkedIn through ValueSERP, with the search result kept as evidence.

  • Read the posting from the board's keyless JSON API (title, company, website, salary, description). Agency postings ("on behalf of our client") are flagged and ranked differently.
  • Find people: site:linkedin.com/in "<Company>" (founder OR CEO OR CTO OR …). Results that don't name the company as itself are dropped ("Raydar Studios" ≠ "Raydar").
  • Verify on the company site: published addresses attach to the person whose name they are (david@raydar.xyz → David Phillips); names on the site set on_company_site. Once the site names anyone, a result whose own headline doesn't claim the company sinks (the music "Raydar" founder seen live).
  • Promote a contact into a campaign via intakeSocialPeople, setting current_company_id so find_email has a domain. Nothing sends; approval unchanged.

Surfaces: /api/v1/job-posts, og jobs …, MCP (list_job_posts, search_job_posts, add_job_posts, find_job_post_contacts, promote_job_post_contact, update_job_post), /jobs page (linked from Products), worker job resolve_job_post, migration 0046_job_posts (SQLite + PG). Docs: docs/job-posts.md.

Verified

  • bun run check: format, typecheck, 2132 tests green; apps/web tsc clean.
  • Live, locally against real ValueSERP + boards: the Raydar posting resolves to David Phillips (founder, david@raydar.xyz from raydar.xyz) first; keyword search "senior software engineer (remote)" found 30 postings, saved 3 (Pavago, GiveDirectly, Brigit), and the worker resolved each to named people.

To ship

VALUESERP_API_KEY must be set on the outreachgraph Railway service (a key exists in the profullstack-sharable-keys vault). Without it, URLs can still be added and read; keyword search is refused with that reason.

🤖 Generated with Claude Code

ralyodio and others added 3 commits October 2, 2026 03:34
…behind each one

Paste job posting URLs, or search Workable, Greenhouse, Lever and Ashby by
keyword ("senior software engineer (remote)") through ValueSERP. Each posting
is read from its board's keyless API, then ValueSERP searches LinkedIn for the
company's founders, engineering leaders and recruiters. A result is kept only
when it names the company as itself, and the company's own site is read for
addresses (attached to the person whose name they are) and names (a person the
site names is marked on_company_site, which is what tells one Raydar from
another). A contact joins a campaign through intakeSocialPeople with their
employer's domain set, so find_email can work; nothing is sent.

API /api/v1/job-posts, og jobs, six MCP tools, /jobs in the PWA, worker job
resolve_job_post, migration 0046. Uses the existing VALUESERP_API_KEY.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
app.env on dev2 is the runtime's only env and nothing wrote it but a human
over ssh. A secret a feature needs (VALUESERP_API_KEY for job posts) now ships
as a repo secret: the step upserts it into app.env, keeps a numbered backup
when anything changes, skips unset secrets, and passes values on stdin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d job-post credits

The public auth routes mail whatever address they are handed (the b1dz
pattern: a Tor-rotating script drove signup and forgot-password into ~130
strangers' inboxes), and the job-post routes spend ValueSERP credits. Both now
go through form-guard's sliding-window limiter:

- per IP: register 5/h, forgot-password 5/h, login 30/15 min
- per target address: forgot-password 3/h, so rotating IPs cannot keep
  mailing one stranger
- per user: verify-resend 5/h
- per workspace: job search 20/h, inline resolve 60/h, URL adds 30/h
- the quoted User-Agent the b1dz bot carried is refused (403)

Refusals are 429 with Retry-After, so the 4xx reaches nginx's log for
ThreatCrush. The caller is keyed on X-Real-IP, which dev2's nginx sets to
$remote_addr; the first X-Forwarded-For hop is client-controlled, so the
public directory's limiter now prefers X-Real-IP too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​profullstack/​form-guard@​0.1.17510010088100

View full report

@ralyodio
ralyodio merged commit da7671d into main Oct 2, 2026
5 of 6 checks passed
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