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();
}// 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")][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)# 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);// 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) ← NEWOrder.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) ← NEWGenerated: 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)# 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);
}// 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) ← NEWPayOrderEndpoint.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) ← NEWGenerated: 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# 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 paidStep 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
}// 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) ← NEWdocs/tests/OrderPaymentFeature-coverage.md ← test coverage (Document DSL) ← NEWThe 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 |## 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();
}// 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)][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.