Files
ccn/Packages/Infrastructure/README.md
T
2026-08-19 23:19:08 +02:00

4.4 KiB

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

Role Types
Routing RouterController, RouteCollectionBuilder, the addController extension on RouterMethods
Middlewares SecurityHeadersMiddleware, VaryMiddleware, RateLimitMiddleware, LocalizationMiddleware, NotFoundMiddleware
Pages and assets Page, Asset, AssetExtension, FingerprintAssets
Link previews SocialCard, its Image, and the Tag meta tags it derives
Structured data StructuredData, the Node, Property, and Value types of its schema.org graph, and the open Name and Kind vocabularies
Analytics Analytics, the tracker script Attributes it derives, and the origin its preconnect hint targets
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, the document: closure building a page for a locale, and a Page conformer's metadata plus its optional head concerns (summary, canonicalURL, socialCard, structuredData, analytics). URLs arrive fully formed and absolute; composing them stays with the page.
  • Types own their format; Page renders generically. Each head concern derives its own render-ready representation — SocialCard.tags, StructuredData.payload, Analytics.attributes — and Page applies it without knowing the vocabulary. Page scripts and the tracker render as deferred head tags, with a preconnect hint for the tracker's cross-origin host.
  • Services fill the gaps once, via extensions. A service restores its convenient call sites with retroactive extensions — the Website's *+Defaults extensions are the pattern. The open schema.org vocabularies extend the same way: the package declares the shared Property.Name and Node.Kind constants, and a service adds its own.
  • 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
│   └── Types/             Analytics, SocialCard, StructuredData (the latter two nesting their own types in SocialCard/ and StructuredData/)
└── Internal/
    ├── Extensions/        implementation details (the String separators)
    └── 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 for the kind of API it exercises — .asset, .extension, .middleware, .protocol, or .type, declared in Tests/Utils/Extensions/Tag+Constants.swift — so test plans and summaries can slice a run by kind. A new suite adopts the tag matching its subject, or adds one when none fits.

Requirements

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