The sync read `platform/plugins/` — the directories this machine has installed — and imported each
manifest off the working tree. So publishing meant "get officer-dev's checkout to the release, then
run the script", and nothing showed when that had not happened. Live proof at the time of writing:
av-club 2026.08.29.01, kanban 2026.08.29.02, openseo 0.1.0 and fofos-admin 2026.08.29.26 were all in
the store, and none of the four has ever been tagged.
It is also why the job could not go on a timer. A cron over it published whatever was in a working
tree, on a schedule.
Now every registered plugin is mirrored bare into ~/.cache/officer-marketplace/mirrors and read AT ITS
NEWEST TAG — manifest, README and file list all out of `git cat-file`. No working tree in the path, so
publishing something uncommitted stops being a mistake anyone can make.
docs/marketplace.md proposed reading manifests over Gitea's API, which needed a sandbox or a committed
manifest.json. Git gives the same guarantee with neither, and the trust model is unchanged: we import
our own repositories' code. Third-party submissions still need one of those two.
The list of plugins now comes from the `plugins` registry table, which the docs always called the
authoritative half and which was in fact a by-product of what happened to be installed. That is what
lets `finances` be published without being installed here, and it spans orgs — fofos-admin lives under
fofos/, which an org listing would have missed. Adding one is `--add <clone url>`.
A plugin with no tag is left alone and named in the report, not deleted. It has made no release, so
there is nothing true to say about it; dropping its row would be a decision about somebody's plugin
dressed up as a refresh.
Also: `release_tag` on plugin_metadata, because the tag is the fact when a manifest version disagrees
with it; the sync warns on a mismatch. And icon URLs pin to the tag — `/raw/HEAD/` served whatever was
on the default branch, via a 303, so a plugin could show one icon and ship another.
Verified: 21/25 published from a release, 4 named as untagged, all 14 tag-pinned icons answer 200.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>