public boolean satisfies(ClusterSpec other) {
        if ( ! other.id.equals(this.id)) return false; // ID mismatch
        if (other.type.isContent() || this.type.isContent()) // Allow seamless transition between content and combined
            return other.type.isContent() == this.type.isContent();
        return other.type.equals(this.type);
    }
@Test
    void testSatisfies() {
        var tests = Map.of(
                               List.of(spec(ClusterSpec.Type.content, "id1"), spec(ClusterSpec.Type.content, "id2")), false,
                               List.of(spec(ClusterSpec.Type.admin, "id1"), spec(ClusterSpec.Type.container, "id1")), false,
                               List.of(spec(ClusterSpec.Type.admin, "id1"), spec(ClusterSpec.Type.content, "id1")), false,
                               List.of(spec(ClusterSpec.Type.combined, "id1"), spec(ClusterSpec.Type.container, "id1")), false,
                               List.of(spec(ClusterSpec.Type.combined, "id1"), spec(ClusterSpec.Type.content, "id1")), true,
                               List.of(spec(ClusterSpec.Type.content, "id1"), spec(ClusterSpec.Type.content, "id1")), true
        );
        tests.forEach((specs, satisfies) -> {
            var s1 = specs.get(0);
            var s2 = specs.get(1);
            assertEquals(satisfies, s1.satisfies(s2), s1 + (satisfies ? " satisfies " : " does not satisfy ") + s2);
            assertEquals(satisfies, s2.satisfies(s1), s2 + (satisfies ? " satisfies " : " does not satisfy ") + s1);
        });
    }