You are cross-referencing a C# Web API's actual contract (controllers, DTOs, route definitions) against its TypeScript/JavaScript consumers to find contract drift — in both directions — before it reaches production.
When to use this
Trigger when the user asks to:
- Check whether a DTO/controller change will break frontend or client applications
- Verify the client and backend API contract are still in sync
- Audit a specific endpoint, or the whole API surface, for breaking changes before a release
Do not use this for:
- Generating new API code from an OpenAPI spec (see
openapi-to-application-code) - Scaffolding new endpoints with OpenAPI docs (see
aspnet-minimal-api-openapi) - Comparing two OpenAPI spec files directly — this skill reads source code, not exported specs
Process
Discover Global JSON & Naming Policies:
- Check
Program.csorStartup.csfor active JSON options (e.g.JsonNamingPolicy.CamelCase,PropertyNamingPolicy, or NewtonsoftCamelCasePropertyNamesContractResolver). - Default to
camelCasefor TypeScript/JavaScript field mapping if global camelCase is configured, unless overridden by an explicit[JsonPropertyName("...")]attribute on the C# property. - Ignore C# properties annotated with
[JsonIgnore].
- Check
Identify the C# contract surface. For each Controller action in scope:
- Route: Base
[Route("...")]+ action[HttpGet("...")]/[HttpPost("...")]. Normalize route parameters (e.g.{id:int}or{id:guid}$\rightarrow${id}). - Request DTO: Extract property names, types, and requirement rules:
- Required if: annotated with
[Required],[BindRequired], has the C# 11requiredmodifier (public required string X), or is a non-nullable value type (int,Guid,bool) without a default value. - Optional if: nullable (
string?,int?), or has a default initializer.
- Required if: annotated with
- Response DTO: Property names, types, and nullability.
- Explicit Status Codes:
[ProducesResponseType(statusCode)]attributes and explicitStatusCode(...)return paths.
- Route: Base
Find the matching TypeScript/JavaScript consumer (with Normalized URL Matching):
- Auto-generated client match (high confidence): look for generated client files (NSwag/OpenAPI Generator output) and match by generated method/interface name directly.
- Hand-written service/client match (medium confidence):
- Search TypeScript/JavaScript files for HTTP client calls (
fetch,axios, AngularHttpClient,ky, etc.) whose normalized URL pattern matches the controller's route. - Normalize template strings and concatenations (e.g.,
${this.apiUrl}/users/${id}orbaseUrl + '/users/' + userId$\rightarrow$/users/{id}). - Match normalized routes against C# routes regardless of variable naming in TypeScript/JS.
- Search TypeScript/JavaScript files for HTTP client calls (
- No match found: report as "no client consumer located" rather than guessing — do not assume an endpoint is unused just because a match wasn't found statically.
- Label every finding with which of these three methods was used to locate it.
Compare backend → frontend/client (breaks the client):
- A DTO property renamed or removed that the TypeScript/JS interface or object model still expects
- A new required request field the client never sends
- A response status code the client doesn't handle (e.g. controller now returns 409 Conflict, but client error handler only handles 400/500)
- A response field's type changed (e.g.
long$\rightarrow$string, or non-nullable $\rightarrow$ nullable) in a way the client type assumes differently
Compare frontend/client → backend (stale/dead client code vs. silent bugs):
- Harmless dead field: Client sends a payload property the backend ignores without error.
- Silently broken bug (High Severity): Client logic reads a response property that the backend no longer returns (resulting in
undefinedat runtime and potential application failures).
Produce the report (see Output Format). This skill does not modify code.
Output Format
- Scope Audited — Controllers, DTOs, and TypeScript/JavaScript files audited, along with detected JSON naming policies (e.g.
camelCaseenabled viaProgram.cs). - Backend → Client Breaks — Grouped by endpoint: what changed, match method used (Auto-generated / Normalized Route Match), exact impact on the client, and severity (Compilation Error vs. Silent Runtime Failure).
- Client → Backend Drift — Stale fields sent or expected, explicitly distinguishing harmless dead fields from silently broken client UI logic.
- No Consumer Found — Unmatched backend DTOs/endpoints requiring manual confirmation.
- Match Confidence Summary — Breakdown of findings derived from auto-generated clients vs. normalized hand-written routes vs. unmatched routes.
Guidelines
- URL Normalization: Always strip query parameters (
?status=active) and normalize path parameters (${id}/:id/{id}) before comparing routes. - Naming Policies: Never assume a C# property name matches a TypeScript/JS property verbatim without checking for
[JsonPropertyName("...")]or globalJsonNamingPolicy.CamelCasesettings. - Modern C# Nuances: Check for C# 11
requiredkeyword and#nullable enableannotations (string?vsstring) when assessing required properties. - Framework Agnostic: Apply contract matching across any TypeScript or JavaScript client (Fetch, Axios, Angular, React, Vue, Svelte, Node.js).
- Never Fabricate: If no matching client service or DTO is found, report "No consumer located via static search" — never guess a pairing based purely on loose class names.
- Reporting Only: Do not modify code; output a scannable, actionable audit report.