a plugin can depend on a release binary, and prove it is the right one
osDependencies could only say "this package, from this manager". Gitea's `tea`
is not in any distribution — it is a Go binary from dl.gitea.com — and Debian
has an UNRELATED package of that name: a graphical text editor. So the one
dependency gitea actually wants could not be expressed, and its marketplace
page showed no dependencies at all while music's showed two.
`release: { url, identify }` covers it. {os} and {arch} are filled from the
host in the spelling Go releases use, and the binary is fetched to
~/.local/bin — no root, and nothing a plugin downloaded from the internet
sitting beside what the distribution installed. Written to a temporary name and
moved into place, so a half-downloaded file is never on PATH under the real
one.
`identify` is the part that matters. Bun.which('tea') cannot tell Gitea's CLI
from the text editor, so presence was never the same question as identity —
and reporting the wrong program as satisfied is worse than reporting it
missing, because the install succeeds and every call afterwards fails
strangely. A binary that fails to identify is now `present: false, imposter:
true`.
Found while testing: Bun.which() with no options reads the PATH the PROCESS
started with, which under PM2 frequently excludes ~/.local/bin entirely. A
release binary fetched during an install would have been reported missing
seconds later by stillMissing, failing an install that had just succeeded. The
search now passes PATH explicitly, with ~/.local/bin first.
Verified against the real binaries on this machine: the genuine tea identifies,
a fake that prints text-editor output is caught as an imposter, and both
dl.gitea.com URLs (linux-amd64, darwin-arm64) answer 200.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -298,6 +298,22 @@ pane belonging to the folder you left; and the breadcrumb opted out of that last
|
||||
restored. Deliberate as written — a dashboard can hold two browsers and one URL cannot serve both —
|
||||
but worth re-deciding rather than inheriting.
|
||||
|
||||
## Release-binary dependencies (2026-08-19)
|
||||
|
||||
Built: a plugin can declare `release: { url, identify }` for a dependency no package manager carries.
|
||||
Gitea's `tea` is the motivating case and the first user.
|
||||
|
||||
Two things it does NOT do, both deliberate and both worth knowing:
|
||||
|
||||
- **No checksum.** The download is verified by RUNNING it through the same `identify` rule the probe
|
||||
uses, which catches an HTML error page, a truncated file and a wrong-architecture build — none of them
|
||||
print what the plugin said to look for. It does not catch a compromised upstream. A checksum per
|
||||
os/arch is a table that goes stale every release and would stop installs the day upstream re-cuts a
|
||||
tag; HTTPS and a URL the owner reads in the install dialog is what stands behind it today.
|
||||
- **The version is pinned in the manifest.** `tea` is fixed at 0.15.1, so a new release needs a plugin
|
||||
update. That is the right default — an install that silently fetches whatever is latest is not
|
||||
reproducible — but there is no "check for a newer one" anywhere.
|
||||
|
||||
## Affordances (2026-08-19)
|
||||
|
||||
Agreed and written down in `plugins/CLAUDE.md`; **nothing is built**. An affordance is what the surface
|
||||
|
||||
Reference in New Issue
Block a user