@tantainnovative/ndpr-toolkit 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +20 -0
- package/.eslintrc.json +10 -0
- package/.github/workflows/ci.yml +36 -0
- package/.github/workflows/nextjs.yml +104 -0
- package/.husky/commit-msg +4 -0
- package/.husky/pre-commit +4 -0
- package/.lintstagedrc.js +4 -0
- package/.nvmrc +1 -0
- package/.versionrc +17 -0
- package/CHANGELOG.md +16 -0
- package/CLAUDE.md +90 -0
- package/CNAME +1 -0
- package/CONTRIBUTING.md +87 -0
- package/README.md +84 -431
- package/RELEASE-NOTES-v1.0.0.md +140 -0
- package/RELEASE-NOTES-v1.0.1.md +69 -0
- package/SECURITY.md +21 -0
- package/commitlint.config.js +36 -0
- package/components.json +21 -0
- package/eslint.config.mjs +16 -0
- package/jest.config.js +31 -0
- package/jest.setup.js +15 -0
- package/next.config.js +15 -0
- package/next.config.ts +62 -0
- package/package.json +70 -52
- package/packages/ndpr-toolkit/README.md +467 -0
- package/packages/ndpr-toolkit/jest.config.js +23 -0
- package/packages/ndpr-toolkit/package-lock.json +8197 -0
- package/packages/ndpr-toolkit/package.json +71 -0
- package/packages/ndpr-toolkit/rollup.config.js +34 -0
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +119 -0
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +122 -0
- package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +270 -0
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +199 -0
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +224 -0
- package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +104 -0
- package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +161 -0
- package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +330 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +149 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +88 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +160 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +110 -0
- package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +97 -0
- package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +701 -0
- package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +631 -0
- package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +569 -0
- package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +496 -0
- package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +270 -0
- package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +217 -0
- package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +206 -0
- package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +342 -0
- package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +373 -0
- package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +174 -0
- package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +717 -0
- package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +476 -0
- package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +620 -0
- package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +541 -0
- package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +454 -0
- package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +333 -0
- package/packages/ndpr-toolkit/src/hooks/useBreach.ts +409 -0
- package/packages/ndpr-toolkit/src/hooks/useConsent.ts +263 -0
- package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +457 -0
- package/packages/ndpr-toolkit/src/hooks/useDSR.ts +236 -0
- package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +428 -0
- package/{dist/index.d.ts → packages/ndpr-toolkit/src/index.ts} +14 -1
- package/packages/ndpr-toolkit/src/setupTests.ts +5 -0
- package/packages/ndpr-toolkit/src/types/breach.ts +283 -0
- package/packages/ndpr-toolkit/src/types/consent.ts +111 -0
- package/packages/ndpr-toolkit/src/types/dpia.ts +236 -0
- package/packages/ndpr-toolkit/src/types/dsr.ts +192 -0
- package/packages/ndpr-toolkit/src/types/index.ts +42 -0
- package/packages/ndpr-toolkit/src/types/privacy.ts +246 -0
- package/packages/ndpr-toolkit/src/utils/breach.ts +122 -0
- package/packages/ndpr-toolkit/src/utils/consent.ts +51 -0
- package/packages/ndpr-toolkit/src/utils/dpia.ts +104 -0
- package/packages/ndpr-toolkit/src/utils/dsr.ts +77 -0
- package/packages/ndpr-toolkit/src/utils/privacy.ts +100 -0
- package/packages/ndpr-toolkit/tsconfig.json +23 -0
- package/postcss.config.mjs +5 -0
- package/public/NDPR TOOLKIT.svg +1 -0
- package/public/favicon/android-chrome-192x192.png +0 -0
- package/public/favicon/android-chrome-512x512.png +0 -0
- package/public/favicon/apple-touch-icon.png +0 -0
- package/public/favicon/favicon-16x16.png +0 -0
- package/public/favicon/favicon-32x32.png +0 -0
- package/public/favicon/site.webmanifest +1 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/ndpr-toolkit-logo.svg +108 -0
- package/public/next.svg +1 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/src/__tests__/example.test.ts +13 -0
- package/src/__tests__/requestService.test.ts +57 -0
- package/src/app/accessibility.css +70 -0
- package/src/app/docs/components/DocLayout.tsx +267 -0
- package/src/app/docs/components/breach-notification/page.tsx +797 -0
- package/src/app/docs/components/consent-management/page.tsx +576 -0
- package/src/app/docs/components/data-subject-rights/page.tsx +511 -0
- package/src/app/docs/components/dpia-questionnaire/layout.tsx +15 -0
- package/src/app/docs/components/dpia-questionnaire/metadata.ts +31 -0
- package/src/app/docs/components/dpia-questionnaire/page.tsx +666 -0
- package/src/app/docs/components/hooks/page.tsx +305 -0
- package/src/app/docs/components/page.tsx +84 -0
- package/src/app/docs/components/privacy-policy-generator/page.tsx +634 -0
- package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +123 -0
- package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +328 -0
- package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +28 -0
- package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +91 -0
- package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +118 -0
- package/src/app/docs/guides/breach-notification-process/page.tsx +39 -0
- package/src/app/docs/guides/conducting-dpia/page.tsx +593 -0
- package/src/app/docs/guides/data-subject-requests/page.tsx +666 -0
- package/src/app/docs/guides/managing-consent/page.tsx +738 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +296 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +145 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +33 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +99 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +159 -0
- package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +38 -0
- package/src/app/docs/guides/page.tsx +67 -0
- package/src/app/docs/layout.tsx +15 -0
- package/src/app/docs/metadata.ts +31 -0
- package/src/app/docs/page.tsx +572 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +123 -0
- package/src/app/layout.tsx +37 -0
- package/src/app/ndpr-demos/breach/page.tsx +354 -0
- package/src/app/ndpr-demos/consent/page.tsx +366 -0
- package/src/app/ndpr-demos/dpia/page.tsx +495 -0
- package/src/app/ndpr-demos/dsr/page.tsx +280 -0
- package/src/app/ndpr-demos/page.tsx +73 -0
- package/src/app/ndpr-demos/policy/page.tsx +771 -0
- package/src/app/page.tsx +452 -0
- package/src/components/ErrorBoundary.tsx +90 -0
- package/src/components/breach-notification/BreachNotificationForm.tsx +479 -0
- package/src/components/consent/ConsentBanner.tsx +159 -0
- package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +419 -0
- package/src/components/docs/DocLayout.tsx +289 -0
- package/src/components/docs/index.ts +2 -0
- package/src/components/dpia/DPIAQuestionnaire.tsx +483 -0
- package/src/components/privacy-policy/PolicyGenerator.tsx +1062 -0
- package/src/components/privacy-policy/data.ts +98 -0
- package/src/components/privacy-policy/shared/CheckboxField.tsx +38 -0
- package/src/components/privacy-policy/shared/CheckboxGroup.tsx +85 -0
- package/src/components/privacy-policy/shared/FormField.tsx +79 -0
- package/src/components/privacy-policy/shared/StepIndicator.tsx +86 -0
- package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +335 -0
- package/src/components/privacy-policy/steps/DataCollectionStep.tsx +231 -0
- package/src/components/privacy-policy/steps/DataSharingStep.tsx +418 -0
- package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +202 -0
- package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +172 -0
- package/src/components/ui/Badge.tsx +46 -0
- package/src/components/ui/Button.tsx +59 -0
- package/src/components/ui/Card.tsx +92 -0
- package/src/components/ui/Checkbox.tsx +57 -0
- package/src/components/ui/FormField.tsx +50 -0
- package/src/components/ui/Input.tsx +38 -0
- package/src/components/ui/Loading.tsx +201 -0
- package/src/components/ui/Select.tsx +42 -0
- package/src/components/ui/TextArea.tsx +38 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/tabs.tsx +66 -0
- package/src/hooks/useConsent.ts +64 -0
- package/src/hooks/useLoadingState.ts +85 -0
- package/src/lib/consentService.ts +137 -0
- package/src/lib/dpiaQuestions.ts +148 -0
- package/src/lib/requestService.ts +75 -0
- package/src/lib/sanitize.ts +108 -0
- package/src/lib/storage.ts +222 -0
- package/src/lib/utils.ts +6 -0
- package/src/types/html-to-docx.d.ts +30 -0
- package/src/types/index.ts +72 -0
- package/tailwind.config.ts +65 -0
- package/tsconfig.json +41 -0
- package/dist/components/breach/BreachNotificationManager.d.ts +0 -62
- package/dist/components/breach/BreachReportForm.d.ts +0 -66
- package/dist/components/breach/BreachRiskAssessment.d.ts +0 -50
- package/dist/components/breach/RegulatoryReportGenerator.d.ts +0 -94
- package/dist/components/consent/ConsentBanner.d.ts +0 -79
- package/dist/components/consent/ConsentManager.d.ts +0 -73
- package/dist/components/consent/ConsentStorage.d.ts +0 -41
- package/dist/components/dpia/DPIAQuestionnaire.d.ts +0 -70
- package/dist/components/dpia/DPIAReport.d.ts +0 -40
- package/dist/components/dpia/StepIndicator.d.ts +0 -64
- package/dist/components/dsr/DSRDashboard.d.ts +0 -58
- package/dist/components/dsr/DSRRequestForm.d.ts +0 -74
- package/dist/components/dsr/DSRTracker.d.ts +0 -56
- package/dist/components/policy/PolicyExporter.d.ts +0 -65
- package/dist/components/policy/PolicyGenerator.d.ts +0 -54
- package/dist/components/policy/PolicyPreview.d.ts +0 -71
- package/dist/hooks/useBreach.d.ts +0 -97
- package/dist/hooks/useConsent.d.ts +0 -63
- package/dist/hooks/useDPIA.d.ts +0 -92
- package/dist/hooks/useDSR.d.ts +0 -72
- package/dist/hooks/usePrivacyPolicy.d.ts +0 -87
- package/dist/index.esm.js +0 -2
- package/dist/index.esm.js.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/setupTests.d.ts +0 -2
- package/dist/types/breach.d.ts +0 -239
- package/dist/types/consent.d.ts +0 -95
- package/dist/types/dpia.d.ts +0 -196
- package/dist/types/dsr.d.ts +0 -162
- package/dist/types/privacy.d.ts +0 -204
- package/dist/utils/breach.d.ts +0 -14
- package/dist/utils/consent.d.ts +0 -10
- package/dist/utils/dpia.d.ts +0 -12
- package/dist/utils/dsr.d.ts +0 -11
- package/dist/utils/privacy.d.ts +0 -12
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { DocLayout } from '@/components/docs/DocLayout';
|
|
5
|
+
import { Button } from '@/components/ui/Button';
|
|
6
|
+
import { Card, CardContent } from '@/components/ui/Card';
|
|
7
|
+
|
|
8
|
+
export default function BreachNotificationDocs() {
|
|
9
|
+
return (
|
|
10
|
+
<DocLayout
|
|
11
|
+
title="Breach Notification System"
|
|
12
|
+
description="NDPR-compliant system for managing and reporting data breaches"
|
|
13
|
+
>
|
|
14
|
+
<div className="flex mb-6 space-x-2">
|
|
15
|
+
<Button asChild variant="outline" size="sm">
|
|
16
|
+
<Link href="/ndpr-demos/breach-notification">
|
|
17
|
+
View Demo
|
|
18
|
+
</Link>
|
|
19
|
+
</Button>
|
|
20
|
+
<Button asChild variant="outline" size="sm">
|
|
21
|
+
<a href="https://github.com/tantainnovative/ndpr-toolkit/tree/main/src/components/breach-notification" target="_blank" rel="noopener noreferrer">
|
|
22
|
+
View Source
|
|
23
|
+
</a>
|
|
24
|
+
</Button>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<section id="overview" className="mb-8">
|
|
28
|
+
<h2 className="text-2xl font-bold mb-4">Overview</h2>
|
|
29
|
+
<p className="mb-4">
|
|
30
|
+
The Breach Notification System provides a complete solution for detecting, managing, and reporting data breaches
|
|
31
|
+
in compliance with the Nigeria Data Protection Regulation (NDPR). It includes components for breach reporting,
|
|
32
|
+
risk assessment, notification management, and regulatory reporting.
|
|
33
|
+
</p>
|
|
34
|
+
<div className="bg-blue-50 dark:bg-blue-900/20 p-4 rounded-md">
|
|
35
|
+
<h4 className="text-blue-800 dark:text-blue-200 font-medium mb-2">NDPR Breach Notification Requirements</h4>
|
|
36
|
+
<p className="text-blue-700 dark:text-blue-300 text-sm mb-0">
|
|
37
|
+
Under the NDPR, organizations must report data breaches to the National Information Technology Development Agency (NITDA)
|
|
38
|
+
within 72 hours of becoming aware of the breach. Organizations must also notify affected data subjects without undue delay.
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
</section>
|
|
42
|
+
|
|
43
|
+
<section id="installation" className="mb-8">
|
|
44
|
+
<h2 className="text-2xl font-bold mb-4">Installation</h2>
|
|
45
|
+
<p className="mb-4">
|
|
46
|
+
Install the NDPR Toolkit package which includes the Breach Notification components:
|
|
47
|
+
</p>
|
|
48
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto mb-4">
|
|
49
|
+
<pre><code>npm install @tantainnovative/ndpr-toolkit</code></pre>
|
|
50
|
+
</div>
|
|
51
|
+
<p>
|
|
52
|
+
Or if you're using yarn:
|
|
53
|
+
</p>
|
|
54
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
55
|
+
<pre><code>yarn add @tantainnovative/ndpr-toolkit</code></pre>
|
|
56
|
+
</div>
|
|
57
|
+
</section>
|
|
58
|
+
|
|
59
|
+
<section id="components" className="mb-8">
|
|
60
|
+
<h2 className="text-2xl font-bold mb-4">Components</h2>
|
|
61
|
+
<p className="mb-4">
|
|
62
|
+
The Breach Notification system includes several components that work together:
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<div className="space-y-6">
|
|
66
|
+
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
67
|
+
<h3 className="text-xl font-bold mb-2">BreachReportForm</h3>
|
|
68
|
+
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
69
|
+
A form for internal staff to report suspected data breaches, capturing essential details.
|
|
70
|
+
</p>
|
|
71
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
72
|
+
<pre><code>{`import { BreachReportForm } from '@tantainnovative/ndpr-toolkit';
|
|
73
|
+
|
|
74
|
+
<BreachReportForm
|
|
75
|
+
onSubmit={handleSubmitBreachReport}
|
|
76
|
+
categories={[
|
|
77
|
+
{ id: 'unauthorized-access', label: 'Unauthorized Access' },
|
|
78
|
+
{ id: 'data-loss', label: 'Data Loss' },
|
|
79
|
+
{ id: 'system-compromise', label: 'System Compromise' },
|
|
80
|
+
{ id: 'phishing', label: 'Phishing Attack' },
|
|
81
|
+
{ id: 'other', label: 'Other' }
|
|
82
|
+
]}
|
|
83
|
+
/>`}</code></pre>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
88
|
+
<h3 className="text-xl font-bold mb-2">BreachRiskAssessment</h3>
|
|
89
|
+
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
90
|
+
A tool for assessing the risk level of a data breach and determining notification requirements.
|
|
91
|
+
</p>
|
|
92
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
93
|
+
<pre><code>{`import { BreachRiskAssessment } from '@tantainnovative/ndpr-toolkit';
|
|
94
|
+
|
|
95
|
+
<BreachRiskAssessment
|
|
96
|
+
breachData={breachData}
|
|
97
|
+
onComplete={handleRiskAssessmentComplete}
|
|
98
|
+
/>`}</code></pre>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
103
|
+
<h3 className="text-xl font-bold mb-2">BreachNotificationManager</h3>
|
|
104
|
+
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
105
|
+
A dashboard for managing breach notifications, including tracking notification status and deadlines.
|
|
106
|
+
</p>
|
|
107
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
108
|
+
<pre><code>{`import { BreachNotificationManager } from '@tantainnovative/ndpr-toolkit';
|
|
109
|
+
|
|
110
|
+
<BreachNotificationManager
|
|
111
|
+
breaches={breaches}
|
|
112
|
+
onUpdateStatus={handleUpdateStatus}
|
|
113
|
+
onSendNotification={handleSendNotification}
|
|
114
|
+
/>`}</code></pre>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
119
|
+
<h3 className="text-xl font-bold mb-2">RegulatoryReportGenerator</h3>
|
|
120
|
+
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
|
121
|
+
A tool for generating NDPR-compliant breach notification reports for submission to NITDA.
|
|
122
|
+
</p>
|
|
123
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
124
|
+
<pre><code>{`import { RegulatoryReportGenerator } from '@tantainnovative/ndpr-toolkit';
|
|
125
|
+
|
|
126
|
+
<RegulatoryReportGenerator
|
|
127
|
+
breachData={breachData}
|
|
128
|
+
organizationInfo={organizationInfo}
|
|
129
|
+
onGenerate={handleGenerateReport}
|
|
130
|
+
/>`}</code></pre>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</section>
|
|
135
|
+
|
|
136
|
+
<section id="usage" className="mb-8">
|
|
137
|
+
<h2 className="text-2xl font-bold mb-4">Usage</h2>
|
|
138
|
+
<p className="mb-4">
|
|
139
|
+
Here's a complete example of how to implement the Breach Notification system in your application:
|
|
140
|
+
</p>
|
|
141
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
142
|
+
<pre><code>{`import { useState, useEffect } from 'react';
|
|
143
|
+
import {
|
|
144
|
+
BreachReportForm,
|
|
145
|
+
BreachRiskAssessment,
|
|
146
|
+
BreachNotificationManager,
|
|
147
|
+
RegulatoryReportGenerator
|
|
148
|
+
} from '@tantainnovative/ndpr-toolkit';
|
|
149
|
+
|
|
150
|
+
// Define breach categories
|
|
151
|
+
const breachCategories = [
|
|
152
|
+
{ id: 'unauthorized-access', label: 'Unauthorized Access' },
|
|
153
|
+
{ id: 'data-loss', label: 'Data Loss' },
|
|
154
|
+
{ id: 'system-compromise', label: 'System Compromise' },
|
|
155
|
+
{ id: 'phishing', label: 'Phishing Attack' },
|
|
156
|
+
{ id: 'other', label: 'Other' }
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
// Organization information
|
|
160
|
+
const organizationInfo = {
|
|
161
|
+
name: 'Example Company Ltd.',
|
|
162
|
+
address: '123 Main Street, Lagos, Nigeria',
|
|
163
|
+
dpoName: 'John Doe',
|
|
164
|
+
dpoEmail: 'dpo@example.com',
|
|
165
|
+
dpoPhone: '+234 123 456 7890'
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Sample breach service (replace with your actual data service)
|
|
169
|
+
const breachService = {
|
|
170
|
+
breaches: [],
|
|
171
|
+
|
|
172
|
+
reportBreach: (breachData) => {
|
|
173
|
+
const newBreach = {
|
|
174
|
+
...breachData,
|
|
175
|
+
id: \`breach-\${Date.now()}\`,
|
|
176
|
+
status: 'reported',
|
|
177
|
+
reportedAt: new Date(),
|
|
178
|
+
riskAssessment: null,
|
|
179
|
+
notifications: [],
|
|
180
|
+
regulatoryReport: null
|
|
181
|
+
};
|
|
182
|
+
breachService.breaches.push(newBreach);
|
|
183
|
+
return newBreach;
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
getBreaches: () => {
|
|
187
|
+
return breachService.breaches;
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
getBreachById: (id) => {
|
|
191
|
+
return breachService.breaches.find(breach => breach.id === id);
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
updateBreachStatus: (id, status) => {
|
|
195
|
+
const breach = breachService.breaches.find(breach => breach.id === id);
|
|
196
|
+
if (breach) {
|
|
197
|
+
breach.status = status;
|
|
198
|
+
breach.updatedAt = new Date();
|
|
199
|
+
}
|
|
200
|
+
return breach;
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
saveRiskAssessment: (id, assessment) => {
|
|
204
|
+
const breach = breachService.breaches.find(breach => breach.id === id);
|
|
205
|
+
if (breach) {
|
|
206
|
+
breach.riskAssessment = assessment;
|
|
207
|
+
breach.updatedAt = new Date();
|
|
208
|
+
|
|
209
|
+
// Update status based on risk level
|
|
210
|
+
if (assessment.riskLevel === 'high') {
|
|
211
|
+
breach.status = 'high-risk';
|
|
212
|
+
} else if (assessment.riskLevel === 'medium') {
|
|
213
|
+
breach.status = 'medium-risk';
|
|
214
|
+
} else {
|
|
215
|
+
breach.status = 'low-risk';
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return breach;
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
recordNotification: (id, notification) => {
|
|
222
|
+
const breach = breachService.breaches.find(breach => breach.id === id);
|
|
223
|
+
if (breach) {
|
|
224
|
+
breach.notifications.push({
|
|
225
|
+
...notification,
|
|
226
|
+
id: \`notification-\${Date.now()}\`,
|
|
227
|
+
sentAt: new Date()
|
|
228
|
+
});
|
|
229
|
+
breach.updatedAt = new Date();
|
|
230
|
+
|
|
231
|
+
// Update status if all required notifications are sent
|
|
232
|
+
if (breach.notifications.length >= breach.riskAssessment.requiredNotifications.length) {
|
|
233
|
+
breach.status = 'notifications-complete';
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return breach;
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
saveRegulatoryReport: (id, report) => {
|
|
240
|
+
const breach = breachService.breaches.find(breach => breach.id === id);
|
|
241
|
+
if (breach) {
|
|
242
|
+
breach.regulatoryReport = {
|
|
243
|
+
...report,
|
|
244
|
+
generatedAt: new Date()
|
|
245
|
+
};
|
|
246
|
+
breach.status = 'report-generated';
|
|
247
|
+
breach.updatedAt = new Date();
|
|
248
|
+
}
|
|
249
|
+
return breach;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// Breach reporting form component
|
|
254
|
+
function BreachReportingPage() {
|
|
255
|
+
const [submitted, setSubmitted] = useState(false);
|
|
256
|
+
const [currentBreach, setCurrentBreach] = useState(null);
|
|
257
|
+
|
|
258
|
+
const handleSubmitBreachReport = (breachData) => {
|
|
259
|
+
const newBreach = breachService.reportBreach(breachData);
|
|
260
|
+
setCurrentBreach(newBreach);
|
|
261
|
+
setSubmitted(true);
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const handleRiskAssessmentComplete = (assessment) => {
|
|
265
|
+
const updatedBreach = breachService.saveRiskAssessment(currentBreach.id, assessment);
|
|
266
|
+
setCurrentBreach(updatedBreach);
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return (
|
|
270
|
+
<div>
|
|
271
|
+
<h1>Data Breach Reporting</h1>
|
|
272
|
+
|
|
273
|
+
{!submitted ? (
|
|
274
|
+
<>
|
|
275
|
+
<p>
|
|
276
|
+
Use this form to report a suspected data breach. All breaches must be
|
|
277
|
+
reported internally within 24 hours of discovery.
|
|
278
|
+
</p>
|
|
279
|
+
|
|
280
|
+
<BreachReportForm
|
|
281
|
+
onSubmit={handleSubmitBreachReport}
|
|
282
|
+
categories={breachCategories}
|
|
283
|
+
/>
|
|
284
|
+
</>
|
|
285
|
+
) : (
|
|
286
|
+
<div>
|
|
287
|
+
<h2>Breach Reported</h2>
|
|
288
|
+
<p>
|
|
289
|
+
The breach has been reported successfully. Reference number: <strong>{currentBreach.id}</strong>
|
|
290
|
+
</p>
|
|
291
|
+
|
|
292
|
+
<h3>Risk Assessment</h3>
|
|
293
|
+
<p>
|
|
294
|
+
Please complete the risk assessment to determine notification requirements.
|
|
295
|
+
</p>
|
|
296
|
+
|
|
297
|
+
<BreachRiskAssessment
|
|
298
|
+
breachData={currentBreach}
|
|
299
|
+
onComplete={handleRiskAssessmentComplete}
|
|
300
|
+
/>
|
|
301
|
+
|
|
302
|
+
{currentBreach.riskAssessment && (
|
|
303
|
+
<div>
|
|
304
|
+
<h3>Risk Assessment Complete</h3>
|
|
305
|
+
<p>
|
|
306
|
+
Risk Level: <strong>{currentBreach.riskAssessment.riskLevel}</strong>
|
|
307
|
+
</p>
|
|
308
|
+
<p>
|
|
309
|
+
{currentBreach.riskAssessment.requiresNitdaNotification
|
|
310
|
+
? 'NITDA notification is required within 72 hours.'
|
|
311
|
+
: 'NITDA notification is not required.'}
|
|
312
|
+
</p>
|
|
313
|
+
<p>
|
|
314
|
+
{currentBreach.riskAssessment.requiresDataSubjectNotification
|
|
315
|
+
? 'Data subject notification is required without undue delay.'
|
|
316
|
+
: 'Data subject notification is not required.'}
|
|
317
|
+
</p>
|
|
318
|
+
</div>
|
|
319
|
+
)}
|
|
320
|
+
</div>
|
|
321
|
+
)}
|
|
322
|
+
</div>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Breach management dashboard component
|
|
327
|
+
function BreachManagementDashboard() {
|
|
328
|
+
const [breaches, setBreaches] = useState([]);
|
|
329
|
+
const [selectedBreach, setSelectedBreach] = useState(null);
|
|
330
|
+
|
|
331
|
+
useEffect(() => {
|
|
332
|
+
// Load breaches from service
|
|
333
|
+
setBreaches(breachService.getBreaches());
|
|
334
|
+
}, []);
|
|
335
|
+
|
|
336
|
+
const handleUpdateStatus = (id, status) => {
|
|
337
|
+
const updatedBreach = breachService.updateBreachStatus(id, status);
|
|
338
|
+
setBreaches(breachService.getBreaches());
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const handleSendNotification = (id, notification) => {
|
|
342
|
+
const updatedBreach = breachService.recordNotification(id, notification);
|
|
343
|
+
setBreaches(breachService.getBreaches());
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const handleGenerateReport = (id, report) => {
|
|
347
|
+
const updatedBreach = breachService.saveRegulatoryReport(id, report);
|
|
348
|
+
setBreaches(breachService.getBreaches());
|
|
349
|
+
setSelectedBreach(updatedBreach);
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
return (
|
|
353
|
+
<div>
|
|
354
|
+
<h1>Breach Management Dashboard</h1>
|
|
355
|
+
|
|
356
|
+
<BreachNotificationManager
|
|
357
|
+
breaches={breaches}
|
|
358
|
+
onUpdateStatus={handleUpdateStatus}
|
|
359
|
+
onSendNotification={handleSendNotification}
|
|
360
|
+
onSelectBreach={setSelectedBreach}
|
|
361
|
+
/>
|
|
362
|
+
|
|
363
|
+
{selectedBreach && selectedBreach.riskAssessment &&
|
|
364
|
+
selectedBreach.riskAssessment.requiresNitdaNotification && (
|
|
365
|
+
<div>
|
|
366
|
+
<h2>Regulatory Report Generator</h2>
|
|
367
|
+
<p>
|
|
368
|
+
Generate a NITDA breach notification report for submission.
|
|
369
|
+
</p>
|
|
370
|
+
|
|
371
|
+
<RegulatoryReportGenerator
|
|
372
|
+
breachData={selectedBreach}
|
|
373
|
+
organizationInfo={organizationInfo}
|
|
374
|
+
onGenerate={(report) => handleGenerateReport(selectedBreach.id, report)}
|
|
375
|
+
/>
|
|
376
|
+
</div>
|
|
377
|
+
)}
|
|
378
|
+
</div>
|
|
379
|
+
);
|
|
380
|
+
}`}</code></pre>
|
|
381
|
+
</div>
|
|
382
|
+
</section>
|
|
383
|
+
|
|
384
|
+
<section id="props" className="mb-8">
|
|
385
|
+
<h2 className="text-2xl font-bold mb-4">Props</h2>
|
|
386
|
+
|
|
387
|
+
<h3 className="text-xl font-bold mb-4">BreachReportForm Props</h3>
|
|
388
|
+
<div className="overflow-x-auto">
|
|
389
|
+
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
390
|
+
<thead className="bg-gray-50 dark:bg-gray-800">
|
|
391
|
+
<tr>
|
|
392
|
+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Name</th>
|
|
393
|
+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Type</th>
|
|
394
|
+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Required</th>
|
|
395
|
+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Description</th>
|
|
396
|
+
</tr>
|
|
397
|
+
</thead>
|
|
398
|
+
<tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-800">
|
|
399
|
+
<tr>
|
|
400
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white"><code>onSubmit</code></td>
|
|
401
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><code>(data: BreachReport) => void</code></td>
|
|
402
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">Yes</td>
|
|
403
|
+
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">Callback function when user submits a breach report</td>
|
|
404
|
+
</tr>
|
|
405
|
+
<tr>
|
|
406
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white"><code>categories</code></td>
|
|
407
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><code>{'{ id: string, label: string }[]'}</code></td>
|
|
408
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">Yes</td>
|
|
409
|
+
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">Array of breach categories to display</td>
|
|
410
|
+
</tr>
|
|
411
|
+
<tr>
|
|
412
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white"><code>initialValues</code></td>
|
|
413
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400"><code>Partial<BreachReport></code></td>
|
|
414
|
+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">No</td>
|
|
415
|
+
<td className="px-6 py-4 text-sm text-gray-500 dark:text-gray-400">Initial values for the form fields</td>
|
|
416
|
+
</tr>
|
|
417
|
+
</tbody>
|
|
418
|
+
</table>
|
|
419
|
+
</div>
|
|
420
|
+
|
|
421
|
+
<h3 className="text-xl font-bold mt-8 mb-4">BreachReport Type</h3>
|
|
422
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
423
|
+
<pre><code>{`type BreachReport = {
|
|
424
|
+
id?: string;
|
|
425
|
+
title: string;
|
|
426
|
+
category: string;
|
|
427
|
+
description: string;
|
|
428
|
+
discoveredAt: Date;
|
|
429
|
+
reportedBy: {
|
|
430
|
+
name: string;
|
|
431
|
+
email: string;
|
|
432
|
+
department: string;
|
|
433
|
+
};
|
|
434
|
+
affectedSystems: string[];
|
|
435
|
+
affectedDataTypes: string[];
|
|
436
|
+
estimatedImpact: string;
|
|
437
|
+
initialActions: string;
|
|
438
|
+
status?: string;
|
|
439
|
+
reportedAt?: Date;
|
|
440
|
+
updatedAt?: Date;
|
|
441
|
+
};`}</code></pre>
|
|
442
|
+
</div>
|
|
443
|
+
</section>
|
|
444
|
+
|
|
445
|
+
<section id="72-hour-timeline" className="mb-8">
|
|
446
|
+
<h2 className="text-2xl font-bold mb-4">72-Hour Notification Timeline</h2>
|
|
447
|
+
<p className="mb-4">
|
|
448
|
+
The NDPR requires organizations to notify NITDA of data breaches within 72 hours of becoming aware of the breach.
|
|
449
|
+
Here's a recommended timeline for handling breaches:
|
|
450
|
+
</p>
|
|
451
|
+
|
|
452
|
+
<div className="relative border-l-2 border-blue-500 pl-8 pb-8 space-y-10">
|
|
453
|
+
<div className="relative">
|
|
454
|
+
<div className="absolute -left-10 mt-1.5 h-6 w-6 rounded-full bg-blue-500 flex items-center justify-center">
|
|
455
|
+
<span className="text-white font-bold text-sm">1</span>
|
|
456
|
+
</div>
|
|
457
|
+
<h3 className="text-xl font-bold">Hour 0-4: Initial Response</h3>
|
|
458
|
+
<p className="text-gray-600 dark:text-gray-300 mt-2">
|
|
459
|
+
- Report the breach internally using the BreachReportForm<br />
|
|
460
|
+
- Assemble the response team<br />
|
|
461
|
+
- Begin containment measures<br />
|
|
462
|
+
- Preserve evidence
|
|
463
|
+
</p>
|
|
464
|
+
</div>
|
|
465
|
+
|
|
466
|
+
<div className="relative">
|
|
467
|
+
<div className="absolute -left-10 mt-1.5 h-6 w-6 rounded-full bg-blue-500 flex items-center justify-center">
|
|
468
|
+
<span className="text-white font-bold text-sm">2</span>
|
|
469
|
+
</div>
|
|
470
|
+
<h3 className="text-xl font-bold">Hour 4-24: Risk Assessment</h3>
|
|
471
|
+
<p className="text-gray-600 dark:text-gray-300 mt-2">
|
|
472
|
+
- Complete the BreachRiskAssessment<br />
|
|
473
|
+
- Determine notification requirements<br />
|
|
474
|
+
- Continue containment and investigation<br />
|
|
475
|
+
- Begin preparing notification drafts
|
|
476
|
+
</p>
|
|
477
|
+
</div>
|
|
478
|
+
|
|
479
|
+
<div className="relative">
|
|
480
|
+
<div className="absolute -left-10 mt-1.5 h-6 w-6 rounded-full bg-blue-500 flex items-center justify-center">
|
|
481
|
+
<span className="text-white font-bold text-sm">3</span>
|
|
482
|
+
</div>
|
|
483
|
+
<h3 className="text-xl font-bold">Hour 24-48: Notification Preparation</h3>
|
|
484
|
+
<p className="text-gray-600 dark:text-gray-300 mt-2">
|
|
485
|
+
- Use the RegulatoryReportGenerator to prepare NITDA notification<br />
|
|
486
|
+
- Draft data subject notifications if required<br />
|
|
487
|
+
- Review and approve notifications<br />
|
|
488
|
+
- Continue investigation and remediation
|
|
489
|
+
</p>
|
|
490
|
+
</div>
|
|
491
|
+
|
|
492
|
+
<div className="relative">
|
|
493
|
+
<div className="absolute -left-10 mt-1.5 h-6 w-6 rounded-full bg-blue-500 flex items-center justify-center">
|
|
494
|
+
<span className="text-white font-bold text-sm">4</span>
|
|
495
|
+
</div>
|
|
496
|
+
<h3 className="text-xl font-bold">Hour 48-72: Notification Submission</h3>
|
|
497
|
+
<p className="text-gray-600 dark:text-gray-300 mt-2">
|
|
498
|
+
- Submit notification to NITDA<br />
|
|
499
|
+
- Begin notifying affected data subjects if required<br />
|
|
500
|
+
- Document all notification activities<br />
|
|
501
|
+
- Continue remediation efforts
|
|
502
|
+
</p>
|
|
503
|
+
</div>
|
|
504
|
+
</div>
|
|
505
|
+
</section>
|
|
506
|
+
|
|
507
|
+
<section id="api" className="mb-8">
|
|
508
|
+
<h2 className="text-2xl font-bold mb-4">API Reference</h2>
|
|
509
|
+
|
|
510
|
+
<h3 className="text-xl font-bold mt-8 mb-4">BreachReport Interface</h3>
|
|
511
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
512
|
+
<pre><code>{`export interface BreachReport {
|
|
513
|
+
/**
|
|
514
|
+
* Unique identifier for the breach report
|
|
515
|
+
*/
|
|
516
|
+
id: string;
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Title/summary of the breach
|
|
520
|
+
*/
|
|
521
|
+
title: string;
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Detailed description of the breach
|
|
525
|
+
*/
|
|
526
|
+
description: string;
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Category of the breach
|
|
530
|
+
*/
|
|
531
|
+
category: string;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Timestamp when the breach was discovered
|
|
535
|
+
*/
|
|
536
|
+
discoveredAt: number;
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Timestamp when the breach occurred (if known)
|
|
540
|
+
*/
|
|
541
|
+
occurredAt?: number;
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Timestamp when the breach was reported internally
|
|
545
|
+
*/
|
|
546
|
+
reportedAt: number;
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Person who reported the breach
|
|
550
|
+
*/
|
|
551
|
+
reporter: {
|
|
552
|
+
name: string;
|
|
553
|
+
email: string;
|
|
554
|
+
department: string;
|
|
555
|
+
phone?: string;
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Systems or data affected by the breach
|
|
560
|
+
*/
|
|
561
|
+
affectedSystems: string[];
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Types of data involved in the breach
|
|
565
|
+
*/
|
|
566
|
+
dataTypes: string[];
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Estimated number of data subjects affected
|
|
570
|
+
*/
|
|
571
|
+
estimatedAffectedSubjects?: number;
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Whether the breach is ongoing or contained
|
|
575
|
+
*/
|
|
576
|
+
status: 'ongoing' | 'contained' | 'resolved';
|
|
577
|
+
}`}</code></pre>
|
|
578
|
+
</div>
|
|
579
|
+
|
|
580
|
+
<h3 className="text-xl font-bold mt-8 mb-4">RiskAssessment Interface</h3>
|
|
581
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
582
|
+
<pre><code>{`export interface RiskAssessment {
|
|
583
|
+
/**
|
|
584
|
+
* Unique identifier for the risk assessment
|
|
585
|
+
*/
|
|
586
|
+
id: string;
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* ID of the breach this assessment is for
|
|
590
|
+
*/
|
|
591
|
+
breachId: string;
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Timestamp when the assessment was conducted
|
|
595
|
+
*/
|
|
596
|
+
assessedAt: number;
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Person who conducted the assessment
|
|
600
|
+
*/
|
|
601
|
+
assessor: {
|
|
602
|
+
name: string;
|
|
603
|
+
role: string;
|
|
604
|
+
email: string;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Confidentiality impact (1-5)
|
|
609
|
+
*/
|
|
610
|
+
confidentialityImpact: number;
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Integrity impact (1-5)
|
|
614
|
+
*/
|
|
615
|
+
integrityImpact: number;
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Availability impact (1-5)
|
|
619
|
+
*/
|
|
620
|
+
availabilityImpact: number;
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Likelihood of harm to data subjects (1-5)
|
|
624
|
+
*/
|
|
625
|
+
harmLikelihood: number;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Severity of potential harm to data subjects (1-5)
|
|
629
|
+
*/
|
|
630
|
+
harmSeverity: number;
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Overall risk score
|
|
634
|
+
*/
|
|
635
|
+
overallRiskScore: number;
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Risk level based on the overall score
|
|
639
|
+
*/
|
|
640
|
+
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Whether the breach is likely to result in a risk to the rights and freedoms of data subjects
|
|
644
|
+
*/
|
|
645
|
+
risksToRightsAndFreedoms: boolean;
|
|
646
|
+
}`}</code></pre>
|
|
647
|
+
</div>
|
|
648
|
+
|
|
649
|
+
<h3 className="text-xl font-bold mt-8 mb-4">NotificationRequirement Interface</h3>
|
|
650
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
651
|
+
<pre><code>{`export interface NotificationRequirement {
|
|
652
|
+
/**
|
|
653
|
+
* Whether NITDA notification is required
|
|
654
|
+
*/
|
|
655
|
+
nitdaNotificationRequired: boolean;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Deadline for NITDA notification (72 hours from discovery)
|
|
659
|
+
*/
|
|
660
|
+
nitdaNotificationDeadline: number;
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Whether data subject notification is required
|
|
664
|
+
*/
|
|
665
|
+
dataSubjectNotificationRequired: boolean;
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Justification for the notification decision
|
|
669
|
+
*/
|
|
670
|
+
justification: string;
|
|
671
|
+
}`}</code></pre>
|
|
672
|
+
</div>
|
|
673
|
+
|
|
674
|
+
<h3 className="text-xl font-bold mt-8 mb-4">useBreach Hook</h3>
|
|
675
|
+
<div className="bg-gray-800 text-gray-200 p-4 rounded-md overflow-x-auto">
|
|
676
|
+
<pre><code>{`// Import the hook
|
|
677
|
+
import { useBreach } from '@tantainnovative/ndpr-toolkit';
|
|
678
|
+
|
|
679
|
+
// Use the hook in your component
|
|
680
|
+
const {
|
|
681
|
+
breaches, // Array of all breach reports
|
|
682
|
+
submitBreachReport, // Function to submit a new breach report
|
|
683
|
+
updateBreachReport, // Function to update an existing breach report
|
|
684
|
+
performRiskAssessment, // Function to perform a risk assessment
|
|
685
|
+
determineNotificationRequirements, // Function to determine notification requirements
|
|
686
|
+
generateRegulatoryReport, // Function to generate a report for NITDA
|
|
687
|
+
getBreachById, // Function to get a breach by ID
|
|
688
|
+
} = useBreach();
|
|
689
|
+
|
|
690
|
+
// Submit a new breach report
|
|
691
|
+
const newBreachReport = submitBreachReport({
|
|
692
|
+
title: 'Unauthorized Database Access',
|
|
693
|
+
description: 'An unauthorized IP address accessed our customer database.',
|
|
694
|
+
category: 'unauthorized-access',
|
|
695
|
+
discoveredAt: Date.now(),
|
|
696
|
+
occurredAt: Date.now() - 3600000, // 1 hour ago
|
|
697
|
+
reporter: {
|
|
698
|
+
name: 'John Doe',
|
|
699
|
+
email: 'john@example.com',
|
|
700
|
+
department: 'IT Security',
|
|
701
|
+
phone: '1234567890'
|
|
702
|
+
},
|
|
703
|
+
affectedSystems: ['customer-database'],
|
|
704
|
+
dataTypes: ['personal-information', 'contact-details'],
|
|
705
|
+
estimatedAffectedSubjects: 500,
|
|
706
|
+
status: 'contained'
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
// Perform a risk assessment
|
|
710
|
+
const riskAssessment = performRiskAssessment({
|
|
711
|
+
breachId: newBreachReport.id,
|
|
712
|
+
assessor: {
|
|
713
|
+
name: 'Jane Smith',
|
|
714
|
+
role: 'Data Protection Officer',
|
|
715
|
+
email: 'jane@example.com'
|
|
716
|
+
},
|
|
717
|
+
confidentialityImpact: 4,
|
|
718
|
+
integrityImpact: 3,
|
|
719
|
+
availabilityImpact: 2,
|
|
720
|
+
harmLikelihood: 3,
|
|
721
|
+
harmSeverity: 4
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
// Determine notification requirements
|
|
725
|
+
const requirements = determineNotificationRequirements({
|
|
726
|
+
breachId: newBreachReport.id,
|
|
727
|
+
riskAssessmentId: riskAssessment.id
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// Generate a regulatory report for NITDA
|
|
731
|
+
if (requirements.nitdaNotificationRequired) {
|
|
732
|
+
const report = generateRegulatoryReport({
|
|
733
|
+
breachId: newBreachReport.id,
|
|
734
|
+
riskAssessmentId: riskAssessment.id
|
|
735
|
+
});
|
|
736
|
+
}`}</code></pre>
|
|
737
|
+
</div>
|
|
738
|
+
</section>
|
|
739
|
+
|
|
740
|
+
<section id="best-practices" className="mb-8">
|
|
741
|
+
<h2 className="text-2xl font-bold mb-4">Best Practices</h2>
|
|
742
|
+
<ul className="list-disc pl-6 space-y-2">
|
|
743
|
+
<li>
|
|
744
|
+
<strong>Breach Response Plan:</strong> Develop a comprehensive breach response plan that includes roles, responsibilities, and procedures.
|
|
745
|
+
</li>
|
|
746
|
+
<li>
|
|
747
|
+
<strong>Regular Training:</strong> Conduct regular training for staff on breach identification, reporting, and response procedures.
|
|
748
|
+
</li>
|
|
749
|
+
<li>
|
|
750
|
+
<strong>Documentation:</strong> Maintain detailed documentation of all breach-related activities, including containment, investigation, and notification.
|
|
751
|
+
</li>
|
|
752
|
+
<li>
|
|
753
|
+
<strong>Testing:</strong> Regularly test your breach response procedures through tabletop exercises or simulations.
|
|
754
|
+
</li>
|
|
755
|
+
<li>
|
|
756
|
+
<strong>Post-Breach Review:</strong> Conduct a thorough review after each breach to identify lessons learned and improve your response procedures.
|
|
757
|
+
</li>
|
|
758
|
+
</ul>
|
|
759
|
+
</section>
|
|
760
|
+
|
|
761
|
+
<section id="help-resources" className="mb-8">
|
|
762
|
+
<h2 className="text-2xl font-bold mb-4">Need Help?</h2>
|
|
763
|
+
<p className="mb-4">
|
|
764
|
+
If you have questions about implementing the Breach Notification system or need assistance with NDPR compliance, check out these resources:
|
|
765
|
+
</p>
|
|
766
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
767
|
+
<Card>
|
|
768
|
+
<CardContent className="p-4">
|
|
769
|
+
<h3 className="font-medium text-gray-900 dark:text-white mb-2">GitHub Issues</h3>
|
|
770
|
+
<p className="text-gray-600 dark:text-gray-300 text-sm mb-3">
|
|
771
|
+
Report bugs or request features on our GitHub repository.
|
|
772
|
+
</p>
|
|
773
|
+
<Button asChild variant="outline" size="sm">
|
|
774
|
+
<a href="https://github.com/tantainnovative/ndpr-toolkit/issues" target="_blank" rel="noopener noreferrer">
|
|
775
|
+
View Issues
|
|
776
|
+
</a>
|
|
777
|
+
</Button>
|
|
778
|
+
</CardContent>
|
|
779
|
+
</Card>
|
|
780
|
+
<Card>
|
|
781
|
+
<CardContent className="p-4">
|
|
782
|
+
<h3 className="font-medium text-gray-900 dark:text-white mb-2">NDPR Resources</h3>
|
|
783
|
+
<p className="text-gray-600 dark:text-gray-300 text-sm mb-3">
|
|
784
|
+
Learn more about NDPR compliance requirements.
|
|
785
|
+
</p>
|
|
786
|
+
<Button asChild variant="outline" size="sm">
|
|
787
|
+
<a href="https://nitda.gov.ng/wp-content/uploads/2020/01/NDPR-Implementation-Framework.pdf" target="_blank" rel="noopener noreferrer">
|
|
788
|
+
NDPR Framework
|
|
789
|
+
</a>
|
|
790
|
+
</Button>
|
|
791
|
+
</CardContent>
|
|
792
|
+
</Card>
|
|
793
|
+
</div>
|
|
794
|
+
</section>
|
|
795
|
+
</DocLayout>
|
|
796
|
+
);
|
|
797
|
+
}
|