Skip to content

feat: alignment improvements — DDD building blocks, testing package, and example extensions#17

Merged
aseguragonzalez merged 20 commits into
mainfrom
feat/improve-aligment
May 18, 2026
Merged

feat: alignment improvements — DDD building blocks, testing package, and example extensions#17
aseguragonzalez merged 20 commits into
mainfrom
feat/improve-aligment

Conversation

@aseguragonzalez
Copy link
Copy Markdown
Owner

@aseguragonzalez aseguragonzalez commented May 18, 2026

Summary

A batch of non-breaking enhancements and breaking changes to align the library with the TypeScript seedwork counterpart and internal design decisions.

Non-breaking (B-series)

  • B0aggregate_id added to DomainEvent protocol and BaseDomainEvent
  • B1AccountOpenedIntegrationEvent: causation_id now correctly set to event.id; correlation_id read from ContextVar
  • B2InMemoryRepository gains RepositorySpy protocol with reset() and all accessor
  • B3IntegrationEventPublisherSpy marked @runtime_checkable
  • B4 — Infrastructure concrete classes no longer inherit from Protocol explicitly
  • B5BankAccountRepository redundant Protocol base reverted (structural typing preserved)
  • B6 — End-to-end composition root test added to the bank_account example
  • B7BaseIntegrationEvent consolidated into integration_events.py; base_integration_event.py deleted
  • B8AccountOpenedIntegrationEvent declares TYPE / VERSION as ClassVar[str]

Breaking (A-series / vNext)

  • A1Result.succeeded()Result.ok()
  • A2DomainEventRecordBaseDomainEvent
  • A3Result.ok: bool field → is_ok / is_failed properties
  • A4 — New src/seedwork/testing/ package (InMemoryRepository, RepositorySpy, InMemoryTaskScheduler, TaskSchedulerSpy, InMemoryIntegrationEventPublisher, IntegrationEventPublisherSpy, outbox in-memory helpers); removed from seedwork.infrastructure and seedwork.application

Example extensions (E-series)

  • E-withdrawwithdraw_money use case (WithdrawMoneyCommand, WithdrawMoneyHandler, tests); wired into composition_root.py
  • E6SendWelcomeEmailTask background task: AccountOpenedDomainEventHandler now schedules a task; composition_root wires InMemoryTaskScheduler; tests cover scheduling and execute_scheduled()

Fixes

  • WithdrawMoneyCommand was missing from build_command_bus(); added WithdrawMoneyHandler registration and composition-level tests for deposit and withdraw paths
  • docs/examples/bank_account/tests added to testpaths in pyproject.toml so example tests are collected by uv run pytest and CI automatically (156 tests total, up from 132)
  • check and test-no-cov added to .PHONY in Makefile so make all always runs the intended commands regardless of filesystem state

Test plan

  • make check passes (lint + typecheck + 156 tests at 100% coverage)
  • Example tests run as part of the default suite — no extra flags needed
  • Breaking changes confirmed: Result.ok, BaseDomainEvent, seedwork.testing imports

🤖 Generated with Claude Code

aseguragonzalez and others added 17 commits May 17, 2026 16:18
- Add `make pre-commit` to run all pre-commit hooks against all files
- Add `make all` as the full validation gate (check + pre-commit)
- Simplify devcontainer postCreateCommand to use `make install`
- Fix CHANGELOG.md consecutive blank lines that broke markdownlint (MD012)
- Document new targets in CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…te() hook

- Entity and AggregateRoot are now abstract classes; direct instantiation is
  prevented and validate() is declared abstract, forcing subclasses to
  explicitly define their invariants
- ValueObject is abstract with a no-op validate() default, since VOs with no
  invariants beyond their field types are legitimate
- validate() is called from __post_init__ in both base classes, removing the
  need for subclasses to call super().__post_init__()
- Update bank_account example: Money moves validation from __post_init__ to
  validate(); BankAccount implements the required validate() stub
- Update test fixtures to implement validate()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes account_id from event payloads — aggregate_id on the base
covers identity and enables traceability without payload duplication.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…m ContextVar

Adds request_context.py with the correlation_id ContextVar and documents
the correlation/causation propagation pattern in coding-standards.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds all property and reset() so test suites can inspect and clear
state without injecting extra infrastructure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nce checks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ncrete classes

Structural typing (pyright strict) validates compliance without inheritance.
Handlers retain explicit inheritance as idiomatic intent declaration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verifies the full wiring: OpenAccountCommand → repository → domain event
→ AccountOpenedDomainEventHandler → AccountOpenedIntegrationEvent published.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes base_integration_event.py — all integration event contracts now
live in a single module alongside IntegrationEvent, IntegrationEventPublisher,
IntegrationEventPublisherSpy, and IntegrationEventHandler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Event

Documents the canonical subclass pattern for BaseIntegrationEvent in
coding-standards.md, aligned with the BaseBackgroundTask convention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
….is_ok

Aligns the factory method name with TS/PHP conventions. The ok field is
renamed to is_ok to avoid the classmethod/field namespace conflict in
Python dataclasses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aligns naming with BaseIntegrationEvent and makes the base class
relationship explicit. DomainEventRecord implied persistence semantics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exposes is_ok/is_failed as @Property over internal _ok field,
aligning with isOk()/isFailed() patterns in TS and PHP.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create src/seedwork/testing/ with repository, task_scheduler,
integration_event_publisher, and outbox modules. Remove these helpers
from seedwork.infrastructure and seedwork.application to keep the
production surface clean. Update all test and example imports accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add WithdrawMoneyCommand, WithdrawMoneyHandler, and handler tests
covering successful withdrawal, account-not-found, and insufficient-funds.
Mirrors the deposit_money use case structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AccountOpenedDomainEventHandler now schedules a SendWelcomeEmailTask
after publishing the integration event. composition_root wires
InMemoryTaskScheduler with SendWelcomeEmailTaskHandler. Tests verify
scheduling and execute_scheduled() end-to-end.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 18, 2026 18:20
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aligns the Python seedwork with updated DDD/testing conventions, moving test doubles into seedwork.testing, renaming result/domain-event APIs, and extending the bank account example with withdraw and welcome-email task flows.

Changes:

  • Introduces BaseDomainEvent, Result.ok()/is_ok/is_failed, and a new seedwork.testing package for in-memory/spying utilities.
  • Refactors infrastructure exports to remove testing-only concrete classes and rely on structural typing.
  • Extends the bank account example with withdraw handling, task scheduling, correlation/causation propagation, and related docs/tests.

Reviewed changes

Copilot reviewed 62 out of 65 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
uv.lock Updates package lock version to 0.3.0.
tests/infrastructure/test_transactional_command_bus.py Updates assertions to Result.is_ok.
tests/infrastructure/test_registry_command_bus.py Updates assertions to Result.is_ok.
tests/infrastructure/test_outbox.py Moves in-memory outbox imports to seedwork.testing.
tests/infrastructure/test_in_memory_task_scheduler.py Moves scheduler/spy imports to seedwork.testing.
tests/infrastructure/test_in_memory_repository.py Moves repository imports and adds all/reset spy coverage.
tests/infrastructure/test_in_memory_integration_event_publisher.py Moves publisher imports and adds spy protocol coverage.
tests/infrastructure/test_domain_event_coordinator_command_bus.py Updates result factory/assertion API usage.
tests/infrastructure/test_deferred_domain_event_bus.py Migrates domain event fixtures to BaseDomainEvent with aggregate_id.
tests/infrastructure/test_command_bus_builder.py Updates result assertion API usage.
tests/infrastructure/test_bus_stack_composition.py Moves repository import and updates result assertion API usage.
tests/domain/test_entity.py Adds concrete validate() implementations for abstract Entity tests.
tests/domain/test_domain_event.py Migrates domain event tests to BaseDomainEvent and aggregate_id.
tests/application/test_result.py Updates result API tests and adds failed-state checks.
tests/application/test_open_account_handler.py Moves repository import to seedwork.testing.
tests/application/test_deposit_money_handler.py Moves repository import to seedwork.testing.
src/seedwork/testing/task_scheduler.py Keeps task scheduler structurally typed against the spy protocol.
src/seedwork/testing/repository.py Adds testing repository and RepositorySpy.
src/seedwork/testing/outbox.py Adds in-memory outbox repositories and spy protocols.
src/seedwork/testing/integration_event_publisher.py Adds runtime-checkable publisher spy protocol.
src/seedwork/testing/__init__.py Exports testing utilities.
src/seedwork/infrastructure/transactional_command_bus.py Removes explicit protocol inheritance.
src/seedwork/infrastructure/registry_query_bus.py Removes explicit protocol inheritance.
src/seedwork/infrastructure/registry_command_bus.py Removes explicit protocol inheritance and returns Result.ok().
src/seedwork/infrastructure/outbox.py Removes testing-only in-memory outbox implementations.
src/seedwork/infrastructure/in_memory_repository.py Deletes infrastructure in-memory repository implementation.
src/seedwork/infrastructure/domain_event_coordinator_command_bus.py Uses result.is_ok.
src/seedwork/infrastructure/__init__.py Removes testing-only exports from infrastructure.
src/seedwork/domain/value_object.py Adds validate() hook via __post_init__.
src/seedwork/domain/entity.py Makes entities abstract with required validate().
src/seedwork/domain/domain_event.py Replaces DomainEventRecord with BaseDomainEvent including aggregate_id.
src/seedwork/domain/__init__.py Updates domain exports.
src/seedwork/application/integration_events.py Consolidates BaseIntegrationEvent into integration events module.
src/seedwork/application/commands.py Renames result state API.
src/seedwork/application/base_integration_event.py Deletes old base integration event module.
src/seedwork/application/__init__.py Updates application exports.
src/seedwork/__init__.py Updates package root exports.
README.md Removes best-practices guide link.
Makefile Adds pre-commit and all targets.
docs/README.md Removes best-practices guide link.
docs/getting-started.md Removes best-practices guide link.
docs/examples/bank_account/tests/test_withdraw_money_handler.py Adds withdraw handler tests.
docs/examples/bank_account/tests/test_send_welcome_email_task_handler.py Adds task scheduling/execution tests.
docs/examples/bank_account/tests/test_composition_root.py Adds composition-root integration event test.
docs/examples/bank_account/infrastructure/in_memory_bank_account_repository.py Moves repository base import to seedwork.testing.
docs/examples/bank_account/domain/money.py Migrates validation to ValueObject.validate().
docs/examples/bank_account/domain/events/account_opened.py Migrates event to BaseDomainEvent.
docs/examples/bank_account/domain/events/account_debited.py Migrates event to BaseDomainEvent.
docs/examples/bank_account/domain/events/account_credited.py Migrates event to BaseDomainEvent.
docs/examples/bank_account/domain/bank_account.py Adds aggregate_id, validate(), and debit event updates.
docs/examples/bank_account/composition_root.py Wires task scheduler and welcome-email task handling.
docs/examples/bank_account/application/withdraw_money/withdraw_money_handler.py Adds withdraw command handler.
docs/examples/bank_account/application/withdraw_money/withdraw_money_command.py Adds withdraw command DTO.
docs/examples/bank_account/application/withdraw_money/__init__.py Adds withdraw package marker.
docs/examples/bank_account/application/send_welcome_email/send_welcome_email_task.py Adds welcome-email background task.
docs/examples/bank_account/application/send_welcome_email/send_welcome_email_task_handler.py Adds welcome-email task handler.
docs/examples/bank_account/application/send_welcome_email/__init__.py Adds welcome-email package marker.
docs/examples/bank_account/application/request_context.py Adds request-scoped correlation ID context variable.
docs/examples/bank_account/application/account_opened_integration_event.py Updates integration event metadata and causation/correlation propagation.
docs/examples/bank_account/application/account_opened_domain_event_handler.py Schedules welcome-email task after publishing integration event.
docs/coding-standards.md Documents correlation ID and integration event conventions.
docs/best-practices.md Deletes the best-practices guide.
CLAUDE.md Documents new validation commands.
CHANGELOG.md Cleans up spacing.
.devcontainer/devcontainer.json Uses make install for setup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/examples/bank_account/tests/test_withdraw_money_handler.py
aseguragonzalez and others added 2 commits May 18, 2026 20:28
Register WithdrawMoneyHandler in build_command_bus so compose() can
dispatch WithdrawMoneyCommand without KeyError. Add composition-level
tests for deposit and withdraw paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add docs/examples/bank_account/tests to testpaths so uv run pytest
and CI collect the example tests automatically without extra flags.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 18, 2026 18:30
@aseguragonzalez aseguragonzalez self-assigned this May 18, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 66 changed files in this pull request and generated 3 comments.

Comment thread Makefile Outdated
Comment thread src/seedwork/application/commands.py
Prevents make from skipping these targets if a file or directory with
the same name exists in the working tree.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@aseguragonzalez aseguragonzalez merged commit 688f036 into main May 18, 2026
9 checks passed
@aseguragonzalez aseguragonzalez deleted the feat/improve-aligment branch May 18, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants