Summary
POST /api/accounts can answer 409 with two different bodies — the structured NamespaceConflictResponse (namespace conflicts awaiting takeover selection) and, since #438, a bare string (duplicate account). ASP.NET's OpenAPI generator keeps only the last .Produces<T> declared for a status code, so the two cannot both be documented.
During #438 that collision silently deleted the NamespaceConflictResponse and NamespaceConflict component schemas from openapi/v1.json altogether. Because src/foundry-web/package.json:10 regenerates the frontend's schema.ts from that spec and account.model.ts derives its types from those exact keys, the next npm run generate:api would have broken the frontend build. #438 resolved it by dropping the .Produces<string>(409), which restores the schemas but leaves the duplicate-account 409 body undocumented.
Acceptance Criteria
Type
bug
Notes
Needs a short design decision. The likely mechanism is an IOpenApiOperationTransformer emitting oneOf for that response. Program.cs:67 already has an AddOpenApi(options => ...) block (currently only customising schema reference ids) as the extension point; the repo has no operation transformer yet, so this would be the first.
Worth weighing a simpler alternative first: give the duplicate-account rejection a structured body of its own so each status maps to one schema. That trades a new contract type for avoiding a transformer, and the frontend's 409 handler already branches on payload shape (account.service.ts:120), so a second object shape would need that branch tightened.
The latent-drift hazard is the more valuable half of this issue. schema.ts is generated but checked in, so a spec regression stays invisible until someone regenerates — #438's reviewer initially read the dropped schemas as pre-existing for exactly that reason. A CI check comparing a freshly generated schema.ts against the committed one would have caught it immediately.
Surfaced by the code review on #438.
Summary
POST /api/accountscan answer 409 with two different bodies — the structuredNamespaceConflictResponse(namespace conflicts awaiting takeover selection) and, since #438, a bare string (duplicate account). ASP.NET's OpenAPI generator keeps only the last.Produces<T>declared for a status code, so the two cannot both be documented.During #438 that collision silently deleted the
NamespaceConflictResponseandNamespaceConflictcomponent schemas fromopenapi/v1.jsonaltogether. Becausesrc/foundry-web/package.json:10regenerates the frontend'sschema.tsfrom that spec andaccount.model.tsderives its types from those exact keys, the nextnpm run generate:apiwould have broken the frontend build. #438 resolved it by dropping the.Produces<string>(409), which restores the schemas but leaves the duplicate-account 409 body undocumented.Acceptance Criteria
POST /api/accounts409 is inspected, then both possible bodies are documented.NamespaceConflictResponseandNamespaceConflictremain present incomponents.schemas.npm run generate:apifollowed by an Angular build, then the frontend compiles — ideally with a check that fails CI when the checked-inschema.tsdrifts from the spec.Type
bug
Notes
Needs a short design decision. The likely mechanism is an
IOpenApiOperationTransformeremittingoneOffor that response.Program.cs:67already has anAddOpenApi(options => ...)block (currently only customising schema reference ids) as the extension point; the repo has no operation transformer yet, so this would be the first.Worth weighing a simpler alternative first: give the duplicate-account rejection a structured body of its own so each status maps to one schema. That trades a new contract type for avoiding a transformer, and the frontend's 409 handler already branches on payload shape (
account.service.ts:120), so a second object shape would need that branch tightened.The latent-drift hazard is the more valuable half of this issue.
schema.tsis generated but checked in, so a spec regression stays invisible until someone regenerates — #438's reviewer initially read the dropped schemas as pre-existing for exactly that reason. A CI check comparing a freshly generatedschema.tsagainst the committed one would have caught it immediately.Surfaced by the code review on #438.