Access reviews
Access reviews (access certification) are how you periodically prove that the people who have access still
need it. The server runs them as campaigns over a frozen snapshot. Code lives in
src/Domain/Governance/Reviews/.
Motivation
Grants accumulate. People change teams, projects end, contractors leave — but their access lingers. An
auditor will ask “who reviewed this access, and when?”. A campaign produces exactly that evidence: a dated,
signed certify/revoke decision per access item.
The lifecycle
Create & open a campaign
curl -X POST https://iam.example.com/api/iam/v1/access-reviews/campaigns \ -H "Authorization: Bearer $ADMIN_TOKEN" -d '{"name":"Q3 warehouse review","scope":{...}}' curl -X POST https://iam.example.com/api/iam/v1/access-reviews/campaigns/{campaign}/open \ -H "Authorization: Bearer $ADMIN_TOKEN"CampaignEnginegenerates items (subject × access) and freezes a snapshot of grants and signals.Review items with context.
ReviewSignalsattaches risk signals — unused grants, anomalies — to
each item so reviewers decide with evidence:curl https://iam.example.com/api/iam/v1/access-reviews/campaigns/{campaign}/items \ -H "Authorization: Bearer $ADMIN_TOKEN"Certify or revoke each item (both audited):
curl -X POST https://iam.example.com/api/iam/v1/access-reviews/items/{item}/certify -H "Authorization: Bearer $ADMIN_TOKEN" curl -X POST https://iam.example.com/api/iam/v1/access-reviews/items/{item}/revoke -H "Authorization: Bearer $ADMIN_TOKEN"Close the campaign:
curl -X POST https://iam.example.com/api/iam/v1/access-reviews/campaigns/{campaign}/close -H "Authorization: Bearer $ADMIN_TOKEN"
From the CLI: php artisan iam:reviews:open --campaign=..., iam:reviews:remind --campaign=...,
iam:reviews:close --campaign=....
Snapshot, not live data
Removing a role from the catalog after a campaign opens must not retroactively change its outcome — and
must never leave a permanent orphan grant. The campaign decides against the grants and signals as they were
when it opened.
Feature gating
Access reviews are a governance feature gated per layer / app / role / user via NativeFeatureScope. The
default is on (iam-governance.php → features.access_review, permission
iam:access_review.manage). See Configuration.
Opening, closing and item decisions are read-then-write transitions. The server runs them under
DB::transaction + lockForUpdate + re-check, so two concurrent closes or a late catalog change can’t
produce orphan grants or double certifications. This is a hard TOCTOU invariant of the package.
Next
- Access requests — the request/approval side of governance.
- Least-privilege & SoD — feeding reviews with risk signals.
- Audit & compliance — turning campaigns into evidence.