Skip to content

Public directory: the crawler's public half, keyless, for nichedb.dev - #73

Merged
ralyodio merged 1 commit into
mainfrom
nichedb-public-export
Sep 13, 2026
Merged

ralyodio merged 1 commit into
mainfrom
nichedb-public-export

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Anthony: "from all our public data put it all in nichedb.dev too from outreachgraph.com crawler/scanner". nichedb ingests only by pulling, so this is the endpoint it pulls.

GET /api/v1/public/directory, keyless, above the session guard. Paged by since and an opaque cursor (keyset on updated, id), cache-control: public, max-age=300, sixty requests a minute per caller.

What is listed: a company or site by its domain (site when the crawler named the row after the domain alone); a person only when they publish their own profile: an OpenProfile.md they serve (published_url), or a profile and a home page that point at each other with rel=me, which the openprofile job now records as openprofiles.corroborated (migration 0036, applied at boot).

What is never listed: email, phone, location, bio, score, signal, campaign, note, workspace id, avatar. A person known from a scraped handle alone is not listed. Topics come from a company's industry and technologies, and only from the ## Topics line of a person's profile. The rule lives in apps/api/src/public-directory.ts and nowhere else.

Row shape: { id, kind, name, url, description, topics, country, openprofile, updated }.

Checks: 15 new tests (route, withholding, paging, cursor, limiter); full suite 1506 passing; tsc --noEmit clean in apps/api. The nichedb adapter that reads this is a separate PR in niche-db.

🤖 Generated with Claude Code

https://claude.ai/code/session_014cmNRtR2vL1p89dbVQ7FZJ

Anthony: "from all our public data put it all in nichedb.dev too from
outreachgraph.com crawler/scanner". nichedb ingests only by pulling, so
this is the endpoint it pulls: GET /api/v1/public/directory, above the
session guard, paged by since + cursor (keyset on updated, id), cached
five minutes, sixty requests a minute per caller.

The line it holds, in one query: a company or site by its domain; a
person only when they publish their own profile, meaning an
OpenProfile.md they serve (published_url) or a profile and a home page
that point at each other with rel=me, which the openprofile job now
records as openprofiles.corroborated (migration 0036). Never an email,
a phone, a location, a bio, a score, a signal, a campaign, a note or a
workspace id; a person known from a scraped handle alone is not listed.
Topics come from the industry and technologies on a company, and only
from the ## Topics line of a person's profile.

Tests: 15 for the route, the withholding rules, paging, the cursor and
the limiter; the full suite is 1506 passing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014cmNRtR2vL1p89dbVQ7FZJ
@ralyodio
ralyodio merged commit 5410dab into main Sep 13, 2026
4 checks passed
ralyodio added a commit that referenced this pull request Sep 13, 2026
Both blocks sit above the session guard and both stay. #73 took migration
0036, so the settings table is 0037.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S7yeJUHGxA4P5N74xnsRPQ
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