The thin use case
An application use case is deliberately thin. It's a sealed class with its ports injected through the constructor and one method, Execute, that returns a Result. Its job is orchestration: guard the request at the trust boundary, build the domain objects, call the port, return the Result. The domain rules live in the domain; the IO lives behind ports; the use case just conducts.
Two real details worth copying. The trust-boundary guard lives IN the use case, not in decorative DTO attributes: the code comment notes the DTO's [Required] annotations are inert because no validation filter is wired, so the real check is the is not { Count: > 0 } guard here. And this use case accumulates its own errors in a loop rather than a FailIf chain, because it needs to build a List as it goes, which is exactly the "imperative is fine when the fluent chain is structurally incompatible" exception (convention D5, anti-pattern #21).
Try it yourself
Check the use-case shape
Verify you can recognise the anatomy.
Reading SaveFlightNote, you can point to each part: sealed class; a ctor-injected IFlightNoteRepository port (an interface, not a concrete type); an Execute(request, CancellationToken) returning Task<Result<...>>; a trust-boundary guard first; domain objects built via FlightNoteVo.Create; a single port call (SaveMany); and a Result returned on every path. No SQL, no domain calculation, no new FlightNote() DBO in sight.
Where the trust-boundary guard lives
A subtle real-world point.
In SaveFlightNote, why is the "at least one flight key" check written as an explicit guard in Execute rather than relying on a [Required]/[MinLength] attribute on the request DTO?