Files
InvoiceShelf/docs/architecture/0001-modular-monolith.md
T
Darko Gjorgjijoski 5ef7804e60 refactor: adopt modular domain architecture (#747)
* refactor: stabilize model identities for domain migration

* refactor: extract module platform context

* refactor: assign models to domain contexts

* refactor: extract ai platform context

* refactor: extract storage platform context

* refactor: extract mail platform context

* refactor: extract pdf platform context

* refactor: extract operations platform context

* refactor: move installation into operations platform

* refactor: extract money domain context

* refactor: extract taxation domain context

* refactor: extract catalog domain context

* refactor: extract metadata domain context

* refactor: extract reporting domain context

* refactor: extract purchases domain context

* refactor: extract receivables domain context

* refactor: extract accounts domain context

* refactor: complete reporting statement boundary

* refactor: extract contacts domain context

* refactor: extract sales domain context

* refactor: remove legacy application layers

* fix: migrate legacy bouncer role identities
2026-08-05 17:40:03 +02:00

2.7 KiB

ADR 0001: Laravel-native modular monolith

Date: 2026-08-05

Status: Accepted

Context

InvoiceShelf 3.x is still in alpha and may break PHP namespaces and internal extension contracts. Existing installations must retain their database data, document links, and public /api/v1 behavior. The current layer-first layout mixes sales, receivables, purchases, reporting, and infrastructure in global model, controller, and service directories.

Decision

The backend is organized as a modular monolith under app/Domains and app/Platform.

Business contexts are Accounts, Contacts, Catalog, Taxation, Money, Metadata, Sales, Receivables, Purchases, and Reporting. Platform capabilities are Modules, AI, Mail, PDF, Storage, and Operations.

Each context owns its models, actions, queries, policies, events, jobs, and HTTP adapters. Large contexts may contain feature subdirectories. Every context is registered explicitly through a service provider; root route files are composition roots for context-owned route fragments.

Direct Eloquent relationships across contexts are permitted for read navigation when declared by the architecture dependency map. Cross-context writes and workflows use contracts and application actions. Reporting may query shared tables through read-only query objects. Infrastructure is reached through platform contracts. No repository abstraction is required around Eloquent by default.

All first-party models use stable morph aliases. Model namespaces, Hashids connection names, and public API discriminators are separate identities. The database stores aliases, Hashids retain their historical salt inputs, and v1 resources retain their existing discriminator strings.

Modules depend on the versioned invoiceshelf/modules SDK and must not import domain internals.

Migration rules

  • Contexts move in independently green pull requests.
  • A moved class has one canonical namespace; class aliases are forbidden.
  • Temporary adapters may connect migrated and unmigrated contexts, but must be deleted when the counterpart context moves.
  • Existing table and column names remain unchanged and moved models declare their table explicitly.
  • HTTP methods, paths, middleware, payloads, status codes, and OpenAPI schemas remain stable.
  • Queue workers are drained and restarted for the namespace cutover; serialized legacy jobs are not supported.

Consequences

Feature ownership and cross-domain writes become explicit, while Eloquent remains usable without a framework-independent persistence layer. Namespace changes require coordinated imports across application code, factories, seeders, configuration, tests, and historical migrations, but no persisted record depends on those namespaces after the alias migration.