Since 3.3.0 the inventory row is the only copy of a device's services and
every canvas drawing it reads that list, but the scanner still assigned
`keep.services = fingerprint_ports(...)` — the pre-split behaviour, when a
node held its own copy. One re-scan therefore deleted every service the user
added by hand, on every canvas at once, and brought back the ones they had
deleted. It unions now, like every other writer of that field.
Two more things #347 turned up:
* A node whose view matches nothing the row still holds drew nothing at all —
the row had been replaced under it, so every key was gone and every key was
new, and `apply_view` hid the lot. Such a view says nothing about the list
that replaced it, so it is treated as no view: the row is drawn. An empty
view is untouched, being a real answer ("this canvas draws none of them").
* The 3.3.3 view seed recovers a node's arrangement from the pre-3.3.0 backup,
which is 3.2.0-era and cannot know about a property added afterwards. On
3.3.0-3.3.2 the row was the only place to add one and every canvas drew it,
so seeding strictly from the backup took it off all of them at once. Those
are appended visible, keeping the recovered order and hidden flags for
everything the backup does know. Services keep the strict recovery: holding
back what a scan fingerprinted is the whole point of the view.
ha-relevant: maybe