@tantainnovative/ndpr-toolkit
Version:
Nigeria Data Protection Toolkit — enterprise-grade compliance components for the Nigeria Data Protection Act (NDPA) 2023
1,437 lines (1,371 loc) • 54.1 kB
text/typescript
import React__default from 'react';
/**
* Adequacy status of a destination country
*/
declare type AdequacyStatus = 'adequate' | 'inadequate' | 'pending_review' | 'unknown';
/**
* Breach notification types aligned with NDPA 2023 Section 40
* Data controllers must notify the NDPC within 72 hours of becoming aware of a breach
* Data subjects must be notified without undue delay when breach is likely to result in high risk
*/
/**
* Represents a data breach category
*/
declare interface BreachCategory {
/** Unique identifier for the category */
id: string;
/** Display name for the category */
name: string;
/** Description of this breach category */
description: string;
/** Default severity level for this category */
defaultSeverity: 'low' | 'medium' | 'high' | 'critical';
}
/**
* Represents the data submitted by the breach report form.
*/
declare interface BreachFormSubmission {
/** Title/summary of the breach */
title: string;
/** Detailed description of the breach */
description: string;
/** Breach category identifier */
category: string;
/** Timestamp (ms) when the breach was discovered */
discoveredAt: number;
/** Timestamp (ms) when the breach occurred (if known) */
occurredAt?: number;
/** Timestamp (ms) when the form was submitted */
reportedAt: number;
/** Person reporting the breach */
reporter: {
name: string;
email: string;
department: string;
phone?: string;
};
/** Systems or applications affected by the breach */
affectedSystems: string[];
/** Types of data involved in the breach */
dataTypes: string[];
/** Estimated number of affected data subjects */
estimatedAffectedSubjects?: number;
/**
* Approximate number of personal data RECORDS concerned. Distinct from
* subject count (one subject may have many records). NDPA Section 40(2).
*/
approximateRecordCount?: number;
/**
* Categories of data subjects affected (e.g. customers, employees, minors).
* NDPA Section 40(2).
*/
dataSubjectCategories?: string[];
/** Whether sensitive personal data (NDPA Section 30) is involved */
involvesSensitiveData?: boolean;
/**
* Likely consequences of the breach for affected data subjects.
* Required content for the NDPC report and Section 40(3) communications.
*/
likelyConsequences?: string;
/**
* Measures taken or proposed to mitigate adverse effects.
* NDPA Section 40(3).
*/
mitigationMeasures?: string;
/**
* Data Protection Officer contact details (Section 32(3)(c) — DPO is the
* named NDPC contact). Falls back to organisation-level DPO if omitted.
*/
dpoContact?: {
name: string;
email: string;
phone?: string;
};
/**
* Whether this is a phased / interim report submitted under Section 40(2)
* before complete information is available.
*/
isPhasedReport?: boolean;
/** ID of the prior phased report this report supplements, if any. */
supplementsReportId?: string;
/** Current status of the breach */
status: 'ongoing' | 'contained' | 'resolved';
/** Initial actions taken to address the breach */
initialActions?: string;
/** File attachments included with the report */
attachments: Array<{
name: string;
type: string;
size: number;
file: File;
}>;
}
declare interface BreachReportFormClassNames {
root?: string;
title?: string;
form?: string;
fieldGroup?: string;
label?: string;
input?: string;
select?: string;
textarea?: string;
submitButton?: string;
/** Alias for submitButton */
primaryButton?: string;
notice?: string;
/** Custom class applied when isSubmitting is true (e.g. a loading overlay) */
loadingOverlay?: string;
/** Live NDPC-notification completeness panel */
completeness?: string;
}
declare interface ComplianceInput {
consent: {
hasConsentMechanism: boolean;
hasPurposeSpecification: boolean;
hasWithdrawalMechanism: boolean;
hasMinorProtection: boolean;
consentRecordsRetained: boolean;
};
dsr: {
hasRequestMechanism: boolean;
supportsAccess: boolean;
supportsRectification: boolean;
supportsErasure: boolean;
supportsPortability: boolean;
supportsObjection: boolean;
/** Expected max response time in days (>30 counts as a gap) */
responseTimelineDays: number;
};
dpia: {
conductedForHighRisk: boolean;
documentedRisks: boolean;
mitigationMeasures: boolean;
};
breach: {
hasNotificationProcess: boolean;
notifiesWithin72Hours: boolean;
hasRiskAssessment: boolean;
hasRecordKeeping: boolean;
};
policy: {
hasPrivacyPolicy: boolean;
isPubliclyAccessible: boolean;
/** ISO date string (YYYY-MM-DD); >13 months old counts as a gap */
lastUpdated: string;
coversAllSections: boolean;
};
lawfulBasis: {
documentedForAllProcessing: boolean;
hasLegitimateInterestAssessment: boolean;
};
crossBorder: {
hasTransferMechanisms: boolean;
adequacyAssessed: boolean;
ndpcApprovalObtained: boolean;
};
ropa: {
maintained: boolean;
includesAllProcessing: boolean;
/** ISO date string (YYYY-MM-DD); >6 months since review counts as a gap */
lastReviewed: string;
};
}
declare interface ConsentBannerClassNames {
root?: string;
container?: string;
title?: string;
description?: string;
optionsList?: string;
optionItem?: string;
optionCheckbox?: string;
optionLabel?: string;
optionDescription?: string;
buttonGroup?: string;
acceptButton?: string;
rejectButton?: string;
customizeButton?: string;
saveButton?: string;
customizePanel?: string;
selectAllButton?: string;
/** The optional on-page cookie scan panel (shown in the customize view) */
cookieScanPanel?: string;
/** Alias for acceptButton */
primaryButton?: string;
/** Alias for rejectButton */
secondaryButton?: string;
}
/**
* Consent types aligned with NDPA 2023 Section 25-26
* Consent must be freely given, specific, informed, and unambiguous
*/
/**
* Represents a consent option that can be presented to users
*/
declare interface ConsentOption {
/** Unique identifier for the consent option */
id: string;
/** Display label for the consent option */
label: string;
/** Detailed description of what this consent option covers */
description: string;
/** Whether this consent option is required (cannot be declined) */
required: boolean;
/**
* The specific purpose for which data will be processed
* NDPA Section 25(2) requires consent to be specific to each purpose
*/
purpose: string;
/**
* Default state of the consent option
* @default false
*/
defaultValue?: boolean;
/**
* Categories of personal data covered by this consent option
*/
dataCategories?: string[];
}
/**
* Represents the user's consent settings
*/
declare interface ConsentSettings {
/** Map of consent option IDs to boolean values indicating consent status */
consents: Record<string, boolean>;
/** Timestamp when consent was last updated */
timestamp: number;
/** Version of the consent form that was accepted */
version: string;
/** Method used to collect consent (e.g., "banner", "settings", "api") */
method: string;
/** Whether the user has actively made a choice (as opposed to default settings) */
hasInteracted: boolean;
/**
* The lawful basis under which processing is conducted
* Required by NDPA Section 25(1)
*/
lawfulBasis?: LawfulBasisType;
}
/**
* Represents a cross-border data transfer record
*/
declare interface CrossBorderTransfer {
/** Unique identifier */
id: string;
/** Destination country or territory */
destinationCountry: string;
/** ISO country code */
destinationCountryCode?: string;
/** Adequacy status of the destination */
adequacyStatus: AdequacyStatus;
/** The transfer mechanism being relied upon */
transferMechanism: TransferMechanism;
/** Categories of personal data being transferred */
dataCategories: string[];
/** Whether sensitive personal data is included */
includesSensitiveData: boolean;
/** Estimated number of data subjects whose data is transferred */
estimatedDataSubjects?: number;
/** Name of the recipient organization */
recipientOrganization: string;
/** Contact details of the recipient */
recipientContact: {
name: string;
email: string;
phone?: string;
address?: string;
};
/** Purpose of the data transfer */
purpose: string;
/** Safeguards in place to protect the data */
safeguards: string[];
/** Risk assessment summary */
riskAssessment: string;
/** Risk level of the transfer */
riskLevel: 'low' | 'medium' | 'high';
/** NDPC approval details (required for some transfer mechanisms) */
ndpcApproval?: {
required: boolean;
applied: boolean;
approved?: boolean;
referenceNumber?: string;
appliedAt?: number;
approvedAt?: number;
};
/** Whether a Transfer Impact Assessment has been conducted */
tiaCompleted: boolean;
/** Reference to the TIA document */
tiaReference?: string;
/** Frequency of the transfer */
frequency: 'one_time' | 'periodic' | 'continuous';
/** Start date of the transfer */
startDate: number;
/** End date of the transfer (if applicable) */
endDate?: number;
/** Status of the transfer */
status: 'active' | 'suspended' | 'terminated' | 'pending_approval';
/** Timestamp when the record was created */
createdAt: number;
/** Timestamp when the record was last updated */
updatedAt: number;
/** Next review date */
reviewDate?: number;
}
declare interface CrossBorderTransferManagerClassNames {
root?: string;
header?: string;
title?: string;
summary?: string;
summaryCard?: string;
transferList?: string;
transferItem?: string;
form?: string;
input?: string;
select?: string;
submitButton?: string;
/** Alias for submitButton */
primaryButton?: string;
riskBadge?: string;
statusBadge?: string;
detailPanel?: string;
approvalStatus?: string;
}
/** A user-defined section added to the policy outside the generated ones. */
declare interface CustomSection {
id: string;
title: string;
content: string;
order: number;
required: false;
}
/** A logical category of personal data the organisation may collect. */
declare interface DataCategory {
/** Machine-readable identifier. */
id: string;
/** Human-readable label shown in the wizard. */
label: string;
/** Grouping for display and compliance checks. */
group: 'identity' | 'financial' | 'behavioral' | 'sensitive' | 'children';
/** Specific data points within this category. */
dataPoints: string[];
/** Whether this category is currently selected by the user. */
selected: boolean;
}
/** A map of question IDs to their answer values */
declare type DPIAAnswerMap = Record<string, DPIAAnswerValue>;
/** Possible value types for a DPIA answer */
declare type DPIAAnswerValue = string | number | boolean | string[];
/**
* Data Protection Impact Assessment types aligned with NDPA 2023 Section 28
* A DPIA is required when processing is likely to result in high risk to data subjects
*/
/**
* Represents a question in the DPIA questionnaire
*/
declare interface DPIAQuestion {
/** Unique identifier for the question */
id: string;
/** The text of the question */
text: string;
/** Additional guidance for answering the question */
guidance?: string;
/** Type of input required for the answer */
type: 'text' | 'textarea' | 'select' | 'radio' | 'checkbox' | 'scale';
/** Options for select, radio, or checkbox questions */
options?: Array<{
value: string;
label: string;
riskLevel?: 'low' | 'medium' | 'high';
}>;
/** For scale questions, the minimum value */
minValue?: number;
/** For scale questions, the maximum value */
maxValue?: number;
/** For scale questions, labels for the scale points */
scaleLabels?: Record<number, string>;
/** Whether the question is required */
required: boolean;
/** Risk level associated with this question */
riskLevel?: 'low' | 'medium' | 'high';
/** Whether this question triggers additional questions based on the answer */
hasDependentQuestions?: boolean;
/** Conditions that determine when this question should be shown */
showWhen?: Array<{
questionId: string;
operator: 'equals' | 'contains' | 'greaterThan' | 'lessThan';
value: string | number | boolean;
}>;
}
declare interface DPIAQuestionnaireClassNames {
/** Outermost wrapper */
root?: string;
/** Header area containing progress indicator */
header?: string;
/** Section title */
title?: string;
/** Section container */
section?: string;
/** Section title heading */
sectionTitle?: string;
/** Individual question wrapper */
question?: string;
/** Question label text */
questionText?: string;
/** Guidance / help text below a question */
guidance?: string;
/** Text / textarea / select inputs */
input?: string;
/** Radio option group container */
radioGroup?: string;
/** Individual radio option row */
radioOption?: string;
/** Navigation button container */
navigation?: string;
/** Next / submit button */
nextButton?: string;
/** Previous button */
prevButton?: string;
/** Alias for nextButton */
primaryButton?: string;
/** Alias for prevButton */
secondaryButton?: string;
/** Progress bar wrapper */
progressBar?: string;
}
/**
* Represents the result of a completed DPIA
*/
declare interface DPIAResult {
/** Unique identifier for the DPIA */
id: string;
/** Title of the DPIA */
title: string;
/** Description of the processing activity being assessed */
processingDescription: string;
/** Timestamp when the DPIA was started */
startedAt: number;
/** Timestamp when the DPIA was completed */
completedAt?: number;
/** Person responsible for conducting the DPIA */
assessor: {
name: string;
role: string;
email: string;
};
/** Answers to all questions in the DPIA */
answers: Record<string, string | number | boolean | string[]>;
/** Risks identified in the DPIA */
risks: DPIARisk[];
/** Overall risk level of the processing activity */
overallRiskLevel: 'low' | 'medium' | 'high' | 'critical';
/** Whether the DPIA concluded that the processing can proceed */
canProceed: boolean;
/** Reasons why the processing can or cannot proceed */
conclusion: string;
/** Recommendations for the processing activity */
recommendations?: string[];
/** Next review date for the DPIA */
reviewDate?: number;
/** Version of the DPIA questionnaire used */
version: string;
/**
* Whether prior consultation with NDPC is required
* Per NDPA Section 28(2), consultation is required when DPIA indicates high residual risk
*/
ndpcConsultationRequired?: boolean;
/** Date when NDPC consultation was initiated */
ndpcConsultationDate?: number;
/** Reference number from NDPC consultation */
ndpcConsultationReference?: string;
/**
* The lawful basis for the processing activity being assessed
*/
lawfulBasis?: string;
/**
* Whether this DPIA involves cross-border data transfers
*/
involvesCrossBorderTransfer?: boolean;
}
/**
* Represents a risk identified in the DPIA
*/
declare interface DPIARisk {
/** Unique identifier for the risk */
id: string;
/** Description of the risk */
description: string;
/** Likelihood of the risk occurring (1-5) */
likelihood: number;
/** Impact if the risk occurs (1-5) */
impact: number;
/** Overall risk score (likelihood * impact) */
score: number;
/** Risk level based on the score */
level: 'low' | 'medium' | 'high' | 'critical';
/** Measures to mitigate the risk */
mitigationMeasures?: string[];
/** Whether the risk has been mitigated */
mitigated: boolean;
/** Residual risk score after mitigation */
residualScore?: number;
/** Questions that identified this risk */
relatedQuestionIds: string[];
}
/**
* Represents a section in the DPIA questionnaire
*/
declare interface DPIASection {
/** Unique identifier for the section */
id: string;
/** Title of the section */
title: string;
/** Description of the section */
description?: string;
/** Questions in this section */
questions: DPIAQuestion[];
/** Order of the section in the questionnaire */
order: number;
}
/**
* Represents the data submitted by the DSR request form.
*/
declare interface DSRFormSubmission {
/** The selected request type identifier */
requestType: string;
/** Data subject personal information */
dataSubject: {
fullName: string;
email: string;
phone?: string;
identifierType: string;
identifierValue: string;
};
/** Additional information provided for the selected request type */
additionalInfo?: Record<string, string | number | boolean | null>;
/** Timestamp (ms) when the form was submitted */
submittedAt: number;
}
declare interface DSRRequestFormClassNames {
root?: string;
title?: string;
description?: string;
form?: string;
fieldGroup?: string;
label?: string;
input?: string;
select?: string;
textarea?: string;
submitButton?: string;
/** Alias for submitButton */
primaryButton?: string;
successMessage?: string;
/** Custom class applied when isSubmitting is true (e.g. a loading overlay) */
loadingOverlay?: string;
}
/**
* Policy engine types for the adaptive privacy policy generator.
* These types power the wizard-driven policy builder, compliance checker,
* and export functionality — all aligned with the NDPA 2023.
*/
/** Industry verticals with sector-specific compliance requirements. */
declare type Industry = 'fintech' | 'healthcare' | 'ecommerce' | 'saas' | 'education' | 'government' | 'other';
/**
* Lawful Basis types aligned with NDPA 2023 Part III (Sections 24-28)
* Every processing activity must have a documented lawful basis
*/
/**
* The six lawful bases for processing personal data per NDPA Section 25(1)
*/
declare type LawfulBasis = 'consent' | 'contract' | 'legal_obligation' | 'vital_interests' | 'public_interest' | 'legitimate_interests';
declare interface LawfulBasisTrackerClassNames {
root?: string;
header?: string;
title?: string;
summary?: string;
summaryCard?: string;
table?: string;
tableHeader?: string;
tableRow?: string;
form?: string;
input?: string;
select?: string;
submitButton?: string;
/** Alias for submitButton */
primaryButton?: string;
statusBadge?: string;
complianceScore?: string;
gapAlert?: string;
}
/**
* Lawful basis for processing personal data per NDPA Section 25(1)
*/
declare type LawfulBasisType = 'consent' | 'contract' | 'legal_obligation' | 'vital_interests' | 'public_interest' | 'legitimate_interests';
export declare const NDPRBreachReport: React__default.FC<NDPRBreachReportProps>;
/**
* UX copy overrides for the NDPRBreachReport preset. Pass any subset to
* replace the default text without dropping to the lower-level
* `<BreachReportForm>` API.
*/
export declare interface NDPRBreachReportCopy {
/** Form heading. Default: "Report a Data Breach" */
title?: string;
/** Body paragraph under the heading. */
description?: string;
/** Submit button label. Default: "Submit Report" */
submitButton?: string;
}
export declare interface NDPRBreachReportProps {
categories?: BreachCategory[];
adapter?: StorageAdapter<BreachFormSubmission>;
classNames?: BreachReportFormClassNames;
unstyled?: boolean;
onSubmit?: (data: BreachFormSubmission) => void;
/**
* UX copy overrides — see {@link NDPRBreachReportCopy}.
*/
copy?: NDPRBreachReportCopy;
/**
* Body paragraph under the heading.
*/
description?: string;
/**
* Public-form mode. Use when the form should submit to your existing
* backend workflow instead of being state-managed by an adapter.
*
* When `submitTo` is set:
* - the form does NOT require an `adapter`
* - on submit, the toolkit POSTs the JSON-serialised `BreachFormSubmission`
* to this URL (with `Content-Type: application/json`)
* - your `onSubmit` callback still fires (after the POST resolves)
* - submit failures are surfaced via `onSubmitError`
*
* @example
* <NDPRBreachReport submitTo="/api/breach" />
*/
submitTo?: string;
/**
* Fetch options for the `submitTo` POST. Useful for adding `credentials`
* (cookies/auth), `X-CSRF-Token`, or any other header your backend
* requires. Ignored unless `submitTo` is set.
*
* @default { credentials: 'same-origin' }
*/
submitOptions?: {
headers?: Record<string, string> | (() => Record<string, string>);
credentials?: RequestCredentials;
};
/**
* Called when a `submitTo` POST fails (network error or non-2xx
* response). Receives the underlying error or Response.
*/
onSubmitError?: (ctx: {
error?: unknown;
response?: Response;
}) => void;
/**
* Called when a `submitTo` POST succeeds (2xx response). Receives the
* `Response` object, the submitted `BreachFormSubmission` payload, and the
* parsed JSON body if the server returned valid JSON.
*/
onSubmitSuccess?: (ctx: {
response: Response;
data: BreachFormSubmission;
body?: unknown;
}) => void;
}
/**
* Preset wrapper for NDPRDashboard.
*
* Accepts raw ComplianceInput, computes the report via getComplianceScore(),
* and delegates rendering to the NDPRDashboard component.
*/
export declare const NDPRComplianceDashboard: React__default.FC<NDPRDashboardPresetProps>;
export declare const NDPRConsent: React__default.FC<NDPRConsentProps>;
/**
* UX copy overrides for the NDPRConsent preset. Pass any subset to
* replace the default text without dropping to the lower-level
* `<ConsentBanner>` API. Strings you omit fall back to the toolkit
* defaults (which already cite NDPA Section 26).
*
* @example
* <NDPRConsent copy={{
* title: 'Cookie preferences',
* description: 'Acme uses cookies to keep you signed in and improve our store.',
* acceptAll: 'Allow all',
* rejectAll: 'Only essentials',
* }} />
*/
export declare interface NDPRConsentCopy {
/** Banner heading. Default: "We Value Your Privacy" */
title?: string;
/** Body paragraph under the heading. Default cites NDPA Section 26. */
description?: string;
/** Primary CTA — accepts all categories. Default: "Accept All" */
acceptAll?: string;
/** Secondary CTA — rejects all non-essential categories. Default: "Reject All" */
rejectAll?: string;
/** Tertiary CTA — opens the per-category controls. Default: "Customize" */
customize?: string;
/** Submit button on the per-category panel. Default: "Save Preferences" */
save?: string;
}
export declare interface NDPRConsentProps {
/**
* Consent categories to present. When omitted, the toolkit's
* default options are used. (4.0: legacy `extraOptions` was removed —
* pass the full options array here instead.)
*/
options?: ConsentOption[];
adapter?: StorageAdapter<ConsentSettings>;
position?: 'top' | 'bottom' | 'center' | 'inline';
classNames?: ConsentBannerClassNames;
unstyled?: boolean;
onSave?: (settings: ConsentSettings) => void;
/**
* UX copy overrides — see {@link NDPRConsentCopy}. Lets you brand the
* banner without dropping to the lower-level `<ConsentBanner>` API.
*/
copy?: NDPRConsentCopy;
}
export declare const NDPRCrossBorder: React__default.FC<NDPRCrossBorderProps>;
/**
* UX copy overrides for the NDPRCrossBorder preset. Pass any subset to
* replace the default text without dropping to the lower-level
* `<CrossBorderTransferManager>` API.
*/
export declare interface NDPRCrossBorderCopy {
/** Manager heading. Default: "Cross-Border Data Transfer Manager" */
title?: string;
/** Body paragraph under the heading. */
description?: string;
}
export declare interface NDPRCrossBorderProps {
/**
* Initial transfers to seed the manager. (4.0: the legacy
* `initialTransfers` alias was removed.)
*/
initialData?: CrossBorderTransfer[];
adapter?: StorageAdapter<CrossBorderTransfer[]>;
classNames?: CrossBorderTransferManagerClassNames;
unstyled?: boolean;
/**
* UX copy overrides — see {@link NDPRCrossBorderCopy}.
*/
copy?: NDPRCrossBorderCopy;
}
declare interface NDPRDashboardClassNames {
root?: string;
header?: string;
scoreCircle?: string;
scoreValue?: string;
ratingBadge?: string;
modulesGrid?: string;
moduleCard?: string;
moduleTitle?: string;
moduleScore?: string;
moduleGaps?: string;
recommendationsSection?: string;
recommendationItem?: string;
recommendationPriority?: string;
recommendationTitle?: string;
primaryButton?: string;
secondaryButton?: string;
}
export declare interface NDPRDashboardPresetProps {
/** Raw compliance input — the preset calls getComplianceScore() internally */
input: ComplianceInput;
/** Dashboard heading. Defaults to "NDPA Compliance Dashboard" */
title?: string;
/** Show/hide the recommendations section. Defaults to true */
showRecommendations?: boolean;
/** Maximum number of recommendations to render. Defaults to 5 */
maxRecommendations?: number;
/** Per-section class name overrides */
classNames?: NDPRDashboardClassNames;
/** When true, strips all default classes so consumers can style from scratch */
unstyled?: boolean;
}
export declare const NDPRDPIA: React__default.FC<NDPRDPIAProps>;
/**
* UX copy overrides for the NDPRDPIA preset. Strings you omit fall back
* to the lower-level `<DPIAQuestionnaire>` defaults. The DPIA wizard does
* not render a single header (each section has its own title); the `title`
* and `description` fields are reserved for future use and currently
* accepted for API parity with the other presets.
*/
export declare interface NDPRDPIACopy {
/** Reserved — DPIA sections render their own titles. */
title?: string;
/** Reserved — DPIA sections render their own descriptions. */
description?: string;
/** Final-step submit button label. Default: "Submit" */
submitButton?: string;
/** Next-section button label. Default: "Next" */
nextButton?: string;
/** Previous-section button label. Default: "Previous" */
prevButton?: string;
}
export declare interface NDPRDPIAProps {
sections?: DPIASection[];
adapter?: StorageAdapter<DPIAAnswerMap>;
classNames?: DPIAQuestionnaireClassNames;
unstyled?: boolean;
/**
* Fired when the questionnaire is submitted, with the full `DPIAResult`
* including risks, overall risk level, conclusion, and recommendations.
*/
onResult?: (result: DPIAResult) => void;
/**
* UX copy overrides — see {@link NDPRDPIACopy}.
*/
copy?: NDPRDPIACopy;
/**
* Public-form mode. Use when the questionnaire should submit to your
* existing backend workflow instead of being state-managed by an adapter.
*
* When `submitTo` is set:
* - the questionnaire does NOT require an `adapter`
* - on completion, the toolkit POSTs the JSON-serialised `DPIAAnswerMap`
* to this URL (with `Content-Type: application/json`)
* - your `onResult` callback still fires (after the POST resolves)
* - submit failures are surfaced via `onSubmitError`
*
* @example
* <NDPRDPIA submitTo="/api/dpia" />
*/
submitTo?: string;
/**
* Fetch options for the `submitTo` POST. Useful for adding `credentials`
* (cookies/auth), `X-CSRF-Token`, or any other header your backend
* requires. Ignored unless `submitTo` is set.
*
* @default { credentials: 'same-origin' }
*/
submitOptions?: {
headers?: Record<string, string> | (() => Record<string, string>);
credentials?: RequestCredentials;
};
/**
* Called when a `submitTo` POST fails (network error or non-2xx
* response).
*/
onSubmitError?: (ctx: {
error?: unknown;
response?: Response;
}) => void;
/**
* Called when a `submitTo` POST succeeds (2xx response). Receives the
* `Response` object, the submitted `DPIAAnswerMap` payload, and the
* parsed JSON body if the server returned valid JSON.
*/
onSubmitSuccess?: (ctx: {
response: Response;
data: DPIAAnswerMap;
body?: unknown;
}) => void;
}
export declare const NDPRLawfulBasis: React__default.FC<NDPRLawfulBasisProps>;
/**
* UX copy overrides for the NDPRLawfulBasis preset. Pass any subset to
* replace the default text without dropping to the lower-level
* `<LawfulBasisTracker>` API.
*/
export declare interface NDPRLawfulBasisCopy {
/** Tracker heading. Default: "Lawful Basis Tracker" */
title?: string;
/** Body paragraph under the heading. */
description?: string;
}
export declare interface NDPRLawfulBasisProps {
/**
* Initial activities to seed the tracker. (4.0: the legacy
* `initialActivities` alias was removed.)
*/
initialData?: ProcessingActivity[];
adapter?: StorageAdapter<ProcessingActivity[]>;
classNames?: LawfulBasisTrackerClassNames;
unstyled?: boolean;
/**
* UX copy overrides — see {@link NDPRLawfulBasisCopy}.
*/
copy?: NDPRLawfulBasisCopy;
}
export declare const NDPRPrivacyPolicy: React__default.FC<NDPRPrivacyPolicyProps>;
/**
* UX copy overrides for the NDPRPrivacyPolicy preset. Strings you omit
* fall back to the underlying `<AdaptivePolicyWizard>` defaults.
*
* Note: the wizard renders many step-specific labels; the fields here
* cover the high-level header text. Step-specific copy is wired through
* the `NDPRProvider` locale.
*/
export declare interface NDPRPrivacyPolicyCopy {
/** Wizard heading. Default: "Privacy Policy Builder" */
title?: string;
/** Optional body paragraph under the heading. */
description?: string;
/** Submit / complete button label. */
submitButton?: string;
}
export declare interface NDPRPrivacyPolicyProps {
adapter?: StorageAdapter<PolicyDraft>;
onComplete?: (policy: PrivacyPolicy) => void;
classNames?: Record<string, string>;
unstyled?: boolean;
/**
* UX copy overrides — see the `NDPRPrivacyPolicyCopy` interface. The wizard
* derives most of its labels from the active `NDPRProvider` locale; the
* fields here cover the high-level header text.
*/
copy?: NDPRPrivacyPolicyCopy;
/**
* Pre-fill the policy wizard with a sector-specific starter template.
*
* Pass one of `'saas' | 'ecommerce' | 'school' | 'healthcare' |
* 'procurement'` and the wizard opens already populated with the data
* categories, lawful-basis defaults, sensitive-data / children /
* cross-border / automated-decisions flags that org type usually needs.
* The user can still flip every flag and rewrite every section.
*
* @example
* <NDPRPrivacyPolicy
* template="healthcare"
* templateOverrides={{ orgName: 'Lagos Heart Centre' }}
* />
*
* @see templateContextFor in `/server` or `/core` for the underlying
* factory if you'd rather build the context yourself.
*/
template?: OrgPolicyTemplateId;
/**
* Organisation-level overrides applied on top of the chosen template.
* Ignored when `template` is unset.
*/
templateOverrides?: OrgPolicyTemplateOverrides;
/**
* Pass a fully-constructed `TemplateContext` to skip the template
* lookup entirely. Takes precedence over `template` if both are set.
*/
initialContext?: TemplateContext;
}
export declare const NDPRROPA: React__default.FC<NDPRROPAProps>;
/**
* UX copy overrides for the NDPRROPA preset. Pass any subset to
* replace the default text without dropping to the lower-level
* `<ROPAManager>` API.
*/
export declare interface NDPRROPACopy {
/** Manager heading. Default: "Record of Processing Activities (ROPA)" */
title?: string;
/** Body paragraph under the heading. */
description?: string;
}
export declare interface NDPRROPAProps {
initialData?: RecordOfProcessingActivities;
adapter?: StorageAdapter<RecordOfProcessingActivities>;
classNames?: ROPAManagerClassNames;
unstyled?: boolean;
/**
* UX copy overrides — see {@link NDPRROPACopy}.
*/
copy?: NDPRROPACopy;
}
export declare const NDPRSubjectRights: React__default.FC<NDPRSubjectRightsProps>;
export declare interface NDPRSubjectRightsProps {
requestTypes?: RequestType[];
adapter?: StorageAdapter<DSRFormSubmission>;
classNames?: DSRRequestFormClassNames;
unstyled?: boolean;
onSubmit?: (data: DSRFormSubmission) => void;
/**
* Public-form mode. Use when the form should submit to your existing
* backend workflow instead of being state-managed by an adapter.
*
* When `submitTo` is set:
* - the form does NOT require an `adapter`
* - on submit, the toolkit POSTs the JSON-serialised `DSRFormSubmission`
* to this URL (with `Content-Type: application/json`)
* - your `onSubmit` callback still fires (after the POST resolves)
* - submit failures are surfaced via `onSubmitError`
*
* For more control over headers, credentials, or retry behaviour, build
* an `apiAdapter` (which now supports CSRF, retry, and error hooks in
* 3.6.0) and pass that as `adapter` instead. `submitTo` is the
* fire-and-forget shortcut for public forms.
*
* @example
* <NDPRSubjectRights submitTo="/api/dsr" />
*/
submitTo?: string;
/**
* Fetch options for the `submitTo` POST. Useful for adding `credentials`
* (cookies/auth), `X-CSRF-Token`, or any other header your backend
* requires. Ignored unless `submitTo` is set.
*
* @default { credentials: 'same-origin' }
*/
submitOptions?: {
headers?: Record<string, string> | (() => Record<string, string>);
credentials?: RequestCredentials;
};
/**
* Called when a `submitTo` POST fails (network error or non-2xx
* response). Receives the underlying error or Response.
*/
onSubmitError?: (ctx: {
error?: unknown;
response?: Response;
}) => void;
/**
* Called when a `submitTo` POST succeeds (2xx response). Receives the
* `Response` object, the submitted `DSRFormSubmission` payload, and the
* parsed JSON body if the server returned valid JSON. Use this to
* display a server-generated reference number, redirect the user, or
* trigger analytics.
*
* The `body` field is `undefined` if the response had no body or the
* body was not valid JSON. It is typed `unknown` to force consumers to
* narrow it themselves before reading fields.
*
* @example
* <NDPRSubjectRights
* submitTo="/api/dsr"
* onSubmitSuccess={({ response, data, body }) => {
* const ref = (body as { referenceId?: string })?.referenceId;
* if (ref) router.push(`/dsr-confirmation?ref=${ref}`);
* }}
* />
*/
onSubmitSuccess?: (ctx: {
response: Response;
data: DSRFormSubmission;
body?: unknown;
}) => void;
}
/**
* Represents organization information for a privacy policy
*/
declare interface OrganizationInfo {
/** Name of the organization */
name: string;
/** Website URL of the organization */
website: string;
/** Contact email for privacy inquiries */
privacyEmail: string;
/** Physical address of the organization */
address?: string;
/** Phone number for privacy inquiries */
privacyPhone?: string;
/** Name of the Data Protection Officer */
dpoName?: string;
/** Email of the Data Protection Officer */
dpoEmail?: string;
/** Industry or sector of the organization */
industry?: string;
/** NDPC registration number (if registered) */
ndpcRegistrationNumber?: string;
}
/**
* Org-specific privacy-policy templates — pre-filled `TemplateContext`
* factories for the most common Nigerian app shapes.
*
* Each template returns a fully-populated `TemplateContext` with:
* - industry set to the matching `Industry` value
* - the data categories the sector typically collects (selected: true)
* - the processing purposes that match the business model
* - sensitive-data / children / cross-border / automated-decisions flags
* set to the defaults that org type usually needs (a school will have
* children data, a hospital will have sensitive data, etc.)
*
* Templates are guidance starters. The wizard still walks the user through
* every step — they can flip any flag, add/remove categories, or rewrite
* any section before the policy is finalised. The legal-notice footer the
* toolkit ships everywhere applies to the generated output.
*
* @example
* import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
* const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
* const draft = assemblePolicy(ctx);
*/
/** Identifiers for the bundled org templates. */
declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
/** Optional overrides applied on top of a template's defaults. */
declare interface OrgPolicyTemplateOverrides {
/** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
orgName?: string;
/** Public website URL. */
website?: string;
/** Privacy contact email. */
privacyEmail?: string;
/** Postal address. */
address?: string;
/** DPO name. Required for DCPMI under NDPA Section 32. */
dpoName?: string;
/** DPO email. Required for the NDPC breach-notification contact. */
dpoEmail?: string;
}
/** Organisation size tiers — affects complexity of generated language. */
declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
/** Represents an in-progress policy being built in the wizard. */
declare interface PolicyDraft {
/** Unique identifier for the draft. */
id: string;
/** The template context driving section generation. */
templateContext: TemplateContext;
/** Custom sections added by the user. */
customSections: CustomSection[];
/** Per-section content overrides keyed by section id. */
sectionOverrides: Record<string, string>;
/** Ordered list of section ids defining the final order. */
sectionOrder: string[];
/** Current wizard step (0-indexed). */
currentStep: number;
/** Timestamp of the last save. */
lastSavedAt: number;
/** The draft is always in "draft" status until finalised. */
status: 'draft';
}
/**
* Privacy policy types aligned with NDPA 2023
* Privacy policies must clearly inform data subjects of their rights under the NDPA
*/
/**
* Represents a section in a privacy policy
*/
declare interface PolicySection {
/** Unique identifier for the section */
id: string;
/** Title of the section */
title: string;
/** Description of the section */
description?: string;
/** Order of the section in the policy */
order?: number;
/** Whether the section is required by NDPA */
required: boolean;
/** Template text for the section */
template: string;
/**
* Default content for the section (legacy field)
* @deprecated Use template instead
*/
defaultContent?: string;
/**
* Custom content for the section (overrides default content)
* @deprecated Use template instead
*/
customContent?: string;
/** Whether the section is included in the policy */
included: boolean;
/** Variables that can be used in the section content */
variables?: string[];
}
/**
* Represents a generated privacy policy
*/
declare interface PrivacyPolicy {
/** Unique identifier for the policy */
id: string;
/** Title of the policy */
title: string;
/** Template used to generate the policy */
templateId: string;
/** Organization information */
organizationInfo: OrganizationInfo;
/** Sections of the policy */
sections: PolicySection[];
/** Values for the variables used in the policy */
variableValues: Record<string, string>;
/** Effective date of the policy */
effectiveDate: number;
/** Last updated date of the policy */
lastUpdated: number;
/** Version of the policy */
version: string;
/**
* Applicable legal frameworks
*/
applicableFrameworks?: ('ndpa' | 'ndpr' | 'gdpr' | 'ccpa')[];
}
/**
* Represents a processing activity and its lawful basis
*/
declare interface ProcessingActivity {
/** Unique identifier */
id: string;
/** Name of the processing activity */
name: string;
/** Description of what processing is performed */
description: string;
/** The lawful basis for this processing activity */
lawfulBasis: LawfulBasis;
/** Justification for why this lawful basis applies */
lawfulBasisJustification: string;
/** Categories of personal data being processed */
dataCategories: string[];
/** Whether sensitive personal data is involved */
involvesSensitiveData: boolean;
/** Condition for processing sensitive data (required if involvesSensitiveData is true) */
sensitiveDataCondition?: SensitiveDataCondition;
/** Categories of data subjects */
dataSubjectCategories: string[];
/** Purposes of the processing */
purposes: string[];
/** Data retention period */
retentionPeriod: string;
/** Justification for the retention period */
retentionJustification?: string;
/** Recipients or categories of recipients */
recipients?: string[];
/** Whether data is transferred outside Nigeria */
crossBorderTransfer: boolean;
/** Timestamp when the record was created */
createdAt: number;
/** Timestamp when the record was last updated */
updatedAt: number;
/** Next review date */
reviewDate?: number;
/** Status of the processing activity */
status: 'active' | 'inactive' | 'under_review' | 'archived';
/** DPO approval details */
dpoApproval?: {
approved: boolean;
approvedBy: string;
approvedAt: number;
notes?: string;
};
}
/** Lawful processing purposes recognised under the NDPA. */
declare type ProcessingPurpose = 'service_delivery' | 'marketing' | 'analytics' | 'research' | 'legal_compliance' | 'fraud_prevention';
/**
* Record of Processing Activities (ROPA) types aligned with NDPA 2023
* Data controllers must maintain comprehensive records of all processing activities
*/
/**
* Represents a single processing record in the ROPA
*/
declare interface ProcessingRecord {
/** Unique identifier */
id: string;
/** Name of the processing activity */
name: string;
/** Detailed description of the processing */
description: string;
/** Data controller details */
controllerDetails: {
name: string;
contact: string;
address: string;
registrationNumber?: string;
dpoContact?: string;
};
/** Joint controller details (if applicable) */
jointControllerDetails?: {
name: string;
contact: string;
address: string;
responsibilities: string;
};
/** Data processor details (if processing is outsourced) */
processorDetails?: {
name: string;
contact: string;
address: string;
contractReference?: string;
};
/** Lawful basis for the processing */
lawfulBasis: LawfulBasis;
/** Justification for the chosen lawful basis */
lawfulBasisJustification: string;
/** Purposes of the processing */
purposes: string[];
/** Categories of personal data processed */
dataCategories: string[];
/** Categories of sensitive personal data (if any) */
sensitiveDataCategories?: string[];
/** Categories of data subjects */
dataSubjectCategories: string[];
/** Recipients or categories of recipients */
recipients: string[];
/** Cross-border transfer details */
crossBorderTransfers?: Array<{
destinationCountry: string;
countryCode?: string;
safeguards: string;
transferMechanism: string;
}>;
/** Data retention period */
retentionPeriod: string;
/** Justification for the retention period */
retentionJustification?: string;
/** Technical and organizational security measures */
securityMeasures: string[];
/** Data source (directly from data subject or from third party) */
dataSource: 'data_subject' | 'third_party' | 'public_source' | 'other';
/** Third-party source details (if dataSource is 'third_party') */
thirdPartySourceDetails?: string;
/** Whether a DPIA is required for this processing */
dpiaRequired: boolean;
/** Reference to the DPIA (if conducted) */
dpiaReference?: string;
/** Whether automated decision-making is involved */
automatedDecisionMaking: boolean;
/** Details of automated decision-making (if applicable) */
automatedDecisionMakingDetails?: string;
/** Status of the processing record */
status: 'active' | 'inactive' | 'archived';
/** Department or business unit responsible */
department?: string;
/** System or application used for processing */
systemsUsed?: string[];
/** Timestamp when the record was created */
createdAt: number;
/** Timestamp when the record was last updated */
updatedAt: number;
/** Timestamp when the record was last reviewed */
lastReviewedAt?: number;
/** Next review date */
nextReviewDate?: number;
}
/**
* Represents a complete Record of Processing Activities
*/
declare interface RecordOfProcessingActivities {
/** Unique identifier */
id: string;
/** Organization name */
organizationName: string;
/** Organization contact information */
organizationContact: string;
/** Organization address */
organizationAddress: string;
/** Data Protection Officer details */
dpoDetails?: {
name: string;
email: string;
phone?: string;
};
/** NDPC registration number */
ndpcRegistrationNumber?: string;
/** All processing records */
records: ProcessingRecord[];
/** Timestamp when the ROPA was last updated */
lastUpdated: number;
/** Version of the ROPA */
version: string;
/** Export format options */
exportFormats?: ('pdf' | 'csv' | 'json' | 'xlsx')[];
}
/**
* Represents a type of data subject request (detailed configuration)
*/
declare interface RequestType {
/** Unique identifier for the request type */
id: string;
/** Display name for the request type */
name: string;
/** Description of what this request type entails */
description: string;
/**
* NDPA 2023 section reference for this right
* (e.g., "Section 34(1)(a)" for access, "Section 38" for portability).
* Used for display purposes only — verify the exact subsection wi