In particular, we've never enforced that an immutable function can't call non-immutable functions. While that would seem like a good idea in the abstract, we've intentionally not tried to do it. (I'm pretty sure there is more than one round of previous discussions of the point in the archives, although locating relevant threads seems hard.) One reason not to is that polymorphic functions have to be marked with worst-case volatility labels. There are plenty of examples of functions that are stable for some input types and immutable for others (array_to_string, for instance); but the marking system can't represent that so we have to label them stable. Enforcing that a user-defined immutable function can't use such a function might just break things for no gain.
More sophisticated type systems (which I am *not* volunteering to graft onto Postgres) can handle some of this, but even Haskell has unsafePerformIO. The current policy is both wise and practical.