Skip to content

Walk the catalogue install and read the pages that describe it - #369

Merged
iderex merged 1 commit into
masterfrom
release/the-catalogue-install-is-walked
Sep 5, 2026
Merged

iderex merged 1 commit into
masterfrom
release/the-catalogue-install-is-walked

Conversation

@iderex

@iderex iderex commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Refs #88.

Three places in this tree describe the channel an operator installs from, and a reader got a different answer from each. This reads all three against the channel and adds the walk none of them had.

What was wrong, and how I found it

I went looking for the second condition of #88 - an install from the catalogue walked once on a clean server - and could not start it without first reading what the tree says about the catalogue. Two of the three accounts had expired.

The readme said the catalogue offers the older of the two releases, and that 0.1.1.0 has to be taken from its release page by hand. It offers both:

curl -sS https://flowfin.dev/manifest.json | grep -c '"name": "Metadata Sync"'
1

curl -sS https://flowfin.dev/manifest.json | python -c "import sys,json;e=[x for x in json.load(sys.stdin) if x['name']=='Metadata Sync'][0];print([(v['version'],v['targetAbi']) for v in e['versions']])"
[('0.1.1.0', '10.11.0.0'), ('0.1.0.0', '10.11.0.0')]

docs/RELEASING.md said this tree has no route to the catalogue's own state, and that whether the served file caught up is read where the catalogue is built rather than here. It has had a route since .github/workflows/channel-freshness.yml landed:

git show origin/master:.github/workflows/channel-freshness.yml | grep -n '^name:\|Read the catalogue as an operator'
31:name: Channel freshness
187:      - name: Read the catalogue as an operator's server reads it

The half of that paragraph a release author needs is kept and sharpened rather than deleted: a green publish run here is still not evidence that the catalogue caught up, because the rebuild on the catalogue's board proposes rather than publishes.

The walk

docs/supported-servers.md recorded a walk that copies an assembly into plugins/. That proves the two gates accept it and says nothing about the catalogue, the entry, the archive an operator is handed or the checksum the server holds it to - which is easy to read past, because both walks end at the same plugin list.

So I walked the install from the catalogue, on 2026-09-05: a fresh data directory of a server started from the vendor's own build of 10.11.11, https://flowfin.dev/manifest.json added as the only repository, and nothing copied in by hand.

The catalogue offered both versions, both admitted by the ABI floor:

Metadata Sync  guid 5c37c4489d944fdda6214238b859165b  owner Flowfin
  0.1.1.0  targetAbi 10.11.0.0  checksum ec56a026ff999b32f9a965c2fa9d7cfd
  0.1.0.0  targetAbi 10.11.0.0  checksum b392689dcaf5809418340a820208fd38

The install was asked for by name and version and reported installed:

POST /Packages/Installed/Metadata%20Sync?version=0.1.1.0&repositoryUrl=https%3A%2F%2Fflowfin.dev%2Fmanifest.json
-> 204

Emby.Server.Implementations.Updates.InstallationManager: Plugin "installed": "Metadata Sync" "0.1.1.0"

and after a restart the server loaded it:

Emby.Server.Implementations.Plugins.PluginManager: Loaded plugin: "Metadata Sync" "0.1.1.0"

GET /Plugins
Metadata Sync 0.1.1.0 Active 5c37c4489d944fdda6214238b859165b CanUninstall=True

The bytes are the same at every hop, which is the part a copy cannot say anything about. The checksum the catalogue advertises is the md5 of the archive the release published, and the assembly the server unpacked is the one inside that archive:

md5sum metadata-sync_0.1.1.0.zip
ec56a026ff999b32f9a965c2fa9d7cfd

md5sum zipcheck/Jellyfin.Plugin.MetadataSync.dll
f8a54bd0f6d924b72cc6c3fcc3cab33e
md5sum "$DATA/plugins/Metadata Sync_0.1.1.0/Jellyfin.Plugin.MetadataSync.dll"
f8a54bd0f6d924b72cc6c3fcc3cab33e

What the walk did not establish

Written into the page with it rather than left for a reader to notice.

The checksum was never made to disagree. The three values above agree, so nothing was handed an archive that did not match its entry, and an install of a corrupted one was not attempted. That the server compares them at all is read from its source and not from this walk.

The selection between the two entries decided nothing here, because the install named 0.1.1.0 explicitly. What a server below 10.11.11 does with two entries that both clear a floor declared as 10.11.0.0, where only one archive loads, remains the reading in the section above it.

The server ran with no web client and no library, and no pass was run. The walk stops at the load, exactly where the earlier one does.

Means

Markdown, because every changed byte is a page a person reads and there is no artefact here to build. The walk itself was driven with curl against the server's own HTTP API rather than through a browser, so each step is a command that reproduces.

The gate

DOTNET_CLI_UI_LANGUAGE=en dotnet test Jellyfin.Plugin.MetadataSync.sln --nologo

net9.0  -> Failed: 0, Passed: 1696, Skipped: 0, Total: 1696
net10.0 -> Failed: 0, Passed: 1696, Skipped: 0, Total: 1696

No guard is added here, so there is nothing to prove bites. ReadmeStatementTests and SupportedServersTests both read the two pages this change edits, and the new section carries no pipe table on purpose: SupportedServersTests finds this page's tables by their cell count, and a third table would be read as a claim about a server line.

No second reader looked at this. The runs and readings above are the evidence in place of one.

What this does not close

#88 stays open. Its second condition is met by the walk; its fifth is not, and the reading of what a check over the changelog side would have as its subject is already on the issue.

Three places in this tree describe the channel an operator installs from.
Two of them had stopped being true and the third recorded a walk that does
not reach the catalogue at all, so a reader had one account of a release
that is published and advertised and another of one that is neither.

The readme said the catalogue offers the older of the two releases and that
0.1.1.0 has to be taken from its release page by hand. It offers both,
read on 2026-09-05:

    curl -sS https://flowfin.dev/manifest.json | python -c "import sys,json;e=[x for x in json.load(sys.stdin) if x['name']=='Metadata Sync'][0];print([(v['version'],v['targetAbi']) for v in e['versions']])"
    [('0.1.1.0', '10.11.0.0'), ('0.1.0.0', '10.11.0.0')]

`docs/RELEASING.md` said this tree has no route to the catalogue's own
state. It has had one since `.github/workflows/channel-freshness.yml`
landed, which reads the served file against the releases daily. The half
of that paragraph a release author needs is kept and sharpened: a green
publish run here is still not evidence that the catalogue caught up.

`docs/supported-servers.md` recorded a walk that copies an assembly into
`plugins/`. That proves the two gates accept it and says nothing about the
catalogue, the entry, the archive an operator is handed or the checksum the
server holds it to, which is easy to read past because both walks end at
the same plugin list. So the install has now been walked from the
catalogue: a fresh data directory of a 10.11.11 server, the address the
readme gives as the only repository, nothing copied in by hand, and the
plugin listed as active after a restart. The bytes are shown to be the same
at every hop - the checksum the catalogue advertises is the archive's, and
the assembly the server unpacked is the one inside that archive.

The failure this prevents is the one that has already happened twice on
this board in the other direction: a page describing the channel from when
it was last read rather than from the channel, so an operator is told to
do by hand something the catalogue now does, or told nothing is there when
it is.

What the new walk does not establish is written with it rather than left to
be assumed. The checksum was never made to disagree, so whether it is
load-bearing is read from the server's source and not measured here; the
install named its version, so the selection between two entries decided
nothing; and the server ran with no library, so the walk stops at the load.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex iderex added documentation Improvements or additions to documentation area: supply-chain Dependencies, packaging, release pipeline labels Sep 5, 2026
@iderex iderex self-assigned this Sep 5, 2026
@iderex
iderex merged commit 6d2d638 into master Sep 5, 2026
14 of 16 checks passed
@iderex
iderex deleted the release/the-catalogue-install-is-walked branch September 5, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: supply-chain Dependencies, packaging, release pipeline documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant