Tweaks and fixes throughout the project (#27)

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 commit is contained in:
2026-07-30 06:33:57 +00:00
committed by javier
parent 0887135328
commit ea00b94841
71 changed files with 633 additions and 512 deletions
@@ -5,12 +5,11 @@ import Localization
/// Resolves the visitor's preferred language and records it on the request context.
///
/// Placed ahead of the localized responders in the middleware chain, it reads the request's
/// `Accept-Language` header, negotiates the best supported match (falling back to the default
/// language), and stores it on the context's ``LocalizedRequestContext/language``.
/// Placed ahead of the localized responders in the middleware chain, it reads the request's `Accept-Language` header, negotiates the best supported
/// match (falling back to the default language), and stores it on the context's ``LocalizedRequestContext/language``.
///
/// The request is otherwise passed through untouched the URL and routing are not affected so
/// each page is served at its existing path and varies its content by header.
/// The request is otherwise passed through untouched the URL and routing are not affected so each page is served at its existing path and varies its
/// content by header.
public struct LocalizationMiddleware<Context: LocalizedRequestContext> {
// MARK: Properties
@@ -3,13 +3,12 @@ import Hummingbird
/// Stamps a set of security-related HTTP headers onto every response.
///
/// Placed at (or near) the top of the middleware chain, it adds the configured headers to whatever
/// response bubbles back up the rendered pages, the error page produced by
/// ``NotFoundMiddleware``, and every static file served by `FileMiddleware` so the browser applies
/// the strict, hardened interpretation of the content instead of its lenient legacy defaults.
/// Placed at (or near) the top of the middleware chain, it adds the configured headers to whatever response bubbles back up the rendered pages, the
/// error page produced by ``NotFoundMiddleware``, and every static file served by `FileMiddleware` so the browser applies the strict, hardened
/// interpretation of the content instead of its lenient legacy defaults.
///
/// The headers are precomputed once from the ``Configuration`` at initialization and reused for
/// every request, so the per-request cost is a handful of header copies.
/// The headers are precomputed once from the ``Configuration`` at initialization and reused for every request, so the per-request cost is a handful of
/// header copies.
public struct SecurityHeadersMiddleware<Context: RequestContext> {
// MARK: Properties
@@ -20,9 +19,8 @@ public struct SecurityHeadersMiddleware<Context: RequestContext> {
// MARK: Initializers
/// Creates a security-headers middleware.
/// - Parameter configuration: the headers applied to every response. Defaults to a hardened
/// baseline suitable for a static site, with `Strict-Transport-Security` left off (see
/// ``Configuration``).
/// - Parameter configuration: the headers applied to every response. Defaults to a hardened baseline suitable for a static site, with
/// `Strict-Transport-Security` left off (see ``Configuration``).
public init(
configuration: Configuration = .init()
) {
@@ -37,14 +35,11 @@ extension SecurityHeadersMiddleware: RouterMiddleware {
// MARK: Functions
/// Passes the request down the chain and stamps the configured security headers onto the
/// response on the way back up.
/// Passes the request down the chain and stamps the configured security headers onto the response on the way back up.
///
/// Errors that can render themselves (`HTTPResponseError`, like the `HTTPError`s thrown by the
/// controllers) are converted to their response here rather than left to the router: the router
/// converts them above the middleware chain, where the response would escape these headers.
/// Existing values for the same header names are replaced so downstream middleware cannot leave
/// a weaker policy in place.
/// Errors that can render themselves (`HTTPResponseError`, like the `HTTPError`s thrown by the controllers) are converted to their response
/// here rather than left to the router: the router converts them above the middleware chain, where the response would escape these headers.
/// Existing values for the same header names are replaced so downstream middleware cannot leave a weaker policy in place.
/// - Parameters:
/// - request: the incoming request.
/// - context: the context the request is resolved against.
@@ -106,10 +101,9 @@ private extension SecurityHeadersMiddleware.Configuration {
extension SecurityHeadersMiddleware {
/// The set of security headers a ``SecurityHeadersMiddleware`` applies.
///
/// Each property maps to a single response header. A `nil` value omits that header entirely,
/// which is how `Strict-Transport-Security` stays disabled by default: it is only safe to send
/// over HTTPS and is "sticky" in browsers, so it must stay off in plain-HTTP development and be
/// switched on (via configuration) only in TLS-terminated production.
/// Each property maps to a single response header. A `nil` value omits that header entirely, which is how `Strict-Transport-Security` stays
/// disabled by default: it is only safe to send over HTTPS and is "sticky" in browsers, so it must stay off in plain-HTTP development and be switched on
/// (via configuration) only in TLS-terminated production.
public struct Configuration: Sendable {
// MARK: Properties
@@ -131,9 +125,8 @@ extension SecurityHeadersMiddleware {
/// Creates a security-headers configuration.
///
/// Every parameter defaults to the hardened baseline defined in `String.Security`, except
/// `strictTransportSecurity`, which defaults to `nil` (omitted). Pass `nil` for any header
/// to drop it from the response.
/// Every parameter defaults to the hardened baseline defined in `String.Security`, except `strictTransportSecurity`, which defaults
/// to `nil` (omitted). Pass `nil` for any header to drop it from the response.
/// - Parameters:
/// - contentSecurityPolicy: the `Content-Security-Policy` value.
/// - contentTypeOptions: the `X-Content-Type-Options` value.