Platform Evolution
Assessment run-2026-07-27-1 · 213 of 213 repos assessed
Analysis / Estate analysis

Estate analysis — through run-2026-07-27-1

Cross-repo themes derived from data/estate.json (all 213 in-scope repos assessed). Scope history: run-2026-07-24-1 assessed the 177 classic release-linked repos; the trace was then extended to follow build-YAML/AWS deployment signals (ECS/Terraform/Lambda via the shared InternalOSS/azure-pipelines-templates), adding 36 AWS-era repos assessed in run-2026-07-27-1, and to exclude repos deleted from or disabled in ADO git. Numbers below come from the front matter aggregated into data/estate.json and the CSV exports alongside it; regenerate with scripts/build-estate-dataset.py then scripts/export-estate-csv.py.

Estate shape

213 assessed repos: 102 APIs, 38 services, 28 web UIs, 18 jobs, 17 libraries, 4 databases, 6 other (thick clients and tooling). C# dominates; SQL, TypeScript and JavaScript follow, plus the estate's first Python service (tc-ml-margin). Two repos still contain VB.NET (travelcounsellors-net, intranet).

Modernisation priority: 41 high, 53 medium, 119 low. The low count is genuinely encouraging — over half the estate is already on .NET 8/10 with CI and at least some tests, and the newly-traced AWS estate is almost entirely modern (28 of 36 low priority, none high).

The AWS estate (new in run-2026-07-27-1)

36 repos deploy straight from build YAML to AWS with no classic release pipeline — invisible to the original trace. They cluster into payments (tc-payment-router hub plus five PSP adapter repos and the payment-components Stencil UI), the mail platform (tc-mail-orchestrator, -composer, -scheduler, -tracked, tc-mail-sender's successors), the public/myTC APIs (tc-public-*), documents (tc-document-platform, tc-copilot-document-analyser) and ML margin pricing (tc-ml-margin, tc-phenix-dynamicmargin). Mostly healthy .NET 8/10 on ECS/Lambda, but the batch adds real findings: committed secrets in phenix-destination-search (OpenSearch credentials), tc-mail-composer (Trustpilot keys) and tc-mail-tracked (Spotler/SFTP); EOL runtimes in six (paymentprovider-dummy, phenix-connectionbroker-api, tc-public-content-api, tc-public-quote-api on .NET 6, tc-ml-margin on Python 3.8, phenix-destination-search net472 remnant); a production-deployed empty Angular scaffold (tc-public-features-ui); a placeholder API returning hardcoded values (phenix-connectionbroker-api); and duplication ripe for consolidation (viewing-as-api vs useraccount-api, payment-components-v1 vs payment-components).

End-of-life stacks

The single biggest theme. 83 repos (39%) still run on .NET Framework (4.5.2 through 4.8.1), all out of mainstream support; a further 13 sit on EOL .NET Core 2.x/3.1, .NET 6, Node 8 or Python 3.8. The percentage fell from 46% only because the newly-traced AWS estate is modern — the absolute Framework count barely moved.

Concentrations worth planning around:

Coupling hotspots

Fan-in from internal_dependencies (see data/dependencies.csv):

RepoDependentsNotes
tc-connectionbroker126Central connection/config choke point for over half the estate
tc-exceptions77Recently multi-targeted net462/net8/net10, but its only test is an empty placeholder
backoffice-useraccount-service40User identity for the back-office estate
application-framework35Legacy Phenix application framework
phenix-feature-service28WCF-only feature flags on net472, no tests
company-info-api27Company/branding lookups
mail-service / mailtemplate-service21 / 18WCF mail path everything still routes through
phenix-user-api18Reaches into shared UserAccount and Phenix DBs
backoffice18The back-office monolith itself

Any framework migration plan should start by making these nine safe to consume from modern .NET — several already multi-target, but phenix-feature-service and the mail pair are WCF-only and effectively pin their consumers.

phenix-retail is the largest single coupling consumer (25+ internal dependencies, a 285-package packages.config), half-migrated to phenix-booking-ui.

Shared data stores

shared-db is flagged on 54 repos. Store-level coupling from data/data-stores.csv:

  • sqlserver:Phenix — 22 repos write to or read from the core Phenix database; its schema lives in phenix-database as an append-only change ledger with table DDL only reconstructable from history.
  • sqlserver:EventLog — 14 repos, sqlserver:ContactCentre — 9, sqlserver:TravelCounsellors/tcdb — 7, sqlserver:UserAccount — 3, sqlserver:VirtualCreditCard — 3 (vcc-service owns it; vccprovider-enett and vccprovider-wex write to it directly).
  • Redis is a second coupling plane: phenix-cache (12 repos), remote-session (9), streams (7), shared-cache (7), tc-cache (5). Redis Streams doubles as a bespoke message bus bridged to MassTransit/SQS by tc-streams-masstransit-adapter.

Repos sharing a store are coupled even without a code edge; the Phenix DB group in particular moves as one unit for schema change.

Duplicated capabilities

Strong consolidation candidates surfaced by comparing purposes:

Health and hygiene

Where to focus

  1. Unpin the core libraries — tc-connectionbroker, tc-exceptions, application-framework and the mail pair gate every other migration; make each consumable from modern .NET (or replaceable) first.
  2. Retire before rewriting — the retirement candidates (dormant + duplicated: phenix-vcc, phenix-post-booking, phenix-zendesk-forms, tc-features, tc-redis-cache-event-*, phenix-retail-configuration-service, tc-swagger-versioning, payment-components-v1, viewing-as-api, tc-public-features-ui, phenix-connectionbroker-api) shrink the Framework surface and the AWS sprawl cheaply.
  3. Treat shared databases as products — the Phenix, ContactCentre and EventLog DB groups need owners and declarative schema before service-level modernisation can proceed safely.
  4. Rotate committed secrets — 36 repos, prioritising the live production credentials called out above.
  5. Plan WCF exit as a programme, not per-repo tickets — 98 repos are touched; sequence by the fan-in table.