Hmm... it's almost like maybe applications shouldn't spew their files all over in the first place, then you wouldn't have to worry about putting them in the wrong places...
If you can tell me what a self-contained equivalent to, say, the libpam package would be, I’m all ears.
Oh, also, a subset of case 2 is: packages that contain servers need to register the server as a service with the OS’s init system, and every OS has its own init system that expects a service definition file in its own distinct format and location.
libpam should be part of the base system, obviously. Like the widget library, ssl, and the display server. It's only really in UNIX world that this separation between "system" and "application" doesn't exist.
OS packaging formats exist for the "base system", in your terminology. "Applications", in the UNIX world, install in /opt.
Keep in mind that the separation you're talking about is very thin, often non-existent, in any OS. Consider, say, an RDBMS daemon. Is that an application, or part of the base system?
An application? You're sure? But what if components of the base system rely on its presence?
This isn't some wacky idea, and it's not a UNIXism, either. Some components of Windows Server rely on MSSQL. So MSSQL has to be built as a Windows component, rather than a standalone application.
This example helps a lot in understanding what OS packages really are. For example, why do Linux distros package scripting languages like Perl, Python, Ruby? It's not for you to use them to write system administration scripts. It's definitely not for applications to use as their runtime. (All the major distros recommend that you vendor your own runtime into your application, if you're creating a standalone application.) No, the point of these language-runtime packages is that there are system components written in these languages, and the OS package is there to support them.
And this is why you're supposed to install your own copy of these when using them for development: the OS copy isn't maintined for you. These OS-packaged runtimes are frequently not up-to-date, and they bundle with them some of the language's package ecosystem, but not all—and frequently not even the most popular language packages.
That's because the runtime isn't there for you. It's there for the OS to use. It may as well be hidden in /usr/libexec and not even in your $PATH. (Except that $PATH is frequently how system components find one-another.)
People make a mistake when they think it's a good idea to package their applications as e.g. Ubuntu PPAs following the Debian packaging guidelines. That format, and those guidelines, exist for the authoring of system components; the guidelines are the way they are (i.e. very strict) to enable other system components to rely on your component.
If you're building an application, none of that applies.
Until recently, applications on UNIX shipped as tarballs containing ./install.sh scripts that you'd have to run as root, that would unpack things into /opt but also maybe write some service scripts into /etc/init.d. (Even now, this is how heavily-integrated applications like VMWare ship.)
More recently, Docker has replaced this format when packaging applications that don't require much of the underlying platform (e.g. network servers.)
Flatpak and Snaps are two attempts to do for GUI apps what Docker did for network servers.
Unlike OS packages, Docker, Flatpak, and Snaps are all interchangable and inter-convertable as long as you have an application that only requires their least-common-denominator subset of capabilities. A Docker "package" can be repackaged as a Flatpak or Snap losslessly. There is no reason that the Flatpak and Snap ecosystems can't proxy through to Docker Hub and let you pull any Docker image and run it under their daemon. There's no real war here.
The reason applications spew files all over the place is because that's how you hook into other systems. Want a man-page? There's a folder for that. Want to autostart? Folder for that. Want your program to be runnable without specifying the full path? Put it in path.
The reason configuration sucks is because we use filesystems, which are necessarily hierarchical, when we should use a more general database.
If we had a table where the first column was "thing to be configured" and the second column was "program" things would be much better. We could query by the first column to get e.g. all programs that want to automatically start, or all programs in path. Or we could query the second column to get all configuration for a given program.
Database people have done a lot of work on how to prevent inconsistent state, and we are stupid for not leveraging that.
> Database people have done a lot of work on how to prevent inconsistent state, and we are stupid for not leveraging that.
It's kind of amusing that on the Windows side, you have a vertical integration between the filesystem (NTFS) and the update mechanism, where any MSI package will actually be installed in a filesystem transaction, such that if you e.g. cut power in the middle of package installation, then your disk will actually have nothing of the package's installed data on it. The transaction failed, and was rolled back.
And yet, even with that fancy tech in place, uninstallers still are manually-written apps that blow away files by explicitly naming them, rather than also taking advantage of these filesystem-level transactions together with some sort of hypothetical transaction WAL log, to reverse what the install did.