Custodian Workforce Compliance
Companion to Custodian Compliance (the supply side: what a custodian holds, for whom, and when it lapses) and Custodian Onboarding (how documents become Tier-2 attestations). This adds the demand side: what each person is required to hold, and where they fall short.
Take a large engineering contractor: tens of thousands of staff and subcontractors, working across client sites, each with its own entry rules. The compliance team asks: for this role on this site, what must a person hold? Of the people starting Monday, who is short, of what? What lapses next quarter, so training capacity can be booked? Can we show a client or auditor the state of all of it without handing over documents?
This inherits Custodian Compliance’s guardrails unchanged — a requirement is met only by a custodian’s own attestation, never a stored/cached gap state, never a DID-keyed link, and never a read of the wallet without consent.
Workforce compliance itself still never delivers training — but a gap can now resolve via an assigned online course as well as a proof link or a waiver; see Course Delivery & Retakes (planned) for that capability, which workforce compliance would consume, not own.
Direction, as of 2026-09-28: the product direction is for the custodian portal to grow into a full end-to-end workforce & compliance management platform — compliance (this doc), course delivery/LMS, rostering, and payroll all included. Course delivery is scoped (Course Delivery & Retakes). Payroll and rostering are not — they are a named, unscoped direction only; see Workforce Platform Expansion before treating either as actionable. Nothing in this doc’s existing compliance model (read-only register, attestation-only gap resolution, no cached state) changes because of that direction.
Concepts
Three new concepts, all custodian-owned configuration, never touching the Program Catalog:
- Group — a named set of people that share requirements: a role, a site, a project, a
department, or a contractor cohort. One mechanism, not separate role/site/project models — a
person in several groups owes the union of their requirements.
kindis cosmetic (icon/filter only, never behavior). - Requirement — “members of this group must hold this policy’s credential,” pointing at an existing Credential Catalog entry, with an optional grace period for new starters.
- Membership — this person is in this group, keyed by the same normalized holder key the roster uses.
Deliberately not introduced: a separate “profile” object (a group already is one), a recommended-vs-mandatory flag (everything is required until proven otherwise), or a group hierarchy (flat until proven insufficient).
Derived state — computed at read time, never stored
If a person owes the same policy through several groups, it’s one requirement row with the
earliest due date used — never double-counted. IN_PROGRESS and SCHEDULED are independent flags
that annotate a state without replacing it (an expired credential with a renewal already in review
still reads EXPIRED + IN_PROGRESS, never a hopeful “in progress” that hides an active lapse).
Waived is its own outcome — a time-bound admin-approved exemption, counted separately from
MET everywhere a roll-up appears, and never a permanent exemption (every waiver has an expiry).
Portal
People becomes a tabbed page:
| Tab | Content |
|---|---|
| Roster | The existing People table, plus a Group filter, a Groups column, and a Requirements roll-up badge per person |
| Groups | Group list with kind, members, requirements, roll-up split; a group’s own page has a requirements editor and member table |
| Gaps | Stat tiles (Has gaps / Lapsing soon / Needs action / Requirements met / Waived), a filterable table, per-row Attest credential / Schedule / Request waiver actions, and a CSV report |
Every screen naming a requirement state carries the Tier-2 provenance badge and the standard disclosure. Forbidden in this feature’s copy: certified, cleared, qualified, approved, authorised to work, fit for work, verified — a roll-up is always “requirements met” or “has gaps,” with “per credentials attested by ‹organisation›” as the basis line.
Bulk import
The browser parses a CSV client-side; the server never receives a file. email is the required
key; groups is a semicolon-separated KIND:Name list. A preview call returns a diff with nothing
written (people to add/update, memberships to add, groups to create, per-row errors); a commit call
applies exactly that. Import is additive-only — it never removes someone from a group — and
idempotent (a blank cell means “leave unchanged,” never “clear”; re-importing the same file is a
no-op).
Gap-driven scheduling
An Admin can schedule a single outstanding requirement, or schedule every outstanding requirement in a group in one bulk, best-effort call (capped, idempotent). Automation only ever creates an obligation — never an attestation — and nothing is sent to anyone beyond the existing notification channels an ordinary schedule already uses.
Readiness and forecast
Two pure reads, gating nothing:
- Readiness (
GET /groups/{id}/readiness?on=) — classifies every requirement as of a future date, so a credential that will have lapsed by then readsEXPIREDthere. A person is ready when every requirement isMETorEXPIRING_SOON(still standing) on that date. - Forecast (
GET /forecast?months=) — per month and group, which attested credentials reach expiry and whichNOT_YET_DUErequirements fall due — reports demand for booking training capacity; it books nothing and notifies no one.
Consented evidence and client-facing proof
A custodian can ask a holder to share a credential they already hold (through the same consent flow
as Custodian Compliance), or a holder can push a credential
straight into a custodian’s intake unprompted. Either way, the shared credential lands as a
CONSENTED_SHARE/EVIDENCE intake item — no document bytes, and it goes through review → attest
like any other document; a requirement is met only by the custodian’s own attestation, never by the
presented credential alone.
Separately, a holder can create a signed, expiring, revocable proof link: a snapshot of selected requirement states (never documents) shared with a named recipient, only after the holder’s explicit consent. The wallet resolves only a custodian-provided group context against the signed-in holder’s own membership — it never lists or browses workforce groups. Revocation is immediate; expiry is required (maximum one year).
Contractor groups
CONTRACTOR is a cosmetic group kind for people employed by another company. Creating one requires
the Admin to confirm a lawful basis (audited), and the portal links to the contractor-specific
privacy-policy section.
Out of scope
Within-custodian roster duplicates (the same real worker entered twice under two email addresses on one custodian’s own roster) are a separate data-entry problem this feature does not solve — see Cross-Wallet Identity Consolidation for the cross-wallet fragmentation problem this is sometimes confused with.