scribble.ReadAll only returns its own ErrMissingCollection when the
collection name is empty - when the collection's directory simply
doesn't exist yet (e.g. before the first firewall rule or IP list entry
is ever created), it returns a raw os.IsNotExist error instead, which
GetFirewallRules/GetIPListEntries/GetServers didn't handle, surfacing as
"open db/ip_list_entries: no such file or directory" on a fresh install.
New isMissingCollectionErr() helper treats both cases as "empty
collection", not a real failure.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>