Records of Processing Activities (ROPA)
Maintain comprehensive records of all data processing activities as required by the NDPA 2023
Overview
The ROPA (Records of Processing Activities) component helps organisations create, maintain, and manage a register of all personal data processing activities. This is a key accountability requirement under the Nigeria Data Protection Act 2023 (NDPA).
NDPA 2023 — Record Keeping Obligations
The NDPA 2023 requires data controllers and processors to maintain records of processing activities under their responsibility. These records must include the purposes of processing, categories of data subjects and personal data, recipients, cross-border transfers, retention periods, and a description of technical and organisational security measures.
Installation
Install the NDPR Toolkit package which includes the ROPA components:
pnpm add @tantainnovative/ndpr-toolkitProduction Readiness
Use this checklist when moving ROPA from demo mode into a customer-facing workflow. Pair the UI package with the source templates in @tantainnovative/ndpr-recipes so validation, persistence, and audit behavior live in your own backend.
Implementation checklist
- Define one owner for each processing record and require review dates before release.
- Capture controller details, purposes, categories, recipients, safeguards, retention, and DPIA references.
- Track updates as versioned records or audit events rather than overwriting operational history.
- Connect ROPA records to lawful basis, DPIA, cross-border transfer, and breach response workflows.
- Restrict edit access to privacy, legal, security, and approved system owners.
Backend notes
- Use the recipes ROPA route as the starting point, then wire it to your organization and user model.
- Run validateProcessingRecord in create/update routes so incomplete records fail before database writes.
- Store archived records for accountability; avoid hard deletion unless your retention policy requires it.
- Keep exports generated from backend data so regulator-ready reports match the system of record.
Testing notes
- Create a complete record, then verify summary counts, CSV export, and compliance gaps.
- Submit incomplete records to the API and confirm validation errors name the missing fields.
- Archive and update records, then confirm the audit trail or updated timestamp is preserved.
- Verify users without the right role cannot create, edit, archive, or export processing records.
Common mistakes
- Using ROPA only as a static spreadsheet while live systems change outside the register.
- Leaving recipients, retention periods, transfer destinations, or security measures blank.
- Hard-deleting old records without preserving why the processing activity changed.
- Letting every admin user edit ROPA records without ownership or approval controls.
Import
Import from the main package:
import {
ROPAManager,
useROPA,
validateProcessingRecord,
generateROPASummary,
exportROPAToCSV,
identifyComplianceGaps,
} from '@tantainnovative/ndpr-toolkit';Components
The ROPA module includes three primary components:
ROPAManager
A comprehensive dashboard for viewing, filtering, and managing all processing activity records. Supports search, categorisation, and bulk operations.
import { ROPAManager } from '@tantainnovative/ndpr-toolkit';
<ROPAManager
ropa={ropa}
onAdd={(record) => console.log('Added:', record)}
onUpdate={(id, updates) => console.log('Updated:', id, updates)}
onArchive={(id) => console.log('Archived:', id)}
/>useROPA Hook
A React hook for managing processing records, generating summaries, and exporting data.
import { useROPA, exportROPAToCSV } from '@tantainnovative/ndpr-toolkit';
function ProcessingRecords() {
const { ropa, addRecord, updateRecord, archiveRecord } = useROPA({
initialData: {
id: 'ropa-1',
organizationName: 'Your Company Ltd',
organizationContact: 'dpo@yourcompany.com',
organizationAddress: 'Lagos, Nigeria',
records: [],
lastUpdated: Date.now(),
version: '1.0',
},
});
return (
<div>
<ROPAManager
ropa={ropa}
onAdd={addRecord}
onUpdate={updateRecord}
onArchive={archiveRecord}
/>
<button onClick={() => exportROPAToCSV(ropa)}>
Export to CSV
</button>
</div>
);
}API Reference
ProcessingRecord Type
interface ProcessingRecord {
id: string;
name: string;
description: string;
controllerDetails: {
name: string;
contact: string;
address: string;
registrationNumber?: string;
dpoContact?: string;
};
jointControllerDetails?: {
name: string;
contact: string;
address: string;
responsibilities: string;
};
processorDetails?: {
name: string;
contact: string;
address: string;
contractReference?: string;
};
lawfulBasis: LawfulBasis;
lawfulBasisJustification: string;
purposes: string[];
dataCategories: string[];
sensitiveDataCategories?: string[];
dataSubjectCategories: string[];
recipients: string[];
crossBorderTransfers?: Array<{
destinationCountry: string;
countryCode?: string;
safeguards: string;
transferMechanism: string;
}>;
retentionPeriod: string;
retentionJustification?: string;
securityMeasures: string[];
dataSource: 'data_subject' | 'third_party' | 'public_source' | 'other';
thirdPartySourceDetails?: string;
dpiaRequired: boolean;
dpiaReference?: string;
automatedDecisionMaking: boolean;
automatedDecisionMakingDetails?: string;
status: 'active' | 'inactive' | 'archived';
department?: string;
systemsUsed?: string[];
createdAt: number;
updatedAt: number;
lastReviewedAt?: number;
nextReviewDate?: number;
}RecordOfProcessingActivities Type
interface RecordOfProcessingActivities {
id: string;
organizationName: string;
organizationContact: string;
organizationAddress: string;
dpoDetails?: {
name: string;
email: string;
phone?: string;
};
ndpcRegistrationNumber?: string;
records: ProcessingRecord[];
lastUpdated: number;
version: string;
exportFormats?: ('pdf' | 'csv' | 'json' | 'xlsx')[];
}ROPAManagerProps
interface ROPAManagerProps {
ropa: RecordOfProcessingActivities;
onAdd?: (record: ProcessingRecord) => void;
onUpdate?: (id: string, updates: Partial<ProcessingRecord>) => void;
onArchive?: (id: string) => void;
title?: string;
description?: string;
className?: string;
buttonClassName?: string;
classNames?: ROPAManagerClassNames;
unstyled?: boolean;
}Lite variant (read-only)
For read-only ROPA surfaces such as compliance dashboards and customer-facing transparency pages, use ROPAManagerLite from the new /ropa/lite subpath. It renders the same record list and summary as the Full component without Add, Edit, Archive, or CSV-export affordances — and ships at 13.2 KB instead of 36.9 KB (a 64% saving, minified and pre-gzip).
import { ROPAManagerLite } from '@tantainnovative/ndpr-toolkit/ropa/lite';
<ROPAManagerLite
ropa={ropa}
onRecordClick={(record) => router.push(`/ropa/${record.id}`)}
/>See the Lite vs Full Managers guide for migration notes, side-by-side examples, and the full bundle-size table.
Best Practices
- Comprehensive Coverage: Record every processing activity, including those handled by third-party processors.
- Regular Updates: Review and update your ROPA at least quarterly, or whenever a new processing activity is introduced.
- Link to DPIA: Cross-reference processing activities with any Data Protection Impact Assessments that have been conducted.
- Include Retention Periods: Clearly document how long data is retained for each activity and the basis for that period.
- Audit Trail: Maintain a history of changes to each record for accountability purposes.