Skip to content

openroles 0.2.0: eleven more systems, careers sites, workplace - #9

Merged
aranculleton merged 3 commits into
mainfrom
v0-2-0-complete-reader
Oct 19, 2026
Merged

aranculleton merged 3 commits into
mainfrom
v0-2-0-complete-reader

Conversation

@aranculleton

@aranculleton aranculleton commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

What changed

openroles 0.2.0. Eleven more systems read into the same Job shape, and one reader for careers sites with no job API.

  • New readers: Workable, Teamtailor, Personio, Recruitee, Rippling, JazzHR, Gem, Polymer, Manatal (each from the vendor's documented public endpoint, quoted in its docstring), Homerun and ClearCompany (the endpoints their own careers pages call, read only where robots.txt allows).
  • careersite: any careers site that publishes its jobs for search engines, read from its sitemap and each job page's schema.org JobPosting. Reaches iCIMS and Eightfold sites, among others. robots.txt must allow it, Crawl-delay is kept, at most 40 pages a call.
  • openroles.configure(): an application embedding openroles sets its own User-Agent and the robots.txt agents it answers to (never fewer than * and openroles), instead of assigning to private module state. openroles.robots_allows() is public.
  • openroles.hosts() / openroles hosts: the hosts reading a board calls, for a network allowlist, with no request for a board given as ats:token. Every reader has a hosts(token).
  • Job.workplace: remote, hybrid or onsite, from the board's own field.
  • Politeness: Content-Signal: ai-input=no honoured; redirects checked against the new host's robots.txt (at most five); ETag on a repeat GET; XML declaring a DTD or entities is refused.
  • Releases publish from a version tag (PyPI, GitHub release from the CHANGELOG, MCP Registry), after checking the tag against __version__, server.json and the CHANGELOG.
  • README "Supported systems", "In your own application" and a new "Not supported, and why" table; llms.txt, server.json, pyproject.toml and the version at 0.2.0. Two docstring examples replaced with invented ones.

How it was checked

Every reader has invented fixtures and tests (fields, a missing board, robots.txt saying no): 141 tests. Each new reader except Workable was run once against a real board on the vendor's own careers site, without keeping its data. Workable was not run live: its hosts answered 429 on every attempt, including today's, so that reader is built from Workable's documentation alone and the README says so.

  • pytest and ruff check . pass (CI on 3.9 to 3.13; the wheel builds with all 16 readers)
  • No runtime dependency added; works on Python 3.9
  • robots.txt and the request limits are respected

🤖 Generated with Claude Code

https://claude.ai/code/session_01LrnN33G65kWMuv8y7xpUk4

New readers, each in the same Job shape: Workable, Teamtailor, Personio,
Recruitee, Rippling, JazzHR, Gem, Polymer, Manatal, Homerun and
ClearCompany, and careersite, which reads any careers site's sitemap and
the schema.org JobPosting on each job page (iCIMS and Eightfold sites
among them). Each reader quotes the vendor's own words for its endpoint.
Where the endpoint is documented as public, only an explicit Disallow
stops a read; elsewhere robots.txt must be readable and allow it.

Job.workplace says remote, hybrid or onsite from the board's own field.
Politeness: Content-Signal ai-input=no is honoured, redirects are
checked against the new host's robots.txt, a GET read twice sends its
ETag, and XML declaring a DTD or entities is never parsed.

Releases now publish from a version tag: PyPI, the GitHub release from
the CHANGELOG entry, and the MCP Registry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LrnN33G65kWMuv8y7xpUk4
Every reader names its hosts, so a network allowlist (a firewall, a cloud
sandbox's allowed domains) can be written from the boards themselves
rather than from a copied list. Nothing is fetched for a board given as
ats:token. Also `openroles hosts <target>...` on the command line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LrnN33G65kWMuv8y7xpUk4
An application sets its own User-Agent and the robots.txt agents it
answers to through a public call, instead of assigning to the private
_http module. Agents are only ever added: "*" and "openroles" are always
kept. robots_allows() is public for anything else the application
fetches. The Workday path example and the country example are invented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LrnN33G65kWMuv8y7xpUk4
@aranculleton
aranculleton merged commit d630fec into main Oct 19, 2026
5 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.

2 participants