Skip to content

Workday real-tenant validation (WW-32)

WW-32 was blocked pending a live Workday tenant. Andrew provided a real one — the CVS Health "Staff Software Development Engineer" posting, which applies through CVS's Workday. This records what a read-only inspection of that tenant confirmed. No account was created, nothing was signed into, no data was entered, nothing was submitted — the walk stopped at the account wall.

The tenant & the flow

  • Careers site: jobs.cvshealth.com (Phenom-hosted). "Apply Now" → a hvhapply redirect → the Workday tenant.
  • Workday tenant: cvshealth.wd1.myworkdayjobs.com, site CVS_Health_Careers.
  • Job apply URL: …/CVS_Health_Careers/job/IL---Work-from-home/Staff-Software-Development-Engineer_R0898371/apply
  • Apply entry page (/apply) offers three standard Workday options, each a real data-automation-id:
  • autofillWithResume — "Autofill with Resume" → /apply/autofillWithResume
  • applyManually — "Apply Manually" → /apply/applyManually
  • useMyLastApplication — "Use My Last Application" → /apply/useMyLastApplication
  • Account wall (reached via Apply Manually, /apply/applyManually): a "Sign In" page offering Sign in with Google / LinkedIn / email. Confirmed data-automation-ids: applyFlowPage, progressBar, signInContent, GoogleSignInButton, utilityButtonSignIn, backToJobPosting, jobTitleHeading.

What this validates in the app

  • ATS detectionAtsDetector classifies myworkdayjobs.com as AtsKind.Workday and extracts the tenant host. CVS's cvshealth.wd1.myworkdayjobs.com matches. ✅
  • Account-wall handlingWorkdayAutomationEngine.SignInAsync raises the account wall unconditionally on first visit (no vault entry → provision credential, capture the page's actual URL as the "Open site" target, park at AwaitingAccount, return false). It never types a stored password and never tries to detect the wall by page content. So the real CVS entry flow (/apply → Apply Manually → Google/LinkedIn/email sign-in) is handled correctly by design: the engine parks and the user navigates the entry + sign-in, then resumes. No dependency on a /login URL (the CVS wall lives at /apply/applyManually). ✅
  • Selector conventions — the real tenant uses exactly the durable data-automation-id convention WorkdaySelectors is built on (applyFlowPage, signInContent, progressBar, jobTitleHeading, backToJobPosting). The post-sign-in form fields (legalNameSection_firstName, formField-degree, dateSectionMonth-input, addButton, formField-skills, …) are standard Workday automation-ids and could not be live-checked without an account, but the account-wall inspection confirms this tenant follows the same convention. ✅

Signed-in "My Information" inspection (WW-32 finish)

Andrew signed into the tenant himself (I never handled credentials, filled a field, or submitted). That advanced the flow to step 2 "My Information", which let me read the real form fields. This surfaced a genuine selector defect the fake ScraperLab site had hidden:

  • Real Workday puts the data-automation-id on the field CONTAINER <div> (formField-legalName--firstName, formField-addressLine1, formField-postalCode, formField-phoneNumber, formField-countryRegion, formField-source, …). The inner <input> carries no data-automation-id and no aria-label — only id/name (e.g. name=legalName--firstName, name=addressLine1, name=postalCode, name=phoneNumber).
  • Our contact selectors were all input[data-automation-id=…] / input[aria-label=…] (shape of the fake site). Against this real tenant:
  • First/Last/Address/City matched only via the last-resort input[name*=…] fallback.
  • Postal code FAILED — real name=postalCode, our only name fallback was *='zip'.
  • Phone FAILED — real name=phoneNumber, type=text (not tel), no aria; the chain had no name fallback at all.
  • Fix (committed): every contact chain now LEADS with the container-scoped [data-automation-id='formField-…'] input selector (the same durable pattern the app already used for the degree/skills/source dropdowns), with the old ids + new name*='phone' / name*='postal' fallbacks kept. State is formField-countryRegion — a listbox button (aria-label="State Select One Required"), consistent with the app's "State is a dropdown a text fill can't drive" note. formField-source (How did you hear, WW-38) matched as-is.

The later steps (My Experience repeater, Education, Skills) already use the container-scoped formField-* pattern this fix aligns the contact fields to, so they weren't the defect — but they couldn't be live-checked without completing the required My Information fields (not done).

Limitation (unchanged, by design)

The multi-step application form (My Information, Experience repeater, Education, Skills, Voluntary Disclosures) sits behind account creation. Validating those field selectors live requires a signed-in session — the app is built to hand that off to the user at the account wall, and the autonomous build never creates accounts or signs in. So the repeater/date/skills selectors remain proven against the ScraperLab fixtures plus Workday's documented automation-id convention (which this real tenant corroborates), not a live signed-in form.

Verdict

No code change needed — the design holds against a real Workday tenant. WW-32's remaining piece (live validation of the signed-in form fields) needs a session a human drives, which is exactly the account-wall handoff the engine already implements.