feat: scaffold Movements service with full CLEAN architecture#3
Closed
ericburcham wants to merge 48 commits into
Closed
feat: scaffold Movements service with full CLEAN architecture#3ericburcham wants to merge 48 commits into
ericburcham wants to merge 48 commits into
Conversation
Define architecture principles, technology stack, coding standards, NServiceBus conventions, and service creation guidelines for MidstreamHub. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set up Directory.Build.props, Directory.Packages.props, nuget.config, StyleCop ruleset, empty .slnx solution, and directory scaffolding for Contracts, Nominations, Shared packages, Web UI, K8S manifests, and Nuke build. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert solution from .slnx to .sln format for Nuke compatibility. Add Nuke build with targets: Clean, Restore, Compile, Test, IntegrationTest, Pack, DockerBuild. Default chain runs Clean → Restore → Compile → Test. Fix TFM to net10.0 for Nuke.Common 10.1.0 compatibility. Also adds .claude/settings.local.json to .gitignore and updates all .slnx references to .sln across config files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nfrastructure.Common) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Counterparty/Product demoted from AggregateRoot to EntityBase - Added missing NuGet packages (MediatR.Extensions.Autofac.DependencyInjection, Microsoft.Data.SqlClient) - Added Autofac + Infrastructure.Common refs to Application .csproj - Added parameterless constructors to shared Volume/UnitOfMeasure VOs - Fixed counterparty lookup to use GetAllAsync (not just active) - Added ProductNotFound test case - Fixed K8S port mapping (container 8080, Service 5001->8080) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ors to shared VOs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… Product entities + domain tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…idators + unit tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ations, repositories, Autofac module Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…module, NServiceBus Add the Contracts API host project with: - Autofac DI composition via ContractsModule (root) and ContractsDomainModule - NServiceBus endpoint with RabbitMQ transport and SQL persistence - Minimal API endpoints for contracts, products, and counterparties - Global exception handler with RFC 7807 ProblemDetails responses - ConversationId middleware and Swagger for development - Fix NuGet package names: NServiceBus.RabbitMQ (was Transport.RabbitMQ), add NServiceBus.Extensions.Hosting for UseNServiceBus host integration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds migrations, migration runner, integration tests, K8S manifests, and wires all 7 projects into the solution. 17/17 unit tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ContractType validation Remove the Application project reference from Infrastructure.csproj (CLEAN architecture: Infrastructure depends on Domain, not Application). Add enum validation for ContractType in CreateContractCommandValidator to prevent unhandled ArgumentException for invalid values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add proper exit code handling and progress logging to the migrations runner for reliable K8S job execution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ract Add idempotent ContractsDataSeeder that runs on API startup to seed reference NGL products (C2–C5+), counterparties, and a sample supply contract. Seeder is registered via Autofac and invoked before endpoints. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add proxy root cert to Dockerfiles for nuget.org SSL trust - Copy local-nuget feed into Docker build context - Remove --no-restore from dotnet publish to avoid stale cache - Add init container to migration Job for DB creation and readiness wait - Fix Tiltfile: remove premature nominations/web-ui refs, fix non-workload resources - Add NServiceBus SystemJsonSerializer (required in v9) - Document Docker & Tilt conventions in CLAUDE.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use correct .NET config key separator (`:` not `__`) for RabbitMQ host/port lookup — .NET normalizes env var `__` to `:` in IConfiguration, so the lookup was returning null and falling back to localhost. Also add TCP readiness probe to RabbitMQ deployment for startup ordering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the complete Nominations service following the Contracts reference
implementation patterns: CLEAN architecture with Domain, Application,
Infrastructure, Api, Migrations, and Tests layers.
- Domain: Nomination aggregate root with state machine (Submitted → Scheduled → InProgress → Completed/Rejected)
- Application: CreateNominationCommand with contract validation via HTTP API, NServiceBus event publishing
- Infrastructure: EF Core DbContext (nominations schema), repository, ContractsApiClient
- Api: Minimal API endpoints (GET /, GET /{id}, POST /), NServiceBus + RabbitMQ config
- Migrations: FluentMigrator schema with nominations.Nominations table
- Tests: 18 unit tests (domain state transitions, handler, validator)
- K8S: Deployment, Service, and migration Job with wait-for-db init container
- Tilt: Added to ACTIVE_SERVICES with proper docker/certs and local-nuget support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each migration runner now uses a custom IVersionTableMetaData that places the VersionInfo table in its own schema (contracts/nominations) instead of dbo, preventing collisions when multiple runners target the same database. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enterprise Products-branded dark theme with sidebar navigation, pipeline visualization dashboard, contracts CRUD with forms/modals, nominations submission with saga notification, and placeholder pages for movements and accounting. Includes typed API client, k8s manifest, and Tilt config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Ingress resource required an Ingress Controller that was never deployed, causing all frontend API calls to fail silently. This replaces it with a plain nginx:alpine reverse proxy using upstream blocks, health probes, and proper Tilt resource dependencies to ensure backends are ready before nginx starts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix Tilt port-forwards to target container port 8080 instead of host ports, add private parameterless constructor to ProductCode for EF Core materialization, and make Vite proxy target configurable via VITE_API_TARGET env var for K8S. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ache-busting - Fix nginx trailing-slash redirects leaking internal K8S hostnames to browser by removing trailing slashes from location/proxy_pass directives - Add Vite proxy autoRewrite to rewrite redirect Location headers - Rename VITE_API_TARGET to API_PROXY_TARGET (VITE_ prefix leaks to client) - Fix contract type dropdown to match backend enum (Supply/Transport/Exchange) - Add Cache-Control headers to nginx API locations to prevent stale 301 caching - Update CLAUDE.md, skills, agents, and script.md with lessons learned: nginx trailing-slash convention, Tilt port-forward mapping, EF Core private constructors, Vite env var naming, frontend-backend enum alignment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract fetch logic into a reusable callback and poll every 5 seconds so the dashboard stays current without manual refresh. Subsequent polls update silently without triggering the loading spinner. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a three-job CI pipeline: build-and-test (all branches), publish NuGet packages to GitHub Packages (main/develop), and Docker image builds (main/develop/release). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves Node.js 20 deprecation warning by upgrading checkout to v6, setup-dotnet to v5, and setup-node to v6. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add GitHub Actions CI workflow
Alpine-based Node images don't trust the corporate proxy root cert, causing npm ci to fail. Inject the cert into Alpine's CA bundle and set NODE_EXTRA_CA_CERTS in both build and dev stages. Also add docker/certs to the Tiltfile only filter for the web-ui build. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swashbuckle 7.2.0 didn't support .NET 10, so Swagger UI returned nothing. Upgrade to 10.1.5 (and Microsoft.AspNetCore.OpenApi to 10.0.4), simplify AddSwaggerGen calls to avoid removed OpenApiInfo type, and remove the dev-only gate so OpenAPI docs are always served. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename the Swagger UI route prefix and JSON endpoint template from /swagger to /openapi to avoid the defunct Swagger branding. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the Node/Alpine corporate proxy cert workaround (manual CA bundle approach), split cert instructions by base image type, and add OpenAPI conventions for Swashbuckle v10 route configuration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sync the demo script with all changes made during end-to-end testing: - Solution structure: fix skills list, k8s filenames, add docker/certs, Dockerfile.web, shared packages - CLAUDE.md section: add Docker/Tilt, Nginx, Vite, and OpenAPI conventions - Replace non-existent hooks config with actual enabledPlugins settings - Fix /swagger references to /openapi throughout prompts and demo narration - Update NuGet package versions appendix to match Directory.Packages.props - Add corporate proxy cert handling to Dockerfile instructions - Add MidstreamHub.Nominations.Messages shared package Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ProcessTasks.StartProcess with DockerTasks.DockerBuild so that Nuke's [LogErrorAsStandard] attribute handles Docker's stderr output correctly. Also skip services whose source directories don't exist yet. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
End-to-end verification, OpenAPI fixes, and CI improvements
Add the Movements SOR service following the Contracts reference implementation:
- Domain: Movement aggregate root with state machine (Scheduled → InTransit →
Delivered → Confirmed/Rejected), value objects (ContractReference, ProductCode,
Volume), and repository interface
- Application: NServiceBus HandleScheduleMovement handler, MediatR
ConfirmMovementCommand with FluentValidation, GetMovementById/List queries,
IContractsApiClient for cross-service hydration
- Infrastructure: EF Core DbContext (movements schema), entity configuration
with owned value objects, MovementRepository, ContractsApiClient HTTP client
- Api: Minimal API endpoints (GET /, GET /{id}, PUT /{id}/confirm), Autofac
module-per-layer, NServiceBus endpoint, OpenAPI at /openapi
- Migrations: FluentMigrator M0001 with schema isolation, MovementsVersionTableMetaData
- Tests: 16 unit tests (domain transitions, NServiceBus handler, MediatR handler)
and integration migration test with TestContainers
- K8S: Deployment + Service (port 5003), migration Job with init container
- Tilt: Added to ACTIVE_SERVICES, nginx upstream + location block
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
HandleScheduleMovementhandler, MediatRConfirmMovementCommand, and query handlersTest plan
tilt updeploys movements-api and movements-migrations successfullyGET /api/movements/returns empty listPOSTa nomination triggersScheduleMovementcommand → creates movement via NServiceBus handlerPUT /api/movements/{id}/confirmconfirms movement and publishesMovementConfirmedevent/api/movements/openapi🤖 Generated with Claude Code