Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dmarc Record Builder Laravel Package

cbowofrivia/dmarc-record-builder

A PHP package for building DMARC TXT records programmatically. Configure policy, subdomain policy, alignment, reporting addresses and percentage, then generate a valid DMARC record string for your DNS zone.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. cbowofrivia/dmarc-record-builder is a narrow, single-purpose value-object library: it constructs and parses DMARC DNS TXT records. It has no persistence, no HTTP surface, and no service-provider footprint in the application, so it sits at the very edge of the architecture — typically called from an admin/settings flow, a provisioning job, or a DNS-sync worker. v4.0.0 materially improves architectural fit by dropping illuminate/collections and webmozart/assert. The package is now framework-agnostic plain PHP, which means it can be shared unchanged between a Laravel monolith, a queue worker, and any extracted Go/PHP DNS service without dragging a Laravel major version along with it. That is a genuine decoupling win, not a cosmetic one.

Integration feasibility. The breaking surface is small and mechanically findable. Three changes matter:

  • pct() / interval() methods, their create()/constructor named arguments, and the $pct / $interval properties are gone.
  • PHP floor moves 8.2 → 8.3.
  • Validation throws CbowOfRivia\DmarcRecordBuilder\Exceptions\InvalidDmarcRecordException, which extends \InvalidArgumentException. Any existing catch (\InvalidArgumentException $e) continues to work untouched; only code that names Webmozart\Assert\InvalidArgumentException in a catch or instanceof needs editing.

A repo-wide grep for pct(, interval(, ->pct, ->interval, and Webmozart will produce a near-complete work list. Realistically this is a half-day change for a typical consumer, most of it in test fixtures and factory data rather than production call sites.

Technical risk. The dominant risk is not the API break — it is the semantic break. pct= is the standard mechanism for staged DMARC enforcement (publish pct=10, observe, ratchet up). Removing it means the library can no longer express a gradual rollout; teams doing that must hand-build the record string or hold at v3.1.0. This is correct per RFC 9989 and defensible, but it is a capability regression for anyone mid-rollout, and it should be treated as a product decision to be scheduled, not a routine dependency bump.

The second risk is silent data loss on re-cast. parse() now treats pct and ri as unknown tags and drops them on re-cast. Any workflow that reads a live DNS record, mutates one field, and writes it back will quietly strip pct=50 from a production record and escalate the policy to 100%. That is a security-posture change executed with no error. Any round-trip path (parse → mutate → __toString) must be identified and tested before upgrade.

Third: the new exception class means any monitoring, alert routing, or log-scrubbing keyed on the fully-qualified Webmozart\Assert\InvalidArgumentException class name will silently stop matching even though messages are unchanged.

Key questions.

  • Do we currently emit pct or ri anywhere, and are any of those records in production mid-rollout?
  • Do we have a parse-modify-reserialize path against live DNS? If so, what is the blast radius of a dropped pct tag?
  • Is any error handling, alerting, or log parsing keyed on the Webmozart exception FQCN?
  • What is the PHP 8.3 readiness of every runtime that loads this dependency (app containers, queue workers, scheduler, CI images)?
  • Who else consumes the parsed array shape, and does anything depend on $record->pct being present-but-null?

Integration Approach

Stack fit. The dependency removal makes this strictly easier to place. v3 pinned consumers to an illuminate/collections major, which effectively pinned the Laravel version of any host application — a real constraint in a monorepo where services upgrade Laravel on different cadences. v4 removes that coupling entirely, so it can be adopted by services on Laravel 10, 11, or 12, or by non-Laravel PHP services, without version arbitration. For a Laravel shop this is the single strongest argument for taking the upgrade.

Migration path. Mechanical and well-bounded:

  1. Inventory call sites (pct(, interval(, ->pct, ->interval, Webmozart) across app code, tests, seeders, and fixtures.
  2. Raise the runtime floor: verify PHP 8.3+ in composer.json, Dockerfiles, CI matrices, and any shared base images used by workers and cron.
  3. Bump the constraint to ^4.0 and run the full suite; expect failures only at the identified call sites.
  4. Delete pct/interval arguments and replace property reads. Where staged rollout is genuinely needed, decide explicitly between (a) accepting full enforcement, (b) pinning that service to ^3.1 temporarily, or (c) constructing the record string manually outside the library.
  5. Replace named Webmozart catches with InvalidDmarcRecordException (or leave as \InvalidArgumentException if the broad catch is acceptable).
  6. Add a regression test asserting that parse() → mutate → __toString() on a record containing pct/ri produces the expected output, so the drop behaviour is documented rather than discovered.

Compatibility. PHP 8.3 is the only hard external requirement, and it is a comfortable floor — 8.2 EOL is December 2026, so this is a forward-looking constraint rather than an urgent one. Laravel 10+ all run happily on 8.3. The exception inheritance chain preserves backward compatibility for broad catches, which is a well-judged piece of API design and reduces the migration to essentially the pct/interval work. CI coverage across 8.3/8.4/8.5 is a good signal on forward compatibility.

Sequencing. Do the PHP 8.3 floor first and independently — it is a prerequisite for everything else and carries its own risk (base images, extension availability). Then upgrade the library in a single PR per service with the grep-driven change set. Handle any pct-dependent rollout logic as a separate, reviewed change with security sign-off, because it alters live mail authentication posture. Services with no pct usage and no round-trip path can take this as a routine bump; services with either should be scheduled, not batched.

Operational Impact

Maintenance. Materially reduced. Zero runtime dependencies means zero transitive CVE surface, no Dependabot noise from webmozart/assert, and no forced upgrade when Laravel ships a new major. For a small utility that should be boring infrastructure, this is exactly the right direction. The trade-off is that validation logic is now hand-rolled in the package rather than delegated to a widely-audited assertion library; given the narrowness of DMARC field validation this is acceptable, but it does mean correctness of those guards now rests entirely on this project's own test suite.

Support. The project is single-maintainer and small. Bus factor and issue-response latency are the standing concerns, unchanged by this release. The mitigating factor is scope: DMARC record syntax is a small, now-standardised surface (RFC 9989), and a dependency-free library is straightforward to vendor, fork, or replace if maintenance lapses. Recommend vendoring or at least pinning with a committed lockfile rather than tracking dev-main.

Scaling. Not a throughput concern — this is string assembly and parsing with no I/O. CPU and memory are negligible even in a per-request settings page or a per-domain batch job over thousands of domains. The scaling consideration is organisational: because the package is now framework-neutral, it can be adopted uniformly across services, which is a small consistency win for how DMARC records are generated org-wide.

Failure modes.

  • Silent policy escalation — highest severity. A round-trip through parse() and re-cast on a record carrying pct=50 will drop the tag and publish full enforcement. Detect by auditing for parse-then-write paths; mitigate with an assertion that the source record contained no unknown tags before re-serialising.
  • Lost capability — teams mid-rollout cannot express partial enforcement through the library. Detect by searching for prior pct usage; mitigate by pinning to 3.1.x until the rollout completes or by hand-building the record.
  • Unmatched error handling — monitoring keyed on Webmozart\Assert\InvalidArgumentException stops firing. Messages are unchanged, so log-based alerting on message text survives; class-name matching does not.
  • Runtime floor miss — a worker, cron container, or CI image left on 8.2 fails at deploy time with a parse or platform error. Cheap to catch by auditing images rather than just composer.json.
  • Round-trip fidelity — unknown tags are silently discarded by design. Any consumer expecting lossless parse/re-serialise will be surprised.

Ramp-up. Low. The API is a handful of named setters on a value object; a developer unfamiliar with DMARC needs an hour with RFC 7489/9989 to understand p, sp, adkim, aspf, rua, and fo, but nothing about this package obscures that. The migration itself requires no new knowledge — it is deletion and a catch-block edit. Budget roughly half a day for a service with clean usage, and one to two days where staged-rollout logic exists and needs a product decision on the replacement approach.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel