Initial commit.

This commit is contained in:
2026-08-19 23:19:08 +02:00
commit 22e737d9c2
153 changed files with 11680 additions and 0 deletions
@@ -0,0 +1,95 @@
import Configuration
extension AbsoluteConfigKey {
/// A namespace for the analytics configuration keys, as absolute keys.
public enum Analytics {
/// The absolute configuration key for the analytics website identifier.
public static let websiteID: AbsoluteConfigKey = .init(.Analytics.websiteID)
/// The absolute configuration key for the comma-delimited domains the tracker reports from.
public static let domains: AbsoluteConfigKey = .init(.Analytics.domains)
/// The absolute configuration key for recorder mode, loading the session recorder script alongside the tracker.
public static let recorder: AbsoluteConfigKey = .init(.Analytics.recorder)
}
/// A namespace for the static files cache configuration keys, as absolute keys.
public enum Cache {
/// The absolute configuration key for the max-age, in seconds, applied to fingerprinted assets and fonts.
public static let maxAgeAsset: AbsoluteConfigKey = .init(.Cache.maxAgeAsset)
/// The absolute configuration key for the max-age, in seconds, applied to unversioned text-based static files.
public static let maxAgeText: AbsoluteConfigKey = .init(.Cache.maxAgeText)
/// The absolute configuration key for the max-age, in seconds, applied to image static files.
public static let maxAgeImage: AbsoluteConfigKey = .init(.Cache.maxAgeImage)
/// The absolute configuration key for the max-age, in seconds, applied to all other static files.
public static let maxAgeDefault: AbsoluteConfigKey = .init(.Cache.maxAgeDefault)
}
/// A namespace for the response compression configuration keys, as absolute keys.
public enum Compression {
/// The absolute configuration key for the minimum response body size, in bytes, before compression is applied.
public static let minResponseSize: AbsoluteConfigKey = .init(.Compression.minResponseSize)
}
/// A namespace for the persistence configuration keys, as absolute keys.
public enum Database {
/// The absolute configuration key selecting migrate-and-exit mode.
public static let migrate: AbsoluteConfigKey = .init(.Database.migrate)
/// The absolute configuration key for the persistence driver.
public static let driver: AbsoluteConfigKey = .init(.Database.driver)
/// The absolute configuration key for the PostgreSQL host.
public static let host: AbsoluteConfigKey = .init(.Database.host)
/// The absolute configuration key for the PostgreSQL port.
public static let port: AbsoluteConfigKey = .init(.Database.port)
/// The absolute configuration key for the database name.
public static let name: AbsoluteConfigKey = .init(.Database.name)
/// The absolute configuration key for the database username.
public static let username: AbsoluteConfigKey = .init(.Database.username)
/// The absolute configuration key for the database password.
public static let password: AbsoluteConfigKey = .init(.Database.password)
/// The absolute configuration key for the TLS posture used when connecting.
public static let tls: AbsoluteConfigKey = .init(.Database.tls)
/// The absolute configuration key for the maximum pooled connections per event loop.
public static let poolMaxPerEventLoop: AbsoluteConfigKey = .init(.Database.poolMaxPerEventLoop)
/// The absolute configuration key for the longest wait, in seconds, for a pooled connection to become available.
public static let poolTimeout: AbsoluteConfigKey = .init(.Database.poolTimeout)
}
/// A namespace for the HTTP server configuration keys, as absolute keys.
public enum HTTP {
/// The absolute configuration key for the host the server binds to.
public static let host: AbsoluteConfigKey = .init(.HTTP.host)
/// The absolute configuration key for the port the server listens on.
public static let port: AbsoluteConfigKey = .init(.HTTP.port)
/// The absolute configuration key for the server's name.
public static let serverName: AbsoluteConfigKey = .init(.HTTP.serverName)
}
/// A namespace for the logging configuration keys, as absolute keys.
public enum Log {
/// The absolute configuration key for the minimum log level.
public static let level: AbsoluteConfigKey = .init(.Log.level)
}
/// A namespace for the rate limit configuration keys, as absolute keys.
public enum RateLimit {
/// The absolute configuration key for the number of requests admitted per client per window.
public static let limit: AbsoluteConfigKey = .init(.RateLimit.limit)
/// The absolute configuration key for the window length, in seconds.
public static let window: AbsoluteConfigKey = .init(.RateLimit.window)
/// The absolute configuration key for keying clients by the first `X-Forwarded-For` entry.
public static let trustForwardedFor: AbsoluteConfigKey = .init(.RateLimit.trustForwardedFor)
}
/// A namespace for the path configuration keys, as absolute keys.
public enum Path {
/// The absolute configuration key for the directory the static files are served from.
public static let staticFiles: AbsoluteConfigKey = .init(.Path.staticFiles)
}
/// A namespace for the security headers configuration keys, as absolute keys.
public enum Security {
/// The absolute configuration key for the `Content-Security-Policy` header value.
public static let contentSecurityPolicy: AbsoluteConfigKey = .init(.Security.contentSecurityPolicy)
/// The absolute configuration key for the `X-Content-Type-Options` header value.
public static let contentTypeOptions: AbsoluteConfigKey = .init(.Security.contentTypeOptions)
/// The absolute configuration key for the `X-Frame-Options` header value.
public static let frameOptions: AbsoluteConfigKey = .init(.Security.frameOptions)
/// The absolute configuration key for the `Referrer-Policy` header value.
public static let referrerPolicy: AbsoluteConfigKey = .init(.Security.referrerPolicy)
/// The absolute configuration key for the `Permissions-Policy` header value.
public static let permissionsPolicy: AbsoluteConfigKey = .init(.Security.permissionsPolicy)
/// The absolute configuration key for the `Strict-Transport-Security` header value.
public static let strictTransportSecurity: AbsoluteConfigKey = .init(.Security.strictTransportSecurity)
}
}
@@ -0,0 +1,95 @@
import Configuration
extension ConfigKey {
/// A namespace for the analytics configuration keys.
public enum Analytics {
/// The configuration key for the analytics website identifier (cleared to disable analytics).
public static let websiteID: ConfigKey = "analytics.websiteID"
/// The configuration key for the comma-delimited domains the tracker reports from.
public static let domains: ConfigKey = "analytics.domains"
/// The configuration key for recorder mode, loading the session recorder script alongside the tracker (set to `false` to disable).
public static let recorder: ConfigKey = "analytics.recorder"
}
/// A namespace for the static files cache configuration keys.
public enum Cache {
/// The configuration key for the max-age, in seconds, applied to fingerprinted assets (CSS, JavaScript) and fonts.
public static let maxAgeAsset: ConfigKey = "cache.maxAge.asset"
/// The configuration key for the max-age, in seconds, applied to unversioned text-based static files (e.g. plain text).
public static let maxAgeText: ConfigKey = "cache.maxAge.text"
/// The configuration key for the max-age, in seconds, applied to image static files (ICO, PNG, SVG).
public static let maxAgeImage: ConfigKey = "cache.maxAge.image"
/// The configuration key for the max-age, in seconds, applied to all other static files (e.g. the web manifest).
public static let maxAgeDefault: ConfigKey = "cache.maxAge.default"
}
/// A namespace for the response compression configuration keys.
public enum Compression {
/// The configuration key for the minimum response body size, in bytes, before compression is applied.
public static let minResponseSize: ConfigKey = "compression.minimumResponseSize"
}
/// A namespace for the persistence configuration keys.
public enum Database {
/// The configuration key selecting migrate-and-exit mode (run migrations, then exit) instead of serving.
public static let migrate: ConfigKey = "database.migrate"
/// The configuration key for the persistence driver (`inMemory` or `postgres`).
public static let driver: ConfigKey = "database.driver"
/// The configuration key for the PostgreSQL host.
public static let host: ConfigKey = "database.host"
/// The configuration key for the PostgreSQL port.
public static let port: ConfigKey = "database.port"
/// The configuration key for the database name.
public static let name: ConfigKey = "database.name"
/// The configuration key for the database username.
public static let username: ConfigKey = "database.username"
/// The configuration key for the database password.
public static let password: ConfigKey = "database.password"
/// The configuration key for the TLS posture used when connecting (`off`, `prefer`, or `require`).
public static let tls: ConfigKey = "database.tls"
/// The configuration key for the maximum pooled connections per event loop.
public static let poolMaxPerEventLoop: ConfigKey = "database.pool.maxPerEventLoop"
/// The configuration key for the longest wait, in seconds, for a pooled connection to become available.
public static let poolTimeout: ConfigKey = "database.pool.timeout"
}
/// A namespace for the HTTP server configuration keys.
public enum HTTP {
/// The configuration key for the host the server binds to.
public static let host: ConfigKey = "http.host"
/// The configuration key for the port the server listens on.
public static let port: ConfigKey = "http.port"
/// The configuration key for the server's name.
public static let serverName: ConfigKey = "http.serverName"
}
/// A namespace for the logging configuration keys.
public enum Log {
/// The configuration key for the minimum log level.
public static let level: ConfigKey = "log.level"
}
/// A namespace for the rate limit configuration keys.
public enum RateLimit {
/// The configuration key for the number of requests admitted per client per window.
public static let limit: ConfigKey = "rateLimit.limit"
/// The configuration key for the window length, in seconds.
public static let window: ConfigKey = "rateLimit.window"
/// The configuration key for keying clients by the first `X-Forwarded-For` entry (enable only behind a trusted proxy).
public static let trustForwardedFor: ConfigKey = "rateLimit.trustForwardedFor"
}
/// A namespace for the path configuration keys.
public enum Path {
/// The configuration key for the directory the static files are served from.
public static let staticFiles: ConfigKey = "path.staticFiles"
}
/// A namespace for the security headers configuration keys.
public enum Security {
/// The configuration key for the `Content-Security-Policy` header value.
public static let contentSecurityPolicy: ConfigKey = "security.contentSecurityPolicy"
/// The configuration key for the `X-Content-Type-Options` header value.
public static let contentTypeOptions: ConfigKey = "security.contentTypeOptions"
/// The configuration key for the `X-Frame-Options` header value.
public static let frameOptions: ConfigKey = "security.frameOptions"
/// The configuration key for the `Referrer-Policy` header value.
public static let referrerPolicy: ConfigKey = "security.referrerPolicy"
/// The configuration key for the `Permissions-Policy` header value.
public static let permissionsPolicy: ConfigKey = "security.permissionsPolicy"
/// The configuration key for the `Strict-Transport-Security` header value (omitted when unset).
public static let strictTransportSecurity: ConfigKey = "security.strictTransportSecurity"
}
}
@@ -0,0 +1,9 @@
import Configuration
extension ConfigValue {
/// A namespace for the HTTP server's default configuration values.
public enum HTTP {
/// The default server name.
public static let serverName: ConfigValue = .init(stringLiteral: .Server.name)
}
}
@@ -0,0 +1,27 @@
extension Int {
/// A namespace for the cache's default configuration values.
public enum Cache {
/// The default max-age, in seconds, applied to fingerprinted assets and fonts (1 year).
public static let maxAgeAsset = 31_536_000
/// The default max-age, in seconds, applied to unversioned text-based static files (1 hour).
public static let maxAgeText = 3_600
/// The default max-age, in seconds, applied to image static files (1 week).
public static let maxAgeImage = 604_800
/// The default max-age, in seconds, applied to all other static files (1 day).
public static let maxAgeDefault = 86_400
}
/// A namespace for the response compression's default configuration values.
public enum Compression {
/// The default minimum response body size, in bytes, before compression is applied (1 KB).
public static let minResponseSize = 1_024
}
/// A namespace for the persistence's default configuration values.
public enum Database {
/// The default PostgreSQL port.
public static let port = 5_432
/// The default maximum pooled connections per event loop.
public static let poolMaxPerEventLoop = 4
/// The default longest wait, in seconds, for a pooled connection to become available (the driver's own default).
public static let poolTimeout = 10
}
}
@@ -0,0 +1,13 @@
import Foundation
import Localization
public extension LanguageList {
// MARK: Initializers
/// Creates a language list backed by the module's String Catalog.
init() {
self.init(bundle: .module)
}
}
@@ -0,0 +1,13 @@
import Foundation
import Infrastructure
public extension LocalizationMiddleware {
// MARK: Initializers
/// Creates a localization middleware that negotiates against the module's String Catalog languages.
init() {
self.init(bundle: .module)
}
}
@@ -0,0 +1,25 @@
import Foundation
import Infrastructure
public extension NotFoundMiddleware {
// MARK: Initializers
/// Creates a not-found middleware that renders the website's error page, localized to the module's String Catalog languages.
/// - Parameters:
/// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
/// - analytics: the analytics tracker the error page embeds, or `nil` (the default) to omit it.
init(
assetVersion: String? = nil,
analytics: Analytics? = nil
) {
self.init(bundle: .module) {
NotFoundPage(
locale: $0,
assetVersion: assetVersion,
analytics: analytics
)
}
}
}
@@ -0,0 +1,53 @@
extension String {
/// A namespace for the analytics default configuration values.
///
/// Analytics ships **off**: ``websiteID`` is empty, so the pages embed no tracker until a deployment sets `analytics.websiteID`. Point
/// ``origin`` at your own instance before enabling it the placeholder is an [RFC 2606](https://www.rfc-editor.org/rfc/rfc2606)
/// reserved domain, so an unconfigured copy can never report to someone else's server.
public enum Analytics {
/// The origin the analytics scripts are loaded from and their beacons are sent to (scheme and host, no trailing slash).
///
/// Single-sourced here: both ``scriptURL`` and the session recorder script the pages embed in recorder mode derive from this
/// constant. It is deliberately not a configuration key the `Content-Security-Policy` must allow the same origin, and a value that
/// can drift at runtime would silently break the tracker it is supposed to permit.
public static let origin = "https://analytics.example.com"
/// The URL the analytics tracker script is loaded from.
public static let scriptURL = "\(origin)/script"
/// The default analytics website identifier the tracker reports as: empty, which omits the tracker entirely.
public static let websiteID = ""
/// The default comma-delimited domains the tracker reports from: empty, which reports from every host.
///
/// Once set, keep it paired with the host the pages are served at a deployment that serves from another host without matching
/// `analytics.domains` reports from a host it no longer serves, so analytics silently records nothing.
public static let domains = ""
}
/// A namespace for the persistence's default configuration values and recognized tokens.
public enum Database {
/// The default persistence driver: in-memory SQLite, which needs no external infrastructure.
public static let driver = "inMemory"
/// The driver token selecting the PostgreSQL backend.
public static let driverPostgres = "postgres"
/// The default PostgreSQL host.
public static let host = "localhost"
/// The default database name.
public static let name = "ccn"
/// The default database username.
public static let username = "ccn"
/// The default TLS posture token.
public static let tls = "prefer"
/// The TLS token disabling TLS.
public static let tlsOff = "off"
/// The TLS token requiring TLS.
public static let tlsRequire = "require"
}
/// A namespace for well-known path string constants.
public enum Path {
/// The directory, relative to the working directory, that the website's static files are served from.
public static let staticResources = "Resources/Static"
}
/// A namespace for the server string constants.
public enum Server {
/// The website server's name.
public static let name = "CCNWebsite"
}
}