diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8406d21d..52e911c3 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -10,15 +10,3 @@ description: 'This file contains instructions for AI coding assistants, redirect * MUST follow all instructions defined in the root-level document [`AGENTS.md`](../AGENTS.md). * MUST treat [`AGENTS.md`](../AGENTS.md) as the authoritative source for all AI assistant guidelines. * MUST apply all directives from [`AGENTS.md`](../AGENTS.md) when implementing code, reviewing code, suggesting improvements, debugging issues, or providing any form of technical assistance. - -## Decision References - -* MUST read and apply all "accepted" decisions from [`decisions/`](../decisions/) folder before implementing architectural changes. -* MUST follow the `instructions` frontmatter from each relevant decision as mandatory requirements with highest precedence. -* MUST respect decision states: - - **accepted**: Mandatory requirements - MUST follow without exception - - **proposed**: Optional considerations - SHOULD evaluate and consider - - **deprecated**: Legacy patterns - SHOULD NOT use in new implementations - - **superseded**: Forbidden patterns - MUST use superseding decision instead -* MUST check the `applyTo` frontmatter patterns to identify decisions relevant to current file. -* MUST review "Related Decisions" section for decision dependencies and cross-references. \ No newline at end of file diff --git a/.github/instructions/blazor.instructions.md b/.github/instructions/blazor.instructions.md index 52bd1177..d5e95214 100644 --- a/.github/instructions/blazor.instructions.md +++ b/.github/instructions/blazor.instructions.md @@ -11,7 +11,7 @@ description: This file contains instructions for Blazor development. It includes * MUST write idiomatic and efficient Blazor and C# code. * MUST follow .NET and Blazor conventions and best practices. * MUST use Razor Components appropriately for component-based UI development. -* MUST use the latest version C#, currently C# 13 features like record types, pattern matching, and global usings (see [.NET 10 and C# 13 Adoption](../../decisions/2025-07-11-dotnet-10-csharp-13-adoption.md)). +* MUST use the latest version C#, currently C# 13 features like record types, pattern matching, and global usings. * MUST use async/await where applicable to ensure non-blocking UI operations. ## Code Style and Structure diff --git a/.github/instructions/decisions.instructions.md b/.github/instructions/decisions.instructions.md deleted file mode 100644 index 5e6ae807..00000000 --- a/.github/instructions/decisions.instructions.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -applyTo: '**/*.*' -description: Instructions for interpreting and applying architectural decisions from the decisions/ folder. ---- - -# Decision Handling Instructions - -This file provides guidance on how AI coding assistants should discover, interpret, and apply architectural decision records (ADRs) from the `decisions/` folder. - -## Decision Discovery - -* MUST scan `decisions/` folder for relevant ADRs before making architectural or structural changes. -* MUST prioritize decisions based on their `applyTo` glob patterns matching the current file path. -* MUST read the complete decision document, not just the `instructions` frontmatter, when making complex architectural changes. -* SHOULD use semantic search to find decisions related to the current task when file patterns don't provide clear matches. - -## Decision Application Priority - -Decisions MUST be applied in the following priority order: - -1. **`instructions` frontmatter**: Primary AI guidance - compact, actionable rules -2. **Decision section**: Detailed implementation requirements and constraints -3. **Consequences section**: Understanding of trade-offs and implications -4. **Related Decisions**: Dependencies and cross-cutting concerns - -## Decision States - -Each decision has a `state` frontmatter field that determines how it MUST be treated: - -### accepted (Mandatory) -* MUST follow all requirements without exception -* MUST treat as non-negotiable architectural constraints -* MUST apply `instructions` frontmatter as highest-priority rules -* MUST NOT deviate unless explicitly overridden by user request - -### proposed (Optional) -* SHOULD consider as recommendations and best practices -* MAY apply based on context and user requirements -* SHOULD discuss with user before implementing significant proposed patterns -* MUST NOT treat as mandatory requirements - -### deprecated (Legacy) -* SHOULD NOT use in new implementations -* MAY remain in existing code until refactored -* SHOULD suggest alternatives when encountered -* MUST warn user when deprecated patterns are detected - -### superseded (Forbidden) -* MUST NOT use in any circumstances -* MUST use the superseding decision referenced in the document -* MUST refactor existing code using superseded patterns when encountered -* SHOULD inform user about the superseding decision - -## Decision Metadata - -Each decision contains frontmatter metadata that MUST be used for proper application: - -* **`applyTo`**: Glob patterns indicating which files the decision affects -* **`state`**: Current status (accepted, proposed, deprecated, superseded) -* **`instructions`**: Compact AI guidance for immediate application -* **`created`**: Original decision date (informational) -* **`lastModified`**: Most recent update date (MUST check for currency) -* **`authors`**: Decision contributors (informational) - -## Workflow for Code Changes - -When making code changes, follow this workflow: - -1. **Identify Affected Files**: Determine which files will be modified -2. **Match Decision Patterns**: Find decisions with `applyTo` patterns matching those files -3. **Check Decision State**: Verify state (only "accepted" decisions are mandatory) -4. **Read Instructions**: Extract and parse the `instructions` frontmatter -5. **Apply Requirements**: Implement code following the decision requirements -6. **Verify Compliance**: Ensure changes align with all applicable decisions -7. **Check Related Decisions**: Review linked decisions for dependencies - -## Examples - -### Example 1: Creating a New Test Project - -**File to create**: `tests/Core.Tests.Unit/UserServiceTests.cs` - -**Relevant Decisions**: -1. `2025-07-10-folder-structure-and-naming-conventions.md` (matches `**/*.*`) -2. `2025-07-11-english-as-project-language.md` (matches `**/*.*`) - -**Applied Instructions**: -- Test project MUST be named `Core.Tests.Unit` -- Test project MUST be placed under `tests/` folder -- All code, comments, and identifiers MUST be in English - -### Example 2: Adding a NuGet Package - -**File to modify**: `Directory.Packages.props` - -**Relevant Decisions**: -1. `2025-07-10-centralized-package-version-management.md` (matches `Directory.Packages.props`) -2. `2025-07-10-dependabot-automated-dependency-updates.md` (matches `Directory.Packages.props`) - -**Applied Instructions**: -- Package version MUST be defined in `Directory.Packages.props` -- Package reference in project file MUST NOT include version attribute -- Dependabot will automatically manage updates - -### Example 3: Making a Commit - -**Context**: All commit operations - -**Relevant Decisions**: -1. `2025-07-10-conventional-commits.md` (matches `**/*.*`) -2. `2025-07-11-english-as-project-language.md` (matches `**/*.*`) - -**Applied Instructions**: -- Commit message MUST follow Conventional Commits 1.0.0 format -- Commit message MUST be in English -- Type MUST be one of: feat, fix, docs, style, refactor, test, chore, build, ci, perf, revert -- Breaking changes MUST be indicated with `!` or `BREAKING CHANGE:` footer - -## Related Decisions Handling - -When a decision references related decisions: - -* MUST read all related decisions to understand full context -* MUST apply requirements from all related decisions that match current file -* MUST respect decision dependency chains (if Decision A depends on B, read B first) -* SHOULD inform user about decision dependencies when making significant changes - -## Conflict Resolution - -If decisions appear to conflict: - -1. **Check states**: "accepted" decisions override "proposed" ones -2. **Check dates**: More recent decisions (`lastModified`) take precedence -3. **Check specificity**: More specific `applyTo` patterns override generic ones -4. **Decisions vs. Instructions**: Accepted decisions from `decisions/` folder override technical instructions from `.github/instructions/` when both apply to the same situation -5. **Ask user**: If conflict remains unclear, request user clarification - -## Decision Updates - -When suggesting changes to decisions: - -* MUST update the `lastModified` field to current date -* MUST update the `instructions` frontmatter if core guidance changes -* MUST maintain backward compatibility notes if changing "accepted" decisions -* SHOULD add to "Related Decisions" if new dependencies are introduced diff --git a/.github/instructions/wording.instructions.md b/.github/instructions/wording.instructions.md index 3064b8db..32939edc 100644 --- a/.github/instructions/wording.instructions.md +++ b/.github/instructions/wording.instructions.md @@ -1,7 +1,7 @@ --- -applyTo: '.github/copilot-instructions.md, .github/instructions/*.instructions.md, decisions/**/*.md' +applyTo: '.github/copilot-instructions.md, .github/instructions/*.instructions.md' -description: 'This file contains instructions for wording and writing style. It includes guidelines for creating and modifying instruction files, decision documents, and Copilot instructions. Ensure to follow the practices outlined in this file to maintain consistency and clarity in documentation.' +description: 'This file contains instructions for wording and writing style. It includes guidelines for creating and modifying instruction files and Copilot instructions. Ensure to follow the practices outlined in this file to maintain consistency and clarity in documentation.' --- # Wording and Writing Style Instructions @@ -34,21 +34,13 @@ description: 'This file contains instructions for wording and writing style. It * MUST use code formatting (backticks) for code, file names, and technical terms. * MUST include both general principles and specific implementation details. -## Decision Documents - -* MUST follow the established ADR (Architecture Decision Record) format. -* MUST include all required frontmatter fields: authors, applyTo, created, lastModified, state. -* MUST provide clear context and problem statements. -* MUST explicitly state the decision and its implications. -* MUST use consistent terminology when referring to technical concepts. - ## Copilot Instructions * MUST structure guidance as imperative statements. * MUST group related instructions under appropriate section headings. * MUST explicitly state constraints and limitations. * MUST reference specific file paths, folders, or patterns when applicable. -* MUST include cross-references to related decisions or instruction files when appropriate. +* MUST include cross-references to related instruction files when appropriate. ## Examples and References diff --git a/.github/prompts/create-architectural-decision-record.prompt.md b/.github/prompts/create-architectural-decision-record.prompt.md deleted file mode 100644 index db9954ed..00000000 --- a/.github/prompts/create-architectural-decision-record.prompt.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -agent: 'agent' -description: 'Create an Architectural Decision Record (ADR) document optimized for decision documentation.' -tools: ['vscode', 'execute', 'read', 'edit', 'search', 'web', 'deepwiki/*', 'fetch/*', 'microsoft-docs/*', 'nuget-server/*', 'agent', 'todo'] ---- -# Create Architectural Decision Record - -Create an ADR document for `${input:DecisionTitle}` using structured formatting optimized for machine parsing and human readability. - -## Inputs - -* **Decision Title**: `${input:DecisionTitle}` -* **Context**: `${input:Context}` -* **Decision**: `${input:Decision}` -* **Consequences**: `${input:Consequences}` -* **Alternatives Considered**: `${input:Alternatives}` -* **Authors**: `${input:Authors}` - -## Input Validation - -* MUST request missing information from the user if any required inputs are not provided or cannot be determined from conversation history. -* MUST obtain all required inputs before proceeding with ADR generation. - -## Requirements - -* MUST use precise, unambiguous language. -* MUST follow the standardized ADR template format with front matter. -* MUST include both positive and negative consequences. -* MUST document all alternatives with rejection rationale. -* MUST structure the document for machine parsing and human reference. -* MUST provide meaningful values for all front matter fields (`authors`, `applyTo`, `created`, `lastModified`, `state`, `instructions`). -* MUST save the ADR in the `decisions/` directory using the naming convention: `YYYY-MM-DD-Title.md`, where the date is the creation date and the title uses hyphens instead of spaces (for example, `2025-07-10-database-selection.md`). - -## Required Documentation Structure - -The documentation file MUST follow the structure defined in `./templates/adr.md`: \ No newline at end of file diff --git a/.github/prompts/csharp-docs.prompt.md b/.github/prompts/csharp-docs.prompt.md index 07a0eb68..d3ac5f91 100644 --- a/.github/prompts/csharp-docs.prompt.md +++ b/.github/prompts/csharp-docs.prompt.md @@ -121,7 +121,6 @@ description: 'Ensure that C# types are documented with XML comments following Mi * MUST use `NotNullAttribute` and related nullable attributes in public API documentation when appropriate. * MUST use `nameof()` operator in examples instead of string literals when referring to member names. * MUST ensure that documentation examples properly demonstrate null-checking patterns using `is null` and `is not null`. -* SHOULD reference related decisions or architectural guidelines when relevant to the API's design or usage. ## Accessibility and Localization diff --git a/AGENTS.md b/AGENTS.md index 6098a418..248c9a7d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,17 +18,6 @@ Use AI coding assistants, such as GitHub Copilot, to enhance productivity and ma * MUST consider the impact on existing workflows and user experience. * MUST evaluate the cost-benefit ratio of proposed changes or new implementations. -## Decision References - -* MUST document all decisions in `decisions/` folder using `templates/adr.md` format. -* MUST treat "accepted" decisions as mandatory requirements with highest precedence. -* MUST respect decision states: - - **accepted**: mandatory requirements - - **proposed**: optional considerations - - **deprecated**: avoid in new implementations - - **superseded**: forbidden, follow superseding decision instead -* MUST use the `instructions` frontmatter property as primary AI guidance for each decision. - ## Configuration Files These files control project-wide settings and should remain unchanged unless specifically requested. diff --git a/decisions/2025-07-10-centralized-package-version-management.md b/decisions/2025-07-10-centralized-package-version-management.md deleted file mode 100644 index 0df37664..00000000 --- a/decisions/2025-07-10-centralized-package-version-management.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "Directory.Packages.props" - - "**/*.csproj" - - "**/*.fsproj" - - "**/*.vbproj" - -created: 2025-07-10 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Enable centralized package version management by setting ManagePackageVersionsCentrally to true in Directory.Packages.props to eliminate version inconsistencies and reduce maintenance overhead. - All projects reference packages without version numbers, with versions controlled centrally from a single source of truth. ---- - -# Decision: Centralized Package Version Management with ManagePackageVersionsCentrally - -We have decided to enable centralized package version management across the entire solution by setting `ManagePackageVersionsCentrally` to `true` in the `Directory.Packages.props` file. - -## Context - -In multi-project .NET solutions, managing NuGet package versions can become challenging and error-prone. Common issues include: - -- **Version Inconsistencies**: Different projects in the same solution referencing different versions of the same package, leading to potential compatibility issues and unexpected behavior. -- **Maintenance Overhead**: Updating package versions requires modifying multiple project files individually, increasing the risk of missing updates or introducing inconsistencies. -- **Dependency Conflicts**: Transitive dependencies can introduce version conflicts when projects use different versions of packages that depend on the same underlying libraries. -- **Security Vulnerabilities**: Difficulty in ensuring all projects use the latest secure versions of packages across the entire solution. -- **Build and Runtime Issues**: Version mismatches can cause build failures, runtime exceptions, or subtle bugs that are difficult to diagnose. - -Our template-dotnet project serves as a foundation for multiple .NET projects and needs to establish consistent package management practices from the start. - -## Decision - -We have implemented centralized package version management by: - -1. **Enabling `ManagePackageVersionsCentrally`**: Set to `true` in `Directory.Packages.props` to enable MSBuild's central package management feature. -2. **Enabling `CentralPackageTransitivePinningEnabled`**: Set to `true` to ensure transitive dependencies are also managed centrally and pinned to specific versions. -3. **Defining Global Package References**: All common packages (analyzers, build tools, etc.) are defined once in `Directory.Packages.props` with specific versions. -4. **Version-only Management**: Individual project files reference packages without version numbers, with versions controlled centrally. - -This approach ensures that all projects in the solution use consistent package versions while maintaining a single source of truth for version management. - -## Consequences - -### Positive Consequences - -- **Consistency**: All projects in the solution use the same versions of shared packages, eliminating version conflicts. -- **Simplified Maintenance**: Package updates only require changes in one location (`Directory.Packages.props`). -- **Better Security Posture**: Easier to ensure all projects use the latest secure versions of packages. -- **Reduced Build Issues**: Eliminates version-related build failures and runtime conflicts. -- **Improved Developer Experience**: Developers don't need to worry about package versions when adding references to existing packages. -- **Transitive Dependency Control**: With `CentralPackageTransitivePinningEnabled`, even indirect dependencies are controlled and predictable. - -### Potential Negative Consequences - -- **Learning Curve**: Developers unfamiliar with central package management may need time to adapt. -- **Flexibility Reduction**: Individual projects cannot override package versions without modifying the central configuration. -- **Migration Complexity**: Existing projects may require significant changes to adopt this pattern. - -## Alternatives Considered - -### 1. Traditional Per-Project Package Management - -**Description**: Allow each project to manage its own package versions independently. - -**Why Not Chosen**: - -- Leads to version inconsistencies across the solution -- Increases maintenance overhead -- Higher risk of dependency conflicts -- Difficult to ensure security updates are applied consistently - -### 2. Shared MSBuild Props Files Without Central Management - -**Description**: Use shared `.props` files to define common package versions but still reference versions in individual projects. - -**Why Not Chosen**: - -- Still requires version references in each project file -- More complex to implement and maintain -- Doesn't leverage MSBuild's built-in central package management features -- Less enforceable than the native MSBuild approach - -### 3. Package Version Variables - -**Description**: Define package versions as MSBuild properties and reference them in individual projects. - -**Why Not Chosen**: - -- Verbose syntax in project files -- No built-in tooling support -- More error-prone than the centralized approach -- Doesn't address transitive dependency management - -## Related Decisions - -- [GitVersion for Automated Semantic Versioning](./2025-07-10-gitversion-automated-semantic-versioning.md) - Related because centralized package management supports automated versioning by ensuring consistent dependency versions across the solution diff --git a/decisions/2025-07-10-conventional-commits.md b/decisions/2025-07-10-conventional-commits.md deleted file mode 100644 index 33b317cb..00000000 --- a/decisions/2025-07-10-conventional-commits.md +++ /dev/null @@ -1,144 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.*" - -created: 2025-07-10 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Adopt Conventional Commits 1.0.0 specification for structured commit messages with type, scope, and description format to enable automated semantic versioning and changelog generation. - Required types include feat, fix, docs, style, refactor, test, chore, build, ci, perf, and revert with breaking change indicators. ---- - -# Decision: Conventional Commits - -A decision to adopt the Conventional Commits specification for standardizing commit messages across the project to improve automation, semantic versioning, and change communication. - -## Context - -The project currently lacks a standardized approach to commit messages, which creates several challenges: - -1. **Inconsistent commit history**: Developers use different styles and formats for commit messages, making it difficult to understand the nature and impact of changes -2. **Manual versioning**: Without structured commit messages, determining semantic version bumps requires manual analysis of changes -3. **Changelog generation**: Creating release notes and changelogs is a manual process that is time-consuming and error-prone -4. **Automated tooling limitations**: The lack of structured commit messages prevents the use of automated tools for CI/CD, semantic versioning, and release management -5. **Communication gaps**: Unclear commit messages make it difficult for team members and stakeholders to understand the impact of changes - -The project already uses GitVersion (as evidenced by `GitVersion.MsBuild` in `Directory.Packages.props`) and follows centralized package management, indicating a preference for automation and structured development practices. - -## Decision - -We will adopt the [Conventional Commits 1.0.0 specification](https://www.conventionalcommits.org/en/v1.0.0/) for all commit messages in this project. - -**Commit Message Structure:** - -```txt -[optional scope]: - -[optional body] - -[optional footer(s)] -``` - -**Required Types:** - -- `feat`: A new feature (correlates with MINOR in Semantic Versioning) -- `fix`: A bug fix (correlates with PATCH in Semantic Versioning) -- `BREAKING CHANGE`: Breaking API changes (correlates with MAJOR in Semantic Versioning) - -**Recommended Additional Types:** - -- `build`: Changes to build system or external dependencies -- `chore`: Maintenance tasks that don't modify src or test files -- `ci`: Changes to CI configuration files and scripts -- `docs`: Documentation changes -- `style`: Code style changes (formatting, missing semicolons, etc.) -- `refactor`: Code changes that neither fix bugs nor add features -- `perf`: Performance improvements -- `test`: Adding or modifying tests - -**Implementation Guidelines:** - -- Commits MUST be prefixed with a type followed by an optional scope, optional `!`, and required terminal colon and space -- Breaking changes MUST be indicated either by `!` after the type/scope or by including `BREAKING CHANGE:` in the footer -- Scope MAY be provided to give additional context (e.g., `feat(api):`, `fix(parser):`) -- Description MUST immediately follow the colon and space after the type/scope prefix -- Body and footers are OPTIONAL and provide additional context when needed - -## Consequences - -**Positive Consequences:** - -1. **Automated versioning**: GitVersion and other tools can automatically determine semantic version bumps based on commit types -2. **Automated changelog generation**: Tools can automatically generate changelogs and release notes from structured commit messages -3. **Improved communication**: Clear, structured commit messages help team members and stakeholders understand the nature and impact of changes -4. **Better CI/CD integration**: Automated tools can trigger appropriate build and deployment processes based on commit types -5. **Consistent commit history**: Standardized format makes the project history more readable and searchable -6. **Enhanced collaboration**: New contributors can quickly understand the commit convention and follow established patterns - -**Potential Challenges:** - -1. **Learning curve**: Team members need to learn and remember the conventional commit format -2. **Enforcement overhead**: Initial effort required to establish tooling and processes to enforce the convention -3. **Commit message length**: Some developers may need to adjust to writing more descriptive commit messages -4. **Retroactive application**: Existing commit history will not follow the convention, creating inconsistency in historical data - -**Risk Mitigation:** - -- Implement commit message linting tools to validate format automatically -- Provide training and documentation for team members -- Use commit message templates in development environments -- Consider squash-and-merge workflow for pull requests to allow maintainers to create properly formatted commit messages - -## Alternatives Considered - -### 1. Custom Commit Convention - -**Description**: Develop a project-specific commit message convention tailored to our needs. - -**Pros**: Complete control over format and requirements, can be optimized for specific project needs - -**Cons**: Requires documentation and training, no existing tooling support, reinventing the wheel, lacks community standards - -**Rejection Reason**: Conventional Commits is already a well-established standard with extensive tooling support - -### 2. Continue with Free-form Commit Messages - -**Description**: Maintain the current approach of allowing developers to write commit messages without specific formatting requirements. - -**Pros**: No learning curve, no enforcement overhead, developer freedom - -**Cons**: Inconsistent history, no automation benefits, poor communication, manual versioning and changelog generation - -**Rejection Reason**: Does not address the identified problems and prevents automation benefits - -### 3. GitHub Flow with Descriptive PR Titles - -**Description**: Focus on descriptive pull request titles and use squash merging to create clean commit messages. - -**Pros**: Reduces individual commit message burden, maintains clean main branch history - -**Cons**: Still lacks standardization, no automation benefits, requires manual formatting of squash commit messages - -**Rejection Reason**: Does not provide the structured format needed for automation tools - -### 4. Semantic Commit Messages (Alternative Format) - -**Description**: Use alternative structured commit formats like Angular commit convention or other semantic formats. - -**Pros**: Similar benefits to Conventional Commits, some tooling support - -**Cons**: Less standardized than Conventional Commits, smaller ecosystem, potential compatibility issues - -**Rejection Reason**: Conventional Commits is more widely adopted and has better tooling ecosystem - -## Related Decisions - -- [Centralized Package Version Management](./2025-07-10-centralized-package-version-management.md) - The adoption of centralized package management demonstrates the project's commitment to automation and standardization, which aligns with adopting Conventional Commits for automated versioning and release management -- [GitVersion for Automated Semantic Versioning](./2025-07-10-gitversion-automated-semantic-versioning.md) - GitVersion is configured to parse conventional commit messages and automatically determine semantic version increments, making conventional commits essential for automated versioning to work correctly diff --git a/decisions/2025-07-10-decision-assets.md b/decisions/2025-07-10-decision-assets.md deleted file mode 100644 index 631b0fea..00000000 --- a/decisions/2025-07-10-decision-assets.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "decisions/**/*" - - "decisions/assets/**/*" - -created: 2025-07-10 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Store all decision-related assets in decisions/assets/ folder and link them using relative paths to ensure proper organization and version control. - Use format [Description](assets/filename.extension) with no external hosting permitted for decision assets. ---- - -# Decision: Decision Assets Storage and Linking - -This decision establishes the standardized approach for storing and referencing assets related to architectural decisions within the project's decision documentation system. - -## Context - -As the project evolves, architectural decisions often require supporting materials such as diagrams, flowcharts, images, PDFs, spreadsheets, and other documentation artifacts. These assets need to be properly organized, version-controlled, and easily accessible from within decision documents. Without a standardized approach, assets may become scattered across different locations, making them difficult to find and maintain over time. - -The current project structure includes a `decisions/` folder for storing architectural decision records (ADRs), and there's a need to establish where and how to store related assets while ensuring they remain linked and accessible. - -## Decision - -All decision-related assets MUST be stored in the `decisions/assets/` folder and MUST be directly linked within decision documents using relative paths. - -### Storage Requirements - -- All assets supporting architectural decisions (diagrams, images, PDFs, etc.) MUST be placed in `decisions/assets/` -- Asset filenames SHOULD use their original names without requiring any specific naming convention -- Assets MAY be organized into subdirectories within `decisions/assets/` if needed for better organization - -### Linking Requirements - -- All assets MUST be referenced using relative paths from the decision document -- Links MUST use the format: `[Asset Description](assets/filename.extension)` for files in the root assets folder -- For assets in subdirectories, use: `[Asset Description](assets/subdirectory/filename.extension)` -- Assets MUST be directly embedded or linked within the relevant decision document -- No external hosting or cloud storage links are permitted for decision assets - -### Example Structure - -```txt -decisions/ -├── 2025-07-10-decision-assets.md -├── 2025-07-10-database-architecture.md -└── assets/ - ├── er-diagram.png - ├── performance-analysis.pdf -``` - -### Example Linking - -```markdown -The proposed database schema is illustrated in the following diagram: - -![Database ER Diagram](assets/er-diagram.png) - -For detailed performance analysis, refer to the [Performance Analysis Report](assets/performance-analysis.pdf). -``` - -## Consequences - -### Positive Consequences - -- **Centralized Asset Management**: All decision-related assets are stored in a single, predictable location -- **Version Control**: Assets are version-controlled alongside the decision documents -- **Accessibility**: Assets remain accessible even when working offline or in different environments -- **Maintenance**: Easier to maintain and update assets as they're co-located with decisions -- **Documentation Integrity**: Direct linking ensures assets and decisions remain connected - -### Potential Risks - -- **Repository Size**: Large assets may increase repository size, though this is manageable with proper asset optimization -- **Binary File Management**: Git may not handle large binary files efficiently, but this can be mitigated with Git LFS if needed -- **Asset Duplication**: Same assets might be referenced by multiple decisions, though this ensures each decision remains self-contained - -## Alternatives Considered - -### External Asset Hosting - -Using cloud storage or external hosting services for assets was considered but rejected because: - -- Creates external dependencies that may become unavailable -- Requires additional access management and permissions -- Breaks the self-contained nature of the decision repository -- May introduce security and compliance concerns - -### Separate Asset Repository - -Creating a separate repository for assets was considered but rejected because: - -- Increases complexity in maintaining relationships between decisions and assets -- Makes it harder to ensure assets remain synchronized with decisions -- Complicates the review process for decision changes that include asset updates - -### Flat Asset Structure - -Storing all assets directly in the `decisions/` folder was considered but rejected because: - -- Creates clutter in the main decisions directory -- Makes it harder to distinguish between decision documents and supporting assets -- Reduces organization and discoverability of assets - -## Related Decisions - -None at this time. This decision is independent and focuses solely on asset storage and organization practices. diff --git a/decisions/2025-07-10-dependabot-automated-dependency-updates.md b/decisions/2025-07-10-dependabot-automated-dependency-updates.md deleted file mode 100644 index 23e61dd3..00000000 --- a/decisions/2025-07-10-dependabot-automated-dependency-updates.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - ".github/dependabot.yml" - - "Directory.Packages.props" - - "**/*.csproj" - - "**/*.fsproj" - - "**/*.vbproj" - -created: 2025-07-10 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Implement Dependabot for automated dependency updates across NuGet packages and GitHub Actions with daily scheduling to maintain security and reduce manual update overhead. - Configuration includes grouped updates, conventional commit formatting, and pull request limits with automatic maintainer assignment. ---- - -# Decision: Dependabot for Automated Dependency Updates - -We have decided to implement Dependabot for automated dependency updates across both NuGet packages and GitHub Actions to maintain security, stability, and currency of our dependencies. - -## Context - -Managing dependencies in modern software projects presents several challenges: - -- **Security Vulnerabilities**: Outdated dependencies may contain known security vulnerabilities that expose the project to risks. -- **Manual Update Overhead**: Manually tracking and updating dependencies across multiple package ecosystems (NuGet, GitHub Actions) is time-consuming and error-prone. -- **Dependency Drift**: Over time, projects tend to fall behind on dependency updates, making future updates more risky and complex. -- **Breaking Changes**: Delayed updates can result in larger version jumps with more breaking changes, making updates more difficult. -- **Compliance Requirements**: Many organizations require keeping dependencies current for security and compliance reasons. -- **Developer Productivity**: Outdated dependencies may lack performance improvements, bug fixes, and new features that could benefit development. - -Our template-dotnet project needs a systematic approach to dependency management that ensures security while minimizing maintenance burden. - -## Decision - -We have implemented Dependabot with the following configuration: - -1. **NuGet Package Ecosystem**: - - Daily update schedule for timely security patches - - Conventional commit format with "chore(deps)" prefix - - Grouped updates for related packages (coverlet, testcontainers, tunit, verify, xunit) - - Pull request limit of 10 to prevent overwhelming the repository - - Automatic assignment to maintainers for review - -2. **GitHub Actions Ecosystem**: - - Daily update schedule for workflow security - - Conventional commit format with "chore(ci)" prefix - - Automatic assignment to maintainers for review - -3. **Configuration Management**: - - Centralized configuration in `.github/dependabot.yml` - - Consistent labeling for dependency tracking - - Integration with existing centralized package management - -## Consequences - -### Positive Consequences - -- **Enhanced Security**: Automatic detection and updates for known security vulnerabilities in dependencies. -- **Reduced Manual Effort**: Eliminates the need for manual dependency monitoring and update initiation. -- **Consistent Updates**: Regular, small updates are easier to review and integrate than large, infrequent updates. -- **Improved Visibility**: Pull requests provide clear visibility into what dependencies are being updated and why. -- **Better Compliance**: Systematic approach to keeping dependencies current supports security and compliance requirements. -- **Grouped Updates**: Related packages are updated together, reducing the number of individual pull requests. -- **Integration with Workflow**: Uses conventional commits and proper labeling to integrate with existing development processes. - -### Potential Negative Consequences - -- **Pull Request Volume**: Daily updates may generate significant pull request activity, requiring regular maintenance. -- **False Positives**: Some updates may introduce issues that require rollback or additional testing. -- **Breaking Changes**: Automatic updates may occasionally include breaking changes requiring code modifications. -- **Review Overhead**: Each update requires human review to ensure compatibility and correctness. -- **Test Dependencies**: Effectiveness depends on having comprehensive test coverage to catch regressions. - -### Mitigation Strategies - -- **Comprehensive Testing**: Rely on automated test suites to catch issues introduced by dependency updates. -- **Gradual Rollout**: Monitor update patterns and adjust configuration based on experience. -- **Grouping Strategy**: Use package grouping to reduce the number of individual pull requests. -- **Review Process**: Establish clear review criteria for dependency updates. - -## Alternatives Considered - -### 1. Manual Dependency Management - -**Description**: Manually monitor and update dependencies on a periodic basis. - -**Why Not Chosen**: - -- Time-consuming and error-prone -- Inconsistent update frequency -- Higher risk of missing critical security updates -- Scales poorly with project growth - -### 2. Automated Dependency Scanning Only - -**Description**: Use tools that scan for vulnerabilities but don't automatically create updates. - -**Why Not Chosen**: - -- Provides visibility but still requires manual update process -- Doesn't address the maintenance overhead of dependency updates -- May lead to delayed responses to security issues - -### 3. Weekly or Monthly Update Schedule - -**Description**: Configure Dependabot to run less frequently. - -**Why Not Chosen**: - -- Slower response to security vulnerabilities -- Larger batch updates are more complex to review -- May accumulate breaking changes over time - -### 4. Alternative Dependency Management Tools - -**Description**: Use tools like WhiteSource, or Snyk for dependency management. - -**Why Not Chosen**: - -- Dependabot is native to GitHub and integrates seamlessly -- No additional third-party service dependencies -- Simpler configuration and maintenance -- Cost considerations for commercial alternatives - -## Related Decisions - -- [Centralized Package Version Management](./2025-07-10-centralized-package-version-management.md) - Dependabot works seamlessly with centralized package management by updating versions in the central `Directory.Packages.props` file -- [Conventional Commits](./2025-07-10-conventional-commits.md) - Dependabot is configured to use conventional commit format for consistency with project standards -- [GitVersion for Automated Semantic Versioning](./2025-07-10-gitversion-automated-semantic-versioning.md) - Dependency updates follow conventional commit format which integrates with GitVersion for appropriate version bumping diff --git a/decisions/2025-07-10-folder-structure-and-naming-conventions.md b/decisions/2025-07-10-folder-structure-and-naming-conventions.md deleted file mode 100644 index 6d85535f..00000000 --- a/decisions/2025-07-10-folder-structure-and-naming-conventions.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.*" - -created: 2025-07-10 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Establish standard folder structure with src/ for production code and tests/ for test projects using ProjectName.TestType naming pattern. - Test types include Unit, Integration, Performance, and Acceptance to ensure clear categorization and automated execution. ---- - -# Decision: Folder Structure and Naming Conventions - -This decision establishes the standard folder structure for .NET projects and defines naming conventions for test projects to ensure consistency and clarity across the codebase. - -## Context - -As .NET projects grow in complexity, maintaining a clear and consistent folder structure becomes crucial for: - -- Developer onboarding and navigation -- Build automation and CI/CD pipelines -- Separation of concerns between production and test code -- Test categorization and execution strategies -- IDE and tooling support - -Without standardized conventions, teams may adopt inconsistent patterns that lead to: - -- Confusion about where to place new code -- Difficulty in setting up automated test execution -- Unclear distinction between different types of tests -- Inconsistent project references and dependencies - -## Decision - -We will adopt the following folder structure and naming conventions: - -### Root Folder Structure - -```txt -/ -├── src/ # All production source code -├── tests/ # All test projects -├── docs/ # Documentation (optional) -├── tools/ # Build tools and scripts (optional) -└── samples/ # Example applications (optional) -``` - -### Source Code Organization - -- All production code MUST be placed under the `src/` folder -- Project folders under `src/` MUST follow the namespace hierarchy -- Each project MUST have its own folder directly under `src/` -- The `SpixSpreed.` prefix is automatically applied to all projects through build automation in `Directory.Build.targets` - -### Test Project Naming Conventions - -Test projects MUST follow this naming pattern: - -- **Unit Tests**: `{ProjectName}.Tests.Unit` -- **Integration Tests**: `{ProjectName}.Tests.Integration` - -Where `{ProjectName}` is the name of the production project being tested (the build system will automatically apply the `SpixSpreed.` prefix). - -### Project Naming Convention - -Project folder names follow a simple `{ComponentName}` pattern, where: - -- `{ComponentName}` describes the functional area or component (e.g., Core, Data, Api, Web) -- The `SpixSpreed.` prefix is automatically applied by the build system through `Directory.Build.targets` -- This ensures consistent assembly names, namespaces, and package IDs without manual prefixing - -### Examples - -```txt -src/ -├── Api/ # Web API controllers, middleware, and HTTP-related logic -├── Core/ # Domain models, business logic, interfaces, and shared utilities -└── Data/ # Data access layer, repositories, Entity Framework contexts - -tests/ -├── Api.Tests.Integration/ # End-to-end API tests with real HTTP requests -├── Api.Tests.Unit/ # Unit tests for controllers, middleware, and API logic -├── Core.Tests.Integration/ # Integration tests for business workflows and cross-component scenarios -├── Core.Tests.Unit/ # Unit tests for domain models, business logic, and utilities -├── Data.Tests.Integration/ # Database integration tests with real or test databases -└── Data.Tests.Unit/ # Unit tests for repositories and data access logic -``` - -## Consequences - -### Positive Consequences - -- **Clear Separation**: Distinct separation between production and test code prevents accidental inclusion of test code in production builds -- **Consistent Navigation**: Developers can quickly locate source code and corresponding tests -- **Test Categorization**: Clear distinction between unit and integration tests enables selective test execution -- **Build Pipeline Optimization**: CI/CD pipelines can easily target specific test categories (e.g., run unit tests on every commit, integration tests on merge to main) -- **IDE Support**: Most IDEs and tools recognize this structure and provide better navigation and project templates -- **Scalability**: Structure scales well as projects grow in size and complexity - -### Potential Drawbacks - -- **Initial Setup**: Requires discipline to maintain the structure, especially in the early stages of a project -- **Migration Effort**: Existing projects may need restructuring to adopt these conventions -- **Tool Configuration**: Some tools may need configuration updates to work with the new structure - -## Alternatives Considered - -### Alternative 1: Flat Structure - -```txt -/ -├── ProjectA/ -├── ProjectA.Tests/ -├── ProjectB/ -└── ProjectB.Tests/ -``` - -**Rejected because**: Doesn't scale well, mixes production and test code at the same level, and doesn't distinguish between test types. - -### Alternative 2: Tests Alongside Source - -```txt -src/ -├── ProjectA/ -│ ├── ProjectA.csproj -│ └── Tests/ -└── ProjectB/ - ├── ProjectB.csproj - └── Tests/ -``` - -**Rejected because**: MSBuild automatically includes all code files in subfolders, which would cause the test code to be included in the production project compilation. This creates build errors and conflicts, making this structure technically infeasible without complex exclusion configurations. - -### Alternative 3: Different Test Suffixes - -Using `.UnitTests` and `.IntegrationTests` instead of `.Tests.Unit` and `.Tests.Integration`. - -**Rejected because**: The chosen format provides better grouping in IDE project explorers and is more explicit about the relationship between test types. - -## Related Decisions - -None at this time. This decision establishes foundational project structure conventions that are independent of other architectural decisions. diff --git a/decisions/2025-07-10-gitversion-automated-semantic-versioning.md b/decisions/2025-07-10-gitversion-automated-semantic-versioning.md deleted file mode 100644 index 63b89e23..00000000 --- a/decisions/2025-07-10-gitversion-automated-semantic-versioning.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.*" - -created: 2025-07-10 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Use GitVersion with ManualDeployment mode and TrunkBased workflow to automatically calculate semantic versions from conventional commit messages. - Breaking changes trigger major versions, feat triggers minor, and fix/chore/docs trigger patch versions for automated CI/CD integration. ---- - -# Decision: GitVersion for Automated Semantic Versioning - -A decision to adopt GitVersion as the primary tool for automated semantic versioning, leveraging conventional commit messages to determine version increments and maintain consistent versioning across the project lifecycle. - -## Context - -The project requires a robust and automated approach to semantic versioning that can: - -1. **Eliminate manual versioning**: Manual version management is error-prone and time-consuming, requiring developers to remember to update version numbers and determine appropriate semantic version increments -2. **Integrate with CI/CD pipelines**: Automated builds and deployments need reliable version information for package creation, release tagging, and deployment tracking -3. **Support trunk-based development**: The project follows a trunk-based development workflow that requires version calculation from commit history rather than complex branching strategies -4. **Leverage conventional commits**: With the adoption of Conventional Commits specification, version increments can be automatically determined from structured commit messages -5. **Maintain version consistency**: Ensure all project artifacts (assemblies, packages, containers) use the same calculated version across different build environments - -The project currently uses .NET 10 with centralized package management and follows modern development practices, indicating a preference for automation and standardization in the development workflow. - -## Decision - -We will use **GitVersion** as the primary tool for automated semantic versioning with the following configuration: - -**GitVersion Configuration (`GitVersion.yml`):** - -```yaml -mode: ManualDeployment -major-version-bump-message: "^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\\([\\w\\s-,/\\\\]*\\))?(!:|:.*\\n\\n((.+\\n)+\\n)?BREAKING CHANGE:\\s.+)" -minor-version-bump-message: "^(feat)(\\([\\w\\s-,/\\\\]*\\))?:" -patch-version-bump-message: "^(build|chore|ci|docs|fix|perf|refactor|revert|style|test)(\\([\\w\\s-,/\\\\]*\\))?:" -workflow: TrunkBased/preview1 -``` - -**Implementation Details:** - -- **Mode**: `ManualDeployment` - Provides full control over when versions are incremented and tagged -- **Workflow**: `TrunkBased/preview1` - Optimized for trunk-based development with feature previews -- **MSBuild Integration**: `GitVersion.MsBuild` package automatically injects version information into all projects during build -- **Conventional Commits Integration**: Version bump rules are configured to parse conventional commit messages and determine appropriate semantic version increments -- **Target Framework Workaround**: Temporary configuration to use `net9.0` for GitVersion processing until full .NET 10 support is available - -**Version Increment Rules:** - -- **Major Version**: Triggered by breaking changes (commits with `!` or `BREAKING CHANGE:` footer) -- **Minor Version**: Triggered by `feat:` commits (new features) -- **Patch Version**: Triggered by `fix:`, `build:`, `chore:`, `ci:`, `docs:`, `perf:`, `refactor:`, `revert:`, `style:`, `test:` commits - -**MSBuild Integration:** - -- GitVersion.MsBuild automatically provides version properties to all projects -- Version information is embedded in assemblies, packages, and other artifacts -- No manual version management required in project files - -## Consequences - -**Positive Consequences:** - -1. **Automated version calculation**: Version numbers are automatically calculated from git history and conventional commit messages, eliminating manual version management -2. **Consistent versioning**: All project artifacts automatically use the same calculated version, ensuring consistency across builds and deployments -3. **CI/CD integration**: Build pipelines can reliably access version information for package creation, tagging, and deployment processes -4. **Semantic versioning compliance**: Automatic adherence to semantic versioning principles based on the nature of changes (breaking, feature, fix) -5. **Developer productivity**: Developers focus on code changes rather than version management, reducing cognitive load and potential errors -6. **Release automation**: Enables automated release processes with proper version tagging and changelog generation -7. **Audit trail**: Version increments are directly traceable to specific commits and their semantic meaning - -**Potential Challenges:** - -1. **Learning curve**: Developers need to understand how conventional commits impact version calculation -2. **Commit message discipline**: Incorrect commit message formats can lead to inappropriate version increments -3. **Build complexity**: Additional dependency in the build process that requires understanding for troubleshooting -4. **Preview versions**: Pre-release and preview version handling requires careful configuration and understanding -5. **Rollback scenarios**: Complex version rollback situations may require manual intervention - -**Risk Mitigation:** - -- Implement commit message validation to ensure proper conventional commit format -- Provide clear documentation and training on conventional commits and their version impact -- Configure appropriate branch and tag patterns for different deployment scenarios -- Establish clear guidelines for handling manual version corrections when necessary -- Monitor version calculations in CI/CD pipelines to catch unexpected increments - -## Alternatives Considered - -### 1. Manual Version Management - -**Description**: Manually manage version numbers in project files and update them with each release. - -**Pros**: Full control over versioning, simple to understand, no additional dependencies - -**Cons**: Error-prone, time-consuming, inconsistent across team members, no automation benefits, requires manual coordination - -**Rejection Reason**: Does not align with project goals for automation and standardization, prone to human error - -### 2. Date-based Versioning - -**Description**: Use date and time stamps or sequential build numbers for versioning. - -**Pros**: Simple to implement, automatically incremental, no semantic meaning required - -**Cons**: No semantic meaning, difficult to understand impact of changes, does not follow semantic versioning principles, poor developer experience - -**Rejection Reason**: Does not provide semantic information about the nature of changes, incompatible with semantic versioning best practices - -### 3. Custom Versioning Scripts - -**Description**: Develop custom PowerShell or batch scripts to calculate versions based on git tags and commits. - -**Pros**: Complete control over versioning logic, can be tailored to specific project needs - -**Cons**: Additional maintenance burden, requires expertise to implement correctly, potential for bugs, reinventing existing solutions - -**Rejection Reason**: GitVersion is a mature, well-tested solution that provides the same functionality without custom development overhead - -### 4. NerdBank.GitVersioning - -**Description**: Alternative automated versioning tool with similar capabilities to GitVersion. - -**Pros**: Similar automation benefits, different configuration approach, Microsoft ecosystem alignment - -**Cons**: Different syntax and configuration model, smaller community, less conventional commit integration - -**Rejection Reason**: GitVersion has better integration with conventional commits and broader ecosystem support - -### 5. Azure DevOps Build Variables - -**Description**: Use Azure DevOps or other CI/CD platform built-in versioning capabilities. - -**Pros**: Platform integration, simple configuration, build-specific versioning - -**Cons**: Platform-dependent, limited semantic versioning support, no local development version consistency, vendor lock-in - -**Rejection Reason**: Lacks semantic versioning automation and creates dependency on specific CI/CD platform - -## Related Decisions - -- [Conventional Commits](./2025-07-10-conventional-commits.md) - GitVersion configuration is specifically designed to integrate with the adopted Conventional Commits specification, using commit message patterns to determine appropriate version increments -- [Centralized Package Version Management](./2025-07-10-centralized-package-version-management.md) - GitVersion works seamlessly with centralized package management, providing automated version information that eliminates the need for manual version specifications in Directory.Packages.props diff --git a/decisions/2025-07-11-dotnet-10-csharp-13-adoption.md b/decisions/2025-07-11-dotnet-10-csharp-13-adoption.md deleted file mode 100644 index bbd23718..00000000 --- a/decisions/2025-07-11-dotnet-10-csharp-13-adoption.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.csproj" - - "**/*.fsproj" - - "**/*.vbproj" - - "Directory.Build.props" - - "Directory.Build.targets" - - "global.json" - - "**/*.cs" - -created: 2025-07-11 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Adopt .NET 10 as the target framework and C# 13 as the primary programming language version to leverage latest performance improvements, cloud-native capabilities, and modern language features. - All projects must target net10.0 with C# 13 preview features enabled for enhanced developer productivity and future-proofing. ---- - -# Decision: .NET 10 and C# 13 Adoption - -A decision to adopt .NET 10 as the target framework and C# 13 as the primary programming language version for the Spix Spreed platform, leveraging the latest performance improvements, language features, and cloud-native capabilities. - -## Context - -The Spix Spreed platform is a modern social media management platform that requires: - -1. **High Performance**: The platform handles high-frequency social media interactions, content processing, and real-time analytics -2. **Cloud-Native Architecture**: Must support microservices, containerization, and distributed deployments across multiple cloud providers -3. **Modern Development Experience**: Development team needs access to the latest language features for improved productivity and code maintainability -4. **Long-Term Support**: The chosen .NET version must provide a stable foundation for the platform's multi-year development lifecycle -5. **Compatibility Requirements**: Must support .NET Aspire for cloud-native orchestration and modern tooling ecosystem - -Key considerations for framework selection: - -- Performance improvements in runtime and garbage collection -- Enhanced cloud-native features and container optimization -- Language improvements in C# 13 for better developer productivity -- Native Ahead-of-Time (AOT) compilation capabilities for faster startup times -- Enhanced observability and diagnostics features -- Compatibility with .NET Aspire and modern cloud-native patterns - -## Decision - -We have decided to adopt **.NET 10** as the target framework and **C# 13** as the primary programming language version for the Spix Spreed platform. This includes: - -### Framework Configuration - -- **Target Framework**: `net10.0` for all projects within the solution -- **Language Version**: C# 13 (preview) to access the latest language features -- **Runtime**: .NET 10 runtime with optimizations for cloud-native workloads - -### Implementation Details - -- Configure `Directory.Build.props` with `net10.0` -- Set `preview` to enable C# 13 features during development -- Maintain compatibility with .NET Aspire orchestration requirements -- Utilize GitVersion workaround for `net9.0` target framework compatibility until official support - -### Key Features to Leverage - -- **Performance Improvements**: Utilize enhanced garbage collection and runtime optimizations -- **Native AOT**: Implement for performance-critical services where applicable -- **C# 13 Language Features**: Adopt new syntax improvements and performance enhancements -- **Cloud-Native Optimizations**: Leverage container-aware configurations and improved startup performance -- **Enhanced Observability**: Use built-in diagnostics and monitoring capabilities - -## Consequences - -### Positive Consequences - -- **Performance Benefits**: Significant improvements in throughput, memory usage, and startup times -- **Developer Productivity**: Access to latest C# 13 language features improves code readability and maintainability -- **Future-Proofing**: Positions the platform for long-term compatibility with evolving .NET ecosystem -- **Cloud-Native Optimization**: Better container performance and resource utilization -- **Aspire Compatibility**: Full support for .NET Aspire cloud-native orchestration patterns -- **AOT Capabilities**: Option for Native Ahead-of-Time compilation for performance-critical scenarios - -### Potential Risks - -- **Preview Stability**: C# 13 preview features may have stability considerations during development -- **Ecosystem Compatibility**: Some third-party libraries may not immediately support .NET 10 -- **Migration Complexity**: Future upgrades from preview to stable versions may require code adjustments -- **Tooling Maturity**: Development tools and IDE support may be evolving for latest features - -### Mitigation Strategies - -- Monitor C# 13 language feature stability and adjust usage based on production readiness -- Maintain compatibility testing with critical third-party dependencies -- Implement comprehensive testing strategies to validate preview feature usage -- Plan for migration path from preview to stable C# 13 release - -## Alternatives Considered - -### .NET 8 LTS with C# 12 - -**Pros:** - -- Long-term support guarantee until November 2026 -- Proven stability and extensive ecosystem compatibility -- Full production readiness with comprehensive tooling support - -**Cons:** - -- Missing latest performance improvements available in .NET 10 -- Limited access to newest language features that improve developer productivity -- Less optimal cloud-native and container performance -- Potential need for earlier migration to newer versions - -**Decision:** Rejected due to performance requirements and desire for latest cloud-native optimizations - -### .NET 9 with C# 12 - -**Pros:** - -- Standard Term Support (STS) with 18-month support lifecycle -- Good balance of stability and modern features -- Broad ecosystem compatibility - -**Cons:** - -- Shorter support lifecycle compared to LTS versions -- Missing .NET 10 performance improvements -- Limited future-proofing for long-term platform development -- Less optimal for high-performance social media processing requirements - -**Decision:** Rejected in favor of latest performance and feature benefits - -## Related Decisions - -- [.NET Aspire for Cloud-Native Orchestration](./2025-07-11-dotnet-aspire-cloud-native-orchestration.md) - This decision depends on .NET 10 compatibility for optimal Aspire integration -- [Centralized Package Version Management](./2025-07-10-centralized-package-version-management.md) - Framework version impacts package compatibility and version management strategies -- [GitVersion Automated Semantic Versioning](./2025-07-10-gitversion-automated-semantic-versioning.md) - Requires compatibility workaround for .NET 10 target framework diff --git a/decisions/2025-07-11-english-as-project-language.md b/decisions/2025-07-11-english-as-project-language.md deleted file mode 100644 index 057fe4f6..00000000 --- a/decisions/2025-07-11-english-as-project-language.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.*" - -created: 2025-07-11 - -lastModified: 2025-07-14 - -state: accepted - -instructions: | - Establish English as the mandatory language for all code, documentation, comments, commit messages, and written content to ensure consistency and global accessibility. - Applies to all identifiers, configuration files, database objects, and communication using clear, professional English standards. ---- - -# Decision: English as Project Language - -A decision to establish English as the primary and mandatory language for all code, documentation, and written content within the project to ensure consistency, professionalism, and global accessibility. - -## Context - -Software development projects often face challenges with language consistency, especially in international teams or when targeting global audiences. Mixed language usage in codebases can lead to several issues: - -1. **Inconsistent Communication**: Using multiple languages creates confusion and reduces readability for team members who may not be fluent in all languages used -2. **Maintenance Complexity**: Mixed language comments, documentation, and variable names make code maintenance more difficult -3. **Global Collaboration**: Non-English content can exclude potential contributors and limit the project's reach -4. **Professional Standards**: Industry best practices favor English as the standard language for software development -5. **Tool Compatibility**: Many development tools, IDEs, and automated systems work better with English content -6. **Documentation Accessibility**: English documentation ensures broader accessibility for users and contributors worldwide - -## Decision - -All code, documentation, comments, and other written content in this project MUST be written in English. This includes: - -- **Source Code**: All variable names, function names, class names, method names, and other identifiers -- **Code Comments**: All inline comments, documentation comments, and code annotations -- **Documentation**: README files, API documentation, user guides, and technical specifications -- **Commit Messages**: All commit messages must follow the established Conventional Commits format in English -- **Issue Tracking**: GitHub issues, pull request descriptions -- **Configuration Files**: Comments and descriptions in configuration files -- **Database Objects**: Table names, column names, stored procedure names, and database documentation - -The English used should be: - -- **Professional**: Use clear, concise, and professional language -- **Consistent**: Follow established naming conventions and terminology -- **Accessible**: Avoid unnecessary jargon and use plain English where possible - -## Consequences - -### Benefits - -1. **Improved Collaboration**: Team members from different linguistic backgrounds can effectively collaborate -2. **Enhanced Maintainability**: Consistent language usage makes code easier to read, understand, and maintain -3. **Global Accessibility**: English content ensures the project is accessible to the widest possible audience -4. **Professional Standards**: Aligns with industry best practices and professional development standards -5. **Tool Integration**: Better compatibility with development tools, linters, and automated systems -6. **Knowledge Transfer**: Easier onboarding of new team members regardless of their native language -7. **Open Source Readiness**: Prepares the project for potential open-source contributions - -### Trade-offs - -1. **Learning Curve**: Team members who are not native English speakers may need additional time to express complex technical concepts -2. **Translation Overhead**: Existing non-English content will need to be translated during migration -3. **Cultural Context**: Some domain-specific terms or concepts may lose nuance when translated to English - -### Risks - -1. **Initial Productivity Impact**: Short-term productivity decrease while team members adapt to English-only communication -2. **Quality Concerns**: Non-native English speakers may initially produce less polished documentation or comments - -## Alternatives Considered - -### Multi-language Approach - -- **Description**: Allow multiple languages based on team member preferences or regional requirements -- **Rejected Because**: Creates inconsistency, reduces maintainability, and limits global collaboration - -### Native Language with English Translation - -- **Description**: Write in native language first, then translate to English -- **Rejected Because**: Increases maintenance overhead, creates potential for translation errors, and delays development - -### Gradual Migration - -- **Description**: Slowly transition to English over time without enforcing immediate compliance -- **Rejected Because**: Would result in inconsistent codebase for extended periods and may never achieve full compliance - -## Related Decisions - -- [Conventional Commits](./2025-07-10-conventional-commits.md) - This decision affects commit message language, which must now be in English following the conventional format -- [Folder Structure and Naming Conventions](./2025-07-10-folder-structure-and-naming-conventions.md) - All folder and file naming conventions must now follow English terminology diff --git a/decisions/2025-11-01-ai-agent-build-restore-test-permissions.md b/decisions/2025-11-01-ai-agent-build-restore-test-permissions.md deleted file mode 100644 index 7e9dbece..00000000 --- a/decisions/2025-11-01-ai-agent-build-restore-test-permissions.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.csproj" - - "**/*.fsproj" - - "**/*.vbproj" - - "**/*.sln" - - "**/*.slnx" - - "**/tests/**/*.cs" - - "AGENTS.md" - - ".github/copilot-instructions.md" - -created: 2025-11-01 - -lastModified: 2025-11-01 - -state: accepted - -instructions: | - AI agents are authorized to execute dotnet build, restore, and test commands for all projects in the solution to verify code correctness and maintain quality standards. - All operations MUST be executed at the solution level using the .sln or .slnx file found in the repository root directory. - Before committing changes, AI agents MUST run restore, build, and test operations to ensure no regressions are introduced. ---- - -# Decision: AI Agent Authorization for Build, Restore, and Test Operations - -AI coding assistants such as GitHub Copilot are authorized to execute `dotnet build`, `dotnet restore`, and `dotnet test` commands for all projects within the solution to verify code correctness, ensure compilation success, and validate functionality through automated tests. - -## Context - -AI coding assistants are increasingly capable of making complex code changes across multiple files and projects. However, without the ability to verify their changes, several issues arise: - -- **Undetected Compilation Errors**: Code changes may introduce syntax errors, missing references, or type mismatches that prevent successful compilation. -- **Broken Dependencies**: Package references may be incomplete or incorrect, causing restore failures. -- **Regression Bugs**: Changes may break existing functionality that is covered by automated tests. -- **Integration Issues**: Multi-project changes may compile individually but fail when integrated. -- **Quality Degradation**: Without verification, the quality of AI-generated code cannot be assured before commit. -- **Developer Burden**: Human developers must manually verify all AI-generated changes, reducing productivity gains. - -To maximize the effectiveness of AI coding assistants while maintaining code quality, agents need the capability to validate their own work through standard .NET development operations. - -## Decision - -We authorize AI coding assistants to execute the following .NET CLI commands: - -1. **`dotnet restore`**: Restore NuGet packages and dependencies for projects and solutions. -2. **`dotnet build`**: Compile projects and solutions to verify code correctness and identify compilation errors. -3. **`dotnet test`**: Execute unit tests, integration tests, and other automated tests to validate functionality. - -### Implementation Guidelines - -AI agents MUST: - -- Detect the solution file (`.sln` or `.slnx`) in the repository root directory and use it for all build, restore, and test operations. -- Execute all commands at the solution level to ensure consistency across all projects and detect integration issues. -- Execute `dotnet restore` before building if package references have been added or modified. -- Execute `dotnet build` after making code changes to verify compilation success. -- Execute `dotnet test` after code changes that may affect functionality to ensure no regressions. -- Report compilation errors, warnings, and test failures clearly to the user. -- Iterate on fixes when errors or test failures are detected. -- Use appropriate command-line options (e.g., `--configuration Release`, `--no-restore`) as context requires. - -AI agents SHOULD: - -- Use `--verbosity` options appropriately to provide useful diagnostic information. -- Consider build performance implications and avoid unnecessary rebuilds. -- Verify that the solution file exists before executing commands and report an error if missing. - -AI agents MAY: - -- Execute `dotnet clean` before building to ensure a clean build environment. -- Use additional CLI options (e.g., `--framework`, `--runtime`) when targeting specific configurations. -- Run specific test filters (e.g., `--filter Category=Unit`) when appropriate. - -## Consequences - -### Positive Consequences - -- **Improved Code Quality**: AI-generated code is validated before being presented to developers. -- **Faster Development Cycles**: Errors are caught and fixed immediately by the AI agent rather than discovered later by developers. -- **Reduced Human Oversight**: Developers can trust that AI-generated changes compile and pass tests. -- **Better Error Context**: AI agents can see and respond to actual compiler and test errors rather than relying on static analysis alone. -- **Continuous Verification**: Changes are validated in real-time as part of the AI's workflow. -- **Test-Driven Development Support**: AI agents can run tests iteratively while implementing features. - -### Potential Negative Consequences - -- **Resource Usage**: Build and test operations consume CPU, memory, and disk I/O resources. -- **Time Overhead**: Each verification cycle adds time to AI operations. -- **Potential for Build Loops**: Poorly designed fixes could lead to repeated failed build attempts. -- **Complexity**: AI agents need to interpret and respond appropriately to build and test output. - -### Mitigation Strategies - -- Use incremental builds where possible to minimize resource usage. -- Set reasonable timeout limits for build and test operations. -- Implement clear error handling and reporting mechanisms. -- Monitor for and prevent infinite fix-attempt loops. -- Allow users to disable automatic verification if needed. - -## Alternatives Considered - -### 1. Manual Verification Only - -**Description**: Require human developers to manually run build and test commands after AI-generated changes. - -**Why Not Chosen**: - -- Reduces the value proposition of AI assistance -- Increases developer workload and slows down development -- Errors are discovered later in the workflow -- Does not leverage AI's ability to iterate on fixes - -### 2. Static Analysis Only - -**Description**: Use static code analysis and linting without actual compilation or test execution. - -**Why Not Chosen**: - -- Cannot detect runtime issues or test failures -- May miss compilation errors not caught by static analysis -- Less comprehensive verification than actual build/test -- Doesn't validate package dependencies and restore operations - -### 3. Sandbox/Mock Build Environment - -**Description**: Create a separate, isolated environment for AI build verification that doesn't use actual project files. - -**Why Not Chosen**: - -- Adds significant complexity to implementation -- May not accurately reflect actual build behavior -- Difficult to maintain parity with real build environment -- Adds maintenance overhead for separate build configuration - -### 4. Read-Only Analysis Without Execution - -**Description**: Allow AI agents to analyze code but not execute any commands. - -**Why Not Chosen**: - -- Severely limits AI effectiveness -- Cannot verify changes work correctly -- Misses the primary benefit of automated verification -- Contradicts the goal of autonomous AI assistance - -## Related Decisions - -- [Centralized Package Version Management](./2025-07-10-centralized-package-version-management.md) - AI agents must respect centralized package versions when executing restore operations -- [.NET 10 and C# 13 Adoption](./2025-07-11-dotnet-10-csharp-13-adoption.md) - Build operations must target the correct .NET version and C# language version diff --git a/decisions/2025-11-15-no-github-discussions-for-communication.md b/decisions/2025-11-15-no-github-discussions-for-communication.md deleted file mode 100644 index 31864c14..00000000 --- a/decisions/2025-11-15-no-github-discussions-for-communication.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*" - -created: 2025-11-15 - -lastModified: 2025-11-15 - -state: accepted - -instructions: | - GitHub Discussions is not used for team communication. Issues serve as the central point of contact for all project-related discussions and coordination. - This decision reduces tool fragmentation and ensures all communication flows through a single, tracked channel. ---- - -# Decision: No GitHub Discussions for Communication - -We do not use GitHub Discussions as a communication channel for this project. All team communication related to project decisions, issues, and coordination occurs through GitHub Issues. - -## Context - -The project needed to establish clear guidelines for where team communication should occur. GitHub provides multiple communication mechanisms including Discussions, Issues, and Pull Request comments. Without clear boundaries, communication can become fragmented across multiple channels, making it difficult to track decisions and maintain context. - -## Decision - -GitHub Discussions will not be used for project communication. GitHub Issues will serve as the central point of contact for all project-related discussions and coordination. - -## Consequences - -**Positive:** - -- Single source of truth for all project communication -- Improved traceability and searchability of decisions -- Reduced cognitive overhead from having fewer communication channels -- Better integration with workflow automation tied to Issues - -**Negative:** - -- Requires discipline to redirect team members away from Discussions -- May require additional effort to maintain Issues as the communication hub -- Issues-only approach requires clear issue templates and categorization to prevent clutter - -## Alternatives Considered - -**Use GitHub Discussions as the primary communication channel:** - -- Rejected because Issues are already established as the central contact point -- Would create fragmentation between Issues and Discussions, making it harder to track decisions - -**Use external communication tools (Slack, Teams, etc.) for discussions:** - -- Rejected as these tools are not being considered for this project -- Communication must remain within the GitHub ecosystem to maintain traceability - -**Use both Issues and Discussions for different purposes:** - -- Rejected because maintaining two communication channels adds unnecessary complexity -- Issues provide sufficient functionality for all communication needs - -## Related Decisions - -None at this time. diff --git a/decisions/2026-01-09-nuget-package-readme-template.md b/decisions/2026-01-09-nuget-package-readme-template.md deleted file mode 100644 index 48374e0e..00000000 --- a/decisions/2026-01-09-nuget-package-readme-template.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/README.md" - - "src/**/README.md" - -created: 2026-01-09 - -lastModified: 2026-01-09 - -state: accepted - -instructions: | - Use templates/readme-project.md as the mandatory template for all NuGet package README files to ensure consistent documentation structure, comprehensive content, and absolute URLs for cross-platform compatibility. - All project READMEs MUST include features, installation instructions, usage examples, requirements, and support information following the template structure. - MUST preserve all automated content markers (e.g., ) under all circumstances when updating existing README files. ---- - -# Decision: NuGet Package README Template - -Establish a standardized template for NuGet package README files to ensure consistent, comprehensive, and professional documentation across all packages in the project ecosystem. - -## Context - -NuGet packages require clear and comprehensive documentation to help users understand the package functionality, installation process, and usage patterns. Without a standardized template, several issues arise: - -1. **Inconsistent Documentation**: Different packages have varying documentation quality and structure, making it difficult for users to find information consistently across packages -2. **Missing Critical Information**: Ad-hoc README files often omit essential sections such as requirements, configuration, or troubleshooting guidance -3. **URL Management**: Relative URLs break when viewed on NuGet.org, GitHub, or other platforms that display README content in different contexts -4. **Maintenance Overhead**: Without a template, maintaining documentation standards requires manual review and correction of each README file -5. **Onboarding Complexity**: New contributors and package authors must determine documentation structure and content independently, leading to variations and potential gaps -6. **Professional Appearance**: Inconsistent documentation reduces the perceived quality and professionalism of packages -7. **Discoverability**: Well-structured documentation with standard sections improves package discoverability and user adoption - -The need for a standardized approach became apparent as the project ecosystem expanded with multiple NuGet packages requiring consistent documentation standards. - -## Decision - -All NuGet package README files MUST use the standardized template located at `templates/readme-project.md` as the foundation for project documentation. - -The template provides a comprehensive structure including: - -- **Package Metadata**: Badges for version, downloads, and license status -- **Project Description**: Clear explanation of package purpose and functionality -- **Features**: Bullet-point list of key capabilities -- **Installation Instructions**: Multiple installation methods (NuGet Package Manager, .NET CLI, PackageReference) -- **Quick Start**: Minimal working example for immediate usage -- **Usage Examples**: Detailed examples covering basic and advanced scenarios -- **Configuration**: Setup and configuration guidance -- **Requirements**: Minimum framework versions and dependencies -- **Related Packages**: Cross-references to related packages in the ecosystem -- **Documentation Links**: References to comprehensive documentation -- **Contributing Guidelines**: Links to contribution processes -- **Support Channels**: GitHub Issues and documentation links (GitHub Discussions is not used for project communication) -- **License Information**: Clear license declaration and reference - -All URLs in package READMEs MUST be absolute URLs pointing to GitHub or NuGet.org to ensure compatibility across all platforms where the README may be displayed. - -The template includes comprehensive comments explaining each section's purpose and providing guidance for content creation. - -### Preservation of Automated Content Markers - -When updating existing README files, all automated content markers MUST be preserved under all circumstances. These markers are HTML comments that define sections managed by automated tools or processes. - -Common marker patterns include: - -- `` and `` - Automated package list sections -- `` and `` - Generic automated sections -- Any other `` and `` pairs - -These markers and their content MUST NOT be modified or removed during manual template updates. Automated tools rely on these markers to maintain dynamic content sections. - -## Consequences - -### Positive - -- **Consistency**: All package READMEs follow the same structure, making information easy to find -- **Completeness**: Template ensures all critical sections are included and properly documented -- **Professional Quality**: Standardized documentation improves the perceived quality and professionalism of all packages -- **Reduced Maintenance**: Template updates automatically improve documentation guidance for all packages -- **Cross-Platform Compatibility**: Absolute URLs ensure README content displays correctly on NuGet.org, GitHub, and other platforms -- **Faster Onboarding**: New package authors have clear guidance for creating documentation -- **Better Discoverability**: Consistent structure with badges and clear descriptions improves package discoverability -- **User Experience**: Users benefit from predictable documentation structure across all packages -- **Quality Assurance**: Template comments guide authors toward complete and accurate documentation -- **Automated Content Protection**: Marker preservation ensures automated tooling continues to function correctly - -### Negative - -- **Initial Effort**: Existing packages require updates to conform to the new template structure -- **Flexibility Constraints**: Specialized packages may need to deviate from the standard template structure -- **Maintenance Obligation**: Template changes require updating existing package READMEs to maintain consistency -- **Learning Curve**: Authors must familiarize themselves with the template structure and guidelines -- **Marker Awareness**: Authors must be aware of automated content markers and avoid modifying them manually - -## Alternatives Considered - -### Manual Documentation Without Template - -Each package author creates README files independently without a standardized template. - -**Rejected because**: - -- Leads to inconsistent documentation quality and structure -- Critical information often omitted or poorly organized -- Increases maintenance burden for ensuring documentation standards -- Reduces professional appearance of package ecosystem -- Makes it difficult for users to find information consistently - -### Minimal Template - -Provide a minimal template with only basic sections (title, description, installation). - -**Rejected because**: - -- Insufficient guidance for comprehensive documentation -- Important sections like configuration, requirements, and support would be frequently omitted -- Does not address cross-platform URL compatibility issues -- Provides less value in standardizing documentation quality - -### Multiple Templates by Package Type - -Create different templates for different types of packages (libraries, tools, extensions). - -**Rejected because**: - -- Adds complexity in choosing the correct template -- Reduces consistency across the package ecosystem -- Most sections are relevant to all package types -- Authors can omit irrelevant sections from the standard template - -### External Documentation Generation Tools - -Use automated documentation generation tools (DocFX, Sandcastle) instead of manual README files. - -**Rejected because**: - -- NuGet.org displays README content prominently, requiring manually crafted content -- Generated documentation is often too technical or detailed for quick package evaluation -- Adds build complexity and tooling dependencies -- Does not replace the need for user-friendly introductory content - -## Related Decisions - -- [English as Project Language](./2025-07-11-english-as-project-language.md) - All README content must be written in English following this decision -- [Folder Structure and Naming Conventions](./2025-07-10-folder-structure-and-naming-conventions.md) - README files are placed at the root of each project directory following folder structure conventions -- [No GitHub Discussions for Communication](./2025-11-01-no-github-discussions-for-communication.md) - GitHub Issues serve as the central point of contact for all project-related discussions diff --git a/decisions/2026-01-10-standardized-solution-level-documentation.md b/decisions/2026-01-10-standardized-solution-level-documentation.md deleted file mode 100644 index 50572c58..00000000 --- a/decisions/2026-01-10-standardized-solution-level-documentation.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "README.md" - - "templates/readme-solution.md" - -created: 2026-01-10 - -lastModified: 2026-01-10 - -state: accepted - -instructions: | - MUST use the standardized solution-level README template from templates/readme-solution.md for all repository-level documentation. - MUST preserve existing content markers (e.g., ) when modernizing existing README files. - MUST include all required sections: Overview, Projects, Features, Getting Started, Development, Architecture, Contributing, Code of Conduct, Documentation, Versioning, Support, and License. - MUST use relative links for all internal repository references (CONTRIBUTING.md, CODE_OF_CONDUCT.md, LICENSE, decisions/). ---- - -# Decision: Standardized Solution-Level Documentation - -This decision establishes a standardized template for solution-level README files to ensure consistency, maintainability, and comprehensive documentation across all repositories. - -## Context - -Repository README files serve as the primary entry point for developers, contributors, and users. Without a standardized approach, documentation quality, structure, and completeness vary significantly across projects. This inconsistency creates several challenges: - -- New contributors struggle to understand project structure and getting started procedures -- Essential information (contributing guidelines, architecture decisions, support channels) is inconsistently documented or missing -- Modernizing documentation requires significant effort due to lack of common structure -- Cross-referencing between documentation files (CONTRIBUTING.md, CODE_OF_CONDUCT.md, ADRs) is inconsistent -- Maintenance burden increases as each repository uses different documentation patterns - -The need for a standardized, maintainable template became apparent as repositories grew and required regular documentation updates. A template-based approach enables consistent structure while preserving repository-specific content and custom markers. - -## Decision - -Adopt a standardized template for solution-level README files (`templates/readme-solution.md`) with specific sections, formatting conventions, and comprehensive inline guidance. - -The template includes: - -1. **Standard Structure**: Overview, Projects, Features, Getting Started, Development, Architecture, Contributing, Code of Conduct, Documentation, Versioning, Support, and License sections -2. **Relative Links**: All internal references use relative paths (e.g., `[CONTRIBUTING.md](CONTRIBUTING.md)`) -3. **Inline Guidance**: HTML comments provide detailed instructions for each section -4. **Badge Support**: Standardized badges for license, build status, and contributors -5. **Placeholder Patterns**: Consistent use of `YourRepo`, `ProjectName`, and similar placeholders for easy customization -6. **Flexible Structure**: Optional sections (Acknowledgments, Configuration) can be removed if not needed -7. **Marker Preservation**: Support for preserving existing content markers (e.g., ``, ``) during modernization -8. **Support Communication**: Directs users to GitHub Issues as the central point of contact (GitHub Discussions is not used) -9. **GitVersion Integration**: Documents the use of automated semantic versioning -10. **Conventional Commits Reference**: Links to commit message standards -11. **ADR Integration**: References Architecture Decision Records with relative links to `decisions/` folder - -When modernizing existing README files: - -- MUST preserve all existing content markers (comments like ``) -- MUST retain existing content where applicable while restructuring to match template sections -- MUST maintain any custom sections that provide repository-specific value -- MUST update links to use relative paths consistently - -## Consequences - -### Positive - -- **Consistency**: All repositories follow the same documentation structure, improving navigation and comprehension -- **Completeness**: Template ensures all essential sections are present and documented -- **Maintainability**: Centralized template allows updating documentation standards across all repositories -- **Onboarding**: New contributors can quickly understand project structure, setup, and contribution process -- **Discoverability**: Standard sections make it easier to find specific information (architecture, testing, support) -- **Cross-referencing**: Relative links create a cohesive documentation ecosystem connecting README, CONTRIBUTING.md, CODE_OF_CONDUCT.md, and ADRs -- **Automation-friendly**: Consistent structure enables automated documentation checks and updates -- **Backward Compatibility**: Marker preservation ensures existing automation and tooling continues to work during modernization - -### Negative - -- **Initial Effort**: Existing repositories require one-time modernization effort to adopt the template -- **Customization Constraints**: Highly specialized repositories may need to adapt template sections -- **Maintenance Overhead**: Template updates may require propagating changes to all repositories using it -- **Learning Curve**: Contributors need to familiarize themselves with template structure and placeholder patterns - -### Trade-offs - -- Prioritizes consistency over complete flexibility in documentation structure -- Requires initial time investment for long-term maintainability gains -- May include sections not relevant to all repository types (can be removed as documented) - -## Alternatives Considered - -### No Template / Freeform Documentation - -**Description**: Allow each repository to define its own README structure without standardization. - -**Pros**: - -- Maximum flexibility for repository-specific needs -- No migration effort required -- Each team can optimize for their specific use case - -**Cons**: - -- Inconsistent documentation quality and completeness across repositories -- Higher maintenance burden as each repository evolves independently -- Poor discoverability for users navigating multiple repositories -- Difficult to enforce documentation standards -- No economies of scale for documentation improvements - -**Rejection Rationale**: The cost of inconsistency and maintenance burden outweighs the flexibility benefits. Standardization improves the experience for all stakeholders. - -### Wiki-Based Documentation - -**Description**: Use GitHub Wiki or external documentation platforms instead of README files. - -**Pros**: - -- More powerful formatting and organization capabilities -- Separate documentation from code repository -- Easier to maintain large documentation sets - -**Cons**: - -- Separate from codebase, harder to keep synchronized -- Not visible in repository root for quick reference -- Requires additional access management -- Less portable (tied to specific platform) -- README files remain necessary for initial overview - -**Rejection Rationale**: README files are essential for repository discoverability and initial orientation. Wiki can complement but not replace solution-level README. - -### Minimal README with External Links - -**Description**: Keep README minimal and link to external documentation sites. - -**Pros**: - -- Reduced repository clutter -- More sophisticated documentation tooling available -- Better version control for documentation history - -**Cons**: - -- Requires maintaining separate documentation infrastructure -- Higher barrier to contribution (separate system to learn) -- Documentation less accessible for offline or restricted environments -- External dependencies for basic project information - -**Rejection Rationale**: Essential information should be readily available in the repository. External documentation can supplement but not replace core README content. - -## Related Decisions - -- [Folder Structure and Naming Conventions](./2025-07-10-folder-structure-and-naming-conventions.md) - Defines where documentation and templates are organized -- [English as Project Language](./2025-07-11-english-as-project-language.md) - Establishes language requirements for all documentation -- [GitVersion Automated Semantic Versioning](./2025-07-10-gitversion-automated-semantic-versioning.md) - Referenced in the Versioning section of the template -- [Conventional Commits](./2025-07-10-conventional-commits.md) - Referenced in Contributing and Versioning sections -- [No GitHub Discussions for Communication](./2025-11-01-no-github-discussions-for-communication.md) - GitHub Issues serve as the central point of contact for all project discussions diff --git a/decisions/2026-01-21-datetimeoffset-and-timeprovider-usage.md b/decisions/2026-01-21-datetimeoffset-and-timeprovider-usage.md deleted file mode 100644 index 117d7b6a..00000000 --- a/decisions/2026-01-21-datetimeoffset-and-timeprovider-usage.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.cs" - -created: 2026-01-21 - -lastModified: 2026-01-21 - -state: accepted - -instructions: | - MUST use DateTimeOffset instead of DateTime for all date and time values unless external constraints require DateTime. - MUST use TimeProvider for obtaining current time to ensure testability. - MUST inject TimeProvider via constructor dependency injection. - MUST NOT use DateTime.Now, DateTime.UtcNow, DateTimeOffset.Now, or DateTimeOffset.UtcNow directly in production code. - MAY use DateOnly or TimeOnly only for performance-critical scenarios or UI display requirements. ---- - -# Decision: DateTimeOffset and TimeProvider Usage - -This decision establishes the mandatory use of `DateTimeOffset` over `DateTime` and requires `TimeProvider` for all time-related operations to ensure consistent timezone handling and testability. - -## Context - -Date and time handling in software development presents several challenges: - -1. **Timezone Ambiguity**: `DateTime` does not inherently store timezone information. The `Kind` property (`Local`, `Utc`, `Unspecified`) is often misinterpreted or lost during serialization, leading to incorrect time calculations across different timezones. - -2. **Serialization Issues**: When `DateTime` values are serialized and deserialized (JSON, databases, APIs), timezone context is frequently lost, causing subtle bugs that are difficult to diagnose. - -3. **Testability Concerns**: Direct calls to `DateTime.Now` or `DateTime.UtcNow` create hidden dependencies on the system clock, making unit tests non-deterministic and time-dependent scenarios impossible to test reliably. - -4. **Global Applications**: Modern applications often serve users across multiple timezones, requiring precise handling of temporal data with explicit offset information. - -5. **.NET Evolution**: .NET 8 introduced `TimeProvider` as a first-class abstraction for time operations, providing a standardized approach for testable time-dependent code. - -## Decision - -The project MUST adhere to the following requirements for date and time handling: - -### DateTimeOffset over DateTime - -- MUST use `DateTimeOffset` instead of `DateTime` for all date and time values. -- MUST only use `DateTime` when external constraints require it (for example, third-party APIs, legacy database schemas, or framework limitations). -- MUST document the reason when `DateTime` usage is unavoidable. -- MUST convert `DateTime` values to `DateTimeOffset` at system boundaries as early as possible. - -### DateOnly and TimeOnly Usage - -- MAY use `DateOnly` or `TimeOnly` only when one of the following conditions applies: - - Performance-critical scenarios where the reduced memory footprint is measurable and relevant. - - UI display requirements where only date or time components are needed for presentation. -- MUST NOT use `DateOnly` or `TimeOnly` as a general replacement for `DateTimeOffset`. -- MUST convert `DateOnly` or `TimeOnly` to `DateTimeOffset` when persisting to databases or transmitting via APIs. -- MUST document the reason when using `DateOnly` or `TimeOnly`. - -### TimeProvider for Current Time - -- MUST use `TimeProvider` to obtain the current time in all production code. -- MUST inject `TimeProvider` via constructor dependency injection. -- MUST NOT call `DateTime.Now`, `DateTime.UtcNow`, `DateTimeOffset.Now`, or `DateTimeOffset.UtcNow` directly. -- MUST use `TimeProvider.System` as the default implementation in production. -- MUST use `Microsoft.Extensions.Time.Testing.FakeTimeProvider` or custom implementations for testing. - -### Implementation Pattern - -```csharp -public class OrderService -{ - private readonly TimeProvider _timeProvider; - - public OrderService(TimeProvider timeProvider) - { - ArgumentNullException.ThrowIfNull(timeProvider); - _timeProvider = timeProvider; - } - - public Order CreateOrder(OrderRequest request) - { - ArgumentNullException.ThrowIfNull(request); - - return new Order - { - Id = Guid.NewGuid(), - CreatedAt = _timeProvider.GetUtcNow(), - // ... other properties - }; - } -} -``` - -### Test Implementation Pattern - -```csharp -public class OrderServiceTests -{ - [Test] - public async Task CreateOrder_ShouldSetCreatedAtToCurrentTime() - { - // Arrange - var fakeTime = new DateTimeOffset(2026, 1, 21, 10, 30, 0, TimeSpan.Zero); - var fakeTimeProvider = new FakeTimeProvider(fakeTime); - var service = new OrderService(fakeTimeProvider); - var request = new OrderRequest { /* ... */ }; - - // Act - var order = service.CreateOrder(request); - - // Assert - await Assert.That(order.CreatedAt).IsEqualTo(fakeTime); - } -} -``` - -## Consequences - -### Positive Consequences - -- **Timezone Safety**: `DateTimeOffset` explicitly stores the offset from UTC, eliminating timezone ambiguity. -- **Serialization Reliability**: Timezone information is preserved during serialization and deserialization. -- **Deterministic Tests**: `TimeProvider` injection enables fully controllable and repeatable time-based tests. -- **Time Travel Testing**: Tests can simulate past and future dates without system clock manipulation. -- **Framework Alignment**: Aligns with .NET 8+ best practices and the `TimeProvider` abstraction. -- **Cross-Timezone Correctness**: Calculations involving multiple timezones produce correct results. - -### Negative Consequences - -- **Migration Effort**: Existing code using `DateTime` requires refactoring. -- **Dependency Injection Overhead**: Every class requiring current time needs `TimeProvider` injection. -- **Learning Curve**: Developers unfamiliar with `DateTimeOffset` or `TimeProvider` require onboarding. -- **Storage Considerations**: Some databases handle `DateTimeOffset` differently than `DateTime`. -- **Third-Party Limitations**: Some external libraries or APIs may still require `DateTime`. - -## Alternatives Considered - -### Continue Using DateTime with UTC Convention - -**Description**: Enforce a convention that all `DateTime` values are UTC and rely on `DateTimeKind.Utc`. - -**Rejection Rationale**: - -- Convention-based approaches are error-prone and not compiler-enforced. -- `DateTimeKind` is easily lost during serialization. -- Does not address testability concerns. -- Requires manual discipline across the entire codebase. - -### Custom Time Abstraction - -**Description**: Create a project-specific `ITimeService` or `IClock` interface for time operations. - -**Rejection Rationale**: - -- Reinvents functionality already provided by .NET's `TimeProvider`. -- Creates maintenance burden for custom abstraction. -- Reduces interoperability with libraries expecting `TimeProvider`. -- `TimeProvider` is the standardized .NET solution since .NET 8. - -### Static Time Helper with Ambient Context - -**Description**: Use a static `TimeHelper.Now` property that can be swapped during testing via ambient context. - -**Rejection Rationale**: - -- Ambient context patterns hide dependencies and reduce code clarity. -- Static access makes parallel test execution problematic. -- Violates explicit dependency principle. -- Not thread-safe without careful implementation. - -## Related Decisions - -- [.NET 10 and C# 13 Adoption](./2025-07-11-dotnet-10-csharp-13-adoption.md) - This decision builds upon the .NET version adoption which provides `TimeProvider` as a standard framework feature. diff --git a/decisions/2026-01-21-no-code-regions.md b/decisions/2026-01-21-no-code-regions.md deleted file mode 100644 index 7bd7e410..00000000 --- a/decisions/2026-01-21-no-code-regions.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "**/*.cs" - - "**/*.razor" - - "**/*.razor.cs" - -created: 2026-01-21 - -lastModified: 2026-01-21 - -state: accepted - -instructions: | - MUST NOT use code regions (`#region`/`#endregion`) under any circumstances. - Regions obscure code structure, hinder navigation, and indicate poor code organization that should be resolved through proper refactoring. ---- - -# Decision: No Code Regions - -A decision to prohibit the use of code regions (`#region`/`#endregion`) in all C# and Razor source files to improve code readability, maintainability, and navigation. - -## Context - -Code regions in C# allow developers to group sections of code that can be collapsed in the IDE using `#region` and `#endregion` directives: - -```csharp -#region Private Methods -private void DoSomething() { } -private void DoSomethingElse() { } -#endregion -``` - -While regions were historically used to organize code, modern development practices and tooling have evolved significantly: - -1. **Code Smell Indicator**: Regions often indicate that a class or file has grown too large and should be refactored into smaller, more focused components. -2. **Navigation Obstruction**: Collapsed regions hide code, making it harder to navigate and understand the full structure of a file. -3. **False Organization**: Regions provide a false sense of organization without addressing the underlying structural issues. -4. **Modern IDE Capabilities**: Current IDEs provide superior navigation tools (outline views, symbol search, code folding based on syntax) that make regions unnecessary. -5. **Code Review Impact**: Regions can hide code during reviews, potentially allowing problematic code to go unnoticed. -6. **Partial Class Alternative**: When code organization is genuinely needed, partial classes provide a better solution with proper file separation. - -## Decision - -We have decided to **prohibit the use of code regions** (`#region`/`#endregion`) in all C# and Razor source files under all circumstances. - -### Implementation Requirements - -- MUST NOT use `#region` or `#endregion` directives in any C# or Razor file. -- MUST remove existing regions during code refactoring or maintenance. -- MUST refactor large files into smaller, focused classes or partial classes instead of using regions. -- MUST use proper class design and separation of concerns as organizational strategies. - -### Enforcement - -- Code reviewers MUST reject pull requests containing new region directives. -- Static analysis tools SHOULD be configured to flag region usage as a warning or error. -- Existing regions SHOULD be removed opportunistically during regular maintenance. - -### Acceptable Alternatives - -Instead of using regions, developers MUST apply these organizational strategies: - -| Problem | Solution | -| ------------------------------------ | ---------------------------------------------------- | -| File is too long | Split into multiple classes or partial classes | -| Grouping related methods | Use proper class design with single responsibility | -| Separating interface implementations | Use partial classes in separate files | -| Organizing generated code | Place generated code in separate partial class files | - -## Consequences - -### Positive Consequences - -- **Improved Readability**: All code is visible and accessible without expanding collapsed sections. -- **Better Code Structure**: Forces developers to address underlying organizational issues through proper refactoring. -- **Enhanced Navigation**: IDE navigation features work consistently without hidden code sections. -- **Clearer Code Reviews**: Reviewers see all code without needing to expand regions. -- **Consistent Codebase**: Uniform code organization approach across the entire project. - -### Negative Consequences - -- **Initial Refactoring Effort**: Existing code with regions requires refactoring to comply with this decision. -- **Learning Curve**: Developers accustomed to using regions must adopt alternative organizational patterns. -- **Potential Resistance**: Some developers may prefer regions for organizing large files. - -### Trade-offs - -- Short-term effort to remove existing regions versus long-term maintainability benefits. -- Requires discipline to maintain small, focused classes instead of relying on regions for organization. - -## Alternatives Considered - -### Allow Regions for Specific Use Cases - -**Rejected** because: - -- Creates ambiguity about when regions are acceptable -- Leads to inconsistent codebase -- Does not address the fundamental issues regions introduce - -### Use EditorConfig to Disable Region Folding - -**Rejected** because: - -- Only affects IDE display, does not prevent region creation -- Does not enforce the underlying code quality principles -- Regions still clutter source files - -### Allow Regions Only in Generated Code - -**Rejected** because: - -- Generated code should be in separate files or partial classes -- Maintaining exceptions complicates the rule -- Modern code generation tools support partial class patterns - -## Related Decisions (Optional) - -None at this time. diff --git a/decisions/2026-09-23-ambient-correlation-context-for-outgoing-http-calls.md b/decisions/2026-09-23-ambient-correlation-context-for-outgoing-http-calls.md deleted file mode 100644 index 1047f081..00000000 --- a/decisions/2026-09-23-ambient-correlation-context-for-outgoing-http-calls.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -authors: - - Martin Stühmer - -applyTo: - - "src/NetEvolve.Http.Correlation.Abstractions/**/*.cs" - - "src/NetEvolve.Http.Correlation.AspNetCore/**/*.cs" - - "src/NetEvolve.Http.Correlation.Azure.Functions/**/*.cs" - - "src/NetEvolve.Http.Correlation.HttpClient/**/*.cs" - -created: 2026-09-23 - -lastModified: 2026-09-23 - -state: accepted - -instructions: | - Outgoing correlation (HttpCorrelationIdHandler) MUST NOT capture IHttpCorrelationAccessor or any other scoped service through its constructor, because IHttpClientFactory builds and caches handlers in its own DI scope. - The incoming middlewares (AspNetCore, Azure Functions) publish an immutable snapshot (correlation id + header name) into an internal AsyncLocal ambient context for the duration of the request; the handler reads that snapshot per call and does nothing when it is absent. - Accessor implementations MUST NOT memoise values derived from HttpContext or FunctionContext; only an explicitly assigned value may be stored. ---- - -# Decision: Ambient Correlation Context for Outgoing HTTP Calls - -Outgoing HTTP calls read the correlation id and header name from an ambient context. Each incoming middleware sets that context for the current request. The handler never takes a scoped `IHttpCorrelationAccessor` in its constructor. The accessors also stop memoising values derived from the host context. This resolves [#858](https://github.com/dailydevops/http.correlation/issues/858) and [#859](https://github.com/dailydevops/http.correlation/issues/859). - -## Context - -### Observed behaviour - -`WithHttpCorrelation()` registers `HttpCorrelationIdHandler` as a transient `DelegatingHandler`. Its constructor takes `IHttpCorrelationAccessor`, which both hosts register as scoped. - -`IHttpClientFactory` does **not** resolve message handlers from the scope of the incoming request. `DefaultHttpClientFactory.CreateHandlerEntry` creates its own scope (`_scopeFactory.CreateScope()`) for every handler chain. It caches that chain for `HandlerLifetime` (2 minutes by default) and shares it across all requests in that window. Microsoft documents this as a known limitation. The guidance is "DO NOT cache any scope-related information … inside `HttpMessageHandler` instances or its dependencies" ([IHttpClientFactory troubleshooting](https://learn.microsoft.com/dotnet/core/extensions/httpclient-factory-troubleshooting#httpclient-doesnt-respect-scoped-lifetime), [dotnet/runtime#47091](https://github.com/dotnet/runtime/issues/47091)). - -The handler therefore holds an accessor instance that: - -1. belongs to the factory's handler scope, **not** to any request scope; -2. was never touched by `HttpCorrelationMiddleware` / `FunctionsCorrelationMiddleware`, so its `HeaderName` is never set to the incoming dialect; -3. memoises its first answer (`_correlationId ??= …`), so it keeps that answer for as long as the handler chain lives (#859). - -The consequences depend on the host. - -| Host | Consequence | Severity | -| --- | --- | --- | -| ASP.NET Core | Every outgoing call forwards the id of the request that happened to build the chain first. | Silent, plausible-looking wrong trace | -| ASP.NET Core | An incoming `X-Request-ID` is forwarded as `X-Correlation-ID`, starting with the **first** request. | Dialect lost | -| ASP.NET Core | Calls with no request in flight send an **empty** `X-Correlation-ID` header, or leak the id of an earlier request once one was memoised. | Wrong or empty header | -| Azure Functions | `FunctionsCorrelationAccessor.Context` is `null` in the handler scope. The first outgoing call throws `NullReferenceException` in `FunctionsCorrelationAccessor.get_CorrelationId()`. | `WithHttpCorrelation()` is unusable in Functions | - -The Functions case is not described in #858. It shows that the fix proposed in the issue, which resolves through `IHttpContextAccessor`, is not enough. The isolated worker has no `HttpContext` unless ASP.NET Core integration is used. `AddHttpCorrelation()` for Functions does not register `IHttpContextAccessor` either. - -### Reproduction - -All tests below go through the real `IHttpClientFactory` pipeline. They use `AddHttpClient(...).WithHttpCorrelation()` with a recording primary handler, and keep one host or provider alive across several requests, as in production. Each test was red before the fix and defines the target behaviour; all of them pass with the decision below. - -`tests/NetEvolve.Http.Correlation.AspNetCore.Tests.Integration/HttpClientForwardingTests.cs` - -| Test | Result before the fix | -| --- | --- | -| `SendAsync_SequentialRequests_ForwardEachRequestsOwnCorrelationId` | forwarded `[First, First]` | -| `Send_SequentialRequests_ForwardEachRequestsOwnCorrelationId` (sync path) | forwarded `[First, First]` | -| `SendAsync_ConcurrentRequests_ForwardEachRequestsOwnCorrelationId` (16 parallel) | forwarded the first request's id 16 times | -| `SendAsync_IncomingAlternativeHeader_ForwardsUsingAlternativeHeader` | incoming `X-Request-ID: Alternative`, forwarded as `X-Correlation-ID: Alternative` | -| `SendAsync_MixedHeaderDialects_ForwardEachRequestsOwnHeaderAndId` | `X-Correlation-ID: Primary` twice, no `X-Request-ID` | -| `SendAsync_OutsideOfRequest_AddsNoCorrelationHeader` | `X-Correlation-ID` with an empty value | -| `SendAsync_OutsideOfRequestAfterRequest_DoesNotLeakPreviousCorrelationId` | background call forwarded the earlier request's id | - -`tests/NetEvolve.Http.Correlation.Azure.Functions.Tests.Integration/HttpClientForwardingTests.cs` - -| Test | Result before the fix | -| --- | --- | -| `SendAsync_SingleInvocation_ForwardsInvocationCorrelationId` | `NullReferenceException` | -| `SendAsync_SequentialInvocations_ForwardEachInvocationsOwnCorrelationId` | `NullReferenceException` | -| `SendAsync_IncomingAlternativeHeader_ForwardsUsingAlternativeHeader` | `NullReferenceException` | -| `SendAsync_OutsideOfInvocation_AddsNoCorrelationHeader` | `NullReferenceException` | - -Accessor memoisation (#859): - -| Test | Result before the fix | -| --- | --- | -| `HttpCorrelationAccessorTests.CorrelationId_Get_AfterHttpContextChanged_ReturnsCurrentTraceIdentifier` | returns the first request's id | -| `HttpCorrelationAccessorTests.CorrelationId_Get_AfterHttpContextCleared_ReturnsNull` | returns the finished request's id | -| `HttpCorrelationAccessorTests.CorrelationId_Get_AfterTraceIdentifierChanged_ReturnsCurrentTraceIdentifier` | returns the server trace id cached before the middleware replaced it | -| `FunctionsCorrelationAccessorTests.CorrelationId_Get_AfterContextChanged_ReturnsCurrentInvocationId` | returns the first invocation's id | - -`CorrelationId_Set_OverridesFallbackValue` (both accessors) is green and must stay green. An explicitly assigned id still wins over the host fallback. - -### Other captures checked - -`HttpCorrelationIdHandler` is the only type in this repository that receives a scoped service and is cached by `IHttpClientFactory`. Both middlewares resolve the accessor per invocation, from `HttpContext.RequestServices` and `FunctionContext.InstanceServices`. If a consumer sets `HttpClientFactoryOptions.SuppressHandlerScope = true`, the handler is resolved from the root provider instead. That is the same bug in a different form, and the chosen design is immune to it as well. - -## Decision - -### 1. Ambient, immutable correlation snapshot (fixes #858) - -Add an internal ambient context to `NetEvolve.Http.Correlation.Abstractions`. `InternalsVisibleTo` already lists AspNetCore, Azure.Functions and HttpClient, so no public API is added. - -```csharp -namespace NetEvolve.Http.Correlation; - -internal sealed record CorrelationSnapshot(string CorrelationId, string HeaderName); - -internal static class CorrelationContext -{ - private static readonly AsyncLocal _current = new(); - - public static CorrelationSnapshot? Current => _current.Value; - - public static void Set(CorrelationSnapshot? snapshot) => _current.Value = snapshot; -} -``` - -Both middlewares publish the snapshot right before calling `next`. The snapshot holds the resolved id and the header dialect actually used: - -```csharp -// HttpCorrelationMiddleware.InvokeAsync / FunctionsCorrelationMiddleware.Invoke -CorrelationContext.Set(new CorrelationSnapshot(correlationId, usedHeaderName)); -await next(context).ConfigureAwait(false); -``` - -An `AsyncLocal` value assigned inside an `async` method is visible to everything that method awaits. The caller does not see it once the method returns. The value is therefore bound to the request, including work the request starts itself, and absent in hosted services or timer or queue triggers. - -`HttpCorrelationIdHandler` no longer takes constructor dependencies. It reads the snapshot on each call: - -```csharp -private static void SetCorrelationId(HttpHeaders headers) -{ - if (CorrelationContext.Current is not { } snapshot || string.IsNullOrWhiteSpace(snapshot.CorrelationId)) - { - return; // no request in flight: stay inert, never send an empty header - } - - if (!headers.Contains(snapshot.HeaderName)) - { - headers.Add(snapshot.HeaderName, snapshot.CorrelationId); - } -} -``` - -The handler stays `internal`, and the `WithHttpCorrelation()` registration does not change. The public surface is unchanged. Only the existing handler unit tests need adapting: they construct the handler with a fake accessor and would publish a snapshot instead. - -This pattern follows ASP.NET Core's own `Microsoft.AspNetCore.HeaderPropagation`. Its `HeaderPropagationMiddleware` writes into an `AsyncLocal` (`HeaderPropagationValues`), which `HeaderPropagationMessageHandler` reads from inside the factory-cached chain. - -### 2. No memoisation of host-derived values (fixes #859) - -Keep a field **only** for an explicitly assigned value and read the fallback live: - -```csharp -// HttpCorrelationAccessor -private string? _explicitCorrelationId; - -public string CorrelationId -{ - get => _explicitCorrelationId ?? _httpContextAccessor.HttpContext?.TraceIdentifier!; - set => _explicitCorrelationId = value; -} - -// FunctionsCorrelationAccessor -public string CorrelationId -{ - get => _explicitCorrelationId ?? Context?.InvocationId!; - set => _explicitCorrelationId = value; -} -``` - -This is option 1 from #859. Once the value is no longer memoised, an accessor held beyond its request answers `null` instead of another request's id. The failure then shows up where it happens. - -## Consequences - -**Benefits** - -- Correct id **and** header dialect on every outgoing call, for ASP.NET Core and Azure Functions, sync and async. -- `WithHttpCorrelation()` works in Azure Functions for the first time. Today it throws. -- No empty `X-Correlation-ID` headers from background work. -- The handler has no scoped dependencies, so it is immune to `HandlerLifetime` and `SuppressHandlerScope`. -- No public API change. The fix can ship as a `fix:` release. - -**Trade-offs and risks** - -- Requests handled by something other than the two middlewares get no forwarding. This includes the case where `UseHttpCorrelation()` is not registered. Today they get a plausible but wrong id. This change is intended, but it should go in the release notes. -- Fire-and-forget work started during a request keeps the request's snapshot after the request ends, because `AsyncLocal` flows with the `ExecutionContext`. For correlation this is desirable, since the work was caused by that request. The snapshot holds only two immutable strings, so there is no risk of use-after-dispose, unlike flowing a scoped service or `HttpContext`. -- Open question for Azure Functions: non-HTTP triggers (timer, queue, …) currently return early from the middleware. They could publish `CorrelationSnapshot(InvocationId, HeaderName1)` so outgoing calls from those functions are correlated too. The proposal leaves them inert, which the test `SendAsync_OutsideOfInvocation_AddsNoCorrelationHeader` expects. -- The handler currently also writes the correlation header into the **downstream response**. The proposal keeps that behaviour. Whether it is useful at all should be decided separately. - -## Alternatives Considered - -### A. Resolve per call through `IHttpContextAccessor` (proposal in #858) - -The handler depends on `IHttpContextAccessor` and resolves `IHttpCorrelationAccessor` from `HttpContext.RequestServices` inside `SendAsync`. - -- ✅ Small change and correct for ASP.NET Core. -- ❌ Does not fix Azure Functions. The isolated worker has no `HttpContext`, and `IHttpContextAccessor` is not registered there. A constructor dependency would fail when the handler is built. An optional lookup would turn today's exception into a silently missing header. -- ❌ Ties the HttpClient package to ASP.NET Core semantics. - -Rejected because it fixes only one of the two supported hosts. - -### B. Ambient snapshot via `AsyncLocal` (chosen) - -See [Decision](#decision). - -### C. Use `System.Diagnostics.Activity` / W3C `traceparent` baggage - -Read the id from `Activity.Current` (baggage or tags) instead of a dedicated context. - -- ✅ Standard mechanism, also flows through other instrumentation. -- ❌ Changes semantics. `X-Correlation-ID` and `X-Request-ID` are independent of W3C trace ids, and consumers may run without any `ActivitySource` listener. -- ❌ Much larger behavioural change than the bug warrants. - -Rejected for this fix. It could be revisited as a separate feature. - -### D. Document only ("never hold an accessor beyond its request") - -Rejected. The compiler cannot enforce it, and the package's own handler already breaks it. - -## Related Decisions - -- [Conventional Commits](./2025-07-10-conventional-commits.md): the fix should be released as `fix(httpclient): …` / `fix(aspnetcore): …` / `fix(functions): …`. -- [AI Agent Authorization for Build, Restore, and Test Operations](./2025-11-01-ai-agent-build-restore-test-permissions.md): the reproduction tests were run at solution level. diff --git a/templates/adr.md b/templates/adr.md deleted file mode 100644 index 816ac196..00000000 --- a/templates/adr.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -# List of authors who contributed to this decision. Include full names and roles if applicable. -authors: - - Name Surname # Replace with actual name - - Another Name Surname # Add more authors as needed - -# The patterns this decision applies to. Each entry is a glob pattern that matches files affected by this decision. -# Example: -# - "**/*.cs" # Applies to all C# files -# - "src/**/*.razor" # Applies to all Blazor components in src folder -# - "tests/**/*.sql" # Applies to all SQL files in tests folder -applyTo: - - "**/*" # Replace with specific glob patterns - -# The date this ADR was initially created in YYYY-MM-DD format. -created: YYYY-MM-DD - -# The most recent date this ADR was updated in YYYY-MM-DD format. -# IMPORTANT: Update this field whenever the decision is modified. -lastModified: YYYY-MM-DD - -# The current state of this ADR. If superseded, include references to the superseding ADR. -# Valid values: proposed, accepted, deprecated, superseded -state: proposed - -# A compact AI LLM compatible definition of this decision. -# This should be a precise, structured description that AI systems can easily parse and understand. -# Include the core decision, key rationale, and primary impact in 1-2 concise sentences. -instructions: | - Compact definition of the decision made and its core purpose. - Key rationale and primary impact on the project or development process. ---- - - -# Title - - - -## Context - - - -## Decision - - - -## Consequences - - - -## Alternatives Considered - - - -## Related Decisions (Optional) - - diff --git a/templates/readme-solution.md b/templates/readme-solution.md index 933832c8..b5955a6a 100644 --- a/templates/readme-solution.md +++ b/templates/readme-solution.md @@ -189,7 +189,6 @@ tests/ # Test projects ├── Unit/ # Unit tests └── Integration/ # Integration tests -decisions/ # Architecture Decision Records (ADRs) templates/ # Documentation and file templates ``` @@ -197,7 +196,6 @@ templates/ # Documentation and file templates @@ -209,8 +207,6 @@ This solution follows modern .NET architectural patterns and best practices: - **Repository Pattern**: Abstraction over data access logic - **SOLID Principles**: Object-oriented design with SOLID principles -For detailed architectural decisions, see the [Architecture Decision Records](decisions/). - ## Contributing -- **[Architecture Decision Records](decisions/)** - Detailed architectural decisions and rationale - **[Contributing Guidelines](CONTRIBUTING.md)** - How to contribute to this project - **[Code of Conduct](CODE_OF_CONDUCT.md)** - Community standards and expectations - **[License](LICENSE)** - Project licensing information