The template's new `site.origin` key arrived empty, as bootstrap fills it in.
Pointing it at the origin robots.txt and sitemap.xml already carry turns on the
canonical and hreflang links, and the HTTPS redirect the production compose
already trusts the forwarded proto for.
Reconciled the bootstrap-customised files: kept the CCN naming, canonical
origin, database slug and analytics comments, dropped the template-only
Makefile, README.md and Scripts/bootstrap that bootstrap removes, and took
the template's ordering for the security headers in the production compose.
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 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 provide optimizations to the current service, such as a health-check endpoint, pre-renders static HTML pages, and hardens the error page's CSP.
To provide further details about the work:
* Added the `HealthController` controller serving GET `/health` with a static JSON payload.
* Added the `CachedHTMLResponse` response, which renders a static HTMLDocument to bytes once and reuses them per request (no Content-Length, so responses stay compressible).
* Integrated the response into the `RootController` and the `NotFoundMiddleware` middleware to avoid re-rendering on hot paths.
* Added a `RouterMethods.addRoutes(_:)` extension and switched the router in App+build to use it.
* Moved the inline style from the `ErrorPage` page into a dedicated style file so the CSP needs no inline-style escape hatch.
* Fixed the `IndexPage` page path inconsistencies.
* Written the `README` file.
Reviewed-on: rock-n-code/loud-amsterdam#9
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 a `SecurityHeadersMiddleware` middleware that stamps hardened security-related HTTP headers onto every response.
To provide further details about the work:
* Implemented the `SecurityHeadersMiddleware` middleware, which precomputes headers once from a `Configuration` object and applies them to every response:
* _Content-Security-Policy_,
* _X-Content-Type-Options_,
* _X-Frame-Options_,
* _Referrer-Policy_,
* _Permissions-Policy_,
* _Strict-Transport-Security_ (optional).
* Integrated this middleware into the router (near the top of the chain), reading each value from configuration with hardened defaults.
* The _Strict-Transport-Security_ has no default value — omitted unless explicitly set, so it stays off in plain-HTTP during development and on only behind TLS.
* Added security-header constants keys and values.
Reviewed-on: rock-n-code/loud-amsterdam#8
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>