Automation · Legal and compliance
How to build a user access review
The quarterly access review is a spreadsheet exported from the identity provider, approved line by line by managers who never open it, and the admin account created directly in the ERP is not on it. The model behind a review that finds things, the prompts that build it, and what it takes to run it every quarter.
Built with Tray Headless
- System Okta
- Step Pull accounts from each app
- Step Match to people and roles
- Step Reviewer keeps or removes
- System Slack
The list is built from each app's own accounts, not just the identity provider, so an account created inside the app shows up on the review.
The short answer
What is a user access review?
A user access review has four parts: a list of every account in each in-scope app, pulled from the app itself and matched to a person in the HRIS, a reviewer for each line who knows whether that person needs it, a decision recorded on every line with removal by a set date for anything not kept, and a record of who reviewed what and when. The usual failure is the list. A review built only from the identity provider misses the accounts created directly in the app, which are exactly the admin and service accounts an auditor asks about.
Stage 2 of 7: User access review. Part of Compliance automation, end to end : every stage, the systems it runs on and the guide that builds it.
What matters here
- Pull accounts from each app, not only from the identity provider. The account created by hand inside the ERP is the one that matters.
- Match every account to a person in the HRIS. An account with no current employee behind it is a finding before anyone reviews it.
- Send each reviewer only their own people. Nobody reads a company-wide spreadsheet.
- Remove what nobody confirms by the date. A review where silence means keep changes nothing.
- Keep the record as you go. The evidence is the list, the decision, the reviewer and the removal, with dates.
Who this is for
You run IT, security or compliance. Access to the apps your auditors care about is reviewed every quarter, the review is a spreadsheet, and proving it happened takes longer than doing it.
How it works in practice
What happens each review cycle, from the list being built to the access nobody needs being gone.
- 1
The apps in scope are listed with an owner
The ERP, the CRM, the cloud console, the code host and anything else the audit covers, each with the person accountable for it.
- 2
Every account is pulled from the app itself
Users, roles and admin rights as each app holds them, plus what the identity provider says, so accounts created outside it show up.
- 3
Each account is matched to a person
Against the HRIS: current employee, leaver, contractor or no match. Leavers and no matches are flagged before the review starts.
- 4
Each reviewer gets their own lines
Managers review their reports' access, app owners review admin rights and service accounts, with the flagged lines first.
- 5
Anything not kept is removed on the date
After one reminder, through the identity provider where it can be, and by a tracked ticket where it cannot.
- 6
The cycle is recorded
The list as it stood, every decision with who made it and when, and every removal with proof it happened.
What a user access review is made of
Four parts. The first decides whether the review can find anything at all.
A list from the source
Accounts and roles pulled from each in-scope app every cycle, alongside the identity provider, never last quarter's list edited by hand.
A person behind every account
Each account matched to the HRIS, with leavers, unmatched accounts and shared or service accounts flagged for their own decision.
The right reviewer per line
Managers for their people's access, app owners for admin rights and service accounts, and nobody reviewing their own access.
Removal and a record
Anything not kept is removed on the date, and the list, decisions and removals are kept together as one record per cycle.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Set up, then list the apps in scope
The review covers what is on this list and nothing else.
Headless skills
build-workflowUse build-workflow. The systems in play are Okta, Workday, NetSuite, Salesforce, GitHub, Slack, Jira and Snowflake, or whatever we run in those seats. Before you plan anything, tell me which of them are already authenticated in the workspace, because I do not want a connector stubbed that I have not authenticated. Then build a table of the apps in scope for the review: app, owner, how to read its users and roles, which roles count as admin, and whether access is granted through the identity provider, inside the app, or both. Flag every app where accounts can be created inside the app. Those are the ones where the identity provider's list is not enough.
- 2
Pull every account and match it to a person
The account nobody knows about is the one the auditor finds.
Headless skills
build-workflowtray-gotchasUse build-workflow and tray-gotchas. At the start of each cycle, for every app on the list, read every account with its roles and last login from the app itself. Read the same app's assignments from Okta. Match each account to a person in Workday by email, then by employee id. Mark each line as one of: Current employee, with their manager and department Leaver, with their end date Contractor, with their contract end date Service or shared account, with its named owner if it has one No match Flag before the review starts: leavers with active accounts, no-match accounts, admin rights, accounts with no login in 90 days, and any account that exists in the app but not in Okta.
- 3
Send each reviewer only their own lines
A reviewer reads the first ten lines carefully and skims the rest.
Headless skills
build-workflowUse build-workflow. Route each line to its reviewer: A current employee's access goes to their manager Admin rights and service accounts go to the app owner Nobody reviews their own access; send it to their manager's manager Send each reviewer one Slack message with their lines only, flagged lines first, and buttons to keep or remove, line by line or for all flagged lines. Ask for a short reason for any flagged line kept. Give a deadline two weeks out and remind once, three working days before. If a reviewer has left, send their lines to their manager.
- 4
Remove what was not kept
Silence means remove, or the review changes nothing.
Headless skills
tray-gotchastray-patternsUse tray-gotchas and tray-patterns. On the deadline, remove every line marked remove and every line nobody answered: Through Okta where the app is assigned there Directly in the app where it supports it Otherwise by a Jira ticket to the app owner with a due date Read the account back after removal and record that it is gone. A removal nobody checked is a removal nobody can prove. Tell each person what they lost and how to ask for it back through the normal access request.
- 5
Keep the record an auditor samples
The next audit should be a query, not a week of screenshots.
Write each cycle to Snowflake: the list as it stood on the start date, every decision with the reviewer and the time, every removal with the read-back result, and every line that went to a ticket with its closing date. Produce one report per app per cycle: accounts reviewed, removed, kept with a reason, and tickets still open. Attach it to the matching control in Drata. Report across cycles: leavers found with active accounts, reviewers who did not answer, and how many removed people asked for access back. A high number asking back means the list was wrong.
- 6
Check it end to end, then hand the cycle to compliance
Because the scope and the schedule are a compliance decision.
Run the per-step checks and the whole-workflow audit before this touches production. Run one cycle against a test app, leave one line unanswered, and confirm it is removed on the date and the person is told. Then open the same workflow in Tray Build so compliance can change the apps in scope, the reviewer rules, the schedule and the deadline in the visual canvas. Access to MCP tools and AI assistants is reviewed in its own cycle; keep this one to people's access to company apps.
What it connects to
The list comes from the apps and the identity provider, the people from the HRIS, and decisions happen where reviewers already work.
Okta
Read app assignments and group membership, and remove access for apps assigned through it.
Reads and writes
Workday
Match every account to a current employee, leaver or contractor, and find each person's manager.
Reads
NetSuite
Read users, roles and admin rights from the ERP itself, where accounts are often created by hand.
Reads and writes
Salesforce
Read users, profiles and permission sets, and deactivate users that were not kept.
Reads and writes
GitHub
Read organization members, owners and outside collaborators, and remove members on the date.
Reads and writes
Slack
Send each reviewer their lines with keep and remove buttons, remind once, and tell people what was removed.
Writes
Jira
Open a ticket with a due date for any removal that has to be done by hand inside an app.
Writes
Drata
Attach each cycle's report to the access review control, where the audit already looks.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, SAP S/4HANA, Google BigQuery, Microsoft Teams, Azure Active Directory or SAP SuccessFactors.
Connections in this build
Field mapping, templates and common problems for each pairing: Okta + Workday REST, NetSuite + Workday REST, Okta + Salesforce and Workday REST + Salesforce.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
This is a control your auditor tests every year. It only counts if it runs on time and removes things.
It runs on the platform, not on your laptop
Each cycle starts on schedule, builds its own list, and applies decisions on the date, with a full history of each step.
Every removal is checked
Access is read back after it is removed, and the result is part of the record.
Credentials are managed, never written into the build
Reading and removing users across the ERP, CRM and code host is a broad permission. Each is a separate authentication in your workspace, scoped and separately revocable.
Compliance owns the scope
The apps in scope, the reviewer rules and the schedule open in Tray Build, maintained by the team that answers to the auditor.
Test with an unanswered line
Before production, leave one line without a decision and confirm it is gone on the date. That is the case that proves the review does anything.
Questions people ask
Why not build the list from the identity provider alone?
Because accounts get created directly inside apps, often admins and service accounts, and they never appear in the identity provider. Pull the list from each app and compare it with the identity provider.
Who should review each line?
The person's manager for ordinary access, the app owner for admin rights and service accounts, and never the person themselves.
What happens to access nobody confirms?
It is removed on the deadline, after one reminder. The person is told and can ask for it back through the normal access request.
How is this different from an access request?
An access request decides whether someone gets access now. A user access review checks, on a schedule, whether everyone who has access should still have it. You need both.
Does this make us compliant?
No workflow does that. It makes the review run on time, removes what was not kept and keeps the record. Your auditor still decides whether the control works.
Related guides
IT and security
How to build access request and approval
Route to the system owner, grant with an expiry by default, provision automatically, and produce the access review as a by-product. The prompts that build it.
People operations
How to build employee offboarding deprovisioning
Revoke on the leave date, cover every system instead of the ones you remember, transfer what they owned, and prove it. The Headless prompts that build it.
IT and security
How to build SaaS licence reclamation
Find the seats nobody uses, ask before you take, reclaim on a schedule, and put the saving where finance sees it. The Headless prompts that build it.
Legal and compliance
How to build audit evidence collection
Map each control to the systems that prove it, collect the evidence on a schedule with its date and source, chase the gaps before the auditor does, and keep one place to look. The prompts.
Last reviewed October 2026.