# 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](docker/README.md) 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)](https://git.keithsolomon.net/keith/MeshVault/issues/1), [dates (#2)](https://git.keithsolomon.net/keith/MeshVault/issues/2), and [changed files (#3)](https://git.keithsolomon.net/keith/MeshVault/issues/3). Tracking lives in [issues](https://git.keithsolomon.net/keith/MeshVault/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. ```sh # 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](LICENSE) for the complete terms, including source availability requirements for modified versions used interactively over a network.