Platform Evolution
Assessment run-2026-07-27-1 · 213 of 213 repos assessed
Repos / tc-mail-orchestrator

tc-mail-orchestrator

.NET 8 orchestration service for automated customer emails: consumes booking/TC Score/passport events over MassTransit and schedules the right email (thank-you, pre-departure, welcome-home, reminders) via the mail scheduler and composer.

93 · greenlowlooseAWSZDD: no excuseservice

Health score

93

0 to 100 across seven weighted factors; nothing is hidden. Green is 75 and above, amber 50 to 74, red below 50. How scoring works.


Runtime currency / 25
25
Runs on supported modern .NET
Legacy transport / 15
15
No legacy WCF or SOAP surface
Test posture / 15
8
Some tests, coverage is thin
Security hygiene / 15
15
No credentials found in source
Dangerous coupling / 15
15
No dangerous coupling detected
Activity / 10
10
Actively maintained
Deployment hygiene / 5
5
CI in place
Health over time
2026-07-27 (run-2026-07-27-1): 93
Baseline 93 recorded 2026-07-27. The trend fills in with each monthly assessment run.

Facts

Languagescsharp
FrameworksASP.NET Core 8, MassTransit 8
Runtimes.NET 8
Tests / CIsome / CI in place
Last commit2026-06-08
OwnerOwner unknown (mapping to be curated)
DomainCustomer communications (system generated; curate in repo-owners.json to override)
Product areaShared platform
HostedAWS Deployed to AWS
  • build "tc-mail-orchestrator" (azure-pipeline.yaml): AWS signal "ecsTerraformRepo"
Releases0 release pipeline(s):
Integrationrest, masstransit, sqs
SourceOpen in Azure DevOps

Risk flags

Each flag links to its glossary definition.

Dependencies in context

Laying out the graph…
greenamberreddata store (square, dashed link)Node size follows fan-in. Click any node to open it.

Entanglement

loose No binding mechanisms apply: this system needs no untangling work.

    Migration playbooks

    Generated from this repo's assessment data: what is feasible, what blocks it, and the steps in order. Ratings: green means actionable now, amber means sequence other work first, red means blocked, grey means not applicable.

    ZDD adoption

    No excuse

    Nothing technical is holding this repo on the three-week release. It either already deploys without downtime (AWS) or is a modern, well-tested service the automated stealth path can carry today. Already deploys as a container to AWS, which releases without downtime today. Separating it from the three-week release is a process decision, not a technical one.

    Dependencies and gotchas
    • Serialized state or messages in flight (Redis or queues): new code must deserialize objects written by the previous version
    Steps
    1. Adopt the four-stage discipline from the ZDD engineering standard: pre-deployment compatibility, deployment, feature activation behind a flag, post-release cleanup.
    2. Raise automated test coverage first: ZDD trades the end-of-sprint manual gate for continuous automated confidence, so the tests are the entry ticket.
    3. Make every change dual-version safe: backwards-compatible APIs (new major version for breaking wire changes), expand and contract for any schema change, and consumers tolerant of unknown fields.
    4. Audit serialized data: anything in Redis, queues or shared caches must deserialize cleanly across adjacent versions.
    5. Wrap behaviour changes in feature flags so code deploys dark and release becomes a business decision, not a deployment event.
    6. Use ECS rolling deployments with health checks gating traffic, and take this service off the three-week release train.
    7. Verify with area-scoped regression rather than the whole-platform cycle, and watch error rates after rollout with automated rollback on alert.

    SQL Server exit

    Not applicable

    No SQL Server dependency is recorded for this repo. Nothing to migrate.

    Containerisation

    Already containerised

    Its pipelines already build containers and deploy to AWS. Nothing to do here.

    Recommended actions

    No specific actions for this repo. It either needs only normal maintenance, or its work is covered by an estate-level action. See the full programme.

    Assessment notes

    tc-mail-orchestrator

    Purpose

    The decision layer of the modern TC mail pipeline. Event-adapter consumers handle BookingChanged (arriving from Redis streams via the streams-MassTransit adapter), PassportExpiringSoon, TC Score saved/updated/deleted, and ScheduleCustomEmailCommand; per-email-type rules in config (ThankYouForBooking +2 days from booking, HaveANiceTime -4 days before departure, WelcomeHome +2 days after return, PassportReminder -270 days before expiry, TcScore/TcScoreReminder) compute send times, and scheduling/composition commands are issued to tc-mail-scheduler and tc-mail-composer.

    Tech stack

    C# on .NET 8: MassTransit 8.5 over Amazon SQS/SNS with S3 claim-check support, FluentValidation, Polly, Swashbuckle/OpenAPI on the host, TC.Cognito.Auth.Client for outbound authenticated calls, ConnectionBroker, TC health checks. Sub-projects wrap the mail-scheduler API client and a PublicTravelCounsellors API client; tools/CustomEmailSender.Net10 is a documented console test client for injecting custom email commands.

    Deployment

    Included via build->yaml-deploy with 0 classic releases: build pipeline tc-mail-orchestrator from azure-pipeline.yaml, shared InternalOSS ci.yml (SDK 8.x), containerAfterBuild: true into the cx namespace, ECS Terraform from aws-cx-tc-apps (eu-west-1, functional area cx).

    Dependencies

    Internal: TC.Mail.Composer.Contracts (tc-mail-composer), TC.Mail.Scheduler.Contracts (tc-mail-scheduler), TC.StreamsMassTransitAdapter.Events (tc-streams-masstransit-adapter), TC.PassportExpiration.Service.Events (tc-passport-expiration-service), Phenix.Contact.Contracts (phenix-contact-api), TC.Phenix.CompanyInfo (company-info-api), the public Travel Counsellors profile API (tc-public-travelcounsellors) and TC.ConnectionBroker.*/TC.Diagnostics platform packages. External: AWS Cognito for service-to-service auth.

    Data stores

    None of its own — state lives with the scheduler; the orchestrator is stateless event-in/command-out logic with config-driven timing calculators and email-rewrite processors.

    Integration points

    MassTransit over Amazon SQS/SNS for all event consumption and command publication; outbound REST (via ConnectionBroker with Cognito auth) to the mail-scheduler and public-TC APIs; a small inbound HTTP host with Swagger and health checks.

    Code health

    One unit-test project (~14 test files) covering calculators and consumers — adequate but not deep. The README is mostly boilerplate except for a genuinely useful test-client section. Actively maintained — last commit 2026-06-08.

    Modernisation risks

    Low — modern .NET 8, containerised, message-driven. Risks are of the coupling kind: it sits at the centre of the mail pipeline fan-out (five upstream event/contract packages and two downstream mail services), so contract version drift is the likeliest breakage, and email-timing business rules live in per-environment config that has no owning UI or validation.

    Data store follow-up (2026-07-28)

    A targeted scan of project files confirmed no database. The service uses Amazon S3 through MassTransit.AmazonS3 (large message payloads offloaded to a message-data bucket, resolved at runtime via SSM), now recorded as a data store, alongside SQS/SNS messaging via MassTransit.