Custodian Compliance
Companion to Custodian Onboarding, which specifies how a Custodian brings third-party documents into the platform (intake → review → Tier-2 attestation). This covers what a Custodian does with those attestations afterward: see them, see the people they belong to, keep them current, and re-perform them when they lapse.
A custodian such as a workforce-compliance platform or an HR/records team treats its documents as internal competency records (an induction, a site-access assessment) that lapse on a fixed cycle. The job is: know what’s held and for whom, know what’s about to lapse, know who must re-perform an assessment and when, and be able to prove all of it to an auditor.
Design guardrails
These bind every part of this feature — a change that needs to break one goes back to first principles.
| Guardrail | Meaning |
|---|---|
| Attests, never issues | Nothing here presents a custodian’s record as an accredited issuer’s statement. The provenance tier and disclosure copy stay visible on every screen and notification naming a credential. |
| No document bytes, ever | Roster, compliance, and scheduling data are structured metadata only. Reports and exports carry no document content or evidence keys. |
| Re-performance is always a new attested document | There is no “renew” action that re-signs or extends an attestation. A lapsed credential is replaced only by a fresh document through the normal intake → review → attest path. |
| Credential Issuance owns credential state | wallet.credentials is the single source of truth for status/expires_at. Core Engine only reads it; compliance status is computed at read time, never cached. |
| A Custodian is never linked to a Holder’s DID by merging identities | The custodian↔holder relationship is data keyed by what the custodian itself knows (holder email / matched DID). |
| No reading a holder’s wallet profile without consent | The custodian sees only what it extracted from its own documents, unless the holder explicitly grants more (see Consented holder profile). |
| Tenant isolation from the session, never the request | Every read/write is scoped by custodian_id resolved from the session. A cross-tenant id returns 404, not 403. |
| The platform tracks obligations and appointments, not assessments | A schedule records that a holder owes a re-performance and when the custodian says it will happen; the assessment itself happens off-platform. |
| Advisory automation never gates | Automatic schedule/reminder creation never blocks intake, review, attestation, or revocation. A notification failure is logged, never surfaced as a failed operation. |
| Everything sensitive is audited | Policy changes, schedule state changes, report exports, and consented-profile reads are audited; routine list views are not. |
Real expiry on attestations
A custodian attestation’s expiry follows the document itself, not a flat default:
- Custodian-internal credential — the reviewer sets expiry per credential: an explicit date
(pre-filled from the extracted
expiry_dateas a suggestion) or “no expiry.” - Program Catalog credential — the catalog’s own validity rule wins (
validity_monthsfrom the issue date, or “never expires”). The custodian acknowledges the computed date rather than overriding it. - Attestation is refused until an expiry decision exists — never silently defaulted. A date already in the past is accepted (old documents are still worth recording); the credential is simply already expired the moment it’s issued.
Credential register
A read path over the custodian’s own attested credentials, paged and filterable by status, with a per-credential detail, verification history, and audit history. A credential archived after an approved erasure request is excluded — it’s revoked deliberately, not a lapse to chase.
People roster
One roster, two inputs, one row per person. A person is on the roster if the custodian has reviewed at least one document for them (grouped by a normalized holder key) or added them directly. Their identity lives in exactly one place — the wallet account, keyed by email — never copied onto the roster row.
- Reference ID — the custodian’s own identifier (staff/learner number), searchable on the roster and shown to the custodian only — never returned to the person, their wallet, a notification, or a credential.
- What’s shown — display name/email as extracted, item and attested-item counts, and a claim
state (
UNCLAIMED/CLAIMED) derived from the holder DID. No wallet name, phone, DID string, or activity data beyond what the custodian itself extracted. - Add and invite are separate actions. Adding records a person and sends nothing. Invite emails the wallet’s ordinary sign-up link — no token, no wallet access; a credential is only ever claimed by proving the email is theirs. Rate-limited like any other outbound mail.
- Person lifecycle — a record added explicitly by the custodian survives its last document being discarded; a record that exists only to annotate documents is deleted when the last document leaves.
Compliance policies and status
A policy describes one kind of internal credential: how long it’s valid, reminder offsets, whether a lapse requires re-performance. It’s the custodian’s own configuration and never touches the Program Catalog.
Compliance status is derived at read time, never stored:
REVOKED → EXPIRED → EXPIRING_SOON (inside the reminder window) → VALID (has an expiry) → NO_EXPIRYA credential attested before real expiry existed is additionally flagged EXPIRY_UNVERIFIED. A
credential superseded by a newer attestation for the same holder + policy is RENEWED and drops
out of “needs action” counts. The dashboard shows status tiles, a needs-action table, a per-policy
breakdown, and a CSV export (metadata only, audited on every export, rate-limited).
Expiry reminders
A daily scheduled job reads custodian-attested credentials approaching expiry and sends the tightest reminder offset already reached — never a burst of every crossed threshold.
A ledger, keyed by (credential_id, offset_days, audience), guarantees at-most-once delivery even
under a concurrent or re-run scheduler pass.
Re-performance scheduling
A schedule records an obligation, never an assessment:
There is no “mark complete” action anywhere in the UI — the only way to close a schedule is a fresh, evidence-backed attestation. This generalizes to a first-time obligation too (a holder due for a credential type they’ve never held), not only a re-performance of a lapsing one.
Consented holder profile
The roster shows only custodian-extracted data by default. A holder with a claimed wallet can choose to share more — currently name and phone — by approving a specific request from a specific custodian in the wallet. Nothing is shared by default; the grant is revocable at any time and takes effect on the next read; every consented read is audited and visually marked “shared by the holder.” Passkeys, recovery codes, sessions, other custodians’ attestations, and access logs are never exposed even with consent.
Unified Credentials (catalog, direct attestation, wallet visibility)
The custodian’s internal credential types are managed up front as a Credential Catalog (display name, category, validity, reminder offsets, reperformance toggle) rather than discovered only after a reviewer types a free-text code.
- Direct attestation — a new attestation path that doesn’t require a source document batch: the custodian picks a holder, a credential type, and evidence (an uploaded document, or a system-generated one-page attestation-record PDF when there’s no document to upload). Evidence is never optional — a Tier-2 credential’s “backed by a document” guarantee stays unconditional. The created item goes through the same review/attest path as an intake-derived one.
- Wallet visibility — the holder’s “Your credentials” view splits into Global/Recognized (Tier-1, or a Tier-2 attestation whose review confirmed a real catalog entry) and one tab per custodian the holder has a non-catalog attestation from, each split Active/Past.
Portal information architecture
One page, Credentials, with four tabs: Overview (dashboard + alerts), Catalog (credential types), Registry (attested instances, direct attestation, erasure folded in as row state), and Schedule (re-performance). See Custodian Portal UX for the full page-anatomy standard.