ddd-architecture

star 0

Comprehensive DDD (Domain-Driven Design) skill for Xuanwu. Covers all four layers (Presentation, Application, Domain, Infrastructure), implementation patterns, scaffolding, and audit workflows. Use when designing, implementing, or auditing DDD-structured code in this repository.

7Spade By 7Spade schedule Updated 3/16/2026

name: ddd-architecture description: 'Comprehensive DDD (Domain-Driven Design) skill for Xuanwu. Covers all four layers (Presentation, Application, Domain, Infrastructure), implementation patterns, scaffolding, and audit workflows. Use when designing, implementing, or auditing DDD-structured code in this repository.'

DDD Architecture Skill

This skill provides comprehensive guidance for Domain-Driven Design implementation in Xuanwu. It covers all four layers and the agent/prompt kit that drives the DDD development cycle.

When to use

  • Designing a new domain module with proper DDD layering.
  • Auditing existing code for layer boundary violations.
  • Implementing entities, value objects, aggregates, or use cases.
  • Wiring infrastructure adapters to port interfaces.
  • Building a new bounded context from scratch.

DDD Layer Architecture

┌──────────────────────────────────────────────┐
│ Presentation Layer                           │
│ src/app/, src/modules/{module}/_components/  │
│ UI components, Server Actions (thin wrapper) │
└─────────────────────▲────────────────────────┘
                      │ calls (Application API only)
┌─────────────────────┴────────────────────────┐
│ Application Layer                            │
│ src/modules/{module}/core/_use-cases.ts      │
│ src/modules/{module}/core/_actions.ts        │
│ src/modules/{module}/core/_queries.ts        │
│ Use Cases, Command Handlers, Query Handlers  │
└─────────────────────▲────────────────────────┘
                      │ calls (Domain objects)
                      │ calls (Port interfaces in same module)
┌─────────────────────┴────────────────────────┐
│ Domain Layer                                 │
│ src/modules/{module}/domain.*/_entity.ts     │
│ src/modules/{module}/domain.*/_value-objects │
│ src/modules/{module}/domain.*/_ports.ts      │
│ Entities, VOs, Domain Services, Events       │
└─────────────────────▲────────────────────────┘
                      │ implements (Port interfaces)
┌─────────────────────┴────────────────────────┐
│ Infrastructure Layer                         │
│ src/modules/{module}/infra.{adapter}/        │
│ Firestore repos, Redis, QStash adapters      │
└──────────────────────────────────────────────┘

DDD Development Order (always follow this sequence)

Step Layer Agent Prompt command
1 Domain ddd-domain-modeler /ddd-domain-model
2 Application ddd-application-layer /ddd-application-service
3 Infrastructure ddd-infrastructure /ddd-infrastructure-adapter
4 Presentation xuanwu-ui / xuanwu-implementer /xuanwu-ui / /xuanwu-implementer

Full cycle shortcut: /ddd-slice-scaffold via ddd-orchestrator. Audit existing code: /ddd-layer-audit via ddd-orchestrator.

Domain Layer Patterns

Entity (Aggregate Root)

// src/modules/{module}/domain.{context}/_entity.ts
export class OrderEntity {
  private _events: DomainEvent[] = []

  private constructor(
    readonly id: OrderId,
    private _status: OrderStatus,
    private _items: OrderItem[],
  ) {}

  static create(cmd: CreateOrderCommand): Result<OrderEntity> {
    if (cmd.items.length === 0) return Err('items_required')
    const entity = new OrderEntity(OrderId.generate(), OrderStatus.draft(), cmd.items)
    entity._events.push(new OrderCreatedEvent(entity.id))
    return Ok(entity)
  }

  confirm(actor: ActorId): Result<void> {
    if (!this._status.canTransitionTo('confirmed')) return Err('invalid_transition')
    this._status = OrderStatus.confirmed()
    this._events.push(new OrderConfirmedEvent(this.id, actor))
    return Ok(undefined)
  }

  pullDomainEvents(): DomainEvent[] {
    const events = [...this._events]
    this._events = []
    return events
  }
}

Value Object

// Immutable, self-validating, equality by value
export class OrderId {
  private constructor(readonly value: string) {}
  static generate(): OrderId { return new OrderId(nanoid()) }
  static from(raw: string): Result<OrderId> {
    if (!raw || raw.length < 1) return Err('invalid_id')
    return Ok(new OrderId(raw))
  }
  equals(other: OrderId): boolean { return this.value === other.value }
}

Application Layer Patterns

Use Case (Command Handler)

// src/modules/{module}/core/_use-cases.ts
export async function confirmOrderUseCase(
  cmd: ConfirmOrderCommand,
  deps: { repo: IOrderRepository; events: IEventBus }
): Promise<CommandResult> {
  const order = await deps.repo.findById(OrderId.from(cmd.orderId).unwrap())
  if (!order) return CommandResult.notFound('order')

  const result = order.confirm(ActorId.from(cmd.actorId).unwrap())
  if (!result.ok) return CommandResult.domainError(result.error)

  await deps.repo.save(order)                          // S1: atomic write + outbox
  await deps.events.publishAll(order.pullDomainEvents())

  return CommandResult.success()
}

Server Action (Presentation → Application bridge)

// src/modules/{module}/core/_actions.ts
'use server'
export async function confirmOrderAction(orderId: string): Promise<ActionResult> {
  const session = await getServerSession()
  const deps = resolveDeps()  // inject concrete adapters here
  return confirmOrderUseCase({ orderId, actorId: session.userId }, deps)
}

Infrastructure Layer Patterns

Repository Adapter

// Implements IOrderRepository port interface
export class FirestoreOrderRepository implements IOrderRepository {
  async save(order: OrderEntity): Promise<void> {
    await db.runTransaction(async (tx) => {
      tx.set(db.doc(`orders/${order.id.value}`), OrderMapper.toDoc(order))
      // S1: write domain events to outbox atomically
      for (const event of order.pullDomainEvents()) {
        tx.set(db.collection('outbox').doc(), OutboxMapper.toDoc(event))
      }
    })
  }
}

Port Interface Pattern

// src/modules/{module}/domain.{context}/_ports.ts
export interface IOrderRepository {
  findById(id: OrderId): Promise<OrderEntity | null>
  save(order: OrderEntity): Promise<void>
  findByWorkspace(workspaceId: WorkspaceId): Promise<OrderEntity[]>
}

Slice Public API Pattern

// src/modules/{module}/index.ts
// ONLY export presentation-safe APIs
export { confirmOrderAction } from './core/_actions'
export { getOrdersQuery } from './core/_queries'
export type { OrderDTO, OrderStatus } from './_contract'
// Do NOT export: entities, VOs, repositories, domain events

Agent and Prompt Kit

Available Agents

Agent Role
ddd-orchestrator Entry point, coordinates DDD delivery order
ddd-domain-modeler Domain layer: entities, VOs, aggregates, invariants
ddd-application-layer Application layer: use cases, actions, queries
ddd-infrastructure Infrastructure layer: repository, outbox, event bus

Available Prompts

Slash command What it does
/ddd-domain-model Design/implement domain entities or VOs
/ddd-application-service Design/implement use cases and application services
/ddd-infrastructure-adapter Implement repository or outbox adapters
/ddd-layer-audit Audit layer compliance and D24 violations
/ddd-slice-scaffold Scaffold a complete new DDD module (all 4 layers)

Related Repository Files

  • DDD layer rules: .github/instructions/xuanwu-ddd-layers.instructions.md
  • Architecture SSOT: docs/architecture/README.md
  • Business entities: docs/architecture/catalog/business-entities.md
  • Event catalog: docs/architecture/catalog/event-catalog.md
  • Domain modules: src/modules/README.md
Install via CLI
npx skills add https://github.com/7Spade/xuanwu-platform --skill ddd-architecture
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator