|
| 1 | +# LocalStack .NET Client - AI Agent Instructions |
| 2 | + |
| 3 | +Hey Copilot, welcome to the team! Before we start writing some brilliant code, let's get aligned on how we'll work together. Think of this as our "prime directive." |
| 4 | + |
| 5 | +## **1. Our Partnership Philosophy** |
| 6 | + |
| 7 | +* **Be my brainstorming partner:** Be talkative, conversational, and don't be afraid to use some quick and clever humor. We're in this together, so let's make it fun. |
| 8 | +* **Innovate, but be practical:** I love creative, outside-the-box thinking. But at the end of the day, our code needs to be robust, maintainable, and solve the problem at hand. Practicality is king. |
| 9 | +* **Challenge me:** I'm not looking for a yes-person. If you see a flaw in my logic, a potential edge case I've missed, or a more elegant solution, please speak up! I expect you to provide constructive criticism and explain the "why" behind your suggestions. A healthy debate leads to better code. |
| 10 | + |
| 11 | +## **2. The "Plan-Then-Execute" Rule** |
| 12 | + |
| 13 | +This is the most important rule: **Do not write a full implementation without my approval.** |
| 14 | + |
| 15 | +* **Step 1: Propose a plan.** Before generating any significant block of code, first outline your approach. This could be pseudo-code, a list of steps, or a high-level description of the classes and methods you'll create. |
| 16 | +* **Step 2: Wait for the green light.** I will review your plan and give you the go-ahead. This ensures we're on the same page before you invest time generating the full implementation. |
| 17 | + |
| 18 | +## **3. Technical Ground Rules** |
| 19 | + |
| 20 | +* **Centralized NuGet Management:** This solution uses centralized package management. When a new package is needed, you should: |
| 21 | + 1. Add a PackageReference to the Directory.Packages.props file, specifying both the Include and Version attributes. |
| 22 | + 2. Add a corresponding PackageReference with only the Include attribute to the relevant .csproj file. |
| 23 | +* **Testing Our Code:** Our testing stack is **xUnit**, **Moq**, and **Testcontainers**. Please generate tests following the patterns and best practices for these frameworks. Use Fact and Theory attributes from xUnit, set up fakes with Mock<T>, and help configure services for integration tests using Testcontainers. |
| 24 | +* **Roslyn Analyzers Are King (Usually):** We adhere to our configured analyzer rules. However, if we're quickly testing an idea or prototyping, you can safely use #pragma warning disable to ignore a specific rule. Just be sure to add a comment like // TODO: Re-address this analyzer warning so we can clean it up later. |
| 25 | +* **Modern C#:** Let's default to modern C# conventions: file-scoped namespaces, record types for DTOs, top-level statements, expression-bodied members, and async/await best practices. |
| 26 | + |
| 27 | +## Project Overview |
| 28 | + |
| 29 | +**LocalStack .NET Client** is a sophisticated .NET library that wraps the AWS SDK to work seamlessly with LocalStack (local AWS emulation). The project is undergoing a major architectural evolution with **Native AOT support** via source generators and **AWS SDK v4 migration**. |
| 30 | + |
| 31 | +> 📖 **Deep Dive**: For comprehensive project details, see [`artifacts/Project_Onboarding.md`](../artifacts/Project_Onboarding.md) - a detailed guide covering architecture, testing strategy, CI/CD pipeline, and contribution guidelines. |
| 32 | +
|
| 33 | +### What I Learned from the Onboarding Document |
| 34 | + |
| 35 | +**Key Insights for AI Agents:** |
| 36 | + |
| 37 | +1. **Testing is Sophisticated**: The project uses a 4-tier testing pyramid (Unit → Integration → Functional → Sandbox). Functional tests use **TestContainers** with dynamic port mapping across multiple LocalStack versions (v3.7.1, v4.3.0). |
| 38 | + |
| 39 | +2. **Version-Aware Development**: The project carefully manages AWS SDK compatibility. Currently migrated to **AWS SDK v4** with specific considerations: |
| 40 | + - .NET Framework requirement bumped from 4.6.2 → 4.7.2 |
| 41 | + - Extensions package uses new `ClientFactory<T>` pattern vs old non-generic `ClientFactory` |
| 42 | + - Some functional tests may fail due to behavioral changes in SNS/DynamoDB operations |
| 43 | + |
| 44 | +3. **Enterprise Build System**: Uses **Cake Frosting** (not traditional Cake scripts) with cross-platform CI/CD across Ubuntu/Windows/macOS. The build system handles complex scenarios like .NET Framework testing on Mono. |
| 45 | + |
| 46 | +4. **Service Coverage**: Supports **50+ AWS services** through intelligent endpoint resolution. Services are mapped through `AwsServiceEndpointMetadata.All` with both legacy per-service ports and modern unified edge port (4566). |
| 47 | + |
| 48 | +5. **Reflection Strategy**: The codebase heavily uses reflection to access AWS SDK internals (private `serviceMetadata` fields, dynamic `ClientConfig` creation). This is being modernized with UnsafeAccessor for AOT. |
| 49 | + |
| 50 | +### Core Architecture |
| 51 | + |
| 52 | +The library follows a **Session-based architecture** with three main components: |
| 53 | + |
| 54 | +1. **Session (`ISession`)**: Core client factory that configures AWS clients for LocalStack endpoints |
| 55 | +2. **Config (`IConfig`)**: Service endpoint resolution and LocalStack connection management |
| 56 | +3. **SessionReflection (`ISessionReflection`)**: Abstraction layer for AWS SDK private member access |
| 57 | + |
| 58 | +### Key Innovation: Dual Reflection Strategy |
| 59 | + |
| 60 | +The project uses a sophisticated **conditional compilation pattern** for .NET compatibility: |
| 61 | + |
| 62 | +- **.NET 8+**: Uses **UnsafeAccessor** pattern via Roslyn source generators (`LocalStack.Client.Generators`) for Native AOT |
| 63 | +- **Legacy (.NET Standard 2.0, .NET Framework)**: Falls back to traditional reflection APIs |
| 64 | + |
| 65 | +## Development Workflows |
| 66 | + |
| 67 | +### Build System |
| 68 | +- **Build Scripts**: Use `build.ps1` (Windows) or `build.sh` (Linux) - these delegate to Cake build tasks |
| 69 | +- **Build Framework**: Uses **Cake Frosting** in `build/LocalStack.Build/` - examine `CakeTasks/` folder for available targets |
| 70 | +- **Common Commands**: |
| 71 | + - `build.ps1` - Full build and test |
| 72 | + - `build.ps1 --target=tests` - Run tests only |
| 73 | + |
| 74 | +### Project Structure |
| 75 | + |
| 76 | +``` |
| 77 | +src/ |
| 78 | +├── LocalStack.Client/ # Core library (multi-target: netstandard2.0, net472, net8.0, net9.0) |
| 79 | +├── LocalStack.Client.Extensions/ # DI integration (AddLocalStack() extension) |
| 80 | +└── LocalStack.Client.Generators/ # Source generator for AOT (netstandard2.0, Roslyn) |
| 81 | +
|
| 82 | +tests/ |
| 83 | +├── LocalStack.Client.Tests/ # Unit tests (mocked) |
| 84 | +├── LocalStack.Client.Integration.Tests/ # Real LocalStack integration |
| 85 | +├── LocalStack.Client.AotCompatibility.Tests/ # Native AOT testing |
| 86 | +└── sandboxes/ # Example console apps |
| 87 | +``` |
| 88 | + |
| 89 | +## Critical Patterns & Conventions |
| 90 | + |
| 91 | +### 1. Multi-Framework Configuration Pattern |
| 92 | + |
| 93 | +For .NET 8+ conditional features, use this pattern consistently: |
| 94 | + |
| 95 | +```csharp |
| 96 | +#if NET8_0_OR_GREATER |
| 97 | + // Modern implementation (UnsafeAccessor) |
| 98 | + var accessor = AwsAccessorRegistry.GetByInterface<TClient>(); |
| 99 | + return accessor.CreateClient(credentials, clientConfig); |
| 100 | +#else |
| 101 | + // Legacy implementation (reflection) |
| 102 | + return CreateClientByInterface(typeof(TClient), useServiceUrl); |
| 103 | +#endif |
| 104 | +``` |
| 105 | + |
| 106 | +### 2. Session Client Creation Pattern |
| 107 | + |
| 108 | +The Session class provides multiple client creation methods - understand the distinction: |
| 109 | + |
| 110 | +- `CreateClientByInterface<IAmazonS3>()` - Interface-based (preferred) |
| 111 | +- `CreateClientByImplementation<AmazonS3Client>()` - Concrete type |
| 112 | +- `useServiceUrl` parameter controls endpoint vs region configuration |
| 113 | + |
| 114 | +### 3. Source Generator Integration |
| 115 | + |
| 116 | +When working on AOT features: |
| 117 | +- Generator runs only for .NET 8+ projects (`Net8OrAbove` condition) |
| 118 | +- Discovers AWS clients from referenced assemblies at compile-time |
| 119 | +- Generates `IAwsAccessor` implementations in `LocalStack.Client.Generated` namespace |
| 120 | +- Auto-registers via `ModuleInitializer` in `AwsAccessorRegistry` |
| 121 | + |
| 122 | +### 4. Configuration Hierarchy |
| 123 | + |
| 124 | +LocalStack configuration follows this pattern: |
| 125 | +```json |
| 126 | +{ |
| 127 | + "LocalStack": { |
| 128 | + "UseLocalStack": true, |
| 129 | + "Session": { |
| 130 | + "RegionName": "eu-central-1", |
| 131 | + "AwsAccessKeyId": "accessKey", |
| 132 | + "AwsAccessKey": "secretKey" |
| 133 | + }, |
| 134 | + "Config": { |
| 135 | + "LocalStackHost": "localhost.localstack.cloud", |
| 136 | + "EdgePort": 4566, |
| 137 | + "UseSsl": false |
| 138 | + } |
| 139 | + } |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +## Testing Patterns |
| 144 | + |
| 145 | +### Multi-Layered Testing Strategy |
| 146 | +Based on the comprehensive testing guide in the onboarding document: |
| 147 | + |
| 148 | +- **Unit Tests**: `MockSession.Create()` → Setup mocks → Verify calls pattern |
| 149 | +- **Integration Tests**: Client creation across **50+ AWS services** without external dependencies |
| 150 | +- **Functional Tests**: **TestContainers** with multiple LocalStack versions (v3.7.1, v4.3.0) |
| 151 | +- **Sandbox Apps**: Real-world examples in `tests/sandboxes/` demonstrating usage patterns |
| 152 | + |
| 153 | +### TestContainers Pattern |
| 154 | +```csharp |
| 155 | +// Dynamic port mapping prevents conflicts |
| 156 | +ushort mappedPublicPort = localStackFixture.LocalStackContainer.GetMappedPublicPort(4566); |
| 157 | +``` |
| 158 | + |
| 159 | +### Known Testing Challenges |
| 160 | +- **SNS Issues**: LocalStack v3.7.2/v3.8.0 have known SNS bugs (use v3.7.1 or v3.9.0+) |
| 161 | +- **SQS Compatibility**: AWSSDK.SQS 3.7.300+ has issues with LocalStack v1/v2 |
| 162 | +- **AWS SDK v4 Migration**: Some functional tests may fail due to behavioral changes |
| 163 | + |
| 164 | +## Package Management |
| 165 | + |
| 166 | +**Centralized Package Management** - Always follow this two-step process: |
| 167 | + |
| 168 | +1. Add to `Directory.Packages.props`: |
| 169 | +```xml |
| 170 | +<PackageVersion Include="MyPackage" Version="1.0.0" /> |
| 171 | +``` |
| 172 | + |
| 173 | +2. Reference in project: |
| 174 | +```xml |
| 175 | +<PackageReference Include="MyPackage" /> |
| 176 | +``` |
| 177 | + |
| 178 | +### Code Quality Standards |
| 179 | +The onboarding document emphasizes **enterprise-level quality**: |
| 180 | +- **10+ Analyzers Active**: Roslynator, SonarAnalyzer, Meziantou.Analyzer, SecurityCodeScan |
| 181 | +- **Warnings as Errors**: `TreatWarningsAsErrors=true` across solution |
| 182 | +- **Nullable Reference Types**: Enabled solution-wide for safety |
| 183 | +- **Modern C# 13**: Latest language features with strict mode enabled |
| 184 | + |
| 185 | +## Working with AWS SDK Integration |
| 186 | + |
| 187 | +### Service Discovery Pattern |
| 188 | +The library auto-discovers AWS services using naming conventions: |
| 189 | +- `IAmazonS3` → `AmazonS3Client` → `AmazonS3Config` |
| 190 | +- Service metadata extracted from private static `serviceMetadata` fields |
| 191 | +- Endpoint mapping in `AwsServiceEndpointMetadata.All` |
| 192 | + |
| 193 | +### Reflection Abstraction |
| 194 | +When adding AWS SDK integration features: |
| 195 | +- Always implement in both `SessionReflectionLegacy` and `SessionReflectionModern` |
| 196 | +- Modern version uses generated `IAwsAccessor` implementations |
| 197 | +- Legacy version uses traditional reflection with error handling |
| 198 | + |
| 199 | +## Key Files to Understand |
| 200 | + |
| 201 | +- `src/LocalStack.Client/Session.cs` - Core client factory logic |
| 202 | +- `src/LocalStack.Client/Utils/SessionReflection.cs` - Facade that chooses implementation |
| 203 | +- `src/LocalStack.Client.Generators/AwsAccessorGenerator.cs` - Source generator main logic |
| 204 | +- `tests/sandboxes/` - Working examples of all usage patterns |
| 205 | +- `Directory.Build.props` - Shared MSBuild configuration with analyzer rules |
| 206 | + |
| 207 | +## Plan-Then-Execute Workflow |
| 208 | + |
| 209 | +1. **Propose architectural approach** - especially for cross-framework features |
| 210 | +2. **Consider AOT implications** - will this work with UnsafeAccessor pattern? |
| 211 | +3. **Plan test strategy** - unit, integration, and AOT compatibility |
| 212 | +4. **Wait for approval** before implementing significant changes |
| 213 | + |
| 214 | +The codebase prioritizes **backwards compatibility** and **AOT-first design** - keep these principles central to any contributions. |
0 commit comments