Files
harmony/docs/adr/drafts/topology-proliferation.md
2026-05-20 12:03:19 -04:00

3.3 KiB

Working draft: Topology proliferation

Not an ADR yet. A concern noted in many places that doesn't yet have a clean answer. Parked here so it doesn't get lost. When the answer is clear, promote to a numbered ADR under docs/adr/.

The concern

Harmony has accumulated topology structs without a clear rule for when a new topology is the right answer versus when a capability trait on an existing topology is the right answer:

  • K8sAnywhereTopology — dynamic discovery, the "any place that runs k8s" default.
  • HAClusterTopology — bare-metal HA with redundant firewalls/switches.
  • K8sBareTopology — minimal topology for ad-hoc Score execution (introduced in this branch).
  • FailoverTopology<T> — higher-order, primary/replica.
  • DecentralizedTopology<T> — higher-order, multi-site.
  • FirewallPairTopology, SwitchTopology, …

There is no written framework rule for which path to take. The result is a slow drift toward "every new deploy shape becomes a new topology struct," which is the opposite of ADR-015's zero-cost higher-order composition direction.

Where the concern is already noted

  • ROADMAP/12-code-review-april-2026.md task 12.6 — "topology proliferation."
  • ROADMAP/12-code-review-april-2026.md task 12.1 — phased topology (LinuxHostTopologyKvmHostTopology after package install). Different angle on the same shape problem: how does a topology gain capabilities at runtime?
  • ADR-015 ("Higher-order topologies via blanket trait impls") argues for capability composition, but doesn't lock the rule "prefer capabilities over new topology structs."
  • ADR-023 §6 references topology as compile-time-static — closing the door on Box<dyn Topology> plugins but leaving open which axis of variability is a new type and which is a capability impl.

Open question

Is the right rule:

  • (a) Capability-first: a new deploy shape adds a capability trait to an existing topology when possible; new topology structs are reserved for genuinely new physical-shape categories (single-host vs. HA vs. cloud). K8sBareTopology arguably should have been a constructor on K8sAnywhereTopology.
  • (b) Topology-first: every coherent deploy environment is its own topology. K8sBareTopology is correct; the concern is just naming and documentation.
  • (c) A test-driven middle ground: capability sets are primary, topologies are bundles of capability-set + physical context. Re-frames the existing types but doesn't break anything.

The fleet platform work (ADR-024 draft, capability decomposition) points toward (a) or (c). The framework as it stands runs on (b)-by-default.

What's needed before this can be an ADR

  • A worked example of converting one of the existing topology structs to its capability-first equivalent (probably K8sBareTopology → constructor on K8sAnywhereTopology with a feature-flag capability set).
  • A look at whether ADR-024's capability decomposition for the fleet platform suggests a generalization of the same decomposition for the framework's topology layer.
  • A look at how phased topology (task 12.1) fits — phase transition is conceptually a gain of capabilities, which is hard to express in (b) but natural in (a)/(c).

Owner

Unassigned. Next time someone touches topology code and feels the itch, this draft is the place to add their notes.