11.3 Review campaigns and remediation work items
packs:security-governance
After this you can: open a review campaign, decide each item, let a revoke open remediation work, close the campaign into the ledger, and set a cadence.
Before you start — tick each one:
- Lesson 11.2 — Controls and the evidence ledger (
opschain learn 11.2)
In the GUI: Governance → Compliance — review campaigns (open, decide, close into an attestation) beside the posture report.
A campaign turns a point-in-time dataset into a governed sign-off:
items, each with a reviewer and a decision, closing into a ledger
attestation. The first shipped campaign content is the access
review — "who can do what, reviewed quarterly" — with every revoke
decision opening a named remediation work item instead of silently
auto-revoking. The model reference is opschain docs governance.
Licence entitlement. The campaign machinery is base platform, but a campaign with no items cannot close, and item sourcing is pack content: the access-review kind requires
packs:security-governance(seeopschain docs entitlements). Work items stay base — an entitlement lapse never hides open remediation work.Who can do this. Opening campaigns and configuring cadences are admin-plane acts. Reviewing is user-plane: a reviewer is an ordinary user with a path-RBAC grant on
/governance/campaigns(readable: reads; updatable: decisions and closure), and work items ride/governance/work_itemsthe same way. Decisions, closure and work-item completion sit on the step-up floor (opschain learn 7.4).
1. Open an access review
The access-review campaign sources its items server-side from the
live access dataset: every grant at the per-identity (rule × principal)
grain, every superuser/block assignment, and both token inventories —
each item carrying a provider-badged, point-in-time subject_summary
the reviewer decides on, so the campaign reviews a snapshot that cannot
drift with the live rows. As an admin:
opschain admin governance campaigns open-access-review \
--control access-governance --reviewer thomas --due 2026-11-30T00:00:00Z
opened access-review campaign 01a2f8a0-1c2d-7e3f-8a4b-5c6d7e8f9a0b with 14 sourced item(s) — due 2026-11-30T00:00:00Z
opschain governance campaigns list --status open
ID CONTROL KIND STATUS OPENED AT DUE AT ITEMS
01a2f8a0-1c2d-7e3f-8a4b-5c6d7e8f9a0b 01a2f0e2-… access_review open 2026-10-27T10:20:00Z 2026-11-30T00:00:00Z 14
(The cited control must exist — create it first as in lesson 11.2. A
generic campaign of your own items uses opschain admin governance campaigns open --control <key> --kind <kind> --item '<subject-kind>:<subject-id>[:<reviewer>]'.)
2. Decide the items
As thomas (the reviewer, elevated), walk the items and record
decisions in the shared approval grammar — retain, revoke or
flag:
opschain governance campaigns show <campaign-id>
id: 01a2f8a0-1c2d-7e3f-8a4b-5c6d7e8f9a0b
control: 01a2f0e2-…
kind: access_review
status: open
opened at: 2026-10-27T10:20:00Z
due at: 2026-11-30T00:00:00Z
ITEM SUBJECT REVIEWER DECISION DECIDED BY SUMMARY
01a2f8a1-… grant:01a2e1b0-… thomas - - policy "LimeBank operators" grants jessica (ldap:corp) read, update on /projects/limebank/environments/prod
01a2f8a2-… api_token:01a2e2c0-… thomas - - api token for contractor-ci (CI pipeline), expires 2027-01-01T00:00:00Z
opschain governance campaigns decide <campaign-id> <item-id> --decision retain
decision recorded — item 01a2f8a1-…: retain
opschain governance campaigns decide <campaign-id> <item-id-2> --decision revoke \
--comment "contractor offboarded 2026-09"
decision recorded — item 01a2f8a2-…: revoke
remediation work item 01a2f8b0-…: Revoke api_token 01a2e2c0-… (open)
A revoke does not auto-revoke: in the decision's own transaction
it opens a named work item carrying the subject's snapshot summary —
one per campaign item, however often the decision is re-recorded.
3. Remediate — the work items
The operator remediates by hand (delete the grant, revoke the token), then records it:
opschain governance work-items list --status open
ID NAME STATUS CAMPAIGN SUBJECT CLOSED BY
01a2f8b0-… Revoke api_token 01a2e2c0-… open 01a2f8a0-… api_token:01a2e2c0-… -
opschain governance work-items complete <work-item-id> \
--notes "revoked api token tok_7f2; removed limegrid operator grant"
work item 01a2f8b0-… completed by thomas
A completed item refuses a second completion rather than overwriting the recorded notes. Work items are deliberately base — no pack gate ever hides open remediation.
4. Close into the ledger
A fully-decided campaign closes into the evidence ledger: all-retain
closes verified; any revoke or flag closes verified_with_exceptions
— the closing attestation cites the campaign:
opschain governance campaigns close <campaign-id> --notes "Q4 access review"
campaign 01a2f8a0-1c2d-7e3f-8a4b-5c6d7e8f9a0b closed — attestation seq 42 (sha256:6d2f…b0e9)
opschain governance evidence list --limit 5
A campaign with undecided items refuses to close: nothing was reviewed, so nothing can honestly be attested.
5. Put it on a cadence
A cadence is "this control is reviewed every N": a 5-field cron schedule on the scheduler leader tick. A due cadence opens a campaign of its kind and advances; while the previous campaign is still open the schedule advances without opening a duplicate:
opschain admin governance cadences create --control access-governance \
--schedule "0 2 1 */3 *" --campaign-kind access_review --grace 604800
created cadence 01a2f8c0-… on control 01a2f0e2-… — next due 2027-01-01T02:00:00Z
opschain admin governance cadences list
ID CONTROL SCHEDULE CAMPAIGN KIND GRACE NEXT DUE ENABLED
01a2f8c0-… 01a2f0e2-… 0 2 1 */3 * access_review 604800s 2027-01-01T02:00:00Z yes
An open campaign past its due time plus the grace draws the loud
warn:review_cadences:lapsed event once — overdue reviews are
themselves compliance evidence:
opschain audit --type warn:review_cadences:lapsed
Two campaign kinds source their items server-side when a cadence fires:
access_review (the live access-review dataset, above) and
secret_rotation — "secrets are rotated every N, attested": the items
are the vault's secret paths at firing time (paths only, values are
never read), one per node, for the reviewers to attest rotation on:
opschain admin governance cadences create --control secret-rotation \
--schedule "0 3 1 * *" --campaign-kind secret_rotation --grace 604800
Check yourself
- What does a
revokedecision create in the same transaction, and what verdict does the closing attestation carry when any item was revoked? Then: what does the campaign refuse while an item is undecided?
What you learned
- Campaigns review a server-sourced snapshot; decisions are the shared
approval grammar (
audit:review_campaigns:approve|reject|flag), and closure appends a verdict-bearing attestation to the ledger. - Revoke opens a named work item — remediation is an explicit, recorded operator act, and the work-item surfaces never hide behind a pack.
- Cadences ride the scheduler leader tick, fire exactly once, never stack duplicates, and lapse loudly.
Next: lesson 11.4 — Notification mandates and delivery evidence (opschain learn 11.4), or back to your track (opschain learn).