A Real Gatekeeper


In the years since Apple released the iPhone, with its “locked-down-by-nature” approach to application security, the company has progressively chipped away at the freedoms Mac developers have historically had to do, more or less, whatever the heck they wanted.

With the introduction of the Mac Application Sandbox in 2012, Apple applied an iOS-like mechanism through which applications are entitled only to access their own data, and must explicitly request permission from Apple to access any resources “outside of their own sandbox.” At the time, I wrote that while the technology was promising, it left much to be desired.

Around the same time, they introduced Developer ID, a system for certifying at runtime that a given piece of software has been cryptographically signed by a developer whose identity is known to Apple. Applications that are not signed with Developer ID are allowed to run in macOS, but by default are met with a foreboding warning about the safety of doing so. The component of macOS that is responsible for limiting the launch of software from unknown developers is called “Gatekeeper.”

Last year, in 2018, Apple introduced a new notarization service, an expansion of Developer ID functionality. Developers submit their applications to Apple, where they are scanned for known malware, and have their use of specific system technologies vetted. The “notarization” on an app allows the system to verify at runtime that a given application passes a baseline safety metric for downloaded software.

Finally, in 2019, Apple announced that software signed with Developer ID certificates, that is to say all non-Mac App Store software, must also be notarized. The Catalina 10.15 public beta identifies software that has not been notarized as potentially risky because it “cannot be scanned for malware.”

In effect: developers who ship software directly to end-users are now required to notarize their apps.

While working on the notarization process for my own apps, and a company I work for, I noticed an interesting error from “altool”, the command line program that is used to submit binaries to Apple for verification:

1 package(s) were not uploaded because they had problems:
Error Messages:
To use this application, you must first sign in to 
iTunes Connect and sign the relevant contracts. (1048)

The error is easily worked around by logging in to App Store Connect and agreeing to any updates Apple has recently made to their contracts. I’m so used to more-or-less blindly agreeing to these changes, that it didn’t sink in for me at first what a potentially major change this is.

My colleague Patrick Machielse noticed right away what the larger implication is: all Mac software, inside or outside of the Mac App Store, can now be held up by unsigned contract agreements with Apple. In a rush to fix a horrible bug and get it out to customers? Better review that new contract ASAP.

For the past 35 years, any Mac developer who wanted to ship an update directly to customers could do so by recompiling a binary and distributing it. When macOS 10.15 ships this fall, the status quo will change. Mac developers must register with Apple and sign their products. They must submit their binaries to Apple for notarization. And most significantly of all, they must agree to the terms of Apple’s App Store developer contracts, even if they don’t distribute their apps through the App Store.

Unloved Patches

For a long time I have admired the WordPress project, for developing such a robust blogging platform that is ultimately open, and free, and anybody can contribute improvements to it. I encourage many of my customers to use WordPress with MarsEdit, because it seems like a “safe bet” going forward.

My admiration has diminished a bit in the past 7 months because … I haven’t succeeded in contributing to it.

For a long time, I heard reports from my customers that dates were being set wrong in posts to WordPress. The issue in summary is that if you have a draft post on WordPress, changing its status to “Published” doesn’t update the publish date from the time the draft was originally saved.

I didn’t really get a handle on this problem until it started affecting me. Sometimes I write the show notes for my podcast, Core Intuition, ahead of the time the podcast actually goes public. In these situations, the blog post has a published date corresponding to the time I first starting writing the post, and when we finally go to publish the podcast, the date remains the same.

I did the hard work of not only diagnosing the problem in WordPress’s source code, but also writing a fix, and writing unit tests to confirm the fix. I filed a bug with a patch that will fix the problem for my customers, and any other clients of the WordPress API:

#45322: Editing a draft post with wp.editPost causes its published date to be set

Shortly after filing the bug, I went to the WordPress Slack to see what I could do about having my fixes integrated. I was lucky to have a positive response from a couple members of the WordPress team, and my bug fix seemed slated for integration.

Time passed. I wondered. I didn’t want to nag the hard-working members of the team, but I also didn’t want my hard work to have been for naught. Also, my customers, as well as other clients of the WordPress API, would benefit from this.

It’s been on my TODO list for 7 months now to “check in” with the WordPress team about this. Unfortunately, every time I do, the only thing I’ve noticed is that nobody substantially responds to my inquiries. I’m in the dead zone.

I don’t think the WordPress team is bad, by any means, but I think this reflects a problem in their process. When somebody comes to your project with a well-thought-out, unit-tested fix, and is met by radio silence? The chances are high that they will never come back again. I have submitted WordPress patches in the past, but after this experience I don’t know if I will bother submitting them again. That’s a big change in my perspective on how the WordPress team works, and on how it should work.

This post is about WordPress, but I think there are lessons for every open source project. Obviously, you can’t coddle every contributor. Some submissions will be bogus, some will be contrary to the aims of the project. But mine was a clear fix to a defect that affects multiple clients of the API. If it’s not a clear fix, I’m at least owed an explanation for why it hasn’t been committed after 7 months. In. My. Humble. Opinion.

Blog a Little

Over on Twitter today, I was inspired to ask people to write “just one blog post” today:

Later, it occurred to me that after 10+ years on Twitter, I am privileged to have a substantial following. I thought I would take the opportunity to help promote some folks who don’t have as much immediate reach:

I tagged all my retweets to those responses with #LongLiveTheOpenWeb. I think it turned out to be a pretty cool cross-section of bloggers, and I sort of editorialized the kind of blogging that people were doing.

I think people neglect to write blog posts because the feedback loop is not as tangible as the onslaught of (sometimes mechanical) likes or faves that you can receive on a social network. With blogging, you need a little faith that you will gain an audience. And on the open web, you never know who might come along and expand your audience.

The Mac Open Web

These days, as the giant social networks behave more and more reprehensibly, many people are looking back to the “good old days” of the web, when self-published blogs were the primary means of sharing one’s thoughts.

Brian Warren has taken this enthusiasm, and combined it with his nostalgia for another classic resource: the links page. He’s created a new one called Mac Open Web:

A collection of open and indie Mac, iOS, and web apps that help promote the open web.

The solitary page is jam-packed with links to resources for creating and perusing content on “the open web,” that is to say “the web.” If you’re sick of Facebook and Twitter owning your experience of what is still a hugely diverse and free global network, then spend some time investing in writing and reading on the web “the way we used to do it.”

Mac Sandboxing: Privileged File Operations

At WWDC 2018, Apple announced with great fanfare that two beloved Mac apps, Transmit and BBEdit, would be returning to the Mac App Store.

Each of these apps had departed the App Store years ago, citing various reasons, but chief among them the limitations of the Mac App Sandbox, which restricts the functionality of apps in the Mac App Store.

I was curious whether Apple made any specific concessions to these developers, and whether those concessions would be opened up to “the rest of us” or not.

Today, Panic launched Transmit 5 on the Mac App Store. It’s a free download, and costs $24.99/year after an initial 7-day free trial.

I downloaded Transmit even though I own a copy of the direct-purchase version. I wanted an answer to my question, which I got, at least partially, by dumping the application binary’s “entitlements”, which represent the sandboxing exceptions that the app has received.

New to me among the entitlements is “com.apple.developer.security.privileged-file-operations”, which is a boolean value set to true for Transmit. I don’t see any Google results for this key, so I’m assuming it’s something new that was added for Panic (and maybe BBEdit), and which may or may not be documented in the future for use by other developers.

Another interesting entitlement is “com.apple.security.automation.apple-events”, which is documented by Apple, but only in the context of the new “Hardened Runtime.” This technology is aimed primarily at developers who are not developing for the Mac App Store, but who want to provide enhanced security for their customers. In that context, I believe this entitlement provides unfettered access to sending AppleEvents, excepting that in Mojave and later the app is still subject to fine-grained system alerts that require user approval for each application that is targeted.

In short: it appears that Transmit possesses at least two “official” entitlements that could be made available, or are perhaps already available, to other developers. One way to find out: add them to your app and submit it for approval!

Update: Thanks to Jeff Nadeau for alerting me to the pertinent API that correlates with the privileged file operations entitlement. NSWorkspaceAuthorization can be used to request privileged file access from the user, and Apple includes a link for requesting access to the entitlement.

Update 2: It turns out my intrigue around “com.apple.security.automation.apple-events” was ill-founded. I assumed that a sandboxed app could use this entitlement to gain unfettered access to automating other apps, but in the case of a sandboxed app it turns out to work in conjunction with the existing “com.apple.security.temporary-exception.apple-events” entitlement, which requires enumeration of specific targets. Thanks to Jeff Johnson and Paolo Andrade for talking me through my misunderstanding of the situation.

Terminal Security Profiles

In macOS Mojave, Apple introduced a number of new security features that impact the day-to-day use of the computer. Activities such as running scripts, or using apps that access private information, are altered now such that users are prompted with one-time permission-granting requests.

One consequence of these changes is that you can no longer access certain parts of your home directory from the Terminal. Don’t believe me? Try opening Applications > Utilities > Terminal, and run the following command:

ls ~/Library/Mail

In all previous macOS releases, this would list the contents of Apple’s internal Mail files. As a privacy enhancement, access to these files is now restricted unless apps have requested or been proactively granted access.

If you really wanted to regain access to these files via the Terminal, you have to grant the app “Full Disk Access.” This is a new section of the Security & Privacy pane in System Preferences.

Well, that’s fine. Now you can “ls” anything in your home folder, but absolutely every other thing you run in Terminal can as well. To grant myself the ability to list files in ~/Library/Mail, am I willing to grant the same access to every single thing I’ll ever run in Terminal?

This isn’t earth-shattering: it’s been the case forever that tools you run in the Terminal have access to “all your files.” But the new restrictions in macOS Mojave shine a light on a problem: the bluntness of security restrictions and relaxations with regard to Terminal.

I’ve run into a variation of this problem in the past. I use the excellent TripMode to limit bandwidth usage when I’m traveling, and tethered to my phone. A consequence of this is that, unless I grant unlimited network access to Terminal, I can’t perform routine tasks such as pushing git changes to a server.

Ideally these permission grants would be applicable at the tool level, rather than at the application level. It would be better if I could say “let ls access my Mail” rather than “let anything I run from Terminal access my Mail.”

I don’t completely understand the limitations there, but I suspect that because commands in the Terminal are running as subprocesses of Terminal, there is some technical challenge to making the permissions apply at such a fine-grained level.

As an alternative, I wonder if Apple could introduce some kind of “Security Profiles” feature for Terminal so that individual windows within the app could be run when different permissions? This could build on Terminal’s existing support for “Profiles” which already support varying Terminal settings dramatically on a per-window basis.

With Security Profiles, a user would be configure an arbitrary number of named profiles, and security privileges acquired by Terminal would be stored separately for the active profile. Each profile would be considered by the system effectively as a different app. For example, given my uses of Terminal, I might set up a few profiles for the types of work I regularly do:

  • Personal: Everyday productivity tasks including running scripts, editing files in my home directory, etc.
  • Administrative: Tasks that pertain to the overall maintenance of my Mac: examining system logs, delving into configuration files, etc.
  • Collaborative: Tasks that involve installing and running third-party tools that I trust, committing to shared source repositories, etc.
  • Experimental: Tasks that involve installing or running third-party tools that I am not familiar with and do not have a high degree of faith in.

These are off the top of my head, and just to give an idea of the kinds of profiles that might make sense here. Switching between these modes would also switch the system’s active list of entitlements for Terminal. If I run a script that accesses my Calendar items from the “Personal” profile, the system would prompt me once to ask my permission, but never prompt me again in that profile. When I switch to “Experimental” and run some unfamiliar third-party tool that tries to access my calendar, it would ask permission again for that profile.

I filed Radar #45042684: “Support a finer-grained permissions model for Terminal”, requesting access for this or something like it.

Saying Goodbye to NetNewsWire 3

In case you haven’t heard the news, Brent Simmons recently regained the rights to NetNewsWire, the groundbreaking Mac news reader, which also happens to be the progenitor of MarsEdit.

I have been a fan of NetNewsWire since before Brent sold it to NewsGator. Since before NewsGator sold MarsEdit to me. Before they sold NetNewsWire to Black Pixel. For a long time.

After Black Pixel took the reins, they put a lot of effort into a massive overhaul of the app, modernizing the look and feel and adding a robust, in-house syncing mechanism. When they released NetNewsWire 4 in 2015, it seemed as though the future for the app was bright.

As nice as NetNewsWire 4 was, it also differed a lot from NetNewsWire 3. They pared back the feature set a lot, in ways that made switching inconvenient to me. So I soldiered on with 3.3.2, thinking that I would update to 4.x eventually.

I never did. For whatever reason, work on NetNewsWire seemed to stall, and I never found the updated version of the app to fit my needs. NetNewsWire 3 worked just fine.

The meaning of “just fine” started to shift as macOS changed underneath the app. Subtle bugs emerged, the app’s lower-resolution graphics started to look fuzzy, and the networking infrastructure of the app is from an older era that is failing to connect to some SSL servers. In short, it’s no longer the great app that it once was. One particular bug with the size of the “Clippings” folder icon has been bugging me for years:

Screenshot of NetNewsWire showing blurry icons and a missized Clippings folder icon.

Over the years I considered other news readers such as Reeder (which is free for a limited time, by the way), but none of them scratched that NetNewsWire 3 itch. I rely upon some arcane features of the app including “scripted feeds,” which allow me for example to run Python scripts on my Mac that connect to Twitter and generate RSS feeds from search results. That’s not possible in most feed readers.

I used to fantasize about getting access to the NetNewsWire 3 source code and sprucing it up. I wondered how things might have turned out differently if, in addition to acquiring MarsEdit from NewsGator, I had acquired both? I can’t say I would have done a better job than Black Pixel, but I would have preserved the features I care about, and that Clippings folder icon would be the right size!

Because Brent and I are still close friends, we have been in conversation about NetNewsWire and the various options for moving it forward into the future. I’ve also been contributing to the NetNewsWire open source project, which is based on an entirely new code base unrelated to NetNewsWire 3.

Since I’m not the only stalwart NetNewsWire 3 user, one of the things Brent was curious about was whether he could give that version “one last hurrah,” so to speak. Fix a few of the most glaring bugs, build against a modern SDK, and not only create an artifact for history to more accurately judge the app’s virtues, but to give long-standing users something to tide them over while development continues on NetNewsWire 5.

I was honored when Brent handed me the keys to the castle, so to speak, by sending me a copy of NetNewsWire 3’s source code. To heavily paraphrase what he said, it was basically “let me know if it’s worth saving.”

I got the app building with Xcode 10 on macOS Mojave beta 9. There were some major glitches. The sidebar was pure black, fonts were rendering wrong. Probably whole subsets of functionality were not working, or working unreliably. I sent the source base back to him with a report that it builds and runs, but would probably take some work to get into shippable shape.

Brent made the pragmatic choice not to release an updated NetNewsWire 3. Putting the bugs aside, he recognized that any time invested in that old version is an investment in older technology that does not have a viable future. It’s a distraction from the New World NetNewsWire.

To be honest, the decision doesn’t sting at all. I’ve switched most of my news reading to development releases of NetNewsWire 5, and only use NetNewsWire 3 for a handful of those geeky script-based RSS feeds I am still relying on.

I was grateful to have the opportunity after all these years to take a peek at the source code to the app, and to get a feel for what it would take to salvage what’s left. I couldn’t resist fixing at least one bug before I passed it along though:

Screenshot of the NetNewsWire window with Clippings folder icon restored to normal size

If you’re curious: the Clippings icon is obtained from the Mac operating system. At one point in history it must have come from the system at just the perfect size to fit the source list in the app, but as Apple modernized and adapted to higher resolution Macs, they must have updated the icon to support drawing at much larger sizes. NetNewsWire 3.3.2 doesn’t manually set the size to the expected 16x16pt size, but 3.3.3j (for Jalkut!) does.

Goodbye, NetNewsWire 3. You were a great app, but your time has passed. Long live NetNewsWire 5.

More on Mojave’s Automation Sandbox

I wrote last month about macOS Mojave’s restrictions on automation, and how users can reset the database that controls them. In that post, I cited Felix Schwarz’s excellent article on the subject.

In recent weeks, Apple has made changes to the behavior of macOS Mojave, and added some API calls to help developers better handle the restrictions of the system. Felix is back with an updated post, describing the changes, and what he thinks can still be improved.

Reauthorizing Automation in Mojave

The macOS Mojave betas include a significant enhancement to user control over which applications can perform automation tasks. When we talk about automation on the Mac, we usually think of AppleScript or Automator, but with a broader view automation can be seen as any communication from one application to another.

One ubiquitous example of such an automation is the prevalence of “Reveal in Finder” type functionality. For example if you right-click a song file in iTunes, an option in the contextual menu allows you to reveal the file in the Finder. This is a very basic automation accomplished by sending an “Apple Event” from iTunes to the Finder.

In the macOS Mojave betas, you’ll notice that invoking such a command in an application will most likely lead to a panel asking permission from the user. The terminology used is along the lines of:

“WhateverApp” would like to control the application “Finder”.

If the user selects “OK”, the application sending the command will be thereafter whitelisted, and allowed to send arbitrary events (not just the one that prompted the alert) to the Finder. If you’re running macOS Mojave you can see a list of applications you’ve already permitted in System Preferences, under “Security and Privacy,” “Privacy,” “Automation”.

These alerts are a bit annoying, but I can get behind the motivation to give users more authority over which applications are allowed to control other applications. Unfortunately, there are a number of usability issues and practical pitfalls that come as side-effects of this change. Felix Schwarz made a great analysis of many of the problems on his blog.

I ran into another usability challenge that Felix didn’t itemize: the problem of denying authorization to an application and then living to regret it. I guess at some point I must have hastily denied permission for Xcode (Apple’s software development app) to control the Finder. This resulted in a seemingly permanent impairment to Xcode’s “Show in Finder” feature. I’m often using this feature to quickly navigate from Xcode’s interface to the Finder’s view on the same files. After denying access once, the feature has the unfortunate behavior of succeeding in activating the Finder (I guess that one is whitelisted), but failing silently when it comes to revealing the file.

OK, that’s fine. I messed up. But how do I undo it? Unfortunately, the list of applications in the Security and Privacy preference pane is only of those that I have clicked “OK” for. There’s no list of the ones that I’ve denied, and no apparent option to drag in or add applications explicitly. For this high level problem, I filed Radar #42081464: “TCC needs user-facing mechanism for allowing previously denied privileges.”

What’s TCC? I’ll be darned, I don’t know what it stands for. But it’s the name of the system Apple uses for managing the system’s so-called “privacy database.” This is where these and other permissions, granted by the user, are saved. For instance, in macOS 10.13 when the system asks whether to grant access to your Address Book or Contacts, the permission is saved, and managed thereafter, by TCC.

Resetting TCC Privileges

I knew from past experience testing Contacts privileges in my own apps, that Apple supports a mechanism for resetting privileges. Unfortunately, it’s pretty crude: if you want to change the authorization setting for an application you’ve previously weighed in on, you have to universally wipe out all the privileges for all apps using a particular service. For Contacts, for example:

tccutil reset AddressBook

This completely removes the list of apps authorized to access Contacts. (The AddressBook naming is a vestige of the app’s former user-facing name.) In fact, if you type “man tccutil” from the Terminal, you’ll find that AddressBook is the only service explicitly documented by the tool. Fixing my Xcode problem is not going to happen by resetting AddressBook privileges. So what do I reset? I tried the most obvious choice, “Automation,” results in an error: “tccutil: Failed to reset database”.

What’s the service called, and does tccutil even support resetting it? After a crude search of the private TCC.framework’s binary, I discovered I was looking for “AppleEvents”:

tccutil reset AppleEvents

After running this, I quit and reopened Xcode (the TCC privileges seem to be cached), and selected “Show in Finder” on a file. Voila! The Finder was activated and I was again asked if I wanted to permit the behavior. This time, I made sure to say “OK.”

You can get a sense for the variety of services tccutil apparently supports resetting by dumping the pertinent strings from the framework:

strings /System/Library/PrivateFrameworks/TCC.framework/TCC | grep kTCCService

The list of matching strings includes names like AppleEvents and AddressBook, as well other names for things I don’t recognize, and a seemingly useful “All,” which can presumably be used to wipe out all authorizations across all services.

Because the tccutil is far more useful than is advertised, and because users are undoubtedly going to end up needing to reset services more than ever in Mojave, I also filed Radar #42081070: “Documentation and command-line help for tccutil should enumerate services.” There are some items in the dumped list that appear likely to be private to Apple, but anything genuinely useful to customers (or more likely, the consultants who fix their Macs) should be listed in the manual.

Lighten Up, Eh?

While I support the technical and user-facing changes suggested by Felix Schwarz in the previously linked blog post, some issues would be avoided by simply giving apps the benefit of the doubt for widely used, innocuous forms of automation.

I mentioned earlier that the Apple Event sent by Xcode to “activate the Finder,” was apparently whitelisted by the system. Evidently Apple saw wisdom in the thinking that simply causing another application to become active is unlikely to be widely abused. I think the same argument holds for asking the Finder to reveal a file. I filed Radar #42081629: “TCC could whitelist certain widely used, innocuous Apple Events.”

I mentioned before that I can support Apple’s effort to put more power into users’ hands with this feature, but one side-effect of requiring the authorization even for innocuous events like “Show in Finder” is that apps that do not otherwise offer automation functionality to users will nonetheless require that users grant that power.

If the merit in the feature is to allow users to limit what kinds of automation apps can perform, then supporting a “Show in Finder” feature for an application should not require me to simultaneous permit it to do whatever kind of Finder automation it chooses to. For example, an application so-authorized is now empowered, presumably, to send automation commands to the Finder that modify or delete arbitrary user files.

These days Apple always seems to be pushing the privacy and security envelope, and in many ways that is great for their users and for their platforms. With a little common-sense and some extra engineering (“It should be easy” — Hah!), we can get the best of the protection these features offer, while suffering the fewest of the downsides.

Ersatz Free Trials

On Monday Apple announced that they are officially supporting so-called “free trials” for non-subscription apps. The reaction has been a breathless celebration that Apple has finally relented and given developers something we’ve been asking, no begging, for since the dawn of the App Store.

But what really changed? Not much. Apple announced no functional changes to the way the apps are categorized, how pricing is conveyed to customers, or how the physical transaction of downloading, trialing, and potentially purchasing an app takes place. What they did announce is a change to the App Review Guidelines, adding a bullet item to section 3.1.1 describing a kind of ersatz substitute for actual free trials, built on the in-app purchase system:

Non-subscription apps may offer a free time-based trial period before presenting a full unlock option by setting up a Non-Consumable IAP item at Price Tier 0 that follows the naming convention: “14-day Trial.”

This change to the review guidelines is fantastic, because it will give app developers greater confidence that such a workaround will continue to be approved by Apple. But the practice of offering free trials in this manner is not new, and is not particularly great by any stretch of the imagination.

The Origin of Ersatz Free Trials

To my knowledge, the first developers to come up with the idea of using in-app purchases to approximate free trials were The Omni Group. In September 2016 they wrote about a novel solution for the long-standing absence of free trials (and upgrade pricing) on the App Store, which is based on providing a baseline free download and unlocking premium functionality through in-app purchases:

With the original download free, we can implement any pricing options we want to offer customers through In-App Purchases. We can offer our standard unlocks of Standard and Pro, of course. But we can also offer a free 2-week trial which unlocks all of the features of Pro and Standard, letting you freely choose between them.

Many of us who had also been waiting for App Store support for free trials and upgrades waited in anticipation to see whether it would really work. Would Apple actually approve such a use? Would customers understand it? Would the App Store Infrastructure reliably handle the approach? The answer, as it turns out, was yes. Sort of.

Omni’s approach worked well enough that developers of other apps soon followed suit. MindNode 5, Acorn 6, and Sparkle all launched as “free” App Store titles that can only be substantially improved with in-app purchases ranging from free, timed trials to paid, permanent feature unlocks.

The approach seemed to be gaining momentum so in mid-2017 as I was looking forward to the release of MarsEdit 4, I decided that I would embrace the same idea. Since December, 2017, I have sold MarsEdit 4 as a free app with in-app purchases for free trials, free upgrades for recent purchases, discounted upgrades, and full-price upgrades. In many ways the change has been a revelation. It’s a great relief to be able to offer my customers nearly as many trial and pricing accommodations as I can offer directly through my own store.

The Problem with Ersatz Free Trials

While I’ve enjoyed many of the upsides of the Omni approach, I’ve also had the opportunity to appreciate the many downsides. You might say it’s “a pretty sweet solution” for offering free trials.

I think it’s particularly important, in the face of all the celebration this week about Apple’s perceived changes to the App Store, to understand the many ways in which this solution falls short of what many developers still hope for: bona fide support for real free trials in the App Store.

In summary: none of the mechanics of supporting ersatz free trials are substantially supported by the App Store. Every aspect of the solution is bolted on to a system which was not designed for, yet is somewhat admirably being used to simulate real support for free trials. Let me elaborate by listing several shortcomings and how they affect both users and developers in significant ways. Just off the top of my head …

  • Paid apps are listed as free, even though payment is required to unlock core functionality. This is confusing to many users and leads some to a feeling of bait-and-switch, and that they’ve been betrayed by the developer. This is particularly problematic with apps whose price points make them most suitable to free trials. MarsEdit is $50, so some users who download the “free app” are understandably annoyed when the first thing they learn is that it will cost a significant amount to unlock it.
  • Bulk purchase programs are unavailable. Apple’s Volume Purchase Programs for business and education are based on a system of allocating a certain number of “primary” App Store products to an institution. In the case of a free app with paid in-app purchases, there is no mechanism by which a school or company can for example purchase 500 copies of MarsEdit from the App Store. They can “purchase” 500 free copies and then proceed to unlock each copy individually through the in-app purchase dialog in each app. This is a particularly unfortunate limitation for apps that are uniquely suited either to education or to business uses.
  • Family sharing is unavailable. For the same reasons that bulk purchases are off the table, a developer who wants to allow families to purchase an app once and share it among their family’s devices and accounts is unable to do so unless they sell their app with a fixed, up-front cost in the App Store.
  • Not applicable to all app types. Although Apple doesn’t explicitly state it in their revised App Review Guidelines, I strongly suspect that a continuing requirement for ersatz free trials is that the app must continue to function in some way as a perpetually free, unlocked app. For document-based apps such as Omni’s, they went with an approach whereby the app becomes a read-only document viewer when it is not paid for. In MarsEdit, I took a similar tack by allowing all features to function except for publishing changes to blogs. In many cases it is possible to contrive a free/paid functionality divide, but for some apps it would be very awkward, or maybe impossible to do so.
  • Apps are ranked and featured in the wrong charts. A problem rooted in these paid apps being listed as free is that there is no natural place for them to be honestly ranked among the App Store’s two-tier division of apps into “Paid” and “Free” charts. An app that is $50 and sells very well will never make its way to the top of the “Paid” charts, and if it is lucky enough to beat out actually free apps in the free charts, it will only confound users who are surprised to learn that one of the top free apps actually costs money. The presence of a “Top Grossing” category provided a sort of compromise category for such apps, but Apple removed the ranking from iOS 11, and appears to be set to remove it from the Mac App Store in macOS Mojave.
  • Transaction mechanics are pushed onto developers. One of the primary advantages of the App Store to developers is being able to get out of the business of managing direct sale transactions. With the paid-up-front approach, users browse the store, conduct a transaction with Apple, and download the app. In exchange for taking on this work, Apple is rewarded with a 30% cut. With ersatz free trials, almost every aspect of this complexity is pushed into the app, where developers have to laboriously devise a mechanism for conveying app limitations to users, blocking pertinent functionality, transacting an in-app purchase, facilitating the unlock of app functionality, and so on.
  • Free trials cannot be easily reset. It is typical outside of App Store marketplaces for developers who offer free trials to periodically reset free trials so that users who, for example, enjoyed a free trial on version 1.0 of an app, can give it a fresh look on 1.1. The use of in-app purchases for accommodating free trials would, strictly speaking, require that developers perpetually add new SKUs to the App Store representing a different “free trial” product for each of the timeframes in which a developer wants to reset things.
  • Apps cannot be made to “just work” out of the box. One of the main rationales for offering free trials is to get prospective customers to download and start using the great features of an app as quickly and with as little effort as possible. With ersatz free trials a customer must first authorize Apple to allow the download of the free app, and then they must commence a confusing in-app purchase process during which they will be asked again whether they want to start a free trial.
  • Real Free Trials

    Now that I’ve listed a number of significant problems with ersatz free trials, let’s talk a little bit about what real support in the App Store might look like, and how it would alleviate the problems I’ve described.

    For starters, real free trials would allow developers who currently list their apps as “free” in the App Store to list them by their actual price. The App Store could convey that information both more honestly and more informatively to users. Instead of “Free with in-app purchases,” MarsEdit could be identified succinctly as “$49.95 with 14-day free trial.” These apps would no longer be erroneously featured among free apps, but would rank alongside other paid apps, where they belong.

    Having a bona fide price associated with the main App Store SKU would re-open access to the bulk purchase programs and family sharing. You know you want 500 copies of MarsEdit for your company? Go ahead and purchase 500 copies. The fact that the App Store happens to support free trials would be irrelevant to your conducting this transaction with Apple.

    Real free trials would open the functionality up to any developer who chooses to participate, regardless of their app’s functionality. Instead of forcing developers to come up with arbitrary lock-downs on functionality in the app, they would simply flip a switch in App Store Connect, ideally specifying a trial duration. When free trials are downloaded from the store, the receipt would have the trial information baked right in.

    Putting the logic in the store itself would also empower developers to start or stop offering free trials whenever they like, and to reset free trials across the board with major updates, in the same way they can choose to reset star ratings today. And all the tedious mechanics of offering, transacting, and enforcing free trial limitations would obviously be back in Apple’s court, where they can efficiently support such functionality in one place instead of requiring every developer to re-implement the same kind of support in every app.

    Finally, and probably equally importantly to users and developers alike, real free trials would enable users to effortlessly download and use all the features of an app without having to labor through any of the administrative tedium that is currently required by ersatz free trials. Happy customers trying excellent apps and ultimately paying for them is something that we can all get excited about.

    I hope this article has been helpful in illustrating why Apple’s review policy announcements, while very welcome indeed, do not constitute a major shift in their support for free trials in the App Store, and do not substantially change the status quo. Many of us are stretching the limits of the App Store to provide something that comes close to real free trials, but we would all be far better off if Apple announced a substantial change in supporting them. That didn’t happen this week.

Late to the Mac

A few weeks ago I was asked by Stephen Hackett to contribute a story, to his members-only newsletter, about my early experiences with computers and/or with the Mac. I was happy to help Stephen out because he does great work at 512 Pixels, because he is a friend, and because I like to talk about myself.

I agreed with Stephen that my contribution would be exclusive to his newsletter for a few weeks, and that afterwards I could publish it on my own blog. Here it comes!

Stephen’s version in the newsletter was spruced up with cool pictures of the mentioned computers, and possibly edited in ways that made me sound better than I do here. This is the raw, uncut version. Enjoy!


I’ve been a rabid Mac user and developer for 25 years, so it’s fair to say I’ve been a part of this community “for a long time.” But in my heart, I still consider myself something of a newbie. After all, I didn’t get my first Mac until I was 18 years old. My entire childhood was spent using, enjoying, even obsessing over computers made by other companies.

In 1982, I was 7 years old and lived with my mom in the rural town of Dunsmuir, California. While Silicon Valley’s famous fixation with technology was well underway, it hadn’t substantially reached the folks in my small, relatively poor home town. Meanwhile, my dad was living separately from us in Santa Cruz. He had gone back to school as an older student to obtain a computer science degree, and started his professional career working for IBM in San Jose. His enthusiasm for computers would turn out to be crucial to my interest in computers, and to my eventually programming them.

On one of his visits, he brought my first computer: a Timex Sinclair 1000. It was barely the size of a small book, used a television set for a display, saved files to audio cassette tapes, and featured a whopping 2KB of RAM. It’s fascinating that even the content of this article I’m writing would not fit in the memory banks of that computer. My dad gave me some copies of Compute! magazine, which featured BASIC program listings, some of which I guess were applicable to the Timex Sinclair. One of my earliest programming memories is of him walking me through the rough notion of source code as a sequence of instructions, and the computer as the obedient executor of those commands.

That Timex Sinclair wasn’t much of a machine, but it may still have made me the very first person in Dunsmuir to own a “home computer.” Apart from typing in the occasional program from those magazines, I never really learned to program it. But having those computing concepts introduced when I was so young, and in such a fundamentally hands-on way, set me up for the deeper understanding of computers and programming that I would later gain.

In 1983, my mom and I moved to Santa Cruz to live with my dad. In the Bay Area, we were far from the only family with a home computer, but my dad’s enthusiasm certainly meant our home saw a greater variety of them than most! My dad bought me a Commodore 64, which I adored, but the real thrill was his Kaypro IV. This beast was a semi-portable, all-in-one computer that ran the CP/M operating system, and featured a monochrome green display. I’d sneak onto it while he was out of the house, scouring his piles of floppy disks for anything of interest. I spent hours playing Ladder, a Donkey Kong-like game whose graphics consisted entirely of ASCII characters animated on the screen.

When the Amiga 1000 was released in 1985, my dad bought one, and I threw myself completely into it. I experimented with programming, studying the “ROM Kernel Manual”, but never learned how to put together a whole program. Still, for many years, I was “an Amiga guy.” I met other Amiga users, traded software, and reveled in the various technically superior capabilities of that platform.

Through the Santa Cruz BBS community, I got hooked up with an extensive network of UC Santa Cruz computer nerds, and found my way onto the internet by around 1989. That’s how I fell in love with UNIX. Throughout my teenage years, I played with various UNIX systems through the Adm–3A terminals in the university’s computer labs, and eventually ended up owning both a Sun 3/50, and an SGI Indigo. Obviously, I loved computers, but in spite of my diverse experience with various systems, I’d never really learned to program, and I’d never really used a Mac.

By 1993, I had a few friends through the Santa Cruz computer scene who were then working at Apple, about a 45-minute drive away. David Van Brink was a software engineer on the QuickTime team, and he opened my eyes to the virtues of the Mac. As much as I had enjoyed other computers, from that Timex Sinclair, through the Amigas, UNIX systems, and occasional other platforms, I had never witnessed a computer seeming particularly empathetic to its users. The Amigas came closest, but even at their most charming, they were obviously meant for nerds. The Mac, I finally came to realize, truly was “the computer for the rest of us,” and I was ready to become one of us.

David shared his employee discount with me and, after convincing my dad it would be useful for my college work, I came up with the cash for my very first Mac: a PowerBook Duo 210. This curious machine came from an era when Apple supported the notion of a “dockable” computer that could be used as a portable, but also plugged in to a desktop case connected to a full monitor, keyboard, etc. I could only afford the computer itself, so I made do with its limitations, but it was marvelous. Finally, more than 10 years after first being introduced to programming and computers, I owned a Mac, and was eager to write software for it.

I used a program called THINK Reference to study the Macintosh Toolbox API, and got to work writing my first app, Super Robots, which was a blatant clone of a text-graphics based app for UNIX called “robots.” (Fun fact: because the PowerBook Duo had a grayscale screen, I developed and shipped the app without ever having seen it for myself in full color.)

After shipping an app, and becoming vaguely familiar with the Mac operating system, I took the step that would ultimately be most impactful on my career and life-long love of computers: I went to work for Apple! At the encouragement of Qarin Van Brink (David’s sister), I applied at a Silicon Valley contract agency that was known to supply many of Apple’s QA testers. A few improbably successful interviews later, I was working in Cupertino on the System 7 integration team.

I eventually made my way out of testing and into engineering, where at long last, I started to sort of maybe learn to program. I also started learning how to really use and appreciate the Mac, and how to empathize with users. Compared to many Apple fans, I was late to the Mac party, but I’ve been making up for lost time. For 25 years, I devoted myself to using and programming Macs. Here’s hoping I can eke out at least another 25!