Text2Store

Developer notes

The license decides the architecture

Open-source licensing gets filed under legal housekeeping, something to tidy up before release. It is not. Two of this app's dependencies dictated structural decisions months before there was anything to ship: one forced a process boundary, the other forced us to compile it ourselves. Neither was avoidable, and the second one started with a widely used binary that says, about itself, that it is not legally redistributable.

Two dependencies, two copyleft licenses, two completely different shapes of solution. The difference between GPL and LGPL is not a matter of degree here. It produced different architectures.

GPL: keep it in another process

Device communication runs through pymobiledevice3, which is GPL. Linking GPL code into a closed-source binary is not something you can disclose your way out of, so the tool stays a separate executable that we speak to over its command line interface, exchanging arguments and parsed output rather than function calls. Our code is not a derivative work, and we publish the corresponding source for exactly what we ship.

The cost is real and worth naming: parsing another program's output is less pleasant than calling a function, and it means treating a CLI's behavior as an API. The chapter on device communication covers what that discipline actually took. The same constraint is why our encrypted-backup support was written from the published format rather than ported from code that already worked. The license did not make the code worse. It decided where the code was allowed to live.

LGPL: link freely, and be able to prove what you linked

ffmpeg is the other one, used for video thumbnails and for converting audio attachments. LGPL is the friendlier license: you may link it into a proprietary application, provided the user can replace that component and you say clearly what you used. Fine. So use one of the well-known prebuilt static ffmpeg binaries that everyone uses and move on.

We checked first, which turned out to matter. A widely circulated prebuilt macOS build had been configured with --enable-nonfree. Binaries built that way self-report their status, and this one, asked about its own license, says it is not legally redistributable. It is a popular download. It is shipped inside a lot of products by people who never ran that command.

The lesson is not that the people distributing it did anything wrong; a nonfree build is a perfectly legitimate thing to compile for your own use. The lesson is that a prebuilt binary carries whatever flags the person who compiled it happened to pass, and the only way to know is to ask the artifact rather than trust the download page.

So we build it ourselves

The bundled ffmpeg is now compiled by a script in our own repository, from source tarballs pinned by SHA-256. No --enable-gpl, no --enable-nonfree. The only external library linked in is LAME, itself LGPL, needed for the MP3 path when converting audio attachments. Everything else the app relies on, the container demuxing, the video decoding, the image encoding, the scaling, is native to ffmpeg.

And because "we were careful" is not a verifiable claim, the build asserts its own compliance: it asks the finished binary what license it is under, and the build aborts unless the answer is LGPL version 2.1 or later. A rebuild that silently picks up the wrong flag fails loudly instead of shipping. That check costs one line and removes an entire category of mistake, which is roughly the best trade available in build engineering.

Corresponding source includes the build script

The obligation that people most often get wrong is what "corresponding source" means. It is not just the upstream tarball. It includes the scripts used to control compilation, because source you cannot reproduce the binary from is not meaningfully source. So we host all three: the ffmpeg source, the LAME source, and the exact script that turns them into the binary we ship, alongside a third-party notices file that names versions and links. Bump a version and those artifacts get re-hosted in the same change. That rule is written into the top of the build script itself, where the next person to touch it cannot miss it.

The bug that came free with compliance

A compliance rebuild is still a build, and it inherits your machine unless you stop it. The first ffmpeg we compiled ourselves worked beautifully on the machine that made it and would not launch on macOS 13, 14, or 15, because without an explicit deployment target the binary had stamped the build machine's own OS version as its minimum. The app supports 13.3 and up. We had produced a perfectly compliant binary that a chunk of our users could not run.

It is now pinned and, like the license check, verified at the end of the build, which aborts if the minimum version is wrong. Both checks exist for the same reason: the properties that matter most about a build artifact are invisible when you look at it, and the machine that produced it is the least reliable place to test them.

What this is worth

None of the above made a feature. It made a subprocess boundary, a hand-written implementation of a format someone else had already implemented, a build script, and two assertions. Junior engineers are rarely taught any of it, and it is genuinely load-bearing: get the GPL boundary wrong and your only remedies are open-sourcing your product or shipping without the feature, discovered at the worst possible moment. Reading a license before you take a dependency is not diligence theater. It is design work, and it is cheapest at the beginning.