build: M1 Dockerized development stack with PHP skeleton, config/logging, Tailwind assets, and wrappers
Implements MeshVault M1 (issues #6–11): - Four-service Docker Compose stack (nginx, PHP-FPM 8.3, PostgreSQL 17, Node assets) - Slim 4 + PHP-DI routing with escaped PHP views and production/dev error handling - Immutable validated AppConfig with redacted diagnostics - JSON stdout Monolog logging with job-scoped context - Tailwind CSS v4 deterministic locked builds with template scanning - POSIX and PowerShell dev wrappers (up/down/test/lint/assets/watch) - Startup config validation fails before FPM serves as unprivileged www-data - migrate/seed explicitly unavailable until M2 (#12); #10 remains open Verified via clean-start acceptance on remote host (keith@192.168.2.23).
This commit is contained in:
1 parent
c2747a5762
commit
d3e8cf8fae
39 files changed
+5291
-38
No files matched your search
@@ -3,10 +3,11 @@
|
||||
MeshVault is a self-hosted 3D model library being built as a Docker service.
|
||||
It catalogs logical models containing STL parts, images and supplementary documents.
|
||||
|
||||
**Status:** M0 foundations only. There is no runnable web application, database
|
||||
schema or Docker stack yet. Installation and a verified application quick start
|
||||
are deliverables of [M1](https://git.keithsolomon.net/keith/MeshVault/milestones).
|
||||
Do not deploy this scaffold as a service.
|
||||
**Status:** M1 development stack is up. A four-service Docker Compose stack serves
|
||||
a Slim 4 landing page with Tailwind CSS, configuration/logging, and cross-platform
|
||||
task wrappers. There is no catalog application, database schema or migration runner
|
||||
yet. See [the development stack setup](docker/README.md) for first-run instructions.
|
||||
Do not deploy this as a production service.
|
||||
|
||||
## Planned MVP
|
||||
|
||||
@@ -33,8 +34,10 @@ management, external imports, AI and multi-user libraries are outside MVP.
|
||||
## Architecture and decisions
|
||||
|
||||
Docker, PostgreSQL and PHP application logic; PHP-rendered templates with Tailwind
|
||||
CSS and browser JavaScript. Node is planned for asset builds, with mesh processing
|
||||
introduced only when those future features are scoped. No PHP framework is selected.
|
||||
CSS and browser JavaScript. Node runs inside an assets container for deterministic
|
||||
locked builds and watch; no host Node is required. Slim 4, PHP-DI and Monolog are
|
||||
installed, locked and wired. HTTP, configuration, logging and task wrappers are
|
||||
verified on the remote development host.
|
||||
|
||||
Accepted decisions: [managed storage (#1)](https://git.keithsolomon.net/keith/MeshVault/issues/1),
|
||||
[dates (#2)](https://git.keithsolomon.net/keith/MeshVault/issues/2),
|
||||
@@ -49,7 +52,7 @@ Local planning notes and ADR copies are deliberately not versioned.
|
||||
| `src/` | PHP application and domain code |
|
||||
| `public/` | Future HTTP document root and generated browser assets |
|
||||
| `db/migrations/` | Ordered PostgreSQL schema migrations |
|
||||
| `docker/` | Future container definitions and service configuration |
|
||||
| `docker/` | Development container definitions, configuration and setup |
|
||||
| `assets/` | Source assets, including the project icon |
|
||||
| `tests/` | Automated checks and future application fixtures/tests |
|
||||
|
||||
@@ -57,18 +60,51 @@ Directory READMEs describe boundaries; they are not application implementations.
|
||||
|
||||
## Development checks
|
||||
|
||||
With PHP 8.3+ and Composer 2 installed:
|
||||
The only host prerequisite is Docker Compose v2+ with Linux containers. All PHP
|
||||
and Node tooling runs inside containers.
|
||||
|
||||
```sh
|
||||
composer install --no-interaction
|
||||
composer validate --strict
|
||||
composer lint
|
||||
composer test
|
||||
# Start the stack (builds images if needed)
|
||||
./dev.sh up
|
||||
# Or on Windows: .\dev.ps1 up
|
||||
|
||||
# Run checks inside the app container
|
||||
./dev.sh test
|
||||
./dev.sh lint
|
||||
|
||||
# Build minified assets inside the assets container
|
||||
./dev.sh assets
|
||||
# Watch for template changes
|
||||
./dev.sh watch
|
||||
```
|
||||
|
||||
These commands validate foundation files and PSR-12 configuration, not application
|
||||
behavior. See [CONTRIBUTING.md](CONTRIBUTING.md) for conventions and test limitations.
|
||||
Container-based development, migrations and frontend build commands arrive in M1.
|
||||
`composer test` and `composer lint` also work on a host with PHP 8.3+ and Composer 2.
|
||||
`composer audit` checks locked PHP dependencies. `migrate` and `seed` are unavailable
|
||||
until M2 (#12); they exit nonzero and leave #10 open.
|
||||
|
||||
Asset builds use a locked `package-lock.json` inside a container; host Node is not
|
||||
required. The generated `public/build/app.css` is served statically by nginx.
|
||||
|
||||
### Configuration and logging library
|
||||
|
||||
`MeshVault\Config\AppConfig::fromEnvironment(array $environment)` accepts explicit
|
||||
string values; supported keys, defaults and validation rules are in `.env.example`.
|
||||
Native PHP does not read `.env`: export the variables through your shell/process
|
||||
manager, then pass `getenv()` to the factory after requiring `vendor/autoload.php`.
|
||||
Compose environment injection/startup validation will be wired in Task3. Validate as
|
||||
the actual runtime user, not root. The library never creates or chmods library roots.
|
||||
|
||||
Readonly properties: `environment`, `libraryPath`, `dbHost`, `dbPort`, `dbName`,
|
||||
`dbUser`, `dbPassword`, `logLevel`. Configuration JSON/debug/serialization is redacted;
|
||||
serialized configuration cannot be restored. Read credentials only at their point of
|
||||
use: do not cast configuration to arrays or log credentials/messages containing them.
|
||||
This is not a general-purpose sanitizer for arbitrary caller-supplied secrets.
|
||||
|
||||
`MeshVault\Logging\LoggerFactory::create($config)` returns a PSR-3 logger writing
|
||||
newline-delimited JSON to stdout at the configured level. `forJob($logger, $jobId)`
|
||||
returns an independent scope; its `job_id` takes precedence over caller context,
|
||||
while other context is retained. Re-scoping replaces the job ID; the base logger
|
||||
and other jobs are unchanged. FPM forwarding remains a Task3 verification gate.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in new issue
Block a user