One thing I just realised it's worthwhile to show: the POSIX interfaces I mentioned above are just wrappers around message-passing.
For example, read() is a function implemented in an optional userspace library that's available for programs to link against. When invoked, it constructs and sends a message with the right parameters to the filesystem server, and awaits its response: https://github.com/codyd51/axle/blob/paging-demo/programs/su...