From fc0091dcc8b6bb8f5ce6a2a475f6d63cdc8be0dc Mon Sep 17 00:00:00 2001 From: "Christopher D. Cavell" <28095137+cdcavell@users.noreply.github.com> Date: Sun, 24 May 2026 06:32:11 -0500 Subject: [PATCH 1/4] Add release surface and distribution ADR - Issue #140 --- ...lease-surface-and-distribution-strategy.md | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 docs/adr/0003-record-release-surface-and-distribution-strategy.md diff --git a/docs/adr/0003-record-release-surface-and-distribution-strategy.md b/docs/adr/0003-record-release-surface-and-distribution-strategy.md new file mode 100644 index 0000000..536b9fd --- /dev/null +++ b/docs/adr/0003-record-release-surface-and-distribution-strategy.md @@ -0,0 +1,168 @@ +# ADR-0003: Record Release Surface and Distribution Strategy + +## Status + +Accepted + +## Context + +The template is being prepared for a future `v1.0.0` release. After `1.0.0`, version numbers need to communicate compatibility expectations for developers who install, clone, scaffold, or maintain applications from the template. + +This ADR records the release-readiness decisions needed before that stable release: + +- What parts of the template are part of the SemVer public surface. +- How future changes should be classified as MAJOR, MINOR, or PATCH. +- Whether the stable distribution model is package installation or clone-and-modify. +- Which API versioning scheme is the default. +- Which container base image strategy the template follows. +- How repository metadata should cross-link related public works. + +## Decision + +Use this ADR as the release-readiness decision record for SemVer, template distribution, API versioning, container image strategy, and repository metadata cross-linking. + +### Semantic Versioning Public Surface + +The public SemVer surface includes template behavior that consumers are expected to rely on after `v1.0.0`: + +- Generated project and folder layout. +- Template identity, short name, parameters, symbols, and source-name replacement behavior. +- Documented configuration key names and documented default values. +- Default API route conventions and API versioning behavior. +- Default middleware ordering and documented pipeline extension points. +- Documented container build and tag conventions. +- Public or protected class signatures documented for use by generated applications. +- Published documentation, release notes, and repository metadata that describe release behavior. + +Internal implementation details remain changeable unless they are documented as extension points, generated into consumer applications, or required by customization guidance. + +### Change Classification + +Use the following rules after `v1.0.0`. + +| Area | MAJOR | MINOR | PATCH | +|:---|:---|:---|:---| +| Scaffolded project layout | Rename, remove, or relocate generated projects, folders, files, namespaces, or startup entry points in a breaking way. | Add optional projects, examples, folders, or files without breaking existing assumptions. | Correct comments, formatting, documentation, or non-breaking file contents. | +| Template parameters and symbols | Rename, remove, invert, or materially change parameters, symbols, short names, or source-name replacement behavior. | Add optional parameters or symbols with safe defaults. | Fix parameter descriptions, constraints, or packaging metadata without behavior changes. | +| Configuration key names and defaults | Rename or remove documented keys, change value types, or change defaults in a way that materially changes runtime behavior. | Add optional keys, supported values, or provider-specific settings with compatible defaults. | Correct examples, validation messages, docs, or comments without changing documented behavior. | +| Default API route conventions | Change or remove documented route templates, default API version behavior, or canonical versioning conventions. | Add optional route forms, endpoint examples, or supported API versions while preserving existing routes. | Fix route docs, examples, or tests without changing route behavior. | +| Default middleware ordering | Reorder, remove, or replace documented middleware in a way that changes routing, error-handling, forwarded-header, or authorization behavior. | Add optional middleware or new documented extension points without breaking the existing order. | Fix ordering docs, tests, or narrow bugs while preserving the documented pipeline contract. | +| Container image tag conventions | Rename, remove, or redefine documented image names, tag forms, exposed ports, or supported runtime image family. | Add supported tags, image variants, or examples while preserving documented defaults. | Rebuild against compatible patch images or fix Docker docs without changing behavior. | +| Internal class signatures | Change documented public or protected signatures used by generated applications, extension points, tests, or examples in a breaking way. | Add optional overloads, extension methods, or helpers without breaking consumers. | Refactor private or internal details that are not documented consumer extension points. | + +When a change is ambiguous, classify it by the effect on a consumer who already generated an application from the previous stable version. If their documented build, configuration, route usage, deployment script, or customization path breaks, treat the change as breaking unless a clear migration path exists. + +### Template Distribution Model + +The stable release direction is a published NuGet template package installable with `dotnet new install`. + +Expected stable usage: + +```powershell +dotnet new install +dotnet new cdcavell-netcoreapp -n ContosoSecurityPortal +``` + +Clone-and-modify remains valid for source review, contribution, and preview use. Until the published package exists, documentation may continue to describe local installation from the repository root: + +```powershell +dotnet new install ./ +``` + +Documentation should clearly distinguish local preview installation from the intended stable package distribution path. + +### Default API Versioning Scheme + +Use URL segment API versioning as the canonical default for scaffolded API routes. + +Default route convention: + +```text +/api/v{version}/ +``` + +The template also supports `X-API-Version` request header versioning as a secondary compatibility option. + +Default behavior: + +- Default API version: `1.0`. +- Canonical style: URL segment versioning. +- Optional compatibility style: `X-API-Version` request header. +- Assume default version when unspecified: enabled. +- Report API versions: enabled. + +URL segment versioning is the default because it is visible in documentation, logs, browser testing, curl examples, and reverse proxy traces. Header versioning remains available when a consuming application prefers stable resource URLs. + +### Container Base Image Strategy + +Use Microsoft .NET container images with a multi-stage Dockerfile: + +- `mcr.microsoft.com/dotnet/sdk:` for restore, build, and publish stages. +- `mcr.microsoft.com/dotnet/aspnet:` for the final runtime image. +- A non-root runtime user where supported by the selected .NET image. +- A documented default HTTP container port. + +The documented local development image tag remains: + +```text +projecttemplate-web:dev +``` + +If this repository later publishes reusable container images, release tags should align with repository release tags: + +```text +vMAJOR.MINOR.PATCH +vMAJOR.MINOR +vMAJOR +``` + +Production consumers may pin image digests or use organization-approved base images in generated applications when their deployment policies require it. + +### Repository Metadata Cross-Link Strategy + +Repository metadata may cross-link related SSRN works when the relationship is described as related conceptual work, not as a software dependency or proof claim. + +Use these relationship meanings: + +- `isSupplementTo` when repository metadata points to a related conceptual paper or framework that the repository supplements as an applied software artifact. +- `isSupplementedBy` when an external paper or metadata record points back to the repository as a companion artifact. +- `references` when repository documentation explicitly cites a paper for background context. + +The repository should not be described as implementing the Eden Hypothesis or ASI Backbone. It may be described as a practical software-architecture artifact that can be discussed alongside those works when the relationship is framed as conceptual, architectural, or illustrative. + +## Consequences + +Positive consequences: + +- Future maintainers have a single release-surface reference before `v1.0.0`. +- Template consumers receive clearer compatibility expectations. +- Documentation can link to one ADR for versioning, packaging, API versioning, containers, and metadata decisions. +- Later issues can classify breaking and non-breaking work more consistently. + +Trade-offs and risks: + +- The ADR creates a stronger maintenance obligation after `v1.0.0`. +- Documentation can make otherwise internal details part of the practical public surface. +- Package distribution is the intended stable direction, but local installation remains necessary until package publishing is implemented. +- Supporting both URL segment and header API versioning requires documentation clarity. +- Container tag guidance may need revision if the repository later publishes official images. + +## Alternatives Considered + +- Treat the repository as clone-and-modify only: simpler, but weaker as a reusable template release. +- Record separate ADRs for each decision: more granular, but harder to use for the consolidated `v1.0.0` readiness decision set. +- Defer SemVer classification until package publication: avoids early commitment, but leaves readiness work without a decision baseline. +- Use header-only API versioning: keeps URLs stable, but makes examples and troubleshooting less obvious. +- Use custom container base images immediately: possible for specific organizations, but too opinionated for a public template baseline. +- Avoid SSRN/repository metadata cross-linking entirely: safest from an overclaiming perspective, but less useful for artifact discovery when the relationship is carefully bounded. + +## Related References + +- [Issue #140](https://github.com/cdcavell/NetCoreApplicationTemplate/issues/140) +- [Issue #138](https://github.com/cdcavell/NetCoreApplicationTemplate/issues/138) +- [`docs/articles/template-packaging.md`](../articles/template-packaging.md) +- [`docs/articles/api-versioning.md`](../articles/api-versioning.md) +- [`docs/articles/docker.md`](../articles/docker.md) +- [`docs/articles/deployment.md`](../articles/deployment.md) +- [`README.md`](../../README.md) +- [`CITATION.cff`](../../CITATION.cff) From 4d2efa5d09a534b692df53cfb2274b81351f0500 Mon Sep 17 00:00:00 2001 From: "Christopher D. Cavell" <28095137+cdcavell@users.noreply.github.com> Date: Sun, 24 May 2026 06:49:37 -0500 Subject: [PATCH 2/4] Add ADR navigation entry - Issue #140 --- docs/adr/toc.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/adr/toc.yml b/docs/adr/toc.yml index 18b492b..89d4bb2 100644 --- a/docs/adr/toc.yml +++ b/docs/adr/toc.yml @@ -9,3 +9,6 @@ - name: Use Centralized Application Middleware Pipeline href: 0002-use-centralized-application-middleware-pipeline.md + +- name: Record Release Surface and Distribution Strategy + href: 0003-record-release-surface-and-distribution-strategy.md From a1dfba0709aefba042b4e5d6082b8c7652286436 Mon Sep 17 00:00:00 2001 From: Chris Cavell Date: Sun, 24 May 2026 07:22:43 -0500 Subject: [PATCH 3/4] Cross-link release decision ADR in docs - Issue #140 --- README.md | 2 ++ docs/adr/index.md | 1 + docs/articles/api-versioning.md | 17 ++++++++++++++++- docs/articles/deployment.md | 4 +++- docs/articles/docker.md | 18 ++++++++++++++++++ docs/articles/template-packaging.md | 19 +++++++++++++++++++ 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3254eec..7762ed7 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,8 @@ MAJOR.MINOR.PATCH ``` Version numbers are centrally managed through project build metadata so assemblies, future packages, and releases can share a consistent version identity. +See [ADR-0003: Record Release Surface and Distribution Strategy](0003-record-release-surface-and-distribution-strategy.md), for the current versioning and release strategy. + ## Citation Citation metadata is available in [CITATION.cff](CITATION.cff). GitHub can use this file to generate citation formats from the repository sidebar. diff --git a/docs/adr/index.md b/docs/adr/index.md index 322bd4c..7a31850 100644 --- a/docs/adr/index.md +++ b/docs/adr/index.md @@ -56,3 +56,4 @@ When an ADR is superseded, keep the original file and add a link to the replacin |:---|:---|:---| | [0001](0001-use-structured-serilog-logging.md) | Use structured Serilog logging | Accepted | | [0002](0002-use-centralized-application-middleware-pipeline.md) | Use centralized application middleware pipeline | Accepted | +| [0003](0003-record-release-surface-and-distribution-strategy.md) | Record Release Surface and Distribution Strategy | Accepted | diff --git a/docs/articles/api-versioning.md b/docs/articles/api-versioning.md index e0078db..10160ee 100644 --- a/docs/articles/api-versioning.md +++ b/docs/articles/api-versioning.md @@ -52,7 +52,7 @@ public sealed class ExampleController : ControllerBase } ``` If an endpoint should also support header-based versioning without the version in the URL, add an unversioned route as well. -```charp +```csharp [Route("api/example")] ``` @@ -60,6 +60,20 @@ If an endpoint should also support header-based versioning without the version i When `ReportApiVersions` is enabled, responses include API version headers that help clients discover supported and deprecated versions. +## Release Compatibility + +URL segment versioning is the canonical API versioning strategy for the template. The default route convention is: + +```text +/api/v{version}/ +``` + +Header-based versioning with `X-API-Version` remains available as a secondary compatibility option for applications that need stable resource URLs. + +After the `v1.0.0` release, changes to documented API route conventions, default API version behavior, or the canonical versioning strategy should be reviewed as release-surface changes. Removing or changing documented route conventions may require a major version. Adding compatible route forms or additional supported API versions may be treated as minor version work. + +See [ADR-0003: Record Release Surface and Distribution Strategy](../adr/0003-record-release-surface-and-distribution-strategy.md) for the release-surface decision. + ## Production Guidance For production APIs: @@ -68,3 +82,4 @@ For production APIs: - Keep old API versions available long enough for client migration. - Document deprecated versions before removing them. - Add tests for each supported API version. + diff --git a/docs/articles/deployment.md b/docs/articles/deployment.md index 1839649..6de4df0 100644 --- a/docs/articles/deployment.md +++ b/docs/articles/deployment.md @@ -4,6 +4,8 @@ This article provides initial deployment guidance for applications created from The template includes production-oriented defaults for middleware ordering, forwarded headers, security headers, rate limiting, health checks, structured logging, error handling, authentication foundations, and EF Core data access. These defaults are intended to provide a safe baseline, but every deployment environment should still be reviewed before production use. +See [ADR-0003: Record Release Surface and Distribution Strategy](../adr/0003-record-release-surface-and-distribution-strategy.md) for the release-surface decision. + ## Deployment Review Areas Before deploying an application created from this template, review the following areas: @@ -217,4 +219,4 @@ Use this checklist before production release: [ ] Confirm error responses do not expose sensitive implementation details. ``` -Deployment readiness is environment-specific. Treat this article as a starting checklist, not a replacement for organization-specific production review. \ No newline at end of file +Deployment readiness is environment-specific. Treat this article as a starting checklist, not a replacement for organization-specific production review. diff --git a/docs/articles/docker.md b/docs/articles/docker.md index d022e2e..3babb8f 100644 --- a/docs/articles/docker.md +++ b/docs/articles/docker.md @@ -105,5 +105,23 @@ docker compose logs projecttemplate.web ``` The request should complete successfully, and forwarded header handling should not break normal local routing. +## Container Image Strategy + +The application uses Microsoft .NET container images with a multi-stage Dockerfile. The SDK image is used for restore, build, and publish steps. The ASP.NET runtime image is used for the final application image. + +The local development image tag is: + +```text +projecttemplate-web:dev +``` + +This tag is intended for local development and testing. It is not a published production image contract. + +Applications generated from the template may adapt the Dockerfile for production deployment. Production consumers may pin image digests, use organization-approved base images, or apply additional hardening based on their deployment requirements. + +After the `v1.0.0` release, changes to documented image names, tag conventions, exposed ports, or runtime image strategy should be reviewed as release-surface changes. + +See [ADR-0003: Record Release Surface and Distribution Strategy](../adr/0003-record-release-surface-and-distribution-strategy.md) for the release-surface decision. + ## Notes Do not commit generated SQLite databases, local logs, container volumes, secrets, or environment-specific credentials. diff --git a/docs/articles/template-packaging.md b/docs/articles/template-packaging.md index db46f37..292fec3 100644 --- a/docs/articles/template-packaging.md +++ b/docs/articles/template-packaging.md @@ -29,3 +29,22 @@ cd ContosoSecurityPortal dotnet build dotnet test ``` + +## Distribution Direction + +The current scaffold supports local installation from the repository root. This is useful for development, validation, and preview use while the template is still being finalized. + +The intended stable distribution model is a published NuGet template package installable with `dotnet new install`. + +Future stable usage is expected to follow this pattern: + +```powershell +dotnet new install +dotnet new cdcavell-netcoreapp -n ContosoSecurityPortal +``` + +Clone-and-modify remains valid for source review, contribution, and direct customization. However, after package publishing is available, the NuGet template package should be treated as the primary stable distribution path for normal template consumers. + +After the `v1.0.0` release, changes to the template short name, package identity, template parameters, symbols, or source-name replacement behavior should be reviewed as release-surface changes. + +See [ADR-0003: Record Release Surface and Distribution Strategy](../adr/0003-record-release-surface-and-distribution-strategy.md) for the release-surface decision. From afa07345448cbbeb077f61444e31e5f4f13657de Mon Sep 17 00:00:00 2001 From: Chris Cavell Date: Sun, 24 May 2026 07:31:30 -0500 Subject: [PATCH 4/4] Cross-link release decision ADR in docs - Issue #140 --- .../0003-record-release-surface-and-distribution-strategy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/adr/0003-record-release-surface-and-distribution-strategy.md b/docs/adr/0003-record-release-surface-and-distribution-strategy.md index 536b9fd..c7284ca 100644 --- a/docs/adr/0003-record-release-surface-and-distribution-strategy.md +++ b/docs/adr/0003-record-release-surface-and-distribution-strategy.md @@ -164,5 +164,5 @@ Trade-offs and risks: - [`docs/articles/api-versioning.md`](../articles/api-versioning.md) - [`docs/articles/docker.md`](../articles/docker.md) - [`docs/articles/deployment.md`](../articles/deployment.md) -- [`README.md`](../../README.md) -- [`CITATION.cff`](../../CITATION.cff) +- [`README.md`](https://github.com/cdcavell/NetCoreApplicationTemplate/blob/main/README.md) +- [`CITATION.cff`](https://github.com/cdcavell/NetCoreApplicationTemplate/blob/main/CITATION.cff)