Repository navigation
webware/webware serves nothing: no route is registered and there is no handler class #6
Description
Summary
webware/webware does not serve a page in a browser, and the reason is structural rather than environmental: nothing in the application registers a route, and there is no handler class to dispatch to. Every request runs the full middleware pipeline, matches nothing, and terminates at NotFoundHandler with a 404.
Verified again on 2026-09-25, immediately before this issue was filed:
config/routes.phpdoes not exist.- Zero route registrations anywhere:
grep -rcE '\$app->(get|post|route|any)\(' config srcmatches nothing. src/App/src/contains exactly one file,ConfigProvider.php. There is noHandler/directory.router.routesis ABSENT from the merged configuration, which otherwise carries 29 top-level keys contributed by the components.App\ConfigProvider::getDependencies()returns'factories' => [], so there is no handler factory either.__invoke()returns onlydependenciesandtemplates.
The templates are all present (app/home-page.phtml, layout/default.phtml, error/404.phtml, error/error.phtml), which is why this looked finished. The provider was converted to the ConfigProvider-driven shape and given its templates, but the routes half never followed and the handler class was never written.
No pull request is open for this work, and none should be opened until the application loads in a browser. PR #4 (feat/mezzio-app-bootstrap, "Setup") was closed on 2026-09-25 for that reason.
Current state of the branch
| branch | feat/mezzio-app-bootstrap |
| tip | 7f02f55 feat(app): wire the local dev environment and views |
versus origin/1.0.x |
2 ahead, 0 behind |
| PR | #4 closed 2026-09-25 |
| uncommitted | composer.json, composer.lock, config/config.php, config/pipeline.php |
So the pipeline port and the config wiring are sitting in the working tree, uncommitted and unverified, and the recommended course is to land the route and handler before any of it goes up for review.
Why dev mode will not surface it
Dev mode is worth having on (config/development.config.php.dist sets ConfigAggregator::ENABLE_CACHE => false and 'debug' => true, so it bypasses the config cache written at 23:16), but it will not change the outcome, because nothing throws. Checked directly:
AuthorizationMiddlewarereadsRouteResultand returns$handler->handle($request)when it is null or a failure result, which is exactly the case for an unmatched request.AclMiddlewareis a passthrough that attachesAclInterfaceto the request.AttachCoreServicesMiddlewareattaches the input filter manager.
So with Traccio's TracyDebuggerMiddleware piped in place of ErrorHandler, the browser still gets the 404 page rather than a stack trace. Dev mode is not the diagnostic step for this.
Note on enabling dev mode in this repo: there is no dev-mode command here. composer.json registers only clear-config-cache, serve, test, test-coverage, test-integration, mutation-test, test-all; there is no development-enable script and laminas/laminas-development-mode is not in the lock or in vendor/. The mechanism that exists in the ecosystem is webware-console's dev:mode, invoked from the repository root:
vendor/bin/webware dev:mode --enable
It copies config/development.config.php.dist to config/development.config.php and clears the config cache. It takes options, not arguments, so dev:mode enable is rejected with No arguments expected for "dev:mode" command, got "enable", and dev:mode with no option only prints usage. --status and --disable behave as expected. (The console-side reasons behind that interface are tracked in webinertia/webware-console#31, not here.)
What is actually needed for it to load
A route for / plus a handler to dispatch it to. Concretely:
- A
routeskey returned fromApp\ConfigProvider, or aconfig/routes.phpfollowing the Mezzio convention. Nothing else in the repo supplies routes, and no component supplies one either. - A handler class in
src/App/src/Handler/, renderingapp::home-pageinsidelayout::default, which the template map inApp\ConfigProvider::getTemplates()already points at. - A factory for it registered in
getDependencies(), which currently returns an empty factories map.
That is the entire gap between the repository as it stands and a page in the browser.
The uncommitted work, for the record
config/pipeline.php (36 added lines, 22 stages) ports the IMS pipeline onto the current Http\ FQCNs: TracyDebuggerMiddleware or ErrorHandler chosen by class_exists plus debug, then EventDispatcherMiddleware, ServerUrlMiddleware, SessionMiddleware, IdentityMiddleware, AttachCoreServicesMiddleware, MonologMiddleware, DetectAjaxRequestMiddleware, then routing (RouteMiddleware, ImplicitHeadMiddleware, ImplicitOptionsMiddleware, MethodNotAllowedMiddleware), UrlHelperMiddleware, NavigationMiddleware, AclMiddleware, AuthorizationMiddleware, DispatchMiddleware, NotFoundHandler. IMS-only App\Middleware\ImsMessengerMiddleware was deliberately dropped in the port. None of this has been exercised against a real request, because no request can match.
config/config.php adds Webware\Event\ConfigProvider, Webware\Admin\ConfigProvider, Webware\Navigation\ConfigProvider, and a dev-only traccio entry behind class_exists.
composer.json adds a ../traccio path repository and webware/traccio: 0.1.x-dev. The matching lock and vendor entries landed on 2026-09-25 via composer update webware/webware-navigation webware/traccio --with-dependencies, which also pulled tracy/tracy v2.12.1. That cleared InvalidConfigProviderException: Cannot read config from Webware\Navigation\ConfigProvider, which had been blocking the app from booting at all. webware-tools stayed at 1.0.0-beta.3, so the Console guard rule that shipped in 1.0.0-beta.4 is not in force here; raising it needs --with-all-dependencies and will move root dependencies too.
CI is red for a structural reason, not a code reason
Every failing check dies in Install dependencies, before lint or tests. Run 35954754381 on 7f02f55 reported 16 failures, 4 skips, 2 successes, all traced to that step:
latestandlowestlegs, and both Mago jobs:The url supplied for the path (../message-bus) repository does not existfromPathRepository.php line 163, exit 1. The../webware-*and../message-buspath repositories exist only on a developer machine; a GitHub runner has no siblings, so resolution aborts outright.lockedlegs: exit 4 withThe lock file is not up to date with the latest changes in composer.json, becausecomposer.jsonrequireswebware/webware-navigationand the committed lock did not contain it.
The last green run was 28d90f5 on 2026-09-23, and at that commit composer.json declared zero path repositories and no navigation requirement. 7f02f55 introduced both. The default branch 1.0.x still declares none, which is why it stays green.
Consequence: while sibling path repositories are committed, this repository cannot have green CI. Three options, none yet chosen:
- Drop the path repositories from the committed
composer.jsonand require real versions. Everything needed now has one:webware/webware-navigation 1.0.0-alpha.2,webware/webware-console 1.0.0-alpha.2,webware/webware-tools 1.0.0-beta.4. - Keep path repositories as a local-only convenience so the committed file stays installable in CI.
- Leave it red deliberately until the app is further along.
Other verified facts, so they do not have to be re-derived
App\maps tosrc/App/src/via PSR-4, which is why the app'sConfigProviderlives atsrc/App/src/ConfigProvider.phpand notsrc/ConfigProvider.php.config/autoload/mysql.local.phpcontributesPhpDb\Adapter\AdapterInterfaceand its dependencies. Every.local.phpunderconfig/autoload/is ignored by design:config/autoload/.gitignoreholdslocal.phpand*.local.php, andgit check-ignore -vattributes that file to the second of those rules. Local overrides are deliberately not tracked, so its absence from the index is not a tracking defect and should not be changed. The app is nonetheless configured for a database, and MySQL has to be up in the tooling container for anything that touches it.test/unit/ConfigProviderTest.phpfails, and not because of anything recent. It assertsnew ConfigProvider()->__invoke()returns only['dependencies' => ['factories' => []]], while the provider now also returnstemplates(a four-entry map,appanderrorpaths,default_layout). The provider gained that in7f02f55and the test was never updated. Separately, that test declares#[CoversMethod(ConfigProvider::class, '__invoke')]only, so once it passes a coverage run will countgetTemplates()andgetDependencies()as uncovered.- Dev mode is currently not enabled:
config/development.config.phpis absent. - Spec-kit paths are gitignored here by design, the root
.gitignoreholds/.specify/and/specs/, which is the same deliberate untracking used in acl, admin, htmx, mailer and navigation, as opposed to webware-console and webware-migration which track them. Neither directory currently exists in the working tree, so this issue is the record for now. - A local server attempt on port 8080 failed with
Address already in useon 2026-09-25, so something else was already listening there. Anything testing in a browser should confirm the process answering is this application.
Decisions needed
- Route and handler: build them, and decide whether the
/route is declared inApp\ConfigProvideror in aconfig/routes.php. The templates already exist, so this is the whole of the work. - Path repository policy: one of the three options above. Until it is settled, CI on this repository is expected to be red and should not be read as a code problem.
- The in-flight work: whether the ported
config/pipeline.phpand theconfig/config.phpprovider additions are committed as-is, or held until the route exists so they can be exercised end to end. webware-toolspin: whether to raise it to1.0.0-beta.4now, accepting that--with-all-dependencieswill move root dependencies in the same pass.- The stale unit test: whether it is corrected alongside the bootstrap work, including the two extra
CoversMethodentries it will need.
Not in scope here
Anything about the console's prompt behaviour, key handling, or command wrapping belongs in webinertia/webware-console#31. This issue is specifically about why webware/webware serves nothing, and about the dependency and CI facts that surround it.
Activity
tyrsson commentedon Oct 1, 2026
Fixed