.preview-author-links markup.
Commentary — hatched. Not the product.
createWebViewWith (WebView.swift:598)openExternalNSWorkspace.opennil: no new web view.
target="_blank"rel="noopener noreferrer" denies| context | mechanism | who owns it | status |
|---|---|---|---|
| macOS app | createWebViewWith → openExternal → NSWorkspace | WebView.swift | ships, hardened |
| serve, browser | target="_blank" rel="noopener noreferrer" | CodebookPanel.tsx | ships |
exported, file:// | same as browser | the export bundle | ships; links rot |
Opening an external URL costs no entitlement. NSWorkspace.shared.open is a request to
LaunchServices to hand the URL to whichever app registered for that scheme. The sandbox mediates it and the
calling app never touches the target — which is precisely why the handoff is the sandbox-friendly way
to leave an app. What would need an entitlement is fetching the URL ourselves
(network.client, which the app has for the sidecar) or reading a file:// outside
the container.
So the sandbox risk is not the opening; it is which URL you hand over — and that is already
gated by scheme. The entitlements files are skip-worktree
(git ls-files -v | grep '^S' lists both), so git status cannot see changes to
them and committing one obliges regenerating the Mac App Store profile. Read them; do not commit them.
All three already work, and the prototype's inert stub is the only thing that differs from shipped behaviour.
CodebookPanel.tsx:1525emits<a href target="_blank" rel="noopener noreferrer">with the ↗ glyph. There is no handoff to design; there is a stub to replace with the markup that already ships.The Mac is the safest context, which inverts the intuition. Its
decidePolicyForallows exactly one origin —http://127.0.0.1:<assignedPort>— and sends everything else toopenExternal, which passes onlyhttp,httpsandmailto. Its own comment records why:NSWorkspacewill happily openfile://(launching a local app),data:andjavascript:. So a hostile URL in a codebook is already blocked on the Mac and not blocked in a browser.The
_blanktrap is real and we avoid it by luck, not intent. WKWebView has no default new-window behaviour: withoutcreateWebViewWith, atarget="_blank"click does nothing at all — silently, with no error and no navigation. Ours is implemented for the popout video player, and external links fall out of itselsebranch. Correct today; worth knowing that the author links depend on a delegate written for another feature.The export is the one that needs a thought, and it is not a mechanism. A leave-behind is opened by a client, offline, possibly long after the study. Its links rot, and unlike the app there is nobody to repair them. That is not an argument for removing them — a dead link to a book is still a citation — but it is an argument against ever making one load-bearing: nothing in the report may require following a link to be understood.