precision-soft/symfony-doctrine-encrypt
A Symfony bundle that adds transparent field-level encryption to Doctrine ORM entities. Protect sensitive database columns at rest with configurable encryption, simple entity mapping, and seamless integration into Symfony applications.
.example/) that exercises every public capability against real database engines — ORM read/write of encrypted fields, deterministic e-mail lookup, refusal to search randomised columns, lookups spanning active salt versions during a rotation, the encrypt/decrypt commands over a legacy plaintext table, and online salt rotation with checks before and after. That is exactly the evidence a build-vs-buy review needs, and it removes a costly discovery phase from our own integration work.--dry-run --verify check turns "rotate encryption keys" from a scary migration project into a scheduled operational task. If compliance or a customer security questionnaire has ever asked about key rotation cadence, this is the artefact that lets us commit to a cadence rather than answer "annually, under change control, with downtime."database:rotate can no longer be resumed by database:encrypt or against a stale salt; a second run in the same process no longer skips every row and reports success; a short write of the checkpoint file no longer overwrites the last good checkpoint. Those were silent-data-loss and false-success classes of bug in the runbook we would otherwise have to build defensive tooling around.minMsi and minCoveredMsi), plus an example CI job against two database services. Useful in a vendor due-diligence or architecture-review write-up.Consider it when:
openssl_encrypt helpers.--dry-run --verify reads stored columns back and fails naming the fields and row counts still on another salt version — that is the kind of pre-flight check that makes a security change approvable by a change board.Look elsewhere when:
WHERE created_at > … on an encrypted column, the data model has to change or that field stays unencrypted.Upgrade caution for this release (flag to engineering):
CheckpointService now takes the scope as its first constructor argument; setIdentifierValues() accepts integers and strings only; castIdentifierValue() may return an object. Internal API surface, but if we have subclassed or decorated these, budget upgrade work.To executives (30 seconds): We are evaluating a PHP/Doctrine package that encrypts sensitive database columns at the application layer, with the operational tooling to change encryption keys on live data without downtime. The new release is about proving it is safe to run in production: a rotation can no longer be accidentally resumed in the wrong mode or against an out-of-date key, an interrupted run can no longer report success while losing rows, and there is now a runnable reference application that demonstrates every feature against real databases. It converts "we should rotate encryption keys" from a project into a scheduled job, and it comes with the verification steps a change board will ask for.
To engineering: Treat this as a Doctrine-level bundle with a real operational surface. The v4.7.0 work is mostly hardening of exactly the failure modes we would have written custom tooling to defend against — scope-bound checkpoints, cursor values rebuilt through their DBAL type (so bigint, date_immutable and uid identifiers round-trip correctly), batches that stop when the cursor fails to advance, --batch-size values that can no longer saturate to PHP_INT_MAX in a single batch, and checkpoint writes that are byte-counted and fsynced before the rename. The .example/ directory is the fastest route to a proof of concept: micro-kernel boot, package installed from the working tree via a path repository, full suite against real engines. Two things to plan for: checkpoint format v2 means any in-flight run finishes on v4.6.0 first, and CheckpointService's constructor signature changed, so check for subclassing. Mutation score gates are at 95, so the test suite is doing real work — but our own integration tests still need to cover our identifier types and inheritance mapping. Design constraint to internalise early: encrypted columns support exact-match lookup only, and randomised columns are deliberately unsearchable.
To security/compliance: The package provides deterministic, searchable encryption for equality lookups plus randomised encryption for non-searchable fields, versioned salts with online rotation, a pre-flight --dry-run --verify that fails naming the fields and row counts still on an old salt version, and checkpoints that refuse to be resumed outside the command, entity manager, and salt version that wrote them. Salt and key management remain ours; this gives us the mechanism and the audit trail, not the policy.
How can I help you explore Laravel packages today?