Business Rules
The Wrapsfer API today implements a single business concept — greetings — used as a sample to demonstrate the layered architecture. This page lists every rule that exists in the codebase, separating them by the layer that enforces them, and is explicit about what is not a business rule today.
If you are looking for the request/response contract, see the Endpoint Reference. For error shapes, see Errors & Validation.
Layer Map
| Concern | Enforced in |
|---|---|
HTTP-level input shape (name length) | GreetingsController — [ApiController] + data annotations |
| Use-case orchestration & timestamp | GreetingService (Application) |
| Domain invariants (non-blank, trimming, message format) | Greeting (Domain) |
Domain rules apply regardless of how the use case is invoked. API validation only fires for HTTP requests through the controller.
Domain Rules — Greeting
Defined in Wrapsfer.Domain.Greetings.Greeting.
- Construction is restricted to
Greeting.Create(string name). The constructor is private. namemust not be null, empty, or whitespace.CreatethrowsArgumentExceptionwith message"A greeting name is required."and parameter namenameifstring.IsNullOrWhiteSpace(name)is true.nameis trimmed. Surrounding whitespace is removed before the value is stored. The unit testGreetingTests.Create_TrimsNameAndFormatsMessageconfirms" Vernon "becomes"Vernon".- Message format is fixed.
Greeting.Messageis computed as$"Hello, {Name}!"— there is no localization, no template configuration, no salutation variation.
These rules apply to any caller of Greeting.Create, not just the HTTP path.
Application Rules — GreetingService
Defined in Wrapsfer.Application.Greetings.GreetingService.
- Invokes the domain.
GreetingService.CreateGreeting(string name)callsGreeting.Create(name), so all domain rules above apply transitively. - Returns a
GreetingResponseDTO, not the domain entity. The DTO shape is(string Message, DateTimeOffset GeneratedAt). - Timestamp comes from injected
TimeProvider.GeneratedAtistimeProvider.GetUtcNow(). The Infrastructure layer registersTimeProvider.Systemas a singleton (Wrapsfer.Infrastructure.DependencyInjection.AddInfrastructure), so in production the value is the current system UTC time. Tests can substitute a fakeTimeProviderto control the value. IGreetingServiceis registered asScoped. A new instance is created per HTTP request.
There are no further application-layer rules — no caching, no rate limiting, no retries, no logging beyond default ASP.NET Core request logging.
API Validation Rules — GreetingsController
Defined in Wrapsfer.Api.Controllers.GreetingsController.
- Route:
GET /api/greetings(controller routeapi/[controller]). namequery parameter default. When the caller omitsname, the action parameter defaults to"World". A request with no query string therefore succeeds with greeting"Hello, World!".namelength validation. Decorated with[StringLength(80, MinimumLength = 1)]:- Empty string (
?name=) failsMinimumLength = 1. - More than 80 characters fails
MaximumLength = 80. - Either failure causes ASP.NET Core's
[ApiController]automatic model-state validation to short-circuit with400 Bad Requestand a problem-details body. See Errors & Validation.
- Empty string (
- No other API validation rules exist. No content-type negotiation rules, no required headers, no rate limits, no authorization checks (the pipeline includes
UseAuthorization, but no policies or[Authorize]attributes are defined).
What Is Intentionally Not A Business Rule Today
The following concepts are not implemented anywhere in the codebase. They should not be assumed to exist or be enforced.
- Users / accounts / identities. No user model, no registration, no profile.
- Authentication. No authentication scheme is registered. No bearer tokens, cookies, or API keys are validated.
- Authorization.
UseAuthorizationis in the pipeline, but there are no policies, no roles, and no[Authorize]attributes. No request is rejected on authorization grounds. - Sessions. No session state is stored.
- Tenancy / scoping. No tenant resolution, no scoping of data per caller.
- Persistence. No database, no repositories, no entity tracking. Greetings are not saved; each request is fully recomputed.
- Auditing / event sourcing. No audit log, no event publication.
- Payments / billing / quotas. No charging, no usage tracking, no quotas.
- Workflows / state machines. No multi-step business processes.
- Notifications. No email, SMS, push, or webhook delivery.
- Background jobs. No hosted services, no scheduled tasks, no queues.
- Localization / i18n. Greeting message is hard-coded English.
When any of these are added, document them as they land — do not document them in advance.
See Also
- API Overview — high-level view of what the API is and is not.
- Endpoint Reference — request/response contract for the greeting endpoint.
- Errors & Validation — error contract returned when validation fails.
- Architecture — how Domain, Application, and Api responsibilities are kept separate.