Admin DSR Management
DPO/staff-side workflow for handling subject requests: queue, identity verification, response within 30 days, audit trail.
The public DSR portal is half the story. The other half is the DPO / staff workflow: triage the queue, verify identity, generate the response, hit Section 34's 30-day deadline (extendable to 60 if complex, per GAID 2025), and keep an audit trail NDPC can ask for. This recipe wires those pieces.
DPO dashboard
'use client';
import { DSRDashboard } from '@tantainnovative/ndpr-toolkit';
import { useDSR } from '@tantainnovative/ndpr-toolkit/hooks';
import { apiAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
import type { DSRRequest } from '@tantainnovative/ndpr-toolkit/core';
const adapter = apiAdapter<DSRRequest[]>('/api/admin/dsr', {
credentials: 'include',
retry: { attempts: 2 },
});
export default function DPODashboard() {
return (
<DSRDashboard
adapter={adapter}
requestTypes={[
{ id: 'access', name: 'Access', ndpaSection: 'Section 34(1)(a)', estimatedCompletionTime: 30, requiresAdditionalInfo: false },
{ id: 'rectification', name: 'Rectification', ndpaSection: 'Section 34(1)(c)', estimatedCompletionTime: 30, requiresAdditionalInfo: true },
{ id: 'erasure', name: 'Erasure', ndpaSection: 'Section 34(1)(d)', estimatedCompletionTime: 30, requiresAdditionalInfo: false },
{ id: 'portability', name: 'Portability', ndpaSection: 'Section 38', estimatedCompletionTime: 30, requiresAdditionalInfo: false },
{ id: 'objection', name: 'Objection', ndpaSection: 'Section 36', estimatedCompletionTime: 30, requiresAdditionalInfo: true },
{ id: 'withdraw_consent', name: 'Withdraw Consent', ndpaSection: 'Section 35', estimatedCompletionTime: 30, requiresAdditionalInfo: false },
]}
/>
);
}Identity verification workflow
Before fulfilling an access or erasure request, you must verify the requester actually is the data subject. NDPA doesn't prescribe the method — common patterns:
- Email magic link: send a verification link to the email on file. Cheap and good enough for low-sensitivity requests.
- Government ID upload: NIN slip + selfie. Standard for fintech / healthcare. Be careful — you're processing fresh sensitive PII to verify; delete after verification (Section 24(1)(e)).
- Account login: if the data subject has an active account, requiring them to log in to submit the request is sufficient.
Transition the request status from awaitingVerification → inProgress when verification completes:
// app/api/admin/dsr/[id]/verify/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { verifyDSRSession } from '@/server/dsr-verify'; // your custom auth check
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
await verifyDSRSession(req); // ensure caller is the DPO / authorised staff
// Mark verified — Section 34 30-day clock keeps running from submission
await db.dsrRequest.update({
where: { id: params.id },
data: {
status: 'inProgress',
verifiedAt: new Date(),
// dueDate stays at original (createdAt + 30 days)
},
});
return NextResponse.json({ ok: true });
}30-day deadline tracking
The useDSR hook exposes getRequestsByStatus — combine with a custom sort to surface requests close to the 30-day deadline:
'use client';
import { useDSR } from '@tantainnovative/ndpr-toolkit/hooks';
export function OverdueAlert({ requestTypes }: { requestTypes: any[] }) {
const { requests } = useDSR({ requestTypes });
const now = Date.now();
const overdue = requests.filter(
(r) => r.status !== 'completed' && r.dueDate && r.dueDate < now,
);
const closeToDeadline = requests.filter(
(r) =>
r.status !== 'completed' &&
r.dueDate &&
r.dueDate > now &&
r.dueDate - now < 5 * 24 * 60 * 60 * 1000, // 5 days
);
if (overdue.length === 0 && closeToDeadline.length === 0) return null;
return (
<aside className="rounded border border-red-200 bg-red-50 p-3 text-sm">
{overdue.length > 0 && <p><strong>{overdue.length} DSRs are past the 30-day deadline.</strong> Section 34 violation risk.</p>}
{closeToDeadline.length > 0 && <p>{closeToDeadline.length} DSRs due in the next 5 days.</p>}
</aside>
);
}Audit trail
Every state transition (received → verified → in-progress → completed/rejected) should be recorded with a timestamp, the staff member who acted, and a one-line reason. NDPC asks for this trail during compliance investigations. The toolkit's internalNotes field on DSRRequest covers it.