Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

Complete Example — From Requirement to Dashboard

"One feature. Six steps. Seventeen generated files. Zero manual documentation."


The Feature: Order Payment

We are adding a new payment flow to the Order aggregate. This walkthrough shows every step — from requirement definition to production monitoring — with the generated output at each stage.


Step 1: Define the Requirement

// src/Requirements/OrderPaymentFeature.cs

[Feature(
    Description = "Allow customers to pay for orders using multiple payment methods",
    Priority = Priority.Critical)]
public abstract class OrderPaymentFeature : FeatureBase
{
    [AcceptanceCriteria("Order can be marked as paid with a valid payment reference")]
    public abstract Result OrderCanBePaid();

    [AcceptanceCriteria("Payment method is validated against supported providers")]
    public abstract Result PaymentMethodIsValidated();

    [AcceptanceCriteria("Paid order triggers fulfillment workflow via domain event")]
    public abstract Result PaidOrderTriggersFulfillment();

    [AcceptanceCriteria("Payment audit trail is recorded with timestamp and actor")]
    public abstract Result PaymentAuditTrailRecorded();
}

Document declaration:

[assembly: Document<Feature<OrderPaymentFeature>>(
    Format = DocumentFormat.Markdown,
    OutputPath = "docs/features")]

Generated: docs/features/OrderPaymentFeature.md

# OrderPaymentFeature

> Allow customers to pay for orders using multiple payment methods
> Priority: **Critical**

## Acceptance Criteria

| # | Criteria | Implemented | Tests | Status |
|---|---------|-------------|-------|--------|
| 0 | Order can be marked as paid with a valid payment reference | **NO** | **NO TESTS** | Gap |
| 1 | Payment method is validated against supported providers | **NO** | **NO TESTS** | Gap |
| 2 | Paid order triggers fulfillment workflow via domain event | **NO** | **NO TESTS** | Gap |
| 3 | Payment audit trail is recorded with timestamp and actor | **NO** | **NO TESTS** | Gap |

## Traceability

### Implementations
(none yet)

### API Endpoints
(none yet)

### Tests
(none yet)

Everything is a gap. That is correct — we haven't implemented anything yet. The Document DSL reports what exists.


Step 2: Implement the Domain

// src/Domain/Order.cs

[AggregateRoot(BoundedContext = "Ordering",
    Description = "Represents a customer order with line items and payment")]
[ForRequirement(typeof(OrderPaymentFeature))]
public partial class Order
{
    [EntityId]
    public partial OrderId Id { get; }

    [Composition]
    public partial IReadOnlyList<OrderLine> Lines { get; }

    [Composition]
    public partial PaymentInfo Payment { get; }

    [DomainEvent(typeof(OrderPaidEvent))]
    public Result MarkAsPaid(PaymentReference reference, PaymentMethod method)
    {
        if (!PaymentMethod.IsSupported(method))
            return Result.Failure($"Unsupported payment method: {method}");

        Payment = new PaymentInfo(reference, method, DateTime.UtcNow);
        AddDomainEvent(new OrderPaidEvent(Id, reference, method));
        return Result.Success();
    }
}

[ValueObject(Description = "Payment details including reference, method, and timestamp")]
public partial record PaymentInfo(
    PaymentReference Reference,
    PaymentMethod Method,
    DateTime PaidAt);

dotnet build now generates:

Order.g.cs                    ← entity implementation (DDD SG)
OrderRepository.g.cs          ← repository (DDD SG)
OrderConfiguration.g.cs       ← EF Core config (DDD SG)
docs/architecture/Order.md    ← architecture doc (Document DSL) ← NEW
docs/architecture/Order.mermaid ← entity diagram (Document DSL) ← NEW

Generated: docs/architecture/Order.md

# Order

> Bounded Context: **Ordering**
> Represents a customer order with line items and payment

## Entity Diagram

(see Order.mermaid)

## Compositions
- `IReadOnlyList<OrderLine> Lines` — order line items
- `PaymentInfo Payment` — payment details (ValueObject)

## Domain Events
- `MarkAsPaid()` publishes `OrderPaidEvent`

## Linked Requirements
- [OrderPaymentFeature](../features/OrderPaymentFeature.md)

The requirements doc also updates — AC#0 now shows "Implemented: yes" because Order.MarkAsPaid exists with [ForRequirement(typeof(OrderPaymentFeature))].


Step 3: Build the API

// src/Api/PayOrderEndpoint.cs

[TypedEndpoint("POST", "/api/orders/{id}/pay",
    Description = "Mark an order as paid with a payment reference",
    Version = "v2")]
[Authorized(Roles = ["PaymentProcessor", "Admin"])]
[ForRequirement(typeof(OrderPaymentFeature))]
public partial class PayOrderEndpoint
{
    public sealed record Request(OrderId Id, PaymentReference Reference, PaymentMethod Method);
    public sealed record Response(OrderId Id, OrderStatus Status, DateTime PaidAt);
}

dotnet build adds:

PayOrderEndpoint.g.cs              ← Minimal API registration (API SG)
docs/api/PayOrderEndpoint.md       ← API doc (Document DSL) ← NEW
docs/api/openapi-fragment.json     ← OpenAPI spec (Document DSL) ← NEW

Generated: docs/api/PayOrderEndpoint.md

# POST /api/orders/{id}/pay

> Mark an order as paid with a payment reference
> Version: v2

## Authorization
- Roles: `PaymentProcessor`, `Admin`

## Request
| Field | Type | Required |
|---|---|---|
| Id | OrderId | yes |
| Reference | PaymentReference | yes |
| Method | PaymentMethod | yes |

## Response
| Field | Type |
|---|---|
| Id | OrderId |
| Status | OrderStatus |
| PaidAt | DateTime |

## Requirement Link
- [OrderPaymentFeature](../features/OrderPaymentFeature.md) — AC#0: Order can be marked as paid

Step 4: Write the Tests

// tests/OrderPaymentTests.cs

[ForRequirement(typeof(OrderPaymentFeature))]
public sealed class OrderPaymentTests
{
    [Fact]
    [Verifies(typeof(OrderPaymentFeature),
        nameof(OrderPaymentFeature.OrderCanBePaid))]
    public void Order_can_be_paid_with_valid_reference()
    {
        var order = CreateTestOrder();
        var result = order.MarkAsPaid(validReference, PaymentMethod.CreditCard);
        result.IsSuccess.Should().BeTrue();
        order.Payment.Reference.Should().Be(validReference);
    }

    [Fact]
    [Verifies(typeof(OrderPaymentFeature),
        nameof(OrderPaymentFeature.PaymentMethodIsValidated))]
    public void Payment_fails_with_unsupported_method()
    {
        var order = CreateTestOrder();
        var result = order.MarkAsPaid(validReference, PaymentMethod.Unknown);
        result.IsFailure.Should().BeTrue();
    }

    [Fact]
    [Verifies(typeof(OrderPaymentFeature),
        nameof(OrderPaymentFeature.PaidOrderTriggersFulfillment))]
    public void Paid_order_publishes_OrderPaidEvent()
    {
        var order = CreateTestOrder();
        order.MarkAsPaid(validReference, PaymentMethod.CreditCard);
        order.DomainEvents.Should().ContainSingle()
            .Which.Should().BeOfType<OrderPaidEvent>();
    }

    // Note: AC#3 (PaymentAuditTrailRecorded) has NO test yet → gap
}

dotnet build adds:

docs/tests/OrderPaymentFeature-coverage.md ← test coverage (Document DSL) ← NEW

The requirements doc updates again:

## Acceptance Criteria

| # | Criteria | Implemented | Tests | Status |
|---|---------|-------------|-------|--------|
| 0 | Order can be marked as paid | yes | 1 test | Covered |
| 1 | Payment method is validated | yes | 1 test | Covered |
| 2 | Paid order triggers fulfillment | yes | 1 test | Covered |
| 3 | Payment audit trail recorded | **NO** | **NO TESTS** | Gap |

Three covered, one gap. The compiler tells you exactly what is missing.


Step 5: Define the Deployment

// src/Deployment/OrderServiceV24Deployment.cs

[DeploymentOrchestrator("v2.4.0",
    Description = "Order service v2.4 — new payment flow",
    Strategy = DeploymentStrategy.Canary)]
[DeploymentApp("OrderApi", Replicas = 3)]
[DeploymentApp("OrderWorker", Replicas = 2)]
[EnvironmentMatrix("Staging", "Production",
    RequiredSecrets = ["PaymentGateway:ApiKey"])]
[Dashboard("order-v24-deployment",
    Panels = ["error-rate", "latency-p99", "canary-traffic"])]
public partial class OrderServiceV24Deployment
{
    // ── Migration ──
    [MigrationStep(1, Database = "OrdersDb", Kind = MigrationKind.Schema,
        Parallel = true, EstimatedDuration = "30s")]
    [MigrationValidation("SELECT COUNT(*) FROM information_schema.columns WHERE column_name = 'PaymentMethod'",
        Kind = MigrationValidationKind.SchemaCheck, ExpectedResult = "1")]
    public partial Task AddPaymentMethodColumn();

    [ExeMigration(2, App = "OrderMigrator",
        Description = "Backfill payment methods", ExpectedRowCount = "~2.4M")]
    public partial Task BackfillPaymentMethods();

    // ── Configuration ──
    [ConfigTransform("Production", Section = "PaymentGateway", RequiresRestart = true)]
    public partial Task UpdatePaymentConfig();

    [Secret(VaultPath = "orders/payment-gateway-api-key",
        Provider = SecretProvider.AzureKeyVault, RotationPolicy = "30d")]
    public partial string PaymentGatewayApiKey { get; }

    // ── Observability ──
    [HealthCheck("OrderApi", Endpoint = "/health/payment",
        Timeout = "10s", Severity = HealthCheckSeverity.Critical)]
    public partial Task VerifyPaymentEndpoint();

    [Metric("order_payment_latency_ms", Kind = MetricKind.Histogram,
        Unit = "milliseconds", Labels = ["method", "status"],
        AlertThreshold = "p99 > 500ms")]
    public partial Task TrackPaymentLatency();

    [AlertRule("OrderPaymentErrorSpike",
        Condition = "rate(order_payment_errors_total[5m]) > 0.01",
        Duration = "3m", Severity = AlertSeverity.Critical,
        NotifyChannels = ["oncall-slack", "oncall-pager"],
        Runbook = "runbooks/order-payment-errors.md")]
    public partial Task MonitorPaymentErrors();

    // ── Resilience ──
    [RollbackProcedure(nameof(AddPaymentMethodColumn),
        Kind = RollbackKind.Automatic, EstimatedDuration = "10s")]
    public partial Task RollbackPaymentColumn();

    [RollbackProcedure(nameof(BackfillPaymentMethods),
        Kind = RollbackKind.Manual, RequiresApproval = true)]
    public partial Task RollbackPaymentBackfill();

    [CanaryRule(TrafficPercentage = 5, Duration = "15m",
        SuccessMetric = "order_payment_latency_ms.p99 < 300ms",
        RollbackThreshold = "error_rate > 0.5%")]
    public partial Task CanaryPaymentFlow();
}

Document declaration:

[assembly: DocumentSuite<OrderServiceV24Deployment>(
    Formats = [DocumentFormat.Markdown, DocumentFormat.Yaml, DocumentFormat.Json],
    CrossReference = true)]

Step 6: dotnet build — Every Generated File

One build. Every artifact listed:

Application Code (SGs)

# File Source
1 Order.g.cs DDD SG — entity implementation
2 OrderRepository.g.cs DDD SG — repository
3 OrderConfiguration.g.cs DDD SG — EF Core config
4 PayOrderEndpoint.g.cs API SG — Minimal API registration
5 OrderDiRegistration.g.cs Contention SG — DI registration

Documentation (Document DSL)

# File Source Strategy
6 docs/Order/architecture.md AggregateDocumentStrategy
7 docs/Order/architecture.mermaid AggregateDocumentStrategy
8 docs/Order/requirements.md FeatureDocumentStrategy
9 docs/Order/api.md EndpointDocumentStrategy
10 docs/Order/tests.md TestCoverageDocumentStrategy

Deployment & Infrastructure (Document DSL + Ops)

# File Source Strategy
11 docs/Order/deployment/runbook.md DeploymentDocumentStrategy
12 docs/Order/deployment/dag.mermaid DeploymentDocumentStrategy
13 docs/Order/deployment/grafana-dashboard.json GrafanaDocumentStrategy
14 docs/Order/deployment/prometheus-alerts.yaml PrometheusDocumentStrategy
15 docs/Order/deployment/k8s-probes.yaml KubernetesDocumentStrategy
16 docs/Order/deployment/helm-values.yaml HelmDocumentStrategy
17 docs/Order/deployment/rollback-playbook.md ResilienceDocumentStrategy
18 docs/Order/deployment/env-matrix.md ConfigurationDocumentStrategy

Cross-References & Meta

# File Source
19 docs/Order/index.md DocumentSuite — cross-referenced hub
20 docs/Order/Order.json DocumentSuite — machine-readable export

One Feature. Twenty Generated Files. Zero Manual Documentation.

The developer wrote:

  • 1 feature class with 4 acceptance criteria (15 lines)
  • 1 aggregate with domain logic (25 lines)
  • 1 endpoint (10 lines)
  • 3 test methods (30 lines)
  • 1 deployment class with Ops attributes (45 lines)

Total: ~125 lines of typed C# code.

The compiler generated:

  • 5 application code files
  • 15 documentation and infrastructure files
  • Cross-references linking every document to every related document
  • Analyzer diagnostics flagging AC#3 as untested

The developer wrote zero documentation. The types ARE the documentation. The build IS the documentation pipeline.


What's Next

Part IX — the final part — synthesizes the meta-pattern across all blog series: CMF, Contention, Typed Specs, and Auto-Doc. One pattern. Four series. Same principle: declare intent with a type → the compiler produces the artifact.