PHPackages                             ginkelsoft/laravel-data-consent - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. ginkelsoft/laravel-data-consent

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

ginkelsoft/laravel-data-consent
===============================

A Laravel package that implements GDPR art. 6(1)(a) and art. 7 consent recording as a tamper-evident append-only event log, with grant/withdraw actions and a status helper for the current state.

v1.0.0(1mo ago)001MITPHPPHP ^8.2CI passing

Since May 28Pushed 1mo agoCompare

[ Source](https://github.com/ginkelsoft-development/laravel-data-consent)[ Packagist](https://packagist.org/packages/ginkelsoft/laravel-data-consent)[ RSS](/packages/ginkelsoft-laravel-data-consent/feed)WikiDiscussions development Synced 1w ago

READMEChangelog (1)Dependencies (10)Versions (3)Used By (1)

Ginkelsoft Laravel Data Consent
===============================

[](#ginkelsoft-laravel-data-consent)

[![Tests](https://github.com/ginkelsoft-development/laravel-data-consent/actions/workflows/tests.yml/badge.svg?branch=development)](https://github.com/ginkelsoft-development/laravel-data-consent/actions/workflows/tests.yml)[![License](https://camo.githubusercontent.com/6c711032aff1ca0eb6b211aa6cb3649ce7fd64a7714e1181d4bb457f9680e7cf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Laravel](https://camo.githubusercontent.com/255077649ac4ed79e446c4d860d1c53c9764b8ff855456caeb401faf7d250205/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302d2d31332d627269676874677265656e3f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://laravel.com)[![PHP](https://camo.githubusercontent.com/482d9c7691869be159b0bd042060a220a12a89396d63fa223c22b74affaf42c4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532302d2d253230382e352d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://php.net)[![PHPStan](https://camo.githubusercontent.com/fa63e0381a93ba9755a46ec197198ef973137dca1643836d06b3d6263c9aa7c8/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e3f7374796c653d666c61742d737175617265)](phpstan.neon.dist)

Overview
--------

[](#overview)

Implements **GDPR art. 6(1)(a) (consent as lawful basis)** and **art. 7 (conditions for consent — including the demonstrability requirement)** for a Laravel application. Records every grant and every withdrawal as an append-only, hash-chained event in `consent_log`. The current state for a given (subject, purpose, version) is derived from the latest event.

This is the **consent** member of the GinkelSoft compliance family. The chain is built on the shared `HashChain` from `ginkelsoft/laravel-compliance-core` and the signing secret is shared with every other audit log in the family.

The family
----------

[](#the-family)

PackageGDPR Article(s)Role[`laravel-compliance-core`](https://github.com/ginkelsoft-development/laravel-compliance-core)art. 5(2)Shared primitives[`laravel-data-retention`](https://github.com/ginkelsoft-development/laravel-data-retention)art. 5(1)(e)Storage limitation[`laravel-data-right-to-be-forgotten`](https://github.com/ginkelsoft-development/laravel-data-right-to-be-forgotten)art. 17Subject-driven erasure[`laravel-data-subject-access`](https://github.com/ginkelsoft-development/laravel-data-subject-access)art. 15 + 20Subject access**`laravel-data-consent`****art. 6(1)(a) + 7****Consent registry — this package**[`laravel-data-breach-registry`](https://github.com/ginkelsoft-development/laravel-data-breach-registry)art. 33 + 34Breach registry[`laravel-compliance-hub`](https://github.com/ginkelsoft-development/laravel-compliance-hub)art. 5(2)UmbrellaHow it works
------------

[](#how-it-works)

### Record a grant or withdrawal

[](#record-a-grant-or-withdrawal)

```
use Ginkelsoft\DataConsent\Actions\RecordConsent;

$consent = new RecordConsent;

$consent->grant(
    subjectId: '01HXYZ',
    purpose: 'newsletter',
    version: '2026-05',
    source: 'web',
    metadata: ['ip' => '203.0.113.5', 'form' => 'signup-v3'],
);

$consent->withdraw(
    subjectId: '01HXYZ',
    purpose: 'newsletter',
    version: '2026-05',
    source: 'email',
);
```

`version` lets you tie consent to a specific consent text or processing context. When you change your terms, prior consent does not automatically cover the new version — record a fresh grant against the new version string.

### Query consent

[](#query-consent)

```
use Ginkelsoft\DataConsent\Support\ConsentStatus;

$status = new ConsentStatus;

$status->isGranted('01HXYZ', 'newsletter');
$status->isGranted('01HXYZ', 'newsletter', version: '2026-05');
$status->latest('01HXYZ', 'newsletter');
$status->activeFor('01HXYZ');
$status->history('01HXYZ', purpose: 'newsletter');
```

`activeFor` returns only purposes whose latest event is `granted` — perfect for an account dashboard that lists "what you currently consent to".

### CLI

[](#cli)

For ops, backfills, and tests:

```
php artisan retention:consent:grant 01HXYZ newsletter --consent-version=2026-05 --source=web
php artisan retention:consent:withdraw 01HXYZ newsletter --consent-version=2026-05 --source=email
php artisan retention:consent:status 01HXYZ
```

The command names keep the `retention:consent:` prefix for BC with the v1.x monolithic package. `--consent-version` rather than `--version`because Symfony already uses `--version` as a reserved option.

### Verify the chain

[](#verify-the-chain)

```
use Ginkelsoft\ComplianceCore\Config\LogSecret;
use Ginkelsoft\ComplianceCore\Support\HashChain;
use Illuminate\Support\Facades\DB;

$entries = DB::table('consent_log')->orderBy('id')->get()
    ->map(fn ($row) => (array) $row)->all();

$intact = HashChain::verify($entries, LogSecret::value());
```

Or run `php artisan compliance:verify` from the [hub](https://github.com/ginkelsoft-development/laravel-compliance-hub) to verify every chain in the family in one shot.

What the log stores
-------------------

[](#what-the-log-stores)

`consent_log` is the **only** audit log in the family that stores the subject identifier directly. Consent inherently requires identification — you cannot prove "this person consented" without knowing who they are. Document that in your DPIA and apply your own retention policy to this table.

Per row: subject identifier, purpose, version, action (`granted` / `withdrawn`), source, optional metadata, occurred-at timestamp, plus the chain bookkeeping.

Compliance notes
----------------

[](#compliance-notes)

- **GDPR art. 6(1)(a)** — Consent as a lawful basis for processing.
- **GDPR art. 7** — Conditions for consent: demonstrability ("the controller shall be able to demonstrate that the data subject has consented"). The hash-chained log IS the demonstration.
- **GDPR art. 5(2)** — Accountability. Idem.

This package is **not legal advice**. Whether consent is freely given, specific, informed and unambiguous is a question for your DPO.

Installation
------------

[](#installation)

```
composer require ginkelsoft/laravel-data-consent
php artisan vendor:publish --tag=compliance-config
php artisan vendor:publish --tag=consent-config
php artisan vendor:publish --tag=consent-migrations
php artisan migrate
```

Then add a secret to `.env` (shared with the rest of the family):

```
COMPLIANCE_LOG_SECRET="$(openssl rand -base64 32)"
```

Gotchas
-------

[](#gotchas)

- **The log stores subject identifiers directly.** That is necessary for art. 7 accountability — proof of consent has to be linkable to a real person. Mention this table in your DPIA.
- **No automatic deduplication.** Two `grant` calls in a row produce two `granted` rows. Sometimes that is exactly what you want (re-affirming consent). When you want "only when not currently granted" semantics, check `ConsentStatus::isGranted()` first.
- **Withdrawal does not delete the prior grant.** It records a new event that supersedes it. The grant stays in the log forever — that is what makes the chain a usable audit trail.
- **Forget does not automatically cascade to consent\_log.** A subject exercising their right to be forgotten (via `laravel-data-right-to-be-forgotten`) will not have their consent records removed unless you explicitly register `ConsentEntry` as Forgettable. The legal argument for keeping consent + withdrawal records even after forget is real (you may need them to defend the lawfulness of past processing), so this is opt-in rather than default.

Testing
-------

[](#testing)

```
composer install
vendor/bin/pest
vendor/bin/phpstan analyse --memory-limit=1G
vendor/bin/pint --test
```

Reporting bugs
--------------

[](#reporting-bugs)

Found a bug or unexpected behaviour? We want to hear about it.

**Preferred — open a GitHub issue:**

When opening an issue, please include:

1. **Versions** — PHP, Laravel, and the package version (`composer show ginkelsoft/laravel-data-consent`).
2. **What you did** — the artisan command, code snippet, or steps that triggered the bug.
3. **What you expected** vs **what actually happened** — include full error output or a stack trace if there is one.
4. **A minimal reproduction** if you can — a failing test or a small code sample beats a long description.

**Security-sensitive findings** (anything that could expose personal data, break a hash-chain, or bypass an audit log) — please **do not**open a public issue. E-mail **** directly with "SECURITY" in the subject line and we will respond privately.

**Not on GitHub?** You can also e-mail **** with the same information.

Contact
-------

[](#contact)

For commercial support, integration questions, or anything that doesn't fit a GitHub issue: **** — .

License
-------

[](#license)

MIT License — see [LICENSE](LICENSE). (c) 2026 Ginkelsoft

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance89

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

57d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/165766253?v=4)[ginkelsoft](/maintainers/ginkelsoft)[@GinkelSoft](https://github.com/GinkelSoft)

---

Top Contributors

[![ginkelsoft-development](https://avatars.githubusercontent.com/u/179240029?v=4)](https://github.com/ginkelsoft-development "ginkelsoft-development (3 commits)")

---

Tags

laravelgdprcomplianceaudit-logconsentavgginkelsofttoestemming

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ginkelsoft-laravel-data-consent/health.svg)

```
[![Health](https://phpackages.com/badges/ginkelsoft-laravel-data-consent/health.svg)](https://phpackages.com/packages/ginkelsoft-laravel-data-consent)
```

###  Alternatives

[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.5k30.2M151](/packages/laravel-cashier)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[masterix21/laravel-licensing

Laravel licensing package with polymorphic assignment to any model, activation keys, expirations/renewals, and seat control via LicenseUsage. Supports offline verification with public-key–signed tokens, a CLI to generate/rotate/revoke keys, and an extensible architecture via config and contracts.

1613.3k4](/packages/masterix21-laravel-licensing)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
