Stow architecture

How Stow reads archives, talks to Finder and installs things while staying sandboxed, and why it is
built that way. Build and test instructions are in DEVELOPING.md.

Archive engine

All archive parsing happens in StowEngine.xpc, a sandboxed XPC service that runs an official-source
7zz build with a small Stow decoder-registration patch (LGPL — see THIRD_PARTY_NOTICES.md) as a child process inheriting its sandbox.

Finder, Quick Look and Services

The Finder → Stow hand-off

The Finder extension never opens files. It posts the selection (action + paths) under a random
128-bit token and opens stow://handoff/<token>; Stow takes the request once and refuses unknown,
reused or older-than-60-s tokens and any other URL shape. No path ever travels in a URL, so a web
page that opens stow://… can't make Stow do anything. The mailbox is a private named pasteboard:
an App Group container would be the textbook choice, but macOS refuses group containers to builds
without a Team ID (ad-hoc builds get EPERM), while named pasteboards work between any sandboxed
processes and releaseGlobally() makes them single-use. A Team-signed release could move the
mailbox into a group container without touching the token rules (HandoffMailbox).

Sandbox and Finder actions: why Stow asks once per folder

Extract Here and Quick Compress write next to the original, which a sandboxed app can't do by
default. Options considered:

Approach Verdict
Full Disk Access as a default prerequisite Rejected: broader privacy access than archive actions need; it does not remove sandbox restrictions
Remove the main app sandbox Not chosen: retain scoped access and the separate sandboxed engine
Access granted through the extension Not available: the Finder Sync extension is sandboxed too and receives paths, not file access it could hand on
Temporary-exception entitlements for home or / Rejected: the same as no sandbox for people's files
One-time folder grant Chosen

The first time an action needs a folder Stow can't write in, Stow shows an Open panel already
pointing at that folder and says why ("Choose Allow to let Stow extract … here — and next time,
anything in this folder"). Allow grants that folder and everything inside, kept as a
security-scoped bookmark; picking a different folder uses it once and remembers nothing.
Settings › Finder & Permissions lists every grant with Forget. Services and opened documents already
normally give Stow read access to the files themselves. When an archive open is denied (including
files passed from another app), Stow offers the system picker at its source folder. Select that
folder to remember access, or select only the original archive. Folder access includes read/write
access to files and subfolders; Stow verifies the archive is readable before saving the grant and
continuing the open. If access is still denied, it explains how to open an exported copy.
Remove forgets the saved folder bookmark; existing file grants or macOS permissions may remain.
See the source-access plan and its separate native acceptance.

Installing from a sandbox

Stow stays sandboxed (user-selected files only) and asks for the narrowest access each install needs:

Extract commands

In Browser and Glance, File › Extract (⌘E) extracts the selection. File › Extract All
(⇧⌘E) extracts the whole archive without clearing the selection, even when Glance's
selection Actions hide the Extract All button. Extract All waits until listing or a
running step finishes and is unavailable when another window or a sheet is active.

First run and Settings

A skippable Welcome to Stow checklist introduces archives, file types, the Finder
extension and Tray (⌥⌘T). Skip or Get Started finishes it; Help › Welcome to Stow reopens it.
Resetting preferences keeps first-run completion remembered.

Stow has a Settings window (⌘,): a sidebar of General, Extraction, Installing, Packing, Actions,
Glance, Previews, Passwords, File Types, Finder & Permissions, Advanced and Licenses pages, beside one
scrolling page. Tray has its own settings page and master enable switch. The host lives in App/Settings and reuses the extraction and
installing forms in App/Options. Advanced can clean preview caches and reset preferences. The keys and their defaults are listed in
DEVELOPING.md.

Updates

Stow updates itself with Sparkle 2 (Stow › Check for
Updates…, and General › Updates in Settings). The feed is the appcast.xml on the latest
published GitHub release, and each update DMG is EdDSA-signed with Stow's own key (public half
SUPublicEDKey in project.yml) as well as Developer ID–signed and notarized. Stow stays
sandboxed and without network access: Sparkle's downloader service fetches the feed and the update,
and its installer service replaces the app; a restart into an update waits until extracting,
packing or opening finishes (App/Updates). Debug, ad-hoc, test and -Stow… demo runs never
start Sparkle, so they never touch the network or show an update prompt.

New archives and the sample

Welcome and File > New Archive (Command-N) open an unsaved archive draft. Add/remove sources,
then Save configures and creates a real archive using the same engine as quick Pack. Tray and
ordinary-file drops retain the quick Pack path. Closing a changed draft offers Save/Discard/Cancel.

Production Release bundles omit Resources/Sample. Debug builds copy those deterministic
fixtures for tests and scripts/snapshot.sh; the source assets and licenses remain in the repository.
Help > Download Sample Archive (also in Welcome to Stow) is an explicit browser download of the genuine ZIP pinned to revision
33d533e7a74c0f6c862ce49a8d0fc72e93a71e90; Help > Sample Credits and Licenses opens its source
and license directory. Open the downloaded ZIP normally. No sample is fetched at launch, no
network entitlement is added, and a missing fixture never becomes a fabricated production archive.