"Hardened runtime buys nothing without notarization."
Three Switches Built for Someone Else's Mac
Apple's distribution road for a Mac app outside the App Store has three parts. A Developer ID Application certificate signs it. The hardened runtime (codesign --options runtime) is switched on. And the app is notarized: uploaded to Apple's notary service, scanned, and given a ticket that Gatekeeper checks on a stranger's Mac. The Mac App Store adds a fourth, the App Sandbox. Every one of these exists so that a person who did not build the app can trust it. The family's Mac apps are run by the person who built them, on Macs that already hold the signing certificate. That is why the family leaves these roads alone — and why you should know exactly what each one does before a template turns it on for you.
What the Hardened Runtime Actually Changes
Measure it instead of repeating it. Sign the same binary with the self-signed identity twice, once with --options runtime. The CodeDirectory flags differ (0x0(none) against 0x10000(runtime)) and so does the cdhash. The designated requirement does not: both read identifier "…" and certificate leaf = H"…", character for character. A family doc once said the flag changes the requirement; for a certificate-signed app it does not, and a claim like that is exactly what the measurement is for.
The real cost is library validation, which the hardened runtime turns on. A hardened process may only map libraries signed by Apple or by the same Team ID. A self-signed certificate has no Team ID (TeamIdentifier=not set), so a hardened app refuses a dylib signed with its own certificate: "mapping process and mapped file (non-platform) have different Team IDs". The com.apple.security.cs.disable-library-validation entitlement lets it load again, which leaves you with a hardened runtime whose main protection you have just switched off. The runtime also blocks DYLD_* environment variables, unsigned executable memory and debugger attachment unless you add more exception entitlements.
The Ruling, and the Two Apps That Show It
The family default is off. A repository that turns it on says why, and its build gate asserts the state either way. The coding engine's client is hardened with no exception entitlements: it loads no foreign libraries, and its engine is a separate child process with its own signature, which a hardened parent can launch. The video player bundles and signs a pinned libmpv dependency closure, so its doctor script fails if the runtime flag is present. Opposite settings, one rule: the signature's state is checked, never assumed.
Notarization and the Sandbox
Notarization requires the Developer ID certificate, the hardened runtime and a secure timestamp (the family's local scripts pass --timestamp=none, so none of their apps could be notarized as signed). The App Sandbox is inherited by every child process, which rules it out for an app that launches an interpreter into a user-chosen repository, and it requires a user-granted file access for paths the app did not pick, which rules it out for a player that opens a path handed over by another app. The day one of these apps leaves the fleet, the road is already paid for: the Developer Program membership includes Developer ID. On iOS there is no road not taken. Every app is sandboxed, and that is where the iOS track begins.