asignua/filament-vat-id
A Filament form field for collecting and validating VAT IDs in Laravel admin panels. It streamlines country-aware VAT input and validation so forms can verify business tax numbers with minimal setup.
Architecture fit. asignua/filament-vat-id is a Filament 5 form-field package centered on TaxIdInput, not a domain service. It contributes a Blade-rendered input plus validation rules and translation files, with no migrations, models, or persistence footprint — so it sits cleanly in an existing panel's form schema and does not shape application architecture. The relevant architectural boundary is that it is an input-layer concern: it validates and (for remote lookups) enriches a tax identifier at data-entry time, but does not normalize, canonicalize, or store it. That distinction matters to a TPM because the durable business logic (what a valid customer tax ID means for invoicing, tax treatment, reverse-charge eligibility) stays in our application layer and must be specified separately.
Integration feasibility. High for the offline half, moderate for the lookup half. Dropping TaxIdInput::make('vat_id') into a resource form is a one-line change; composing with ->required(), ->live(), ->columnSpan() and our own ->rules() follows normal Filament composition. The offline rule set covers EU VAT format/checksum plus PL NIP/REGON, CZ IČO/DIČ, and UA ЄДРПОУ/РНОКПП — genuinely useful breadth for a European B2B panel, and it means most validation happens with zero network dependency. The remote integrations (VIES, ARES, Polish white list, GUS) are the differentiating feature but also the part that requires the most diligence: each is a third-party service with its own availability, rate limits, and data-freshness characteristics, and we inherit all of them transitively.
Technical risk. Moderate, with the risk concentrated in three places rather than in the code itself. (1) Adoption/vendor risk: 1 GitHub star and a single-maintainer-looking project means bus factor is effectively one; MIT license gives us the legal right to fork, but not the practical capacity unless we budget for it. (2) Platform coupling: the package depends on Filament's internal label-derivation behavior (lcfirst), evidenced by the v1.0.2 message-casing fix. That is a private convention, not a public contract, and Filament majors can change it — every major upgrade needs a message-rendering regression check. (3) Remote dependency: VIES in particular is historically flaky and rate-limited, and ARES/GUS/white-list endpoints are national services with varying SLAs. A lookup failure must never be allowed to masquerade as "invalid tax ID" — that is a silent data-quality and customer-experience bug.
Key questions.
composer.json constraint, and what is actually covered by CI?Stack fit. Laravel + Filament 5 panel applications that collect business counterparty identifiers: vendor/customer onboarding, billing-address forms, supplier master data, procurement or marketplace seller registration. It is a poor fit for headless APIs or non-Filament UIs — the validation logic is wrapped in a field component, so outside Filament we would either need the underlying rule classes (if exposed) or reimplement the checks.
Migration path. Greenfield: one schema entry per form. Brownfield: swap an existing TextInput + regex/custom-rule field for TaxIdInput and delete the bespoke rule, but first confirm the package's acceptance set matches or exceeds what our custom rule enforced — a stricter or looser rule set silently changes who can register. Because the field is input-only, plan explicitly for the adjacent application-layer work: normalization (strip whitespace, uppercase, split country prefix) before persistence, and a stored canonical form plus the raw input for audit. Set ->validationAttribute() wherever product or legal copy must be exact rather than relying on derived labels. Where the expected format depends on country, sequence a country selector ahead of the tax-ID field and re-validate on change with ->live(); validate this interaction explicitly since it is the most likely source of user-visible friction.
Compatibility. Pin the Filament major and PHP minor in composer.json; treat any Filament major as a required re-verification of message rendering and translation output, not a routine bump. Run a locale matrix check (all 10 supported languages plus our panel's default) before rollout, since the v1.0.2 fix addressed English acronym casing specifically and message strings are the most likely place for cosmetic regressions. Verify the package's Filament 5 constraint against our actual installed version and the support window we are committing to.
Sequencing. (1) Stand up the package's workbench demo (DemoSeeder, Acme Supply fixture) to see real rendering and confirm expected behavior without touching our panel. (2) Confirm the country coverage list against the jurisdictions we actually transact in — do not assume full EU coverage from "EU VAT". (3) Decide and document the offline-vs-lookup policy per form, including degraded behavior when a remote service is down. (4) Pilot on a single low-risk, non-blocking form (e.g., a secondary contact or supplier profile) with lookup advisory only. (5) Standardize labels, validationAttribute() values, and translation overrides; remove any pre-existing local workaround for the "vAT" casing bug so it does not shadow the corrected default. (6) Add regression tests asserting rendered validation messages and country-format accept/reject cases, using the seeder as fixture. (7) Roll out to blocking forms (onboarding, billing) only after the failure-mode behavior is proven.
Maintenance. Low for the code itself — small surface, no migrations, patch-level releases, and v1.0.2 was docs plus a cosmetic fix with no API change. The real maintenance line items are elsewhere: (a) an owner assigned to watch the upstream repo and the national rule sources; (b) a recurring review task on every Filament major upgrade covering label casing and messages; (c) a fork-and-patch contingency if the maintainer goes inactive, which for a 1-star package should be a named risk in the register rather than an assumption. Budget a few hours per quarter, not per sprint.
Support. Support load is front-loaded: initial questions will be about country coverage, message customization, and lookup behavior. All three are answerable from documentation plus ->validationAttribute() and translation overrides, provided we write an internal one-pager. The workbench demo is the single biggest support lever — issues become reproducible against a known dataset, which cuts triage time substantially. Expect ongoing "why was this VAT rejected?" tickets; instrument the validation path (log the identifier country, the rule that failed, and whether a lookup was involved) so those tickets are answerable without code archaeology. Do not route vendor-side bugs to our helpdesk without a documented escalation and workaround path.
Scaling. Application-side cost is negligible: rendering a field and running checksum math is CPU-trivial even at high form volume. The scaling question is entirely validation I/O. VIES and the national registries are rate-limited and not designed for high-volume programmatic use, so if lookup runs on every keystroke or every submit, our form throughput becomes bounded by a service we do not control. Mitigations to specify up front: trigger lookups on explicit user action or on blur rather than ->live() per keystroke; cache results per normalized identifier with a sensible TTL (a day or more — tax registrations do not change often); and apply per-service circuit breaking. No database, queue, or storage scaling impact; if we persist lookup results, that is a small table with an obvious growth profile.
Failure modes. Ranked by business impact:
Ramp-up. Half a day for a Laravel-fluent engineer to install, run the demo, and place the field; one to two days to do it properly, including locale checks, the country-selector interaction, normalization in the persistence layer, failure-mode handling, and regression tests. No new infrastructure or specialist knowledge required, which keeps the knowledge-concentration risk low — the main onboarding artifact is the internal decision record on offline-vs-lookup policy and the escalation path to the upstream maintainer or our fork.
How can I help you explore Laravel packages today?