From 5c189bc13dc702ba69fb23f6dcaf85a210114ca0 Mon Sep 17 00:00:00 2001 From: Nithin Date: Sun, 30 Aug 2026 05:15:46 -0400 Subject: [PATCH] fix(workday): accept canonical public job links --- src/fortune_intel/connectors/workday.py | 23 +++++++++++++++-- tests/test_workday_connector.py | 34 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/fortune_intel/connectors/workday.py b/src/fortune_intel/connectors/workday.py index c0370c9..685310b 100644 --- a/src/fortune_intel/connectors/workday.py +++ b/src/fortune_intel/connectors/workday.py @@ -389,13 +389,32 @@ def _public_job_url(self, value: object) -> str: segment in {".", ".."} or "/" in segment or "\\" in segment for segment in decoded_segments ) + external_host = (parsed.hostname or "").casefold().rstrip(".") + # Workday boards can serve their anonymous CXS API from a tenant + # ``*.myworkdayjobs.com`` host while returning the applicant-facing URL + # from Workday's canonical ``wdN.myworkdaysite.com`` host. It is still + # the same board only when the URL repeats the exact tenant and site. + canonical_public_alias = _MYWORKDAYSITE_HOST_PATTERN.fullmatch( + external_host + ) is not None and parsed.path.casefold().startswith( + ( + f"/recruiting/{quote(self.workday.tenant, safe='')}/" + f"{quote(self.workday.site, safe='')}/job/" + ).casefold() + ) + allowed_host = external_host == self.workday.host or canonical_public_alias if ( parsed.scheme != "https" - or (parsed.hostname or "").casefold().rstrip(".") != self.workday.host + or not allowed_host or parsed.username is not None or parsed.password is not None or parsed.port not in {None, 443} - or not parsed.path.startswith(self.workday.public_job_path_prefix) + or ( + not canonical_public_alias + and not parsed.path.casefold().startswith( + self.workday.public_job_path_prefix.casefold() + ) + ) or unsafe_path or ( self.workday.uses_recruiting_path diff --git a/tests/test_workday_connector.py b/tests/test_workday_connector.py index fd0853a..09762e0 100644 --- a/tests/test_workday_connector.py +++ b/tests/test_workday_connector.py @@ -110,6 +110,40 @@ def test_recruiting_path_source_fetches_manifest_and_detail_from_same_fixed_host ) +def test_accepts_workday_canonical_public_alias_for_same_tenant_and_site(): + """A tenant API host can return the same board's canonical apply URL.""" + + detail = workday_detail("JR-1") + detail["jobPostingInfo"]["externalUrl"] = ( + "https://wd5.myworkdaysite.com/recruiting/acme/External/job/US-NY/Role-JR-1_JR-1" + ) + client = StubClient([{"total": 1, "jobPostings": [workday_summary("JR-1")]}, detail]) + key = workday_source("acme.wd5.myworkdayjobs.com", "acme", "External").key + + result = WorkdayConnector(key, client=client).fetch() + + assert result.complete is True + assert result.jobs[0].url.startswith( + "https://wd5.myworkdaysite.com/recruiting/acme/External/job/" + ) + + +def test_accepts_case_variant_of_same_workday_site_path(): + """Workday can capitalize a site path differently from its board URL.""" + + detail = workday_detail("JR-1") + detail["jobPostingInfo"]["externalUrl"] = ( + "https://acme.wd5.myworkdayjobs.com/EXTERNAL/job/US-NY/Role-JR-1_JR-1" + ) + client = StubClient([{"total": 1, "jobPostings": [workday_summary("JR-1")]}, detail]) + key = workday_source("acme.wd5.myworkdayjobs.com", "acme", "External").key + + result = WorkdayConnector(key, client=client).fetch() + + assert result.complete is True + assert result.jobs[0].url.endswith("/EXTERNAL/job/US-NY/Role-JR-1_JR-1") + + def test_fixture_preserves_exact_posting_date_and_native_id(): client = StubClient( [