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).
5.5 KiB
MeshVault
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: 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 for first-run instructions. Do not deploy this as a production service.
Planned MVP
- Managed imports copy existing collections without changing their originals. Read-only source directories are supported; the managed destination must be writable.
- Physical folder browsing and management mirror the managed directory tree.
- Imports provide a pre-scan, progress and per-file failure reasons.
- Logical models support multiple files, categories, tags, notes, source URLs and uploaded thumbnails, with name/tag search and downloads.
- Catalog removal deletes database records only, retaining physical files.
- Missing files, changed content and exact duplicates are visible for user resolution. There is no automatic deletion or merging.
Date added records entry into MeshVault, not filesystem creation. File modification
times and sizes are separate metadata; MVP has no separate creation-date field.
Changed content is flagged Updated, with user acknowledgement re-baselining its
hash. No historical contents are preserved: an external overwrite cannot be undone
by detecting it. Backups must include PostgreSQL metadata, library files and uploaded
media as a consistent set using standard database/filesystem tools.
Other mesh formats, generated thumbnails, 3D viewing, watching, versioning, printer 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 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), dates (#2), and changed files (#3). Tracking lives in issues. Local planning notes and ADR copies are deliberately not versioned.
Repository layout
| Directory | Responsibility |
|---|---|
src/ |
PHP application and domain code |
public/ |
Future HTTP document root and generated browser assets |
db/migrations/ |
Ordered PostgreSQL schema migrations |
docker/ |
Development container definitions, configuration and setup |
assets/ |
Source assets, including the project icon |
tests/ |
Automated checks and future application fixtures/tests |
Directory READMEs describe boundaries; they are not application implementations.
Development checks
The only host prerequisite is Docker Compose v2+ with Linux containers. All PHP and Node tooling runs inside containers.
# 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
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
MeshVault is licensed under GNU AGPL version 3 only (AGPL-3.0-only).
See LICENSE for the complete terms, including source availability
requirements for modified versions used interactively over a network.