Skip to main content

ATS Authorization with OpenFGA

Applicant tracking systems — Greenhouse, Lever, Workday Recruiting, Ashby — handle data that is sensitive both ways: candidates expect their applications to stay private, and hiring teams need scoped access to only the roles they are working on. Recruiters coordinate across many jobs; hiring managers see only their own openings; interviewers see only the candidates they are interviewing; offer approval is reserved for admins.

The full sample lives in openfga/sample-stores/stores/applicant-tracking-system.

Core resources and relations

  • organization — the tenant (employer). Roles: admin, recruiter, hiring_manager.
  • department and office — group jobs by team and location; department heads see scorecards for their org.
  • job — has per-position recruiter and hiring_manager relations distinct from the org-wide roles.
  • candidate — visible to recruiters and admins directly; hiring managers reach a candidate only through an application to one of their jobs.
  • application — links a candidate to a job; inherits visibility from the parent job.
  • interview — the organizer schedules; an interviewer sees only the interviews assigned to them.
  • scorecard — visible to the authoring interviewer, the hiring manager, the department head, and admins.
  • offer — anyone on the hiring team can draft and edit, but only an admin can approve.

What the model gets right

Per-job hiring teams, not org-wide visibility. Recruiter and hiring manager are relations on each job, not just org roles. A hiring manager working on the Senior Backend Engineer req does not see candidates from the Sales Director req — even though both are "hiring managers" in the org.

Hiring manager access flows through applications. A hiring manager doesn't have a direct relation to the candidate; they reach the candidate through an application to a job they own. When the application closes or moves jobs, visibility tracks the relationship automatically.

Interviewer scoping. Interviewers see only the interviews they're assigned to and the scorecards they author. They don't see the rest of the candidate's pipeline, other interviewers' notes, or the offer details — a common compliance requirement so that interview feedback stays independent.

Offer approval separated from offer authorship. Recruiters and hiring managers draft offers; only admins approve. Modeling can_edit and can_approve as distinct relations on offer keeps the four-eyes control without a separate workflow service.

Where this maps to OpenFGA features

ATS requirementOpenFGA feature
Per-job hiring teamdirect recruiter / hiring_manager relations on job
Hiring manager → candidate via applicationuserset traversal through application parent
Interviewer sees only assigned interviewsdirect interviewer relation on interview
Scorecard visibility to dept headrole at department, inherited by scorecards
Offer draft vs. approvedistinct can_edit / can_approve relations on offer
Multi-tenant ATS SaaStenant-scoped types, see multi-tenant SaaS
Reassign a recruiter's reqsbulk tuple writes against recruiter on job

Common extensions

  • Candidate self-service portal. A candidate#self relation lets the candidate view their own application status without granting access to interviewer notes or scorecards.
  • Referrals. A referrer relation on application lets the referring employee see the application status — but not the scorecards or offer terms.
  • External recruiters and agencies. Add an agency type with scoped access to the jobs they're sourcing for, without giving them visibility into the rest of the pipeline.
  • EEO / sensitive demographic fields. Gate via conditions or a separate can_view_eeo relation restricted to compliance staff, distinct from the general candidate viewer set.
  • Time-bound interviewer access. Use conditions so an interviewer's access to a candidate expires after the debrief, instead of relying on a cleanup job.

Working sample

Schema, sample tuples, and assertions are in openfga/sample-stores/stores/applicant-tracking-system. For the broader pattern of "role at the org, scoped relationships per record", see Modeling Roles.