This PR contains the work done to do a little bit of housekeeping pass across all packages and the Website service.
To provide further details about the work:
* Refreshed the READMEs and source documentation to match the current code;
* Tagged every test case consistently across the Infrastructure, Localization, Persistence, and Website test targets;
* Removed Website middleware tests now covered by Infrastructure's own suite;
* Conformed the `PrepareDB` method to Sendable;
* Relaxes the production Compose DATABASE_TLS default from require to prefer;
* Added Persistence test verifying the prefer posture falls back to plaintext connections.
Reviewed-on: rock-n-code/loud-amsterdam#27
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done to rename the _Web_ package as _Infrastructure_, to provide a clear naming and purpose to this particular package within the project.
To provide further details about the work:
* Infrastructure
* Asset fingerprinting: an FNV-1a token derived from the static files directory, appended as ?v= to asset URLs so deploys bust caches; pre-rendered pages also revalidate via weak ETags.
* New middlewares: fixed-window RateLimitMiddleware (per-client budgets keyed by trusted X-Forwarded-For or remote address) and VaryMiddleware (Accept-Encoding on every response); SecurityHeadersMiddleware now also stamps error responses.
* Auto-generated HEAD endpoints, cache max-age configuration, and Docker build/Compose refinements.
* Protocols and scaffolding: Asset/AssetExtension, the Page protocol (viewport, stylesheets, scripts, versioned URLs), and LocalizedRequestContext.
* Rate limiter's counter store swapped from an actor to a Mutex (no executor hop per request) with amortized batch eviction instead of O(n²) scans under client floods.
* FingerprintAssets reports unreadable files to a logger instead of silently producing a token that never busts their cache.
Reviewed-on: rock-n-code/loud-amsterdam#25
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done to address small fixes.
To provide further details:
* HTML template
* Removed the duplicate charset <meta> tag from the Page protocol's head property.
* Router
* Enabled auto-generated HEAD endpoints so every GET route gets a HEAD sibling. Uptime monitors and crawlers probing with HEAD now receive the page's status and headers instead of a 404.
* Docker
* Pinned the asset optimizer versionsvia build args so minified output is reproducible for a given Dockerfile commit.
* Narrowed the build context copied into the release stage, only package manifests and Swift sources are copied. Static assets come from the separate assets stage after the binary is built.
* svgo now minifies all SVGs recursively rather than just icon.svg, and the staging step creates Resources/Static explicitly instead of conditionally moving the unminified sources.
* Added curl to the runtime image (needed for the container healthcheck) and .claude to .dockerignore.
* Docker-compose
* Added a `healthcheck` to the website service hitting GET /health (liveness only), so Compose reports process health without coupling container health to database reachability.
Reviewed-on: rock-n-code/loud-amsterdam#23
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done for build-time optimization of the static assets served by the Website service. The production Docker image now ships minified JS/CSS and losslessly recompressed images, while the sources in the repository stay readable and un-minified.
Reviewed-on: rock-n-code/loud-amsterdam#20
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done to introduce a _Fluent_-based persistence layer for the Website service, selectable at runtime alongside the existing in-memory default, plus the local dev tooling and docs to support it.
To provide further details about the work:
* Persistence package
* The `Driver` and `TLS` enumerations
* The `Configuration` type
* The `Service` factory that builds the service
* `PrepareDB` for migrations registration
* The `Probe` for readiness checks.
* App integration
* Builds the driver, registers migrations, and attaches `Fluent` to the service lifecycle so it starts/stops with the HTTP server.
* Migrate-on-boot is gated to the in-memory backend; MySQL/MariaDB is migrated out of band via --database-migrate so shared databases never race on startup.
* The `ConfigReader+Properties` extension maps database.* config keys onto the driver.
* Library
* Added database configuration constants.
* The `HealthController` controller gains a readiness probe: `GET /health/ready` checks whether the database is reachable, separate from the existing liveness check.
* Others
* Updated the `docker-compose` files to support a database service behind a database profile, and hardened for local development
* New database targets on the `Makefile` file and overall documentation updated
* Updated the `.env.local`, `Dockerfile`, and `README` files to document the persistence workflow, config keys, and local DB commands
Reviewed-on: rock-n-code/loud-amsterdam#13
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done to get the Website service building and running correctly in its Linux container. The service depends on the local _Localization_ package, whose String-Catalog localization was Darwin-only and broke the Docker build. Thus the localization internals have been reworked to be platform-agnostic and fixes the container build context so the local package is actually available during the build.
* Localization package
* Replaced the Darwin-only `String.LocalizationValue` / `String(localized:)` path with a StringCatalog type that reads raw JSON from a given `.xcstrings` file, so lookups resolve identically on macOS and Linux.
* The `LanguageList` now derives available languages from the catalog instead of `Bundle.localizations`
* The `Negotiate` does explicit _Accept-Language_ matching (exact tag, then primary subtag) instead of the Linux-broken `Bundle.preferredLocalizations`.
* Switched the catalog resource rule from `.process` to `.copy` (in both Localization and Website manifests) so the raw `.xcstrings` ships verbatim on every platform.
* Introduced a `CatalogResolving` protocol as a seam between the localizers and the storage backend, enabling test injection and a future native-Apple backend without changing callers.
* Website Docker build
* Build context moved to the repository root so the relative-path `Localization` package is inside the context; `Dockerfile`, `docker-compose.override.yml`, and the _img-release_ make target updated to the new context/paths.
* Added a root `.dockerignore` to keep the context lean.
Reviewed-on: rock-n-code/loud-amsterdam#12
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done to support the static files serving for the **Website** service, and also included the essential boilerplate assets from the **HTML5 boilerplate** project.
To provide further details about the work done:
* Serving: Added the `FileMiddleware` middlewqare to the router; `path`, `server name`, and `log level` now read from config with defaults.
* Library: Added the `StaticFile` enumeration with a `contentType` property, plus typed config-key/value constants and the `Configuration` dependency on WebsiteCore.
* Assets: Added the **HTML5 boilerplate** (HTML, CSS, JS, icons, manifest, robots) to the *Resources/Static* folder.
* Docker: Stage the Resources directory as read-only.
* Tests: Added a test plan, and a shared Xcode scheme.
Reviewed-on: rock-n-code/loud-amsterdam#3
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This PR contains the work done to add and setup the *Website* service target, a **Hummingbird** server app, into the Xcode project as a SwiftPM package with full support for containerization and driven by a `Makefile` file.
To provide further details about the work done:
* Swift package — SwiftPM manifest with a Website executable, related library, and test targets; depends on **hummingbird** and **swift-configuration**.
* Containerization — Multi-stage `Dockerfile` producing a static-linked release build with jemalloc, running as a non-root user on port 8080. Production and local-dev `docker-compose` files included.
* Configuration — `.env.local` template (with `.env` git-ignored) and `.dockerignore`/`.gitignore` entries.
* Makefile — Self-documenting operational commands:
* pkg — SwiftPM: _build, release, test, clean, reset, deps, outdated, update_
* img — Docker lifecycle: _build, mount, unmount, release_
Notes
* New service only — no changes to existing code; nothing else in the repo is affected.
* App logic is currently scaffolding; this PR establishes the service structure, build, and deployment tooling.
Reviewed-on: rock-n-code/loud-amsterdam#2
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>