### Description

When using the DiffableUtils.diff with a vanilla OpenJDK Map, instead of the legacy ImmutableOpenMap interface, we return a mutable map (generic HashMap), which isn't the expected behaviour of the API:

https://github.com/elastic/elasticsearch/blob/45c56b22f946733712ad6d92600411c0885594c5/server/src/main/java/org/elasticsearch/cluster/DiffableUtils.java#L85

We should wrap the map returned by the diff API in an unmodifiable version.
server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java
var builder = Metadata.builder(metadata);
        for (var dsName : dataStreams) {
            var dataStream = metadata.dataStreams().get(dsName);
            if (dataStream == null) {
                
                throw new IllegalArgumentException("unable to find data stream [" + dsName + "]");
            }
            builder.put(dataStream.snapshot(indices));
        }
        return builder.build();
    }
    @Override
    public Diff<Metadata> diff(Metadata previousState) {
        return new MetadataDiff(previousState, this);
    }
    public static Diff<Metadata> readDiffFrom(StreamInput in) throws IOException {
        return new MetadataDiff(in);
    }
    public static Metadata fromXContent(XContentParser parser) throws IOException {
        return Builder.fromXContent(parser);
    }
    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        Builder.toXContent(this, builder, params);
        return builder;
    }
    public Map<String, MappingMetadata> getMappingsByHash() {
        return mappingsByHash;
    }
    private static class MetadataDiff implements Diff<Metadata> {