Traditional layered architectures split code by technical concern (Controllers → Services → Repositories), leading to widespread git conflicts and bloated God Services.
BitzOrcas.Modern practices Vertical Slice Architecture: organizing code along business use cases following “One Use Case, One File”.
Slice Structure & Pipeline Execution Flow
Slice Anatomy: One Use Case, One File Standard Pattern
In BitzOrcas.Modern, a complete Command vertical slice is organized in a single self-contained file:
using System;using System.Threading;using System.Threading.Tasks;using BitzOrcas.Application.Abstractions.Tenancy;using BitzOrcas.Application.Authorization;using BitzOrcas.Domain.Abstractions;using BitzOrcas.Domain.Results;using BitzOrcas.Endpoint.Attributes;using BitzOrcas.Modules.Legal.Contracts;using BitzOrcas.Modules.Legal.Domain;using Mediator;
namespace BitzOrcas.Modules.Legal.Application.Matters;
/// <summary>/// Command contract for initiating a civil/commercial matter intake/// </summary>/// <remarks>/// Mapped directly into a Minimal API endpoint at compile time by source generators./// </remarks>[GenerateEndpoint(HttpRoute.Post, "/api/legal/matters", Tag = "Matters")]public sealed record CreateMatterIntakeCommand( string MatterTitle, string ClientName, string OpposingPartyName, decimal ClaimAmount, bool IsCrossBorder) : ICommand<Result<string>>, IAuthorizedRequest{ /// <summary> /// Protected resource descriptor /// </summary> public ResourceDescriptor Resource { get; } = new("legal", "matter");
/// <summary> /// Required authorization action /// </summary> public AuthorizationAction Action { get; } = AuthorizationAction.Create;}
/// <summary>/// Pure validation rule executed before reaching the handler/// </summary>public sealed class CreateMatterIntakeCommandRule : IRequestRule<CreateMatterIntakeCommand>{ public Result Validate(CreateMatterIntakeCommand command) { // 1. Enforce title length boundaries if (string.IsNullOrWhiteSpace(command.MatterTitle) || command.MatterTitle.Length > 200) { return Result.Failure(LegalErrors.MatterTitleInvalid); }
// 2. Claim amount must be strictly positive if (command.ClaimAmount <= 0) { return Result.Failure(LegalErrors.ClaimAmountPositive); }
return Result.Success(); }}
/// <summary>/// Command handler orchestrating business domain execution/// </summary>/// <remarks>/// Focuses purely on domain orchestration; cross-cutting concerns are governed by the 10-stage pipeline./// </remarks>public sealed class CreateMatterIntakeCommandHandler( ICommandRepository<MatterIntake, string> repository, ICurrentTenant currentTenant) : ICommandHandler<CreateMatterIntakeCommand, Result<string>>{ public async ValueTask<Result<string>> Handle( CreateMatterIntakeCommand request, CancellationToken cancellationToken) { var tenant = currentTenant.Tenant; if (!tenant.IsAvailable) { return Result.Failure<string>(LegalErrors.TenantRequired); }
// 1. Generate sequential business matter code var matterCode = $"MAT-{DateTimeOffset.UtcNow:yyyyMMdd}-{Random.Shared.Next(10000, 99999)}";
// 2. Validate domain invariants via factory method var intakeResult = MatterIntake.CreateIntake( tenantId: tenant.EffectiveTenantId, matterCode: matterCode, matterTitle: request.MatterTitle, clientName: request.ClientName, opposingPartyName: request.OpposingPartyName, claimAmount: request.ClaimAmount, isCrossBorder: request.IsCrossBorder);
if (intakeResult.IsFailure) { return Result.Failure<string>(intakeResult.Error); }
var matter = intakeResult.GetValueOrThrow();
// 3. Commit aggregate via narrow command repository (pipeline handles transactions, outbox, and audit diffs) var saveResult = await repository.SaveAsync(matter, cancellationToken); return saveResult.IsFailure ? Result.Failure<string>(saveResult.Error) : Result.Success(matterCode); }}10-Stage Pipeline Responsibility Matrix
| Order | Pipeline Behavior | Core Responsibility | Interception Behavior |
|---|---|---|---|
1 | LoggingPipelineBehavior | Records request latency and binds ambient TraceId | Structured logging |
2 | RuntimeLicensePipelineBehavior | Validates commercial signed license and tenant seats | Rejects with 403 on invalid license |
3 | DelegatedSessionRestrictionPipelineBehavior | Restricts write operations during operator impersonation | Rejects with 403 on restricted writes |
4 | AuthorizationPipelineBehavior | Enforces declarative RBAC/ABAC resource-action permissions | Rejects with 403 on unauthorized calls |
5 | ValidationPipelineBehavior | Executes pure IRequestRule and tenant policy validators | Rejects with 400 on invariant failure |
6 | IdempotencyPipelineBehavior | Distributed Redis anti-replay and concurrent execution locks | Returns cached response on duplicate |
7 | TransactionPipelineBehavior | Automatically wraps execution in ambient DB transaction | Rolls back on unhandled error |
8 | DomainEventDispatchPipelineBehavior | Dispatches domain events and persists CAP outbox frames | Enforces atomic delivery |
9 | ActivityAuditPipelineBehavior | Records operator identity, IP, and before/after state diffs | Asynchronous batch persistence |
10 | ReadModelDisplayPipelineBehavior | Hydrates display text and multi-language dictionary tags | Zero-reflection fast serialization |
Summary
Vertical Slice Architecture maximizes velocity and simplifies refactoring:
- Modifying a feature touches one file;
- Decommissioning a feature is a single file delete;
- Cross-cutting governance is handled entirely by the 10-stage pipeline.