IArtifactContentService
Pennington.Artifacts
The corpus-derived artifact tier: a service whose URLs and bytes derive from the rendered site (via ISiteProjection) or from configuration — search shards, llms.txt files, book PDFs, well-known verification files. Registered ONLY under this interface, never as IContentService, so request-path discovery walkers (PageResolver), the projection's own input set, sitemap, and the record registry structurally cannot trigger its potentially expensive discovery.
One byte path serves both surfaces: ResolveAsync answers dev requests through the artifact router and produces the static build's output for every route DiscoverAsync enumerates — dev/build parity by construction. Routes that should exist only in dev (e.g. live book previews) are resolvable via Claims without being enumerated.
Properties
ClaimsImmutableList<ArtifactClaim>- URL territories this service serves. Options-derived and consulted on every request — must be cheap and must not trigger discovery, the projection, or any lazy corpus work.
Methods
DiscoverAsync
#public IAsyncEnumerable<DiscoveredItem> DiscoverAsync()
Enumerates every artifact route the static build should write, as GeneratedSource items. May consume the projection — the build invokes this outside any request, after the page crawl has primed the render cache. Never called on the request path.
Returns
IAsyncEnumerable<DiscoveredItem>ResolveAsync
#public Task<ArtifactContent> ResolveAsync(string relativePath, CancellationToken cancellationToken)
Returns the bytes for relativePath (no leading slash, e.g. search/en/index.json), or null to decline so the request falls through to content routing. May materialize the projection, build an index, or run Chromium on demand.
Parameters
relativePathstringcancellationTokenCancellationToken
Returns
Task<ArtifactContent>Pennington.Artifacts.IArtifactContentService
namespace Pennington.Artifacts;
/// The corpus-derived artifact tier: a service whose URLs and bytes derive from the rendered site (via ISiteProjection) or from configuration — search shards, llms.txt files, book PDFs, well-known verification files. Registered ONLY under this interface, never as IContentService, so request-path discovery walkers (PageResolver), the projection's own input set, sitemap, and the record registry structurally cannot trigger its potentially expensive discovery. One byte path serves both surfaces: ResolveAsync answers dev requests through the artifact router and produces the static build's output for every route DiscoverAsync enumerates — dev/build parity by construction. Routes that should exist only in dev (e.g. live book previews) are resolvable via Claims without being enumerated.
public interface IArtifactContentService
{
/// URL territories this service serves. Options-derived and consulted on every request — must be cheap and must not trigger discovery, the projection, or any lazy corpus work.
public ImmutableList<ArtifactClaim> Claims { get; }
/// Enumerates every artifact route the static build should write, as GeneratedSource items. May consume the projection — the build invokes this outside any request, after the page crawl has primed the render cache. Never called on the request path.
public IAsyncEnumerable<DiscoveredItem> DiscoverAsync()
;
/// Returns the bytes for relativePath (no leading slash, e.g. search/en/index.json), or null to decline so the request falls through to content routing. May materialize the projection, build an index, or run Chromium on demand.
public Task<ArtifactContent> ResolveAsync(string relativePath, CancellationToken cancellationToken)
;
}