501 lines
25 KiB
Markdown
501 lines
25 KiB
Markdown
# Phase 1: Architecture Foundation - Research
|
|
|
|
**Researched:** 2026-03-27
|
|
**Domain:** .NET 9 Blazor WASM + ASP.NET Core Web API solution scaffolding
|
|
**Confidence:** HIGH
|
|
|
|
## Summary
|
|
|
|
Phase 1 creates the three-project solution structure (`ChatAgent.Client`, `ChatAgent.Api`, `ChatAgent.Shared`) with working CORS communication between WASM client and API server, and establishes the tutorial commenting convention that applies to all subsequent phases. No feature code is written -- this phase locks in the architectural boundaries (no API key in WASM, no file I/O in WASM, no direct OpenAI calls from WASM) so that later phases build on a verified foundation.
|
|
|
|
The .NET 9 SDK is available on this machine (9.0.312), alongside .NET 10 (10.0.201). Per CLAUDE.md the project targets .NET 9. The `blazorwasm`, `webapi`, and `classlib` templates are all available. The `webapi` template supports `--use-controllers` for the MVC Controller pattern the user chose (D-05). The hosted Blazor WASM template was removed in .NET 8, so the three projects must be created separately and added to a solution manually.
|
|
|
|
**Primary recommendation:** Create the solution using `dotnet new` templates targeting `net9.0`, add a shared class library for DTOs, wire up a minimal health-check endpoint, confirm CORS works from WASM to API, and verify `dotnet publish` completes cleanly.
|
|
|
|
<user_constraints>
|
|
## User Constraints (from CONTEXT.md)
|
|
|
|
### Locked Decisions
|
|
- **D-01:** Solution named `ChatAgent.sln` at repo root with three projects: `ChatAgent.Client` (Blazor WASM), `ChatAgent.Api` (ASP.NET Core backend), `ChatAgent.Shared` (shared models/DTOs)
|
|
- **D-02:** Projects live in `src/` subfolders: `src/ChatAgent.Client/`, `src/ChatAgent.Api/`, `src/ChatAgent.Shared/`
|
|
- **D-03:** Solution file at repo root for easy `dotnet build` from project root
|
|
- **D-04:** Typed HttpClient pattern -- a `ChatApiClient` class in the Client project wraps all backend API calls, registered via DI
|
|
- **D-05:** Backend uses traditional MVC Controllers (not Minimal API) -- more structure, familiar pattern for tutorial
|
|
- **D-06:** CORS configured on the API to allow the WASM client origin during development
|
|
- **D-07:** Full tutorial-style inline comments -- explain everything including basic patterns, treat every file as a teaching moment
|
|
- **D-08:** Comments go inline (XML doc comments and `//` comments right next to the code), no separate companion docs
|
|
- **D-09:** Every Blazor concept introduced must have a comment explaining WHAT it is and WHY it's used
|
|
- **D-10:** Start with plain HTML/CSS in Phase 1 -- no MudBlazor yet. Learn raw Blazor rendering first, add component library later
|
|
- **D-11:** Light theme as default look and feel
|
|
|
|
### Claude's Discretion
|
|
- CORS configuration details (origins, headers, methods)
|
|
- Base URL configuration approach (appsettings.json vs environment variables)
|
|
- Project file (.csproj) configuration details
|
|
- Test project structure (if any placeholder tests needed)
|
|
- .NET version targeting (9 vs 10 based on current stability)
|
|
|
|
### Deferred Ideas (OUT OF SCOPE)
|
|
None -- discussion stayed within phase scope
|
|
</user_constraints>
|
|
|
|
<phase_requirements>
|
|
## Phase Requirements
|
|
|
|
| ID | Description | Research Support |
|
|
|----|-------------|------------------|
|
|
| CODE-01 | Every Blazor concept introduced has inline comments explaining what and why | Tutorial commenting convention (D-07/D-08/D-09); every `.cs`, `.razor`, and `.csproj` file gets comments explaining the Blazor/ASP.NET Core concept it demonstrates |
|
|
| CODE-02 | Each phase introduces one concept incrementally (tutorial-style progression) | Phase 1's concept is "solution structure and project boundaries" -- no feature code, no OpenAI calls, no persistence, no streaming. Just the scaffold + one health-check round-trip to prove communication works |
|
|
</phase_requirements>
|
|
|
|
## Standard Stack
|
|
|
|
### Core (Phase 1 Only)
|
|
| Library | Version | Purpose | Why Standard |
|
|
|---------|---------|---------|--------------|
|
|
| .NET 9 SDK | 9.0.312 | Runtime and tooling | Installed on machine; stable; CLAUDE.md specifies .NET 9 |
|
|
| Blazor WebAssembly Standalone | net9.0 | Client SPA | Non-negotiable per constraints |
|
|
| ASP.NET Core Web API | net9.0 | Backend API server | Required for API key isolation |
|
|
| Class Library | net9.0 | Shared models/DTOs | Referenced by both Client and Api projects |
|
|
|
|
### Not Needed in Phase 1
|
|
| Library | Why Deferred |
|
|
|---------|-------------|
|
|
| `OpenAI` NuGet | No AI calls in Phase 1 -- introduced in Phase 3 |
|
|
| `Markdig` | No markdown rendering in Phase 1 -- introduced in Phase 4 |
|
|
| `MudBlazor` | D-10 explicitly defers this; plain HTML/CSS first |
|
|
| Any test framework | No business logic to test yet; placeholder tests are optional (Claude's discretion -- recommend skipping to keep Phase 1 focused) |
|
|
|
|
**Installation:**
|
|
```bash
|
|
# From repo root
|
|
dotnet new sln -n ChatAgent
|
|
|
|
# Create projects targeting .NET 9
|
|
dotnet new blazorwasm -n ChatAgent.Client --framework net9.0 -o src/ChatAgent.Client
|
|
dotnet new webapi -n ChatAgent.Api --framework net9.0 --use-controllers -o src/ChatAgent.Api
|
|
dotnet new classlib -n ChatAgent.Shared --framework net9.0 -o src/ChatAgent.Shared
|
|
|
|
# Add projects to solution
|
|
dotnet sln ChatAgent.sln add src/ChatAgent.Client/ChatAgent.Client.csproj
|
|
dotnet sln ChatAgent.sln add src/ChatAgent.Api/ChatAgent.Api.csproj
|
|
dotnet sln ChatAgent.sln add src/ChatAgent.Shared/ChatAgent.Shared.csproj
|
|
|
|
# Add Shared reference to both projects
|
|
dotnet add src/ChatAgent.Client/ChatAgent.Client.csproj reference src/ChatAgent.Shared/ChatAgent.Shared.csproj
|
|
dotnet add src/ChatAgent.Api/ChatAgent.Api.csproj reference src/ChatAgent.Shared/ChatAgent.Shared.csproj
|
|
```
|
|
|
|
## Architecture Patterns
|
|
|
|
### Recommended Project Structure (Phase 1)
|
|
```
|
|
ChatAgent.sln # Solution file at repo root (D-03)
|
|
src/
|
|
ChatAgent.Client/ # Blazor WASM standalone app
|
|
ChatAgent.Client.csproj
|
|
Program.cs # DI registration, HttpClient base URL config
|
|
App.razor # Root component
|
|
_Imports.razor # Global using directives
|
|
Layout/
|
|
MainLayout.razor # App shell layout
|
|
Pages/
|
|
Home.razor # Landing page (placeholder in Phase 1)
|
|
Services/
|
|
ChatApiClient.cs # Typed HttpClient wrapper (D-04)
|
|
wwwroot/
|
|
index.html # HTML host page
|
|
css/app.css # Basic styling (plain CSS, D-10)
|
|
|
|
ChatAgent.Api/ # ASP.NET Core Web API
|
|
ChatAgent.Api.csproj
|
|
Program.cs # DI, CORS, controller mapping
|
|
Controllers/
|
|
HealthController.cs # GET /api/health -- proves CORS works
|
|
appsettings.json # API config (base URLs, future API key ref)
|
|
appsettings.Development.json # Dev-specific config
|
|
|
|
ChatAgent.Shared/ # Shared class library
|
|
ChatAgent.Shared.csproj
|
|
Models/
|
|
HealthResponse.cs # Simple DTO for health-check response
|
|
```
|
|
|
|
### Pattern 1: Typed HttpClient in Blazor WASM (D-04)
|
|
**What:** A `ChatApiClient` class wraps `HttpClient` for all API calls. Registered in DI as a typed client.
|
|
**When to use:** Always -- components never use `HttpClient` directly.
|
|
**Example:**
|
|
```csharp
|
|
// Source: ASP.NET Core docs + CONTEXT.md D-04
|
|
// ChatApiClient.cs -- Typed HttpClient wrapper
|
|
// In Blazor WASM, HttpClient is backed by the browser's Fetch API.
|
|
// We wrap it in a typed client so components don't depend on HttpClient directly.
|
|
// This makes testing easier and centralizes API URL management.
|
|
public class ChatApiClient
|
|
{
|
|
private readonly HttpClient _httpClient;
|
|
|
|
public ChatApiClient(HttpClient httpClient)
|
|
{
|
|
_httpClient = httpClient;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calls the health endpoint to verify the API server is reachable.
|
|
/// This is the first HTTP call from WASM to the backend -- proves CORS works.
|
|
/// </summary>
|
|
public async Task<HealthResponse?> GetHealthAsync()
|
|
{
|
|
return await _httpClient.GetFromJsonAsync<HealthResponse>("api/health");
|
|
}
|
|
}
|
|
|
|
// Registration in Program.cs:
|
|
// AddHttpClient<T> registers a typed HttpClient with its own configuration.
|
|
// The base address points to the API server (different port during local dev).
|
|
builder.Services.AddHttpClient<ChatApiClient>(client =>
|
|
{
|
|
client.BaseAddress = new Uri("https://localhost:7100");
|
|
});
|
|
```
|
|
|
|
### Pattern 2: MVC Controller on API (D-05)
|
|
**What:** Traditional `[ApiController]` with `[Route("api/[controller]")]` attributes instead of Minimal API `app.MapGet()`.
|
|
**When to use:** All API endpoints in this project.
|
|
**Example:**
|
|
```csharp
|
|
// HealthController.cs -- ASP.NET Core MVC Controller
|
|
// We use Controllers (not Minimal API) for more explicit structure (D-05).
|
|
// Each controller is a class with methods for each HTTP verb.
|
|
// [ApiController] enables automatic model validation and 400 responses.
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class HealthController : ControllerBase
|
|
{
|
|
/// <summary>
|
|
/// Health check endpoint. Returns server status and timestamp.
|
|
/// Used by the WASM client to verify the API is reachable and CORS is working.
|
|
/// </summary>
|
|
[HttpGet]
|
|
public IActionResult Get()
|
|
{
|
|
return Ok(new HealthResponse
|
|
{
|
|
Status = "healthy",
|
|
Timestamp = DateTime.UtcNow
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
### Pattern 3: CORS Configuration (D-06)
|
|
**What:** Explicit CORS policy on the API allowing the WASM client origin.
|
|
**When to use:** Required for any cross-origin HTTP call from WASM to API during development.
|
|
**Example:**
|
|
```csharp
|
|
// Program.cs (API project) -- CORS setup
|
|
// CORS (Cross-Origin Resource Sharing) is required because the Blazor WASM client
|
|
// runs on a different port (e.g., localhost:5200) than the API (e.g., localhost:7100).
|
|
// Browsers block cross-origin requests by default for security.
|
|
// We define a named policy that allows only our client origin.
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddPolicy("AllowBlazorClient", policy =>
|
|
{
|
|
policy.WithOrigins("https://localhost:5200") // WASM client origin
|
|
.AllowAnyHeader()
|
|
.AllowAnyMethod();
|
|
});
|
|
});
|
|
|
|
// ... after builder.Build()
|
|
app.UseCors("AllowBlazorClient");
|
|
```
|
|
|
|
### Pattern 4: Base URL Configuration (Claude's Discretion)
|
|
**Recommendation:** Use `appsettings.json` in the WASM client for the API base URL. This is standard for Blazor WASM and the file is in `wwwroot/` (public, no secrets). Environment variables are harder to configure for WASM since it runs in the browser.
|
|
|
|
```csharp
|
|
// wwwroot/appsettings.json (Client project) -- PUBLIC config only
|
|
// In Blazor WASM, appsettings.json is a static file served to the browser.
|
|
// NEVER put secrets here. Only public configuration like API URLs.
|
|
{
|
|
"ApiBaseUrl": "https://localhost:7100"
|
|
}
|
|
|
|
// Program.cs -- reading the config
|
|
var apiBaseUrl = builder.Configuration["ApiBaseUrl"]
|
|
?? throw new InvalidOperationException("ApiBaseUrl not configured");
|
|
builder.Services.AddHttpClient<ChatApiClient>(client =>
|
|
{
|
|
client.BaseAddress = new Uri(apiBaseUrl);
|
|
});
|
|
```
|
|
|
|
### Anti-Patterns to Avoid
|
|
- **Any `System.IO.File` usage in the Client project:** WASM runs in a browser sandbox; file I/O does not persist. All persistence is server-side.
|
|
- **Any API key or secret in `wwwroot/appsettings.json`:** This file is publicly accessible. Secrets belong in the API project only.
|
|
- **OpenAI SDK registration in the Client `Program.cs`:** All OpenAI calls go through the backend API. The Client never talks to OpenAI directly.
|
|
- **CORS wildcard (`AllowAnyOrigin`):** Even for local dev, scope to the actual client origin. Prevents accidental exposure.
|
|
- **Logic in `.razor` code blocks:** Components call services; services own logic (D-04 enforces this via typed client pattern).
|
|
|
|
## Don't Hand-Roll
|
|
|
|
| Problem | Don't Build | Use Instead | Why |
|
|
|---------|-------------|-------------|-----|
|
|
| HTTP client management | Manual `HttpClient` instantiation in components | `IHttpClientFactory` via `AddHttpClient<T>` | Proper socket management, DI lifecycle, testability |
|
|
| JSON serialization | Manual string building | `System.Text.Json` (built-in) with `GetFromJsonAsync`/`PostAsJsonAsync` | Type-safe, trim-compatible, zero dependencies |
|
|
| CORS handling | Custom middleware or response headers | `builder.Services.AddCors()` + `app.UseCors()` | Handles preflight OPTIONS requests, header management automatically |
|
|
| Project references | Copy-paste DTOs between projects | `dotnet add reference` to Shared project | Single source of truth; compile-time verification |
|
|
|
|
## Common Pitfalls
|
|
|
|
### Pitfall 1: Wrong Port in CORS or Client Config
|
|
**What goes wrong:** WASM client gets CORS errors because the API CORS policy specifies a different port than the client actually runs on.
|
|
**Why it happens:** `dotnet new blazorwasm` and `dotnet new webapi` assign random ports in `launchSettings.json`. Developer hardcodes one set of ports but the templates use different ones.
|
|
**How to avoid:** After project creation, check `Properties/launchSettings.json` in BOTH projects. Align the CORS origin in the API with the actual client URL. Or set explicit ports in `launchSettings.json`.
|
|
**Warning signs:** Browser console shows `Access-Control-Allow-Origin` errors.
|
|
|
|
### Pitfall 2: Missing `UseCors()` Middleware Order
|
|
**What goes wrong:** CORS policy is registered in DI but `app.UseCors()` is called after `app.MapControllers()`, causing CORS headers to not be applied.
|
|
**Why it happens:** ASP.NET Core middleware order matters. CORS must run before routing/endpoints.
|
|
**How to avoid:** Call `app.UseCors("PolicyName")` before `app.MapControllers()` and before `app.UseAuthorization()`.
|
|
**Warning signs:** CORS errors despite correct policy configuration.
|
|
|
|
### Pitfall 3: IL Trimming Warnings on Publish
|
|
**What goes wrong:** `dotnet publish` for the WASM project produces IL trimmer warnings about types that may be removed.
|
|
**Why it happens:** Blazor WASM uses IL trimming in Release mode. Types used only via reflection (JSON serialization) can be trimmed away.
|
|
**How to avoid:** For Phase 1, the surface area is tiny (one DTO). Verify `dotnet publish` completes without warnings. In later phases, use `[JsonSerializable]` source generators.
|
|
**Warning signs:** `dotnet publish` output contains lines with `IL2xxx` warning codes.
|
|
|
|
### Pitfall 4: Solution File Path Issues
|
|
**What goes wrong:** `dotnet build` from repo root fails because `ChatAgent.sln` references projects with wrong relative paths.
|
|
**Why it happens:** Solution was created in a subdirectory, or projects were moved after being added.
|
|
**How to avoid:** Create the solution at repo root, add projects using their paths relative to the sln file location.
|
|
**Warning signs:** `The project file could not be found` errors.
|
|
|
|
### Pitfall 5: WASM Project Serves on HTTPS But Certificate Not Trusted
|
|
**What goes wrong:** Browser shows security warning when accessing WASM app, blocking API calls.
|
|
**Why it happens:** Dev HTTPS certificate not installed or not trusted.
|
|
**How to avoid:** Run `dotnet dev-certs https --trust` once before starting development. Alternatively, use `--no-https` flag during project creation for Phase 1 simplicity and add HTTPS later.
|
|
**Warning signs:** Browser shows "Your connection is not private" page.
|
|
|
|
## Code Examples
|
|
|
|
### Shared DTO (ChatAgent.Shared)
|
|
```csharp
|
|
// Models/HealthResponse.cs
|
|
// This is a shared model (DTO - Data Transfer Object).
|
|
// It lives in the Shared project so both the Client and Api can use it
|
|
// without duplicating the class definition. When the API returns this object,
|
|
// the Client can deserialize it into the same type.
|
|
namespace ChatAgent.Shared.Models;
|
|
|
|
public class HealthResponse
|
|
{
|
|
/// <summary>
|
|
/// Server health status (e.g., "healthy").
|
|
/// </summary>
|
|
public string Status { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Server timestamp -- proves we're getting a live response, not a cached one.
|
|
/// </summary>
|
|
public DateTime Timestamp { get; set; }
|
|
}
|
|
```
|
|
|
|
### WASM Program.cs (Client)
|
|
```csharp
|
|
// Program.cs -- Blazor WASM application entry point
|
|
// This is where the WebAssembly application starts.
|
|
// WebAssemblyHostBuilder configures:
|
|
// 1. Root components (what Razor components to render)
|
|
// 2. Services (dependency injection container)
|
|
// 3. Configuration (reads from wwwroot/appsettings.json)
|
|
using Microsoft.AspNetCore.Components.Web;
|
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
|
using ChatAgent.Client;
|
|
using ChatAgent.Client.Services;
|
|
|
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
|
|
|
// Add<App>("#app") tells Blazor to render the App component
|
|
// inside the <div id="app"> element in wwwroot/index.html.
|
|
builder.RootComponents.Add<App>("#app");
|
|
|
|
// HeadOutlet manages <head> elements (title, meta tags) from Razor components.
|
|
builder.RootComponents.Add<HeadOutlet>("head::after");
|
|
|
|
// Read the API base URL from configuration (wwwroot/appsettings.json).
|
|
// This file is PUBLIC -- never put secrets here.
|
|
var apiBaseUrl = builder.Configuration["ApiBaseUrl"]
|
|
?? "https://localhost:7100";
|
|
|
|
// Register ChatApiClient as a typed HttpClient.
|
|
// AddHttpClient<T> uses IHttpClientFactory internally, which:
|
|
// - Manages HttpClient lifetimes properly (avoids socket exhaustion)
|
|
// - Allows per-client configuration (base address, headers)
|
|
// - Makes the service injectable via constructor DI
|
|
builder.Services.AddHttpClient<ChatApiClient>(client =>
|
|
{
|
|
client.BaseAddress = new Uri(apiBaseUrl);
|
|
});
|
|
|
|
await builder.Build().RunAsync();
|
|
```
|
|
|
|
### API Program.cs (Server)
|
|
```csharp
|
|
// Program.cs -- ASP.NET Core Web API entry point
|
|
// This is the backend server that the Blazor WASM client talks to.
|
|
// It will eventually proxy OpenAI calls and manage JSON file storage.
|
|
// In Phase 1, it only serves a health check endpoint.
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// AddControllers() registers MVC controller services.
|
|
// We use Controllers (not Minimal API) for explicit structure (D-05).
|
|
builder.Services.AddControllers();
|
|
|
|
// CORS (Cross-Origin Resource Sharing) configuration.
|
|
// The WASM client runs on a different origin (different port),
|
|
// so the browser blocks requests unless the server explicitly allows them.
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddPolicy("AllowBlazorClient", policy =>
|
|
{
|
|
// TODO: Read from configuration instead of hardcoding
|
|
policy.WithOrigins("https://localhost:5200")
|
|
.AllowAnyHeader()
|
|
.AllowAnyMethod();
|
|
});
|
|
});
|
|
|
|
var app = builder.Build();
|
|
|
|
// Middleware order matters in ASP.NET Core.
|
|
// CORS must be applied before routing and authorization.
|
|
app.UseCors("AllowBlazorClient");
|
|
|
|
app.UseAuthorization();
|
|
|
|
// MapControllers() discovers all [ApiController] classes
|
|
// and maps their [HttpGet], [HttpPost], etc. attributes to routes.
|
|
app.MapControllers();
|
|
|
|
app.Run();
|
|
```
|
|
|
|
## State of the Art
|
|
|
|
| Old Approach | Current Approach | When Changed | Impact |
|
|
|--------------|------------------|--------------|--------|
|
|
| Hosted Blazor WASM template (Client+Server+Shared in one template) | Separate projects added to a manual solution | .NET 8 (Nov 2023) | Must create three projects manually; no `--hosted` flag |
|
|
| `Newtonsoft.Json` for serialization | `System.Text.Json` built into .NET | .NET Core 3.0+ | No extra dependency; source generators for trim safety |
|
|
| `HttpClient` registered directly as Singleton/Scoped | `IHttpClientFactory` via `AddHttpClient<T>` | .NET Core 2.1+ | Proper socket management; typed clients for clean architecture |
|
|
|
|
## .NET Version Decision (Claude's Discretion)
|
|
|
|
**Recommendation: Target .NET 9 (`net9.0`)**
|
|
|
|
Rationale:
|
|
- CLAUDE.md explicitly specifies .NET 9 as the target
|
|
- .NET 9.0.312 SDK is installed on this machine
|
|
- .NET 10 SDK (10.0.201) is also available but is not yet at LTS; using it in a tutorial project risks encountering preview-stage breaking changes
|
|
- All recommended packages (OpenAI 2.9.1, Markdig 1.1.1, MudBlazor 9.2.0) are confirmed compatible with .NET 9
|
|
- The `blazorwasm` template with `--framework net9.0` is verified working
|
|
|
|
## Validation Architecture
|
|
|
|
### Test Framework
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| Framework | None yet (greenfield) |
|
|
| Config file | None -- see Wave 0 |
|
|
| Quick run command | `dotnet build ChatAgent.sln` |
|
|
| Full suite command | `dotnet build ChatAgent.sln && dotnet publish src/ChatAgent.Client/ChatAgent.Client.csproj -c Release --nologo` |
|
|
|
|
### Phase Requirements -> Test Map
|
|
| Req ID | Behavior | Test Type | Automated Command | File Exists? |
|
|
|--------|----------|-----------|-------------------|-------------|
|
|
| CODE-01 | Every file has inline comments explaining Blazor concepts | manual | Manual review of all `.cs` and `.razor` files | N/A |
|
|
| CODE-02 | Phase introduces one concept incrementally | manual | Manual review -- Phase 1 concept = "solution structure and project boundaries" | N/A |
|
|
| (SC-1) | `dotnet run` starts both projects without errors | smoke | `dotnet build ChatAgent.sln` (build verification) | N/A -- Wave 0 |
|
|
| (SC-2) | WASM client reaches API server (CORS working) | integration | Manual -- start both projects, verify health endpoint from client UI | N/A |
|
|
| (SC-3) | Shared models referenced by both projects | build | `dotnet build ChatAgent.sln` (compile-time check) | N/A -- Wave 0 |
|
|
| (SC-4) | `dotnet publish` completes with no IL trim warnings | smoke | `dotnet publish src/ChatAgent.Client/ChatAgent.Client.csproj -c Release --nologo 2>&1 \| grep -c "warning IL"` | N/A -- Wave 0 |
|
|
| (SC-5) | Every file contains inline comments | manual | Manual review | N/A |
|
|
|
|
### Sampling Rate
|
|
- **Per task commit:** `dotnet build ChatAgent.sln`
|
|
- **Per wave merge:** `dotnet build ChatAgent.sln && dotnet publish src/ChatAgent.Client/ChatAgent.Client.csproj -c Release --nologo`
|
|
- **Phase gate:** Full build + publish clean + manual CORS verification
|
|
|
|
### Wave 0 Gaps
|
|
- No formal test project needed in Phase 1 -- the verification is build success + publish success + manual CORS check
|
|
- The `dotnet build` and `dotnet publish` commands serve as the automated validation
|
|
- CODE-01 and CODE-02 are inherently manual-review requirements
|
|
|
|
## Environment Availability
|
|
|
|
| Dependency | Required By | Available | Version | Fallback |
|
|
|------------|------------|-----------|---------|----------|
|
|
| .NET 9 SDK | All projects | Yes | 9.0.312 | -- |
|
|
| .NET 10 SDK | Not required | Yes | 10.0.201 | -- |
|
|
| `dotnet new blazorwasm` template | Client project | Yes | Included in SDK | -- |
|
|
| `dotnet new webapi` template | API project | Yes | Included in SDK | -- |
|
|
| `dotnet new classlib` template | Shared project | Yes | Included in SDK | -- |
|
|
| HTTPS dev certificate | Local HTTPS | Unknown | -- | Use `--no-https` flag or run `dotnet dev-certs https --trust` |
|
|
|
|
**Missing dependencies with no fallback:** None.
|
|
|
|
**Missing dependencies with fallback:**
|
|
- HTTPS dev certificate status is unknown -- if untrusted, can use HTTP for Phase 1 local dev or run the trust command.
|
|
|
|
## Open Questions
|
|
|
|
1. **Port numbers for local development**
|
|
- What we know: Templates assign ports in `launchSettings.json` which vary per creation
|
|
- What's unclear: Exact ports until projects are actually created
|
|
- Recommendation: After project creation, inspect both `launchSettings.json` files and align CORS config with actual client URL. Consider setting explicit predictable ports (e.g., Client: 5200, API: 7100).
|
|
|
|
2. **HTTPS vs HTTP for Phase 1 local dev**
|
|
- What we know: HTTPS requires a trusted dev certificate
|
|
- What's unclear: Whether the dev cert is already trusted on this machine
|
|
- Recommendation: Attempt HTTPS first. If certificate issues arise, fall back to HTTP for Phase 1 (add `--no-https` and use `http://` URLs). HTTPS can be re-enabled in later phases.
|
|
|
|
## Project Constraints (from CLAUDE.md)
|
|
|
|
- **Tech stack**: .NET / C# / Blazor WebAssembly -- non-negotiable
|
|
- **LLM provider**: OpenAI GPT API (not used in Phase 1, but architecture must support it)
|
|
- **Storage**: JSON files on local disk (not used in Phase 1, but architecture must support it)
|
|
- **Architecture**: WASM client + backend API (API key stays server-side)
|
|
- **Code style**: Every Blazor concept introduced must have inline comments explaining what it does and why
|
|
- **GSD Workflow**: Use GSD entry points for all file changes
|
|
|
|
## Sources
|
|
|
|
### Primary (HIGH confidence)
|
|
- .NET 9 SDK verified installed: `dotnet --list-sdks` shows 9.0.312
|
|
- `blazorwasm` template verified: `dotnet new list blazorwasm` confirms availability
|
|
- `webapi --use-controllers` flag verified: `dotnet new webapi --help` confirms option exists
|
|
- Template output verified: Created temporary projects to confirm `Program.cs` structure, `.csproj` contents, and default file layout
|
|
|
|
### Secondary (MEDIUM confidence)
|
|
- `.planning/research/ARCHITECTURE.md` -- pre-existing project research on WASM/API split patterns
|
|
- `.planning/research/STACK.md` -- pre-existing stack research with NuGet-verified versions
|
|
- `.planning/research/PITFALLS.md` -- pre-existing pitfalls research from official GitHub issues
|
|
|
|
### Tertiary (LOW confidence)
|
|
- None -- all findings verified against installed SDK and official templates
|
|
|
|
## Metadata
|
|
|
|
**Confidence breakdown:**
|
|
- Standard stack: HIGH -- verified against installed SDK and templates
|
|
- Architecture: HIGH -- three-project structure is well-documented Microsoft pattern; template output confirmed
|
|
- Pitfalls: HIGH -- CORS ordering, port mismatch, and IL trimming are well-known ASP.NET Core issues documented in official sources
|
|
|
|
**Research date:** 2026-03-27
|
|
**Valid until:** 2026-04-27 (stable -- .NET 9 is mature, templates are not changing)
|