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

Application Laravel Package

liberusoftware/application

The Application package from Liberusoftware provides a Laravel application foundation for modular PHP projects, offering shared bootstrapping, structure, and conventions so teams can build maintainable enterprise applications without reinventing core scaffolding.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, opinionated "platform plumbing" module: it gives every Liberu application the same answers to four boring-but-repeated questions — what version am I?, am I healthy?, what time is it?, and what should every response look like? Treat it as infrastructure you wire once per project, not a library you call on every request.

Before writing any code, read the source. With zero stars and zero dependents there is no community documentation to fall back on, and the 2026-10-27 release date suggests the metadata is not a reliable signal. Open these in order:

  1. composer.json — confirm the PHP/Laravel constraints and the PSR-4 namespace (likely Liberu\Application\).
  2. The service provider — what it binds, what it publishes, whether it registers routes or middleware automatically.
  3. config/ — the config key (probably application.*) and every value that can be overridden by env.
  4. routes/ — whether health endpoints are auto-registered or opt-in.
composer require liberusoftware/application
php artisan vendor:publish --provider="Liberu\Application\ApplicationServiceProvider" --tag=config
php artisan route:list | grep -i health
php artisan about   # if the package hooks into the about command

First use case: get a health endpoint into your deploy pipeline the same day you install it. Point your container orchestrator's readiness probe at the package's readiness route and your liveness probe at the liveness route. That single step justifies the dependency, because it replaces the hand-rolled /up route plus a HealthController that every project otherwise reinvents slightly differently.

The second-fastest win is the clock. Replace now() / Carbon::now() in new code with the package's clock abstraction immediately — retrofitting it later is tedious once date logic is scattered across services.

A pragmatic verdict: adopt it for conventions, not for features. The value is consistency across a fleet of modules, and that value is only realized if you actually standardize on it rather than letting it sit installed and unused.

Implementation Patterns

Health and readiness as two distinct probes

The most common mistake is treating "health" as one endpoint. Use them differently:

  • Liveness — "is the process alive?" It must not touch the database, cache, or any network dependency. If it fails, the orchestrator kills and restarts the container, so a transient DB blip must never fail liveness.
  • Readiness — "should traffic be routed here?" This is where DB/cache/queue connectivity belongs. Failing readiness removes the pod from the load balancer without restarting it.
// config/application.php (typical shape — verify against published config)
'health' => [
    'enabled' => env('APP_HEALTH_ENABLED', true),
    'prefix'  => env('APP_HEALTH_PREFIX', '_health'),
    'checks'  => [
        'database' => true,
        'cache'    => true,
        'queue'    => env('APP_HEALTH_CHECK_QUEUE', false),
    ],
],

Keep health routes on an internal listener/port or behind your ingress's private rule. A public readiness endpoint that enumerates your dependencies is a reconnaissance gift.

Metadata for deploy traceability

Expose the application name, version, and build/commit SHA somewhere you can grep after a deploy — either the about command, a metadata endpoint, or an HTTP response header. Wire the version to a build-time env var rather than reading composer.json at runtime (filesystem reads in a request path are waste, and the file may not be present in a slim production image).

// .env, set by CI
APP_VERSION=1.24.3
APP_COMMIT=${GIT_SHA}

Then a one-liner confirms what's actually running:

curl -s https://app.example.com/_health | jq '.version'

Note the subtlety: many packages cache config aggressively, and if metadata is read from config at boot, a config:cache from a previous release can make a fresh container report a stale version. See Gotchas.

Injectable clock instead of now()

The clock's whole point is testability. Inject it into services that make time-based decisions: trial expiry, token TTLs, rate-window boundaries, SLA calculations, "N days ago" logic.

final class TrialExpiry
{
    public function __construct(private ClockInterface $clock) {}

    public function isExpired(Trial $trial): bool
    {
        return $this->clock->now()->greaterThan($trial->endsAt);
    }
}

In tests, bind a frozen clock in the container rather than reaching for Carbon::setTestNow() globally — a frozen clock is scoped to the test case, whereas setTestNow leaks across the suite if a test fails before teardown. Prefer injecting into constructors; reserve facades/helpers for legacy call sites where constructor injection would ripple too far.

For anything measuring elapsed time (timeouts, latency budgets), the clock is still a wall clock. Don't use it for durations where the system clock can jump (NTP correction, DST); use a monotonic source like hrtime() for that.

Secure response defaults as a baseline, not a solution

The package likely registers global middleware applying headers such as X-Content-Type-Options: nosniff, X-Frame-Options, Referrer-Policy, and possibly Strict-Transport-Security. Verify by curling a response:

curl -sI https://app.example.com | grep -iE 'x-frame|x-content|referrer|strict-transport'

Treat these as a floor. They do not replace a CSP tailored to your assets, nor do they handle CORS, cookie flags, or cache-control on sensitive responses. If you need to override a default, do it in middleware registered after the package's middleware, not by disabling the package globally — otherwise new routes silently lose the baseline when someone adds a route group.

Shared identifiers

The identifier component is where you get a single answer to "what ID format does this project use?" — typically UUIDv7 or ULID for primary keys and public-facing references. Two patterns that pay off:

  • Separate internal PK from public ID. Keep an auto-increment or UUID PK for joins, and expose an opaque ULID in URLs and APIs so you never leak row counts or enable enumeration.
  • Route binding on the public ID. getRouteKeyName() returning the ULID column keeps controllers clean and prevents accidental where('id', ...) lookups from user input.
public function getRouteKeyName(): string
{
    return 'public_id';
}

Generate identifiers through the package's factory rather than Str::uuid() scattered in models, so a future format change is a one-line swap instead of a grep across the codebase.

Composing with other Liberu modules

This module is designed to be a dependency of sibling modules, not a top-level feature. The productive pattern is: application code and other modules consume the clock, identifier factory, and secure-response middleware, and never duplicate them. If you find yourself writing a TimeService or a UuidTrait, you've forked the package and lost the consistency benefit that is its only real justification.

Gotchas and Tips

Health checks that lie. A readiness check returning 200 while the DB is unreachable is worse than no check — it keeps a broken pod in rotation. Conversely, a liveness check that pings Redis will restart healthy pods during a cache failover and turn a blip into an outage. Keep the dependency graph of each probe deliberately asymmetric, and add a timeout to each check so a hung dependency doesn't hang the probe past the orchestrator's threshold.

config:cache and metadata drift. If version/build metadata is read from config, php artisan config:cache freezes it into bootstrap/cache/config.php. Building the cache during a Docker build and shipping it into a container that gets a different APP_VERSION at runtime is a classic source of "the version endpoint is wrong" bugs. Either set metadata via runtime env vars that are not baked into the cache, or bust the cache on every deploy.

Clock binding under Octane and long-running workers. Under Octane, queue workers, or any resident process, container bindings resolved at boot persist for the life of the worker. A frozen clock bound in tests is fine; a cached clock resolved once at boot is a bug in a worker that runs for hours. Resolve the clock per-job, or ensure the binding is a factory rather than a singleton holding a timestamp.

Timezone and storage. Store timestamps in UTC and convert at the presentation edge. If the package's clock is timezone-aware, resist the temptation to configure it to a business timezone "so dates look right" — that decision metastasizes into DST bugs in scheduled jobs and reporting. Verify the package respects app.timezone or is explicitly UTC.

Duplicate security headers behind a proxy/CDN. Your ingress, the package middleware, and the framework may all set the same headers. Duplicated Strict-Transport-Security values are invalid per spec and some browsers ignore them. Audit the final response after the full stack, not in a unit test.

HSTS is one-way. If the package enables Strict-Transport-Security with a long max-age, you cannot easily walk it back, and any HTTP-only subdomain in your org will break for users who have the header cached. Confirm the max-age before enabling in production; ship with a short max-age first.

Identifier format is a public contract. Swapping ULID for UUIDv7 after launch invalidates bookmarked URLs, API clients, and any external integration keyed on the ID. Decide before the first release, and if you must migrate, keep the old column readable during a transition window.

Zero dependents means you are the QA. With no downstream users, expect gaps in edge-case handling and no Stack Overflow trail when something breaks. Mitigations: pin an exact version in composer.json (not a caret range), keep the integration surface thin by wrapping the package in your own small adapter/service, and read the diff before every upgrade. Your wrapper is also what makes it cheap to rip the package out — worth having given the adoption risk.

Extension points to look for. In descending order of usefulness: container bindings (clock, identifier factory) → publishable config → middleware ordering in the HTTP kernel → interfaces you can implement and re-bind. If the package only offers config and no interfaces for the clock/identifier services, that's a meaningful limitation — you'll be coupled to concrete classes in tests.

Debugging checklist when a route or header doesn't appear. (1) Is the provider auto-discovered, or does it need registering in bootstrap/providers.php? (2) Is the relevant config block set to false — including via a cached config? (3) Is your own middleware or a route group overriding it downstream? (4) Is a CDN stripping the header before it reaches you? Confirm with curl -v against the origin, not the edge.

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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core