inisiatif/model-shared
Shared Laravel models for Inisiatif Zakat Indonesia covering occupation, education level, geographic regions (country down to village), and marital status, plus a Donor model with configurable branch and employee relations.
Assessment basis: releases through 2.10.6 (adds several new models).
Architecture fit
The package remains a thin Eloquent-model distribution layer, not a framework or service. It ships domain reference models (occupation, education degree, marital status, country→province→regency→district→village hierarchy) plus transactional-ish models accreted over time (Donor, DonorPhone, Bank, Partner, Donation, DonationDetail, FundingCategory/Type, Outflow, Account, FundingSource, SubProgramCategory). 2.10.6 adds another unspecified batch of models, confirming the accretion pattern is the operating model rather than a one-off. Architecturally it assumes a Laravel monolith or modular monolith with a shared database schema — it registers migrations via a service provider rather than exposing a clean schema contract.
The one genuinely reusable design decision is resolveRelationUsing() for Donor → Branch and Donor → Employee. That defers host-app coupling to boot time and is the right pattern for cross-application model sharing; it is also the only extension seam. Everything else is opinionated schema that the host app inherits wholesale.
Fit assessment: narrow, and narrowing slightly with each release. This is fit-for-purpose for Indonesian zakat/charity workflows inside the Inisiatif Zakat ecosystem. It is not a general-purpose package, and treating it as one is the primary architectural mistake to avoid. The 2.10.6 additions do not widen the addressable use case — they deepen the package's investment in its own domain.
Integration feasibility
Low technical effort, moderate governance effort. composer require inisiatif/model-shared plus a service provider is a half-day spike. The real cost is confirming what the package does on boot — migrations are registered automatically, and 2.5.0 added a "region search API," which implies route or controller registration. Both are side effects a TPM must have scoped before a single feature depends on it.
2.10.6 changes the scoping arithmetic modestly: the release note ("menambahkan beberapa model baru" — several new models) does not name them. Consuming the tag means inheriting an unenumerated set of tables and relationships, each with its own migration and its own collision surface. The feasibility verdict holds, but the pre-commitment inventory (question 1 and 2 below) now has to cover models that did not exist when the previous assessment was written. Feasible if the team's spike enumerates 2.10.6 explicitly rather than assuming the prior model list.
Integration is feasible if: (a) the target app's schema can be shaped by the package's migrations rather than the reverse; (b) the team accepts Indonesian-language, README-only documentation; (c) someone owns reading the source as the specification.
Technical risk
| Risk | Severity | Notes |
|---|---|---|
| Bus factor / vendor continuity | High | 0 stars, 0 dependents, releases authored by a handful of named Inisiatif staff, no external consumers. No SLA, no public support channel. |
| Schema evolution by editing existing migrations | High | 2.10.1/2.10.2 "add email / donor_phone_id to donor migration" — column additions to the original create migration do not reach already-migrated environments. Silent schema drift between fresh installs and existing deployments. |
| Feature work shipped as patch releases | Medium-High | 2.10.6 is a patch-level tag whose content is new models — i.e. new schema surface — with no changelog beyond a PR list and no named models in the notes. Semver here signals "increment," not "compatibility contract." Pin and review every bump; never float. |
| Unenumerated model surface | Medium | 2.10.6's new models are unnamed in the release notes. You cannot assess collision risk, naming clashes, or key-strategy consistency until you diff the tag. Treat the release note as a pointer to the source, not as documentation. |
| Migration auto-registration collision | Medium | Package migrations run in the host app's migration order; table-name collisions, rollback ordering, and migrate:fresh behavior must be verified. 2.1.x "fixing migration check return value / table name migrations" and 2.8.0 "fixing double column migration" show this area has been unstable. 2.10.6's new tables add to the collision set. |
| Identity strategy inconsistency | Medium | 2.8.2/2.8.3 added and then fixed HasUuids on Partner, plus "Fixing id and uuid." Mixed integer/UUID keys across models complicate joins and API contracts — and the 2.10.6 models have not been audited for which convention they follow. |
| Route/controller side effects | Medium | Region search API surface is undocumented; verify route prefix, middleware, and throttling before shipping. |
| Dependency coupling | Low-Medium | Pulls laravel-query-builder (bumped in 2.6.0); Laravel/PHP version constraints are not stated in the README and must be read from composer.json. |
| Test coverage unknown | Medium | CI visible only as Dependabot/action bumps. Assume no meaningful test suite; the host app's tests are the safety net. |
| Semver discipline | Medium | Frequent patch releases for typos and key names ('table' key typos across 2.7.5/2.7.6) suggest low release rigor; breaking changes may land in minor versions. 2.10.6 reinforces rather than changes this read. |
Key questions to resolve before commitment
migrate on an existing database?donor or other tables we already depend on?Donor schema changes that downstream apps depend on?Stack fit
Requires Laravel + Eloquent. Non-Laravel PHP, or any project using Doctrine/other ORMs, is out of scope — resolveRelationUsing is Eloquent-only, and the value proposition collapses without it. Best fit: a Laravel app whose domain is Indonesian charitable giving and whose team is comfortable with package-level model sharing.
Recommended posture: adopt as a vendor fork, not as an upstream dependency
Given 0 stars / 0 dependents / single-org ownership, the TPM call is to consume the package but own the code path:
use Inisiatif\ModelShared\Models\Donor directly. Introduce our own Donor extending or composing the package model, so an upstream swap or abandonment is a one-file change.Migration path (brownfield)
donors, banks, partners, regions, etc.) — and extend that inventory to whatever 2.10.6 introduces before the diff is run.donor rows to the package's column set, including donor_phone_id and email; run dual-write only if a cutover window is unavoidable.Greenfield is materially cheaper and is where I would spend the political capital: the package becomes the schema, and there is nothing to reconcile.
Compatibility and sequencing
| Phase | Output | Gate |
|---|---|---|
| 0. Spike (3–5 days) | composer.json constraints read; boot side effects enumerated; 2.10.6 model/migration delta named; migrations run clean and roll back clean on a scratch DB |
Route/migration collisions identified |
| 1. Fork + pin | Private registry entry, exact tag pinned, migrations normalized to additive form, unwanted 2.10.6 models trimmed | migrate + migrate:fresh both pass |
| 2. Adapter layer | Our own models/service provider wrapping package models; contract tests | No direct package imports outside the adapter |
| 3. Data load | Region and reference seeders snapshotted; backfill scripts for existing donors | Row-count and referential-integrity checks |
| 4. First feature | One low-risk read path (region search or a reference dropdown) | Production observation window |
| 5. Broaden | Donor, Donation, Outflow models adopted per-domain | Each domain signed off separately |
Sequence by model family, not by release: reference data first (read-only, reversible), then Donor, then financial/Outflow models last. Financial models carry the highest blast radius if the schema shifts upstream. 2.10.6 is not a sequencing event — it is a supply of optional models whose placement on this ladder is decided by what each one relates to, not by the fact that it shipped.
Explicit non-fit
Do not adopt if the product needs non-Indonesian geography, if the roadmap requires a schema meaningfully divergent from the package's donor/donation shape, or if the team cannot absorb maintaining a fork. For a global or highly customized donor model, the package becomes a drag, not an accelerator. The 2.10.6 additions make the package broader within its domain, not broader across domains.
Maintenance
Ongoing maintenance is effectively ours. Upstream ships frequently — patch releases for typos, minor releases adding models, and now a patch release adding models — which reads as active but low-ceremony development. That cadence is not a support guarantee: no issue triage, no changelog discipline beyond auto-generated PR lists, no deprecation policy, and release notes that occasionally do not name what shipped. Budget a named owner (one backend engineer at ~10–15% time) for fork upkeep, upstream diff review, and region data refresh. Track upstream tags monthly; merge selectively, never automatically. Review the 2.10.6 diff before it enters the fork, and record what was taken versus skipped so the next merge is a comparison rather than a re-discovery.
Support
There is no external support channel. Escalation is a direct message to the Inisiatif contributors. For a TPM, that means the dependency must not sit on any critical path the team cannot patch itself. The adapter layer is the operational mitigation: it caps the blast radius of abandonment at one directory. The 2.10.6 release note style — a single PR line, model names omitted — is a concrete illustration of why that mitigation is not optional.
Scaling
LIKE scan behind the region search API.Failure modes
| Mode | Symptom | Mitigation |
|---|---|---|
| Silent schema drift | New environment has donor_phone_id/email; production does not |
Normalize to additive migrations in fork; schema-diff check in CI |
| Migration collision | Deploy fails or wrong table altered; rollback breaks | Pre-flight migrate --pretend in staging; table-prefix collision audit extended to each new tag |
| Route collision | Region search API shadows or is shadowed by an app route | Enumerate boot-registered routes; set a unique prefix or disable |
| UUID/ID mismatch | Foreign keys type-mismatch on Partner joins | Pin key strategy in the adapter; test joins explicitly; audit new models on adoption |
| Unvetted upstream surface | Fork silently absorbs models/tables the team has not reviewed | Diff every tag before merging; record take/skip decisions in the fork README |
| Upstream abandonment | Fork must be fully self-supported overnight | Adapter layer + frozen migrations make this a non-event |
| Region data staleness | Administrative boundaries changed; distribution/compliance reports wrong | Assign refresh ownership and a review cadence (annual minimum) |
| Version constraint break | composer update pulls an incompatible Laravel or query-builder |
Exact tag pin; dependency review as part of each merge |
Ramp-up
resolveRelationUsing pattern is non-obvious to developers who have not used it; include it in onboarding explicitly, since debugging a misconfigured dynamic relation is slow and produces confusing null relations rather than errors.How can I help you explore Laravel packages today?