Files
ccn/Packages/Infrastructure
javier ea00b94841 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>
2026-07-30 06:33:57 +00:00
..

Infrastructure

The shared Hummingbird toolkit the Loud services build on: declarative routing, hardened HTTP middlewares, pre-rendered localized HTML responses, and the page and asset scaffolding.

Overview

The package provides, grouped by role:

Role Types
Routing RouterController, RouteCollectionBuilder, the addController extension on RouterMethods
Middlewares SecurityHeadersMiddleware, VaryMiddleware, RateLimitMiddleware, LocalizationMiddleware, NotFoundMiddleware
Pages and assets Page, Asset, AssetExtension, FingerprintAssets
Responses CachedHTMLResponse, LocalizedHTMLCollectionResponse
Contexts LocalizedRequestContext
Constants The HTTPField.Name header names, Int.RateLimit limits, and String.Security header values the middlewares default to

Design rules

The package holds only what every service can reuse; anything a service owns is injected, never referenced:

  • No site-specific content. No page markup, no asset catalog, no Bundle.module lookups. A type that needs a service's content takes it as a parameter: the bundle: whose String Catalog names the supported languages (LocalizationMiddleware, LocalizedHTMLCollectionResponse, NotFoundMiddleware), the document: closure that builds a page for a locale, and the metadata requirement through which a Page conformer supplies its icon links and theme colors.
  • Services fill the gaps once, via extensions. A service restores its convenient call sites with retroactive extensions — the Website's Page+Defaults, LocalizationMiddleware+Defaults, and NotFoundMiddleware+Defaults are the pattern to follow.
  • Method structs. Single-operation types such as FingerprintAssets hold their lifetime-fixed configuration in init and take only per-call inputs in callAsFunction.

Layout

Sources are split by visibility, then by kind, one type per file:

Sources/
├── Public/                public API
│   ├── Builders/          RouteCollectionBuilder
│   ├── Enumerations/      AssetExtension
│   ├── Extensions/        addController, plus the default header names and values
│   ├── Methods/           FingerprintAssets
│   ├── Middlewares/       the five HTTP middlewares
│   ├── Protocols/         Asset, LocalizedRequestContext, Page, RouterController
│   └── Responses/         CachedHTMLResponse, LocalizedHTMLCollectionResponse
└── Internal/
    └── Types/             implementation details (FNV1aHash)
Tests/
├── Cases/                 the test suites, mirroring the Sources/ layout
├── Catalogs/              the String Catalog fixture, copied verbatim so it loads on Linux
└── Utils/                 stubs (StubAsset, StubPage, …) and the suite Tag constants

Testing

Every suite carries a tag naming the kind of API it exercises — .asset, .extension, .middleware, .protocol, or .type, declared in Tests/Utils/Extensions/Tag+Constants.swift — so test plans and result summaries can slice the run by kind. A new suite must adopt the tag matching its subject (or add a tag there if none fits).

Requirements

  • Swift 6.3 toolchain (swift-tools-version:6.3).
  • macOS 15, matching the sibling Localization and Persistence packages (the services deploy to Linux containers; the packages carry no UI platforms).