Endpoints and feature flags
Fusion uses minimal APIs: an endpoint is app.MapPost(route, async (body, useCase) => ...), with the use case injected straight into the handler. The handler is thin: validate input, call the use case, and map the Result to an HTTP status. It branches on the Result type (Module 5), guard-clauses first, happy path last (conventions E1, E2).
app.MapPost("/api/v1/flights/{key}:revertDecision",
async (string key, RevertDisruptionDecision useCase) =>
{
var result = await useCase.Execute(new RevertDisruptionDecisionRequest(key));
if (!result.IsSuccess)
{
return result.Errors[0] switch
{
EntityNotFound e => Results.NotFound(e.Message),
DecisionNotFound e => Results.NotFound(e.Message),
_ => Results.BadRequest(result.Errors),
};
}
return Results.Ok(result.Value); // happy path, last line
});New user-facing behaviour ships behind a feature flag (anti-pattern #29, convention FF1), because Fusion deploys trunk-based and every merge reaches the shared environment. The backend calls await _featureClient.GetBooleanValueAsync("FUS-{ticket}-{slug}", false, cancellationToken: cancellationToken); the flag defaults OFF so an unconfigured environment does not accidentally expose an unfinished feature, and each environment turns it ON explicitly once approved (dev on, test/prod off until the PM signs off). The key format is FUS-{ticket}-{slug} in kebab-case.
Try it yourself
Read an endpoint's guard-first flow
Confirm the shape: validate, call, map by type, ok last.
- Open
presentation/api/DisruptionDecisions/DisruptionDecisionEndpoints.cs - Find the revert or confirm handler and read it top to bottom
- Confirm failures are handled first (guard clauses, mapped by error type) and
Results.Ok(...)is the last line - Confirm the handler never inspects a domain status string, only the Result and its error types