azaharizaman/nexus-data-privacy

Framework-agnostic data privacy core: data subject rights, consent management, retention policies, breach notification

Maintainers

Package info

github.com/azaharizaman/nexus-data-privacy

pkg:composer/azaharizaman/nexus-data-privacy

Statistics

Installs: 0

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0-alpha1 2026-05-05 02:28 UTC

This package is auto-updated.

Last update: 2026-05-05 02:43:59 UTC


README

Version: 1.0.0
PHP Version: ^8.3
Type: Atomic Package (Framework-Agnostic)
Status: ✅ Production Ready

Overview

Nexus\DataPrivacy provides a regulation-agnostic foundation for personal data protection and privacy compliance. It implements core privacy management capabilities without embedding any specific jurisdiction's rules.

This package follows the Progressive Disclosure Pattern - it serves as the core abstraction layer, while jurisdiction-specific packages (like Nexus\GDPR or Nexus\PDPA) extend it with regulatory requirements.

Key Features

  • Consent Management - Track, grant, withdraw, and renew data processing consents
  • Data Subject Requests (DSARs) - Full lifecycle management for access, erasure, rectification, and portability requests
  • Retention Policy Engine - Configurable data retention with category-based policies
  • Breach Incident Management - Record, track, and manage data breach incidents
  • Processing Activity Records (ROPA) - Maintain records of processing activities for compliance
  • Audit Trail Integration - Full audit logging for all privacy-related operations
  • Request Handlers - Pluggable handlers for each request type
  • Framework-Agnostic - Pure PHP 8.3+, works with any framework

Installation

composer require azaharizaman/nexus-data-privacy

Installation

composer require azaharizaman/nexus-data-privacy

Architecture

Progressive Disclosure Pattern

This package serves as the regulation-agnostic core. Jurisdiction-specific requirements are provided by extension packages:

┌─────────────────────────────────────────────────────────┐
│                   Application Layer                      │
└───────────────────────┬─────────────────────────────────┘
                        │ uses
         ┌──────────────┼──────────────┐
         ▼              ▼              ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│ Nexus\GDPR  │  │ Nexus\PDPA  │  │ Nexus\CCPA  │
│ (EU Rules)  │  │ (MY Rules)  │  │ (CA Rules)  │
└──────┬──────┘  └──────┬──────┘  └──────┬──────┘
       │ extends        │ extends        │ extends
       └────────────────┼────────────────┘
                        ▼
              ┌─────────────────────┐
              │  Nexus\DataPrivacy  │  ← This package
              │  (Core Abstractions)│
              └─────────────────────┘

Package Structure

DataPrivacy/
├── src/
│   ├── Contracts/
│   │   ├── External/           # Interfaces for framework dependencies
│   │   │   ├── AuditLoggerInterface.php
│   │   │   ├── DataEncryptorInterface.php
│   │   │   ├── NotificationDispatcherInterface.php
│   │   │   ├── PartyProviderInterface.php
│   │   │   └── StorageInterface.php
│   │   ├── ConsentQueryInterface.php
│   │   ├── ConsentPersistInterface.php
│   │   ├── ConsentManagerInterface.php
│   │   ├── DataSubjectRequestQueryInterface.php
│   │   ├── DataSubjectRequestPersistInterface.php
│   │   ├── DataSubjectRequestManagerInterface.php
│   │   ├── RetentionPolicyQueryInterface.php
│   │   ├── RetentionPolicyPersistInterface.php
│   │   ├── RetentionPolicyManagerInterface.php
│   │   ├── BreachRecordQueryInterface.php
│   │   ├── BreachRecordPersistInterface.php
│   │   ├── BreachRecordManagerInterface.php
│   │   ├── ProcessingActivityQueryInterface.php
│   │   ├── ProcessingActivityPersistInterface.php
│   │   ├── ProcessingActivityManagerInterface.php
│   │   └── RequestHandlerInterface.php
│   ├── Enums/
│   │   ├── RequestType.php         # ACCESS, ERASURE, RECTIFICATION, etc.
│   │   ├── RequestStatus.php       # State machine for request lifecycle
│   │   ├── ConsentStatus.php       # GRANTED, WITHDRAWN, EXPIRED, etc.
│   │   ├── DataCategory.php        # Personal data categories with risk levels
│   │   ├── LawfulBasisType.php     # GDPR Article 6 lawful bases
│   │   ├── BreachSeverity.php      # LOW, MEDIUM, HIGH, CRITICAL
│   │   ├── RetentionCategory.php   # Document retention categories
│   │   └── ConsentPurpose.php      # Standard consent purposes
│   ├── ValueObjects/
│   │   ├── DataSubjectId.php       # Unique data subject identifier
│   │   ├── Consent.php             # Immutable consent record
│   │   ├── DataSubjectRequest.php  # DSAR with state machine
│   │   ├── RetentionPolicy.php     # Retention policy configuration
│   │   ├── BreachRecord.php        # Data breach incident record
│   │   └── ProcessingActivity.php  # ROPA entry
│   ├── Services/
│   │   ├── ConsentManager.php
│   │   ├── DataSubjectRequestManager.php
│   │   ├── RetentionPolicyManager.php
│   │   ├── BreachRecordManager.php
│   │   ├── ProcessingActivityManager.php
│   │   ├── RequestHandlerRegistry.php
│   │   └── Handlers/
│   │       ├── AccessRequestHandler.php
│   │       ├── ErasureRequestHandler.php
│   │       ├── RectificationRequestHandler.php
│   │       └── PortabilityRequestHandler.php
│   └── Exceptions/
│       ├── DataPrivacyException.php
│       ├── Invalid*Exception.php   # Validation exceptions
│       └── *NotFoundException.php  # Not found exceptions
└── tests/

Quick Start

1. Consent Management

use Nexus\DataPrivacy\Contracts\ConsentManagerInterface;
use Nexus\DataPrivacy\Enums\ConsentPurpose;
use Nexus\DataPrivacy\Enums\LawfulBasisType;
use Nexus\DataPrivacy\ValueObjects\DataSubjectId;

public function __construct(
    private readonly ConsentManagerInterface $consentManager
) {}

// Grant consent
$consent = $this->consentManager->grantConsent(
    subjectId: DataSubjectId::fromPartyId('party-12345'),
    purpose: ConsentPurpose::MARKETING_EMAIL,
    lawfulBasis: LawfulBasisType::CONSENT,
    expiresAt: new \DateTimeImmutable('+1 year'),
    metadata: ['ip_address' => '192.168.1.1', 'source' => 'web_form']
);

// Check if consent is active
$hasConsent = $this->consentManager->hasActiveConsent(
    subjectId: DataSubjectId::fromPartyId('party-12345'),
    purpose: ConsentPurpose::MARKETING_EMAIL
); // Returns: bool

// Withdraw consent
$this->consentManager->withdrawConsent(
    consentId: $consent->getId(),
    reason: 'User requested via preference center'
);

// Renew consent before expiry
$renewed = $this->consentManager->renewConsent(
    consentId: $consent->getId(),
    newExpiresAt: new \DateTimeImmutable('+2 years')
);

2. Data Subject Requests (DSARs)

use Nexus\DataPrivacy\Contracts\DataSubjectRequestManagerInterface;
use Nexus\DataPrivacy\Enums\RequestType;
use Nexus\DataPrivacy\ValueObjects\DataSubjectId;

public function __construct(
    private readonly DataSubjectRequestManagerInterface $dsrManager
) {}

// Create an access request
$request = $this->dsrManager->createRequest(
    subjectId: DataSubjectId::fromEmail('customer@example.com'),
    type: RequestType::ACCESS,
    metadata: ['verification_method' => 'email_otp']
);

// Verify the request
$this->dsrManager->verifyRequest($request->getId());

// Process the request (moves to IN_PROGRESS)
$this->dsrManager->startProcessing($request->getId());

// Execute the request through handler
$result = $this->dsrManager->executeRequest(
    requestId: $request->getId(),
    handlerResult: ['export_url' => 'https://...', 'expires_at' => '...']
);

// Complete the request
$this->dsrManager->completeRequest(
    requestId: $request->getId(),
    result: $result
);

// Get overdue requests for monitoring
$overdue = $this->dsrManager->getOverdueRequests();

3. Retention Policies

use Nexus\DataPrivacy\Contracts\RetentionPolicyManagerInterface;
use Nexus\DataPrivacy\Enums\DataCategory;
use Nexus\DataPrivacy\Enums\RetentionCategory;

public function __construct(
    private readonly RetentionPolicyManagerInterface $retentionManager
) {}

// Create a retention policy
$policy = $this->retentionManager->createPolicy(
    name: 'Customer Invoice Retention',
    dataCategory: DataCategory::FINANCIAL,
    retentionMonths: 84, // 7 years
    autoDelete: false,   // Require manual review
    description: 'Retain invoices for tax compliance'
);

// Find applicable policies for a data category
$policies = $this->retentionManager->findPoliciesForCategory(DataCategory::FINANCIAL);

// Get items due for deletion
$dueItems = $this->retentionManager->getItemsDueForDeletion();

// Execute retention (delete expired data)
$this->retentionManager->executeRetention(
    policyId: $policy->getId(),
    dryRun: true // Preview what would be deleted
);

4. Breach Management

use Nexus\DataPrivacy\Contracts\BreachRecordManagerInterface;
use Nexus\DataPrivacy\Enums\BreachSeverity;
use Nexus\DataPrivacy\Enums\DataCategory;

public function __construct(
    private readonly BreachRecordManagerInterface $breachManager
) {}

// Report a data breach
$breach = $this->breachManager->reportBreach(
    title: 'Unauthorized Database Access',
    description: 'External actor gained access to customer table',
    discoveredAt: new \DateTimeImmutable(),
    affectedSubjectCount: 1500,
    affectedCategories: [DataCategory::CONTACT, DataCategory::FINANCIAL],
    severity: BreachSeverity::HIGH
);

// Notify regulatory authority (within 72 hours for GDPR)
$this->breachManager->notifyRegulator(
    breachId: $breach->getId(),
    authorityName: 'ICO',
    notifiedAt: new \DateTimeImmutable(),
    referenceNumber: 'ICO-2024-12345'
);

// Record containment actions
$this->breachManager->recordContainmentAction(
    breachId: $breach->getId(),
    action: 'Revoked compromised API keys',
    performedBy: 'security-team',
    performedAt: new \DateTimeImmutable()
);

// Resolve the breach
$this->breachManager->resolveBreach(
    breachId: $breach->getId(),
    resolution: 'All affected users notified, credentials reset, security audit completed',
    resolvedAt: new \DateTimeImmutable()
);

5. Processing Activities (ROPA)

use Nexus\DataPrivacy\Contracts\ProcessingActivityManagerInterface;
use Nexus\DataPrivacy\Enums\DataCategory;
use Nexus\DataPrivacy\Enums\LawfulBasisType;

public function __construct(
    private readonly ProcessingActivityManagerInterface $ropaManager
) {}

// Register a processing activity
$activity = $this->ropaManager->registerActivity(
    name: 'Customer Order Processing',
    purpose: 'Process and fulfill customer orders',
    lawfulBasis: LawfulBasisType::CONTRACT,
    dataCategories: [DataCategory::CONTACT, DataCategory::FINANCIAL, DataCategory::TRANSACTION],
    dataSubjectCategories: ['customers', 'shipping_recipients'],
    recipients: ['payment_processor', 'shipping_provider'],
    retentionPeriod: '7 years',
    technicalMeasures: ['encryption_at_rest', 'tls_1_3', 'access_controls'],
    organizationalMeasures: ['staff_training', 'data_minimization', 'access_reviews']
);

// Check if DPIA is required
if ($activity->requiresDpia()) {
    $this->ropaManager->markDpiaRequired($activity->getId());
}

// Mark activity as reviewed
$this->ropaManager->markReviewed(
    activityId: $activity->getId(),
    reviewedBy: 'dpo@company.com',
    nextReviewDate: new \DateTimeImmutable('+1 year')
);

// Get activities needing review
$needReview = $this->ropaManager->getActivitiesNeedingReview();

External Dependencies

This package defines interfaces for external dependencies. Your application must provide implementations:

PartyProviderInterface

Provides access to personal data stored in Nexus\Party or your party system:

use Nexus\DataPrivacy\Contracts\External\PartyProviderInterface;

final readonly class PartyAdapter implements PartyProviderInterface
{
    public function __construct(
        private PartyManagerInterface $partyManager
    ) {}
    
    public function partyExists(string $partyId): bool
    {
        return $this->partyManager->exists($partyId);
    }
    
    public function getPersonalData(string $partyId): array
    {
        $party = $this->partyManager->findById($partyId);
        return [
            'name' => $party->getName(),
            'email' => $party->getEmail(),
            'phone' => $party->getPhone(),
            // ... other personal data fields
        ];
    }
    
    public function deletePersonalData(string $partyId): void
    {
        $this->partyManager->anonymize($partyId);
    }
    
    // ... implement other methods
}

AuditLoggerInterface

Logs all privacy operations for compliance:

use Nexus\DataPrivacy\Contracts\External\AuditLoggerInterface;

final readonly class AuditLoggerAdapter implements AuditLoggerInterface
{
    public function __construct(
        private AuditLogManagerInterface $auditLogger
    ) {}
    
    public function log(string $action, string $entityType, string $entityId, array $metadata = []): void
    {
        $this->auditLogger->log(
            entityId: $entityId,
            action: $action,
            description: "Privacy action: {$action} on {$entityType}",
            metadata: $metadata
        );
    }
    
    // ... implement other methods
}

Binding in Laravel

// AppServiceProvider.php
public function register(): void
{
    $this->app->singleton(
        PartyProviderInterface::class,
        PartyAdapter::class
    );
    
    $this->app->singleton(
        AuditLoggerInterface::class,
        AuditLoggerAdapter::class
    );
    
    $this->app->singleton(
        ConsentQueryInterface::class,
        EloquentConsentRepository::class
    );
    
    $this->app->singleton(
        ConsentPersistInterface::class,
        EloquentConsentRepository::class
    );
    
    // ... bind other interfaces
}

Enums Reference

RequestType

Value Description Typical Deadline
ACCESS Right to access personal data 30 days (GDPR)
ERASURE Right to be forgotten 30 days (GDPR)
RECTIFICATION Right to correct data 30 days (GDPR)
RESTRICTION Right to restrict processing 30 days (GDPR)
PORTABILITY Right to data portability 30 days (GDPR)
OBJECTION Right to object to processing 30 days (GDPR)
AUTOMATED_DECISION Rights related to automated decisions 30 days (GDPR)

RequestStatus

PENDING → VERIFIED → IN_PROGRESS → COMPLETED
                  ↘             ↗
                    → REJECTED
                    → CANCELLED

DataCategory

Category Special Category Risk Level
BASIC_IDENTITY No Low
CONTACT No Low
FINANCIAL No High
HEALTH Yes Critical
BIOMETRIC Yes Critical
GENETIC Yes Critical
RACIAL_ETHNIC Yes High
POLITICAL Yes High
RELIGIOUS Yes High
SEXUAL_ORIENTATION Yes High
TRADE_UNION Yes High
CRIMINAL Yes Critical
CHILDREN Yes Critical
LOCATION No Medium
BEHAVIORAL No Medium
COMMUNICATION No Medium
TRANSACTION No Medium
EMPLOYMENT No Medium

BreachSeverity

Severity Response Time Criteria
LOW 5 days < 100 subjects, no special categories
MEDIUM 48 hours 100-1000 subjects, low-risk categories
HIGH 24 hours 1000-10000 subjects or sensitive categories
CRITICAL Immediate > 10000 subjects or highly sensitive

Extension Packages

Nexus\GDPR (EU General Data Protection Regulation)

// Enforces GDPR-specific rules:
// - 30-day response deadline for DSARs
// - 72-hour breach notification to regulators
// - Data Protection Impact Assessments (DPIA)
// - Mandatory DPO appointment checks

Nexus\PDPA (Malaysia Personal Data Protection Act)

// Enforces PDPA-specific rules:
// - 21-day response deadline for DSARs
// - Sector-specific requirements (banking, healthcare)
// - Data Commissioner notification rules

Testing

# Run tests
composer test

# Run with coverage
composer test:coverage

# Target: 85%+ code coverage

Dependencies

{
    "require": {
        "php": "^8.3",
        "azaharizaman/nexus-common": "^1.0"
    }
}

License

MIT License. See LICENSE file for details.

Last Updated: December 2025
Maintained By: Nexus Architecture Team