0007. SabreDAV Runtime Decoupling¶
Status¶
Accepted
Context¶
This package is built on top of SabreDAV, but its public architecture is intended to remain Laravel-first and contract-driven.
SabreDAV is responsible for protocol execution, request handling details, and response emission once a configured
Server instance starts running.
At the same time, the package needs the Laravel-side application model to stay decoupled from SabreDAV-specific classes and runtime behavior as much as possible.
If SabreDAV concerns are allowed to spread freely across controllers, auth, storage resolution, and authorization, several problems appear:
- package internals become harder to test because SabreDAV runtime execution is invasive
- transport-specific classes leak into business-facing extension points
- replacing collaborators or adapting runtime behavior becomes harder
- Laravel-side architecture becomes shaped by SabreDAV internals instead of package contracts
The current implementation already maintains an explicit boundary:
WebDavControllerhandles request entry and basic auth-attempt checksWebDavServerFactoryorchestrates request context resolution, storage root construction, and server configuration- request context, auth, storage routing, and authorization are expressed through package contracts and DTOs
ServerRunnerInterfaceis the final runtime boundary- the default runtime adapter is
SabreServerRunner, which executesserver->start(); exit;
Decision¶
The package keeps SabreDAV as the protocol runtime engine, but isolates SabreDAV-specific execution behind dedicated package boundaries.
The architectural rules are:
- package extension points are defined in package contracts, not in SabreDAV interfaces
- request context, principal resolution, storage space mapping, and authorization are expressed in package DTOs and value objects
- SabreDAV
Serverconstruction is centralized inWebDavServerFactory - runtime execution is delegated through
ServerRunnerInterface - the default
SabreServerRunneris the place where SabreDAV takes over the request lifecycle
This means the package integrates with SabreDAV at the runtime edge, while the rest of the package speaks primarily in Laravel- and package-level concepts.
Consequences¶
Positive consequences:
- most package internals can evolve around package contracts instead of third-party runtime types
- testing stays tractable because SabreDAV process termination is isolated to one adapter boundary
- consuming applications override package collaborators through Laravel bindings instead of patching SabreDAV wiring
- the package keeps a clearer separation between protocol runtime and Laravel-side domain orchestration
Trade-offs:
- SabreDAV is still a hard runtime dependency and cannot be considered fully abstracted away
- one more adapter boundary exists between request orchestration and final protocol execution
- developers still need some SabreDAV knowledge when working at the runtime edge
Rejected alternatives:
- call SabreDAV runtime APIs directly throughout controllers and collaborators
- rejected because it would couple package internals tightly to SabreDAV and weaken testability and replaceability
- hide the full request pipeline inside one SabreDAV-facing integration class
- rejected because it would obscure the package architecture and reduce contract-driven extension points
- attempt to abstract all SabreDAV types out of existence
- rejected because the package is explicitly a SabreDAV-based WebDAV server and still needs a concrete protocol engine