Core
Info
Architectural truth for
Corein theTemplatesfeature. This leaf module contains the domain logic, endpoints, and messaging contracts.
Architecture
FastEndpoints
CreateTemplateEndpointGetTemplateEndpointInstantiateDocumentEndpointListProjectTemplatesEndpointPreviewTemplateEndpointUpdateTemplateEndpoint
Domain Models
GetTemplateRequestListProjectTemplatesRequestListTemplatesEndpoint
Caching (HybridCache)
Template blueprints (StructureJson / DocumentStyleJson) contain no secrets, so the read paths are cached (5-minute TTL) under tenant-scoped keys and invalidated by template writes:
ListProjectTemplatesEndpoint→template:{tenantId}:{projectId}(staticLoadProjectTemplatesCachedAsynchelper).ListTemplatesEndpoint→template:{tenantId}:all(staticLoadTemplatesCachedAsynchelper).GetTemplateEndpoint→template:{tenantId}:{templateId}(staticLoadTemplateCachedAsynchelper; a missing template returns null and is never cached, so 404 semantics are unchanged).PreviewTemplateEndpointis a pure in-memory render — deliberately not cached.
Invalidation
After SaveChangesAsync, each template write removes exactly the entries it could have changed (all via static helpers so integration tests drive the real mutation + invalidation):
| Write | Removed tags |
|---|---|
CreateTemplateEndpoint | template:{tenant}:{projectId} (when project-scoped) + template:{tenant}:all |
UpdateTemplateEndpoint | template:{tenant}:{projectId} + template:{tenant}:{templateId} + template:{tenant}:all |
DeleteTemplateEndpoint | template:{tenant}:{projectId} + template:{tenant}:{templateId} + template:{tenant}:all |
DeleteTemplateEndpoint loads the full template row (not just an existence check) so ProjectId is available for the project tag. Keys/tags come from MILTON.Shared.Caching.CacheKeys.