@ryuenn3123/agentic-senior-core 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.agent-context/blueprints/api-nextjs.md +184 -0
  2. package/.agent-context/blueprints/aspnet-api.md +247 -0
  3. package/.agent-context/blueprints/ci-github-actions.md +226 -0
  4. package/.agent-context/blueprints/ci-gitlab.md +200 -0
  5. package/.agent-context/blueprints/fastapi-service.md +210 -0
  6. package/.agent-context/blueprints/go-service.md +217 -0
  7. package/.agent-context/blueprints/graphql-grpc-api.md +51 -0
  8. package/.agent-context/blueprints/infrastructure-as-code.md +62 -0
  9. package/.agent-context/blueprints/kubernetes-manifests.md +76 -0
  10. package/.agent-context/blueprints/laravel-api.md +223 -0
  11. package/.agent-context/blueprints/nestjs-logic.md +247 -0
  12. package/.agent-context/blueprints/observability.md +227 -0
  13. package/.agent-context/blueprints/spring-boot-api.md +218 -0
  14. package/.agent-context/policies/llm-judge-threshold.json +20 -0
  15. package/.agent-context/profiles/platform.md +13 -0
  16. package/.agent-context/profiles/regulated.md +13 -0
  17. package/.agent-context/profiles/startup.md +13 -0
  18. package/.agent-context/prompts/init-project.md +86 -0
  19. package/.agent-context/prompts/refactor.md +45 -0
  20. package/.agent-context/prompts/review-code.md +47 -0
  21. package/.agent-context/review-checklists/architecture-review.md +70 -0
  22. package/.agent-context/review-checklists/frontend-usability.md +33 -0
  23. package/.agent-context/review-checklists/performance-audit.md +65 -0
  24. package/.agent-context/review-checklists/pr-checklist.md +97 -0
  25. package/.agent-context/review-checklists/release-operations.md +29 -0
  26. package/.agent-context/review-checklists/security-audit.md +113 -0
  27. package/.agent-context/rules/api-docs.md +186 -0
  28. package/.agent-context/rules/architecture.md +198 -0
  29. package/.agent-context/rules/database-design.md +202 -0
  30. package/.agent-context/rules/efficiency-vs-hype.md +143 -0
  31. package/.agent-context/rules/error-handling.md +234 -0
  32. package/.agent-context/rules/event-driven.md +226 -0
  33. package/.agent-context/rules/frontend-architecture.md +66 -0
  34. package/.agent-context/rules/git-workflow.md +200 -0
  35. package/.agent-context/rules/microservices.md +174 -0
  36. package/.agent-context/rules/naming-conv.md +141 -0
  37. package/.agent-context/rules/performance.md +168 -0
  38. package/.agent-context/rules/realtime.md +47 -0
  39. package/.agent-context/rules/security.md +195 -0
  40. package/.agent-context/rules/testing.md +178 -0
  41. package/.agent-context/stacks/csharp.md +149 -0
  42. package/.agent-context/stacks/go.md +181 -0
  43. package/.agent-context/stacks/java.md +135 -0
  44. package/.agent-context/stacks/php.md +178 -0
  45. package/.agent-context/stacks/python.md +153 -0
  46. package/.agent-context/stacks/ruby.md +80 -0
  47. package/.agent-context/stacks/rust.md +86 -0
  48. package/.agent-context/stacks/typescript.md +317 -0
  49. package/.agent-context/state/architecture-map.md +25 -0
  50. package/.agent-context/state/dependency-map.md +32 -0
  51. package/.agent-override.md +36 -0
  52. package/.agents/workflows/init-project.md +29 -0
  53. package/.agents/workflows/refactor.md +29 -0
  54. package/.agents/workflows/review-code.md +29 -0
  55. package/.cursorrules +140 -0
  56. package/.gemini/instructions.md +97 -0
  57. package/.github/ISSUE_TEMPLATE/v1.7-frontend-work-item.yml +54 -0
  58. package/.github/copilot-instructions.md +104 -0
  59. package/.github/workflows/benchmark-detection.yml +38 -0
  60. package/.github/workflows/frontend-usability-gate.yml +36 -0
  61. package/.github/workflows/release-gate.yml +32 -0
  62. package/.github/workflows/sbom-compliance.yml +32 -0
  63. package/.windsurfrules +106 -0
  64. package/AGENTS.md +131 -0
  65. package/CONTRIBUTING.md +136 -0
  66. package/LICENSE +21 -0
  67. package/README.md +239 -0
  68. package/bin/agentic-senior-core.js +1147 -0
  69. package/mcp.json +29 -0
  70. package/package.json +50 -0
  71. package/scripts/detection-benchmark.mjs +138 -0
  72. package/scripts/frontend-usability-audit.mjs +87 -0
  73. package/scripts/generate-sbom.mjs +61 -0
  74. package/scripts/init-project.ps1 +105 -0
  75. package/scripts/init-project.sh +131 -0
  76. package/scripts/llm-judge.mjs +664 -0
  77. package/scripts/release-gate.mjs +116 -0
  78. package/scripts/validate.mjs +554 -0
@@ -0,0 +1,47 @@
1
+ # Real-time & WebSockets Architecture
2
+
3
+ > WebSockets are stateful tcp connections in a stateless HTTP world. Treat them with extreme caution.
4
+
5
+ ## 1. Connection Management & Scaling
6
+ WebSockets hold a persistent connection, consuming file descriptors and memory on the server.
7
+ - **Rule:** NEVER scale WebSockets using a standard load balancer without sticky sessions (unless utilizing an external Pub/Sub service).
8
+ - **Architecture:** Use a dedicated external Pub/Sub layer to broadcast messages across multiple WebSocket server instances.
9
+ - **Standard:** Redis Pub/Sub (Socket.io-redis, any standard Redis adapter).
10
+ - **Enterprise:** NATS, Apache Kafka, or managed services like AWS API Gateway WebSockets / Pusher / Socket.io / Soketi.
11
+ - **Goal:** Any user can connect to Server A, and receive a message published by a background job running on Server B.
12
+
13
+ ## 2. Authentication Context
14
+ WebSockets cannot rely on traditional HTTP Authorization headers during the handshake in browser environments (as the WebSocket API does not allow setting custom headers).
15
+ - **Rule:** Authenticate connections explicitly.
16
+ - **Method A (Cookies):** If the application uses HTTPOnly cookies, authentication happens naturally during the initial HTTP upgrade request.
17
+ - **Method B (Tickets/Tokens):** Pass the JWT or an ephemeral ticket in the connection URL query string (`?token=xyz`) or immediately after connecting via a dedicated `auth` JSON payload.
18
+ - **BANNED:** Never trust a client simply because they know the WebSocket URL.
19
+
20
+ ## 3. The "No Business Logic in Sockets" Rule
21
+ A WebSocket controller should be treated exactly like an HTTP controller.
22
+ - **Rule:** The WebSocket handler's **only** responsibility is parsing the incoming message, validating the payload schema, and routing it to a Service/Application layer orchestrator.
23
+ - **BANNED:** Directly writing to databases, executing complex business logic, or calling external APIs directly inside the WebSocket event callback.
24
+
25
+ ## 4. Heartbeats & Dead Connections
26
+ TCP connections drop silently (e.g., when a user drives through a tunnel).
27
+ - **Rule:** Implement Ping/Pong heartbeats. The server MUST periodically ping the client. If the client fails to respond within the expected window (e.g., 30s), the server MUST forcefully sever the connection to free resources (`ws.terminate()`, not `ws.close()`).
28
+
29
+ ## 5. Event Design & Typing
30
+ Treat WebSocket events like a strongly typed REST API.
31
+ - **Rule:** Every WebSocket message MUST have a mandatory `type` or `event` field, and a strongly typed `payload` field defined by a schema (e.g., Zod, JSON Schema).
32
+ - **BANNED:** Emitting arbitrary strings or untyped JSON objects like `{ user_id: 1, message: "hi" }`.
33
+ - **REQUIRED:**
34
+ ```json
35
+ {
36
+ "event": "message.created",
37
+ "payload": {
38
+ "id": "msg_123",
39
+ "text": "Hello World",
40
+ "timestamp": "2026-03-01T12:00:00Z"
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## 6. Rate Limiting & Abuse Prevention
46
+ WebSockets are heavily susceptible to DoS attacks because an open connection bypasses traditional WAF rate limiters.
47
+ - **Rule:** You MUST implement message rate limiting at the application logic layer (e.g., maximum 5 messages per second per connection/user). Violators should be instantly disconnected and IP-banned temporarily.
@@ -0,0 +1,195 @@
1
+ # Security — Trust Nothing, Validate Everything
2
+
3
+ > Every user is a potential attacker. Every input is a potential exploit.
4
+ > You are not paranoid — you are professional.
5
+
6
+ ## The Zero Trust Input Rule
7
+
8
+ **ALL data crossing a system boundary is untrusted until validated.**
9
+
10
+ System boundaries include:
11
+ - HTTP request bodies, query params, headers, cookies
12
+ - URL path parameters
13
+ - File uploads
14
+ - WebSocket messages
15
+ - Queue/event payloads
16
+ - Environment variables (at startup)
17
+ - Database query results (yes, even these — data could be corrupted)
18
+ - Third-party API responses
19
+
20
+ ### Validation Protocol
21
+ ```
22
+ External Input → Schema Validation (Zod/Pydantic/Bean Validation) → Typed Internal Object
23
+
24
+ NEVER:
25
+ External Input → Direct use in business logic
26
+ External Input → Direct use in database query
27
+ External Input → Direct interpolation into strings
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Injection Prevention
33
+
34
+ ### SQL Injection — Parameterized Queries Only
35
+ ```
36
+ ❌ DEATH PENALTY:
37
+ const query = `SELECT * FROM users WHERE id = ${userId}`;
38
+ const query = "SELECT * FROM users WHERE name = '" + name + "'";
39
+
40
+ ✅ ALWAYS:
41
+ const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
42
+ const user = await prisma.user.findUnique({ where: { id: userId } });
43
+ ```
44
+
45
+ **Rule:** NEVER concatenate or interpolate user input into SQL strings. Use parameterized queries or ORMs. No exceptions. Not even "just for testing."
46
+
47
+ ### Command Injection
48
+ ```
49
+ ❌ DEATH PENALTY:
50
+ exec(`convert ${filename} output.png`);
51
+
52
+ ✅ ALWAYS:
53
+ execFile('convert', [filename, 'output.png']);
54
+ ```
55
+
56
+ **Rule:** Never pass user input to shell commands via string interpolation. Use argument arrays.
57
+
58
+ ### XSS Prevention
59
+ ```
60
+ ❌ BANNED:
61
+ element.innerHTML = userInput;
62
+ dangerouslySetInnerHTML={{ __html: userInput }};
63
+
64
+ ✅ REQUIRED:
65
+ element.textContent = userInput;
66
+ // Or sanitize with DOMPurify if HTML is absolutely needed
67
+ ```
68
+
69
+ **Rule:** Default to text content. Only use HTML injection with explicit sanitization AND a code comment explaining WHY.
70
+
71
+ ---
72
+
73
+ ## Secret Management
74
+
75
+ ### Rule: ZERO Secrets in Code
76
+
77
+ ```
78
+ ❌ INSTANT REJECTION:
79
+ const API_KEY = "sk-abc123def456";
80
+ const DB_PASSWORD = "supersecret";
81
+ const JWT_SECRET = "my-jwt-secret";
82
+ // Even in .env.example with real values
83
+
84
+ ✅ REQUIRED:
85
+ const API_KEY = process.env.API_KEY; // Read from environment
86
+ const DB_URL = process.env.DATABASE_URL; // Injected at runtime
87
+ ```
88
+
89
+ ### .env Files
90
+ - `.env` → NEVER committed (must be in `.gitignore`)
91
+ - `.env.example` → Committed with placeholder values ONLY (`API_KEY=your-api-key-here`)
92
+ - `.env.local` → NEVER committed
93
+ - `.env.test` → May be committed with TEST-ONLY non-secret values
94
+
95
+ ### Secret Rotation
96
+ If a secret is accidentally committed:
97
+ 1. Rotate the secret IMMEDIATELY (not after the PR is merged — NOW)
98
+ 2. Remove from git history (`git filter-branch` or BFG)
99
+ 3. Add to `.gitignore`
100
+ 4. Document the incident
101
+
102
+ ---
103
+
104
+ ## Authentication & Authorization
105
+
106
+ ### Authentication Rules
107
+ 1. Never implement custom auth crypto — use established libraries (argon2, bcrypt, Passport, NextAuth)
108
+ 2. Hash passwords with **argon2id** (OWASP primary recommendation) — bcrypt only for legacy systems
109
+ - Argon2id: minimum 19 MiB memory, 2 iterations, 1 parallelism
110
+ - bcrypt: minimum cost 12 (legacy systems only — limited to 72 bytes, no memory-hardness)
111
+ - NEVER: MD5, SHA1, plain SHA256, or PBKDF2 without FIPS requirement
112
+ 3. Use constant-time comparison for tokens and hashes
113
+ 4. Implement rate limiting on auth endpoints (max 5 attempts per minute per IP)
114
+ 5. Session tokens must be cryptographically random (≥ 256 bits)
115
+
116
+ ### Authorization Rules
117
+ 1. **Default deny** — if no rule grants access, deny
118
+ 2. **Server-side only** — NEVER trust client-side role checks for security
119
+ 3. Check authorization at the service layer, not just the controller
120
+ 4. Log all authorization failures with context (userId, resource, action)
121
+
122
+ ```
123
+ ❌ BANNED: Client-side only authorization
124
+ if (user.role === 'admin') { showDeleteButton(); }
125
+ // Attacker just changes user.role in devtools
126
+
127
+ ✅ REQUIRED: Server-side enforcement
128
+ // Controller checks auth, service enforces business rules
129
+ async deleteUser(requesterId: string, targetUserId: string) {
130
+ const requester = await this.userRepo.findById(requesterId);
131
+ if (!requester || requester.role !== Role.ADMIN) {
132
+ throw new ForbiddenError('Insufficient permissions');
133
+ }
134
+ // ... proceed with deletion
135
+ }
136
+ ```
137
+
138
+ ---
139
+
140
+ ## HTTP Security Headers
141
+
142
+ Every web application MUST include:
143
+ ```
144
+ Strict-Transport-Security: max-age=31536000; includeSubDomains
145
+ Content-Security-Policy: default-src 'self'; script-src 'self'
146
+ X-Content-Type-Options: nosniff
147
+ X-Frame-Options: DENY
148
+ Referrer-Policy: strict-origin-when-cross-origin
149
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
150
+ ```
151
+
152
+ ### CORS
153
+ - NEVER use `Access-Control-Allow-Origin: *` in production
154
+ - Whitelist specific origins
155
+ - Be explicit about allowed methods and headers
156
+
157
+ ---
158
+
159
+ ## File Upload Security
160
+
161
+ 1. Validate MIME type server-side (not just file extension)
162
+ 2. Set maximum file size limits
163
+ 3. Generate random filenames — never use user-provided filenames
164
+ 4. Store uploads outside the web root
165
+ 5. Scan for malware if accepting documents
166
+
167
+ ---
168
+
169
+ ## Supply Chain Security (OWASP 2025 A03)
170
+
171
+ 1. **Pin all dependency versions** — use lockfiles, never `*` ranges in production
172
+ 2. **Audit dependencies regularly** — `npm audit`, `pip audit`, `composer audit`
173
+ 3. **Verify package integrity** — check checksums, use signed packages where available
174
+ 4. **Minimize dependency trees** — fewer transitive dependencies = smaller attack surface
175
+ 5. **Monitor for CVEs** — automate vulnerability scanning in CI (Dependabot, Snyk, Trivy)
176
+ 6. **Review new dependencies** — check maintainer history, download trends, and bus factor before adding
177
+
178
+ ---
179
+
180
+ ## The Security Checklist (Quick Reference)
181
+
182
+ Before any code is "done", verify:
183
+
184
+ - [ ] All inputs validated at boundaries with schemas
185
+ - [ ] No string concatenation in queries/commands
186
+ - [ ] No secrets in source code
187
+ - [ ] Authentication uses established libraries
188
+ - [ ] Password hashing uses argon2id (or bcrypt for legacy)
189
+ - [ ] Authorization enforced server-side
190
+ - [ ] Security headers configured
191
+ - [ ] CORS properly restricted
192
+ - [ ] Rate limiting on sensitive endpoints
193
+ - [ ] Error responses don't leak internal details
194
+ - [ ] Logging includes security events (login failures, permission denials)
195
+ - [ ] Dependencies audited for known vulnerabilities
@@ -0,0 +1,178 @@
1
+ # Testing — Prove It Works, Don't Pray
2
+
3
+ > "It works on my machine" is not a test strategy.
4
+ > Untested code is broken code that hasn't been caught yet.
5
+
6
+ ## The Test Pyramid (Enforced)
7
+
8
+ ```
9
+ ╱ E2E ╲ Few — Slow — Expensive — Fragile
10
+ ╱──────────╲ Test critical user journeys only
11
+ ╱ Integration ╲ Medium — Test module boundaries
12
+ ╱────────────────╲ Database, API contracts, service interactions
13
+ ╱ Unit Tests ╲ Many — Fast — Cheap — Stable
14
+ ╱──────────────────────╲ Test business logic in isolation
15
+ ```
16
+
17
+ ### Ratios
18
+ - **Unit tests:** 70% — fast, isolated, test business rules
19
+ - **Integration tests:** 20% — test boundaries (DB, APIs, modules)
20
+ - **E2E tests:** 10% — test critical user flows only
21
+
22
+ ---
23
+
24
+ ## What to Test (And What Not To)
25
+
26
+ ### ✅ ALWAYS Test
27
+ - Business logic and calculations
28
+ - Input validation rules
29
+ - Edge cases (empty arrays, null values, boundary numbers)
30
+ - Error handling paths (what happens when things fail)
31
+ - State transitions and workflows
32
+ - Authorization rules
33
+
34
+ ### ❌ NEVER Test
35
+ - Framework internals (don't test that Express routes work)
36
+ - Simple getters/setters with no logic
37
+ - Third-party library behavior
38
+ - Private implementation details (test behavior, not structure)
39
+ - Database migrations (verify schema, don't test the migration tool)
40
+
41
+ ---
42
+
43
+ ## Test Naming Convention
44
+
45
+ ### Pattern: `should [expected behavior] when [condition]`
46
+
47
+ ```
48
+ ❌ BANNED:
49
+ test('test1')
50
+ test('it works')
51
+ test('calculateDiscount')
52
+
53
+ ✅ REQUIRED:
54
+ test('should apply 20% discount when order total exceeds $100')
55
+ test('should throw ValidationError when email format is invalid')
56
+ test('should return empty array when user has no orders')
57
+ test('should deny access when user lacks admin role')
58
+ ```
59
+
60
+ **Rule:** A reader must understand the expected behavior WITHOUT reading the test body.
61
+
62
+ ---
63
+
64
+ ## Test Structure: AAA Pattern
65
+
66
+ Every test follows **Arrange → Act → Assert**:
67
+
68
+ ```typescript
69
+ test('should calculate shipping as free when order exceeds $50', () => {
70
+ // Arrange — Set up the scenario
71
+ const order = createOrder({ items: [{ price: 60, quantity: 1 }] });
72
+
73
+ // Act — Execute the behavior
74
+ const shippingCost = calculateShipping(order);
75
+
76
+ // Assert — Verify the outcome
77
+ expect(shippingCost).toBe(0);
78
+ });
79
+ ```
80
+
81
+ ### Rules
82
+ - **ONE assert concept per test** (multiple `expect` calls are fine if they test the same concept)
83
+ - **No logic in tests** (no if/else, no loops, no try/catch)
84
+ - **Tests must be independent** — no shared mutable state, no execution order dependency
85
+ - **Tests must be deterministic** — same input = same result, every time
86
+
87
+ ---
88
+
89
+ ## Mocking Rules
90
+
91
+ ### Mock at Boundaries, Not Everywhere
92
+
93
+ ```
94
+ ❌ OVER-MOCKING (testing implementation, not behavior):
95
+ test('should call repository.save exactly once', () => {
96
+ await service.createUser(userData);
97
+ expect(repository.save).toHaveBeenCalledTimes(1);
98
+ // If you refactor to call save differently, the test breaks
99
+ // even though the behavior hasn't changed
100
+ });
101
+
102
+ ✅ CORRECT (testing behavior):
103
+ test('should persist user and return created user', () => {
104
+ const result = await service.createUser(userData);
105
+ expect(result.id).toBeDefined();
106
+ expect(result.email).toBe(userData.email);
107
+ // You can verify the user exists in the test DB if integration test
108
+ });
109
+ ```
110
+
111
+ ### When to Mock
112
+ - External APIs (payment gateways, email services)
113
+ - Time-dependent operations (use fake timers)
114
+ - Non-deterministic operations (random, UUID)
115
+
116
+ ### When NOT to Mock
117
+ - Your own code in the same module ← test the real integration
118
+ - Simple utility functions ← use the real thing
119
+ - Database in integration tests ← use a test database
120
+
121
+ ---
122
+
123
+ ## Test Data Standards
124
+
125
+ ### Use Factories, Not Copy-Pasted Objects
126
+
127
+ ```
128
+ ❌ BANNED:
129
+ test('should calculate total', () => {
130
+ const order = {
131
+ id: '123',
132
+ userId: '456',
133
+ items: [{ productId: '789', price: 29.99, quantity: 2, name: 'Widget' }],
134
+ status: 'pending',
135
+ createdAt: new Date(),
136
+ updatedAt: new Date(),
137
+ // ... 15 more fields copied from another test
138
+ };
139
+ });
140
+
141
+ ✅ REQUIRED:
142
+ test('should calculate total', () => {
143
+ const order = createTestOrder({
144
+ items: [createTestItem({ price: 29.99, quantity: 2 })],
145
+ });
146
+ // Factory fills in all other fields with sensible defaults
147
+ });
148
+ ```
149
+
150
+ ### Rules
151
+ - Create factory functions for each domain entity
152
+ - Factories provide sensible defaults — tests override only relevant fields
153
+ - Never use production data in tests
154
+ - Use descriptive, obviously-fake data (email: `test-user@example.com`, not `john@gmail.com`)
155
+
156
+ ---
157
+
158
+ ## Coverage Expectations
159
+
160
+ | Layer | Min Coverage | What to Focus On |
161
+ |-------|-------------|------------------|
162
+ | Domain / Business Logic | 90%+ | All branching, edge cases, error paths |
163
+ | Application / Service | 80%+ | Orchestration flows, error handling |
164
+ | Transport / Controller | 60%+ | Input validation, error responses |
165
+ | Utilities | 90%+ | All functions and edge cases |
166
+
167
+ **Rule:** Coverage is a floor, not a goal. 100% coverage with bad tests is worse than 80% coverage with good tests. Focus on testing **behavior and edge cases**, not hitting a number.
168
+
169
+ ---
170
+
171
+ ## When to Skip Tests (Rare)
172
+
173
+ You may skip tests ONLY for:
174
+ - Prototype/spike code (must be labeled `// SPIKE: will be replaced`)
175
+ - Pure UI layout (visual testing is better here — use Storybook/Chromatic)
176
+ - Generated code (test the generator, not the output)
177
+
178
+ Everything else gets tested. No excuses.
@@ -0,0 +1,149 @@
1
+ # C# / .NET Stack Profile — Modern C#, Minimal Ceremony
2
+
3
+ > C# has evolved massively. Use the modern features.
4
+ > If your code looks like it's from 2015, it's wrong.
5
+
6
+ ## Language Version: C# 14+ / .NET 10 LTS
7
+
8
+ .NET 10 is the latest LTS release (November 2025, 3 years support). C# 14 ships with .NET 10. Use modern features: records, primary constructors, extension members, nullable reference types.
9
+
10
+ ### Nullable Reference Types (Mandatory)
11
+ ```xml
12
+ <!-- In .csproj — ALWAYS enabled -->
13
+ <PropertyGroup>
14
+ <Nullable>enable</Nullable>
15
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
16
+ </PropertyGroup>
17
+ ```
18
+
19
+ ### Records for DTOs and Value Objects
20
+ ```csharp
21
+ // BANNED: Mutable class with manual properties
22
+ public class UserDto {
23
+ public string Name { get; set; }
24
+ public string Email { get; set; }
25
+ }
26
+
27
+ // REQUIRED: Immutable record
28
+ public record CreateUserRequest(string Name, string Email, int Age);
29
+ public record UserResponse(Guid Id, string Name, string Email, DateTime CreatedAt);
30
+ ```
31
+
32
+ ### Primary Constructors (C# 12+)
33
+ ```csharp
34
+ // Clean dependency injection
35
+ public class UserService(IUserRepository userRepository, ILogger<UserService> logger)
36
+ {
37
+ public async Task<UserResponse> CreateAsync(CreateUserRequest request)
38
+ {
39
+ logger.LogInformation("Creating user {Email}", request.Email);
40
+ var user = await userRepository.CreateAsync(request);
41
+ return user.ToResponse();
42
+ }
43
+ }
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Validation at Boundaries
49
+
50
+ ### Minimal API with FluentValidation
51
+ ```csharp
52
+ public class CreateUserValidator : AbstractValidator<CreateUserRequest>
53
+ {
54
+ public CreateUserValidator()
55
+ {
56
+ RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
57
+ RuleFor(x => x.Email).NotEmpty().EmailAddress();
58
+ RuleFor(x => x.Age).InclusiveBetween(13, 150);
59
+ }
60
+ }
61
+
62
+ app.MapPost("/users", async (CreateUserRequest request, IValidator<CreateUserRequest> validator,
63
+ UserService userService) =>
64
+ {
65
+ var validation = await validator.ValidateAsync(request);
66
+ if (!validation.IsValid)
67
+ return Results.ValidationProblem(validation.ToDictionary());
68
+
69
+ var user = await userService.CreateAsync(request);
70
+ return Results.Created($"/users/{user.Id}", user);
71
+ });
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Project Structure
77
+
78
+ ```
79
+ ProjectName/
80
+ ├── src/
81
+ │ ├── ProjectName.Api/ # Presentation/Transport layer
82
+ │ │ ├── Program.cs # Entry point + DI setup
83
+ │ │ ├── Endpoints/
84
+ │ │ │ ├── UserEndpoints.cs # Minimal API route definitions
85
+ │ │ │ └── OrderEndpoints.cs
86
+ │ │ ├── Middleware/
87
+ │ │ │ └── ExceptionMiddleware.cs
88
+ │ │ └── appsettings.json
89
+ │ │
90
+ │ ├── ProjectName.Application/ # Business logic layer
91
+ │ │ ├── Users/
92
+ │ │ │ ├── UserService.cs
93
+ │ │ │ ├── CreateUserRequest.cs # DTOs / records
94
+ │ │ │ └── UserResponse.cs
95
+ │ │ └── Common/
96
+ │ │ ├── AppError.cs
97
+ │ │ └── IUnitOfWork.cs
98
+ │ │
99
+ │ ├── ProjectName.Domain/ # Domain entities (no dependencies)
100
+ │ │ ├── Entities/
101
+ │ │ │ └── User.cs
102
+ │ │ └── Interfaces/
103
+ │ │ └── IUserRepository.cs # Repository contracts
104
+ │ │
105
+ │ └── ProjectName.Infrastructure/ # Data access, external services
106
+ │ ├── Persistence/
107
+ │ │ ├── AppDbContext.cs # EF Core DbContext
108
+ │ │ └── UserRepository.cs # Repository implementation
109
+ │ ├── Migrations/
110
+ │ └── DependencyInjection.cs # Extension methods for DI
111
+
112
+ └── tests/
113
+ ├── ProjectName.UnitTests/
114
+ └── ProjectName.IntegrationTests/
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Preferred Libraries
120
+
121
+ | Need | Library | Why |
122
+ |------|---------|-----|
123
+ | Framework | ASP.NET Core 10 Minimal APIs | LTS, lightweight, OpenAPI 3.1, passkey auth |
124
+ | ORM | EF Core 10 | LINQ, migrations, vector search, JSON types |
125
+ | Validation | FluentValidation | Expressive, testable, separates concerns |
126
+ | Testing | xUnit + NSubstitute + Testcontainers | Industry standard for .NET |
127
+ | Logging | Serilog + structured sinks | Best structured logging for .NET |
128
+ | API docs | Swashbuckle / NSwag | OpenAPI auto-generation |
129
+ | Mapping | Mapster or manual extension methods | Mapster faster than AutoMapper |
130
+ | HTTP client | `IHttpClientFactory` | Pooled, resilient, built-in |
131
+ | Configuration | Options pattern + `IOptions<T>` | Type-safe, validated config |
132
+ | Auth | ASP.NET Core Identity / JWT / Passkeys | Built-in passkey support in .NET 10 |
133
+ | Cloud-native | .NET Aspire | Orchestration, observability, service defaults |
134
+
135
+ ---
136
+
137
+ ## Banned Patterns
138
+
139
+ | Pattern | Why | Alternative |
140
+ |---------|-----|-------------|
141
+ | `Nullable` disabled | NRE everywhere | Always `<Nullable>enable</Nullable>` |
142
+ | `dynamic` type | No compile-time safety | Generics or strong types |
143
+ | Service Locator | Hidden dependencies | Constructor injection |
144
+ | `async void` | Unhandled exceptions crash the app | `async Task` always |
145
+ | `string.Format` for SQL | SQL injection | EF Core LINQ or parameterized |
146
+ | AutoMapper overuse | Magic mapping hides bugs | Manual mapping or Mapster |
147
+ | Throw in constructor | Breaks DI container | Factory methods or validation |
148
+ | `static` classes for services | Untestable, no DI | Interface + DI registration |
149
+ | Controllers with business logic | Layer leak | Thin controllers, services layer |