A clear way to label where something is leaving or coming into a node is to use "port"-like constructs inside the source/target nodes. Some ways to achieve this:
subgraph.dot
digraph {
subgraph cluster_house {
label="House"
hcw [label="Clean water"]
hdw [label="Dirty water"]
}
subgraph cluster_street {
label="Street"
scw [label="Clean water"]
sdw [label="Dirty water"]
}
scw -> hcw
hdw -> sdw
}

Docs: https://graphviz.org/docs/attrs/cluster/
struct.dot
digraph structs {
node [shape=record];
rankdir=LR
house [label="<l> House|<cw> Clean water|<dw> Dirty water"];
street [label="<l> Street|<cw> Clean water|<dw> Dirty water"];
street:cw -> house:cw;
house:dw -> street:dw;
}

Docs: https://graphviz.org/doc/info/shapes.html#record
I don't know how to make the headers stand out however with this approach: graphviz: record node with a bold title
html.dot
digraph structs {
node [shape=plaintext]
house [label=<
<table border="0" cellborder="1" cellspacing="0">
<th><td><b>House</b></td></th>
<tr><td port="cw">Clean water</td></tr>
<tr><td port="dw">Dirty water</td></tr>
</table>>];
street [label=<
<table border="0" cellborder="1" cellspacing="0">
<th><td><b>Street</b></td></th>
<tr><td port="cw">Clean water</td></tr>
<tr><td port="dw">Dirty water</td></tr>
</table>>];
street:cw -> house:cw;
house:dw -> street:dw;
}

Docs: https://graphviz.org/doc/info/shapes.html#html
Tested on Graphviz 2.42.2, Ubuntu 22.04.