Product Decisions This Supports
- Build vs. buy for field-level encryption. The bundle is a thin, typed Symfony facade over
spaze/encryption — no primitives are invented in-repo, and the repo's own engineering rules forbid writing cryptographic code. That makes "buy/adopt the wrapper" a defensible default versus maintaining an internal EncryptionService utility class that quietly accumulates bespoke crypto.
- Compliance roadmap scoping (GDPR, PCI DSS, SOC 2). The two headline capabilities — configuration-driven encryption groups and key rotation — map directly to controls auditors ask about: per-domain key separation and a documented re-keying path. This lets you scope encryption as a config + ops workstream rather than a cryptography project.
- Data classification and trust boundaries. Encryption groups are a product modelling tool: one group per sensitivity tier, tenant, or data domain (PII, payment tokens, third-party credentials, integration secrets). Deciding the group taxonomy is a product/security decision this package forces you to make explicitly and keep in config.
- Reliability and incident prevention. Interfaces are narrow and a misconfigured group fails at container compile time, not at runtime. This shifts a class of silent-failure incidents ("we encrypted with the wrong key and it decrypted to garbage") left into CI. That is a support-cost and data-integrity argument, not just an engineering nicety.
- Platform standardization. Forces a position on upstream
spaze/encryption vs. the helppc/encryption fork (the fork carries extra contracts and a marker exception interface the bundle must not depend on). Having two sources of truth is a governance decision, not a detail — pick one and write it down.
- Supported-version planning (updated by v2.1.0). The support matrix is now explicit and tested: Symfony 7.4 LTS and 8.0/8.1, on every supported PHP version. For a PM this converts "will this force a framework upgrade or block one?" into an answerable question — we can sit on 7.4 LTS through its window and move to 8.x on our own schedule, not the package's.
- Upgrade-cost budgeting. v2.1.0 is a drop-in from 2.0.0 with no changes under
src/ and no config behaviour differences. That is a useful data point for the roadmap: this dependency's minor bumps have so far cost nothing in application code, so it can be slotted into routine maintenance rather than a dedicated migration epic.
- Feature vs. dependency. If key rotation is on your roadmap, this decides whether you build rotation yourself or inherit it. Conversely, it does not solve data migration: encrypting existing plaintext columns, backfilling, and dual-read cutovers remain your work.
- Roadmap gaps it implies. No described KMS/HSM or envelope-encryption integration — key material supply stays your problem. No searchable/deterministic mode, so "look up a user by encrypted email" is out of scope and must be designed around.
When to Consider This Package
Adopt when:
- Your stack is Symfony on PHP >= 8.4 and you use framework bundle/DI configuration — either on 7.4 LTS (newly supported as of 2.1.0) or on 8.0/8.1. (Despite the framing, this is a Symfony bundle, not a Laravel package — Laravel would need a service provider and config bridge, i.e., a fork or wrapper you now own.)
- You need more than one key, partitioned by data domain — a single app-wide
APP_KEY is already insufficient.
- Key rotation is a named compliance or contractual requirement, not a someday-maybe.
- You want a dependency that doesn't force your framework upgrade timeline. 2.1.0's dual-major support means LTS-aligned shops are not pushed onto a new major to take the package.
- You can accept a low-signal dependency: small adoption, single maintainer. The mitigation is that the wrapper is thin, MIT-licensed, and readable — the exit cost is low — but you must own the risk and be prepared to vendor it. A compatibility release does not change this posture; do not read it as a maturity upgrade.
- Your engineering culture matches the repo's bar (PHPStan level 10,
declare(strict_types=1), PSR-12, Rector, PHPUnit in CI). If your team wouldn't hold that line, the compile-time and type-safety benefits erode fast.
Look elsewhere when:
- You need managed key custody — KMS/HSM, envelope encryption, per-tenant key provisioning, audit trails on key use. This is libsodium-based encryption with configured key material, not a key management service.
- You need deterministic or searchable encryption, blind indexes, or equality lookups on ciphertext.
- You need a certified/audited cryptographic module (FIPS 140, formal third-party audit) or a vendor SLA — low adoption and no dependents won't survive procurement review.
- You're polyglot (services in Go/Java/Python must read the same ciphertext) or non-Symfony.
- You expect the package to migrate your existing data. It won't; budget the backfill and dual-read work separately.
- You can't tolerate upstream/fork divergence and don't want to track two projects.
How to Pitch It (Stakeholders)
To executives: A small, MIT-licensed Symfony component that gives us configuration-driven field-level encryption with a key-rotation path — the two things auditors actually ask for — without us writing or owning cryptographic code. The latest release adds Symfony 7.4 LTS support alongside Symfony 8, so it neither forces a framework upgrade nor blocks one; it installs as a drop-in with zero application-code changes. It is a thin wrapper, so if it doesn't work out, replacing it is cheap. The trade-off remains maturity: single-maintainer, low adoption. We'd adopt it behind a timeboxed spike on one non-critical field, with a documented exit plan, rather than making it a platform-wide dependency on day one.
To engineering: Typed facade over spaze/encryption; no primitives are written in this repo and the contribution rules forbid it. Key generation goes through stable libsodium (random_bytes, sodium_crypto_box_keypair) via a console command. Narrow interfaces plus a compiler pass mean a misconfigured encryption group fails at container compile, not in production. Code quality is enforced: PHPStan level 10, strict types, PSR-12, Rector, PHPUnit. 2.1.0 is a safe bump: constraints widened to ^7.4 || ^8.0, no src/ changes, no config behaviour changes — the only fix is test-only (the extension test now sets kernel.environment and kernel.build_dir the way a real kernel does, since kernel.environment is optional only from 8.1). CI is pinned per Symfony major via Flex, so a 7.4 job is a genuine 7.4 stack rather than a mixed constraint resolution that merely permits it; the full gate is green on 7.4, 8.0 and 8.1. Two constraints to internalize remain: we must not depend on the helppc/encryption fork's extra contracts, and key storage/custody, data backfill, and any searchable-lookup design are ours to build.
The ask: one sprint, one PII field, one threat model, and a written decision on upstream-vs-fork plus a KMS story before we widen adoption.