52615d9139
gates / gates (push) Successful in 6m34s
The catalog published SABnzbd and NZBGet today (app-catalog 8ee687e). Here: - two cards in the media category on both language sets, each with the project's own logo and each saying IN BOLD that a paid Usenet subscription is the household's own - the published count 60 -> 62 everywhere it is stated; the category badges are derived from the cards now (media read 15 with 17 cards, otthon/home read 14 with 16 — both stale) - documentation/audits/usenet-2026-10-12/: both bench runs, both box steps and verdicts, the nine defects with their measurements, what a missing provider left unmeasured, the teardown - R-988 closed (moved to CLOSED-ITEMS in this commit); R-989 filed: the drill-catalog route of 09 §6.5 cannot be followed — that repo is private and no box has catalog credentials, so the templates were staged in the box's own catalog cache instead - walk.app_env: a SECRET field in app.yaml is stored ENC:, so that helper returns ciphertext — the docstring says so now, measured the hard way - STATUS.md and REPORT-usenet-2026-10-12.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
98 lines
6.8 KiB
Markdown
98 lines
6.8 KiB
Markdown
# REPORT — 2026-10-12 (late night): the Usenet pair published (R-988)
|
|
|
|
The operator asked for SABnzbd and NZBGet and asked one question first: does testing need a Usenet
|
|
account? Answered with the line the work then followed — no, except for the download chain itself,
|
|
which is recorded as unmeasured rather than glossed over.
|
|
|
|
## What shipped
|
|
|
|
- **`app-catalog-felhom.eu` `8ee687e`** — `templates/sabnzbd/` and `templates/nzbget/` with
|
|
`onboarding/sabnzbd.md` and `onboarding/nzbget.md` in ONE commit, plus the README tables, two
|
|
`FIRST-ADMIN.md` class-1 rows and a fixture per app in both venues.
|
|
- **This repo** — the two app cards (both language sets) with the projects' own logos, the published
|
|
count 60 → 62 everywhere it is stated, corrected category badges (now derived from the cards),
|
|
`documentation/audits/usenet-2026-10-12/`, the register changes, and this report.
|
|
|
|
## What was measured, and what was not
|
|
|
|
Bench LXC 9401 (twelve questions per app) and scratch guest 9202 **through the product** (install from
|
|
a staged FROM pin, stranger and household through traefik on the app's own public name, the guarded
|
|
Update with its per-app backup, both remove choices). Both ladder steps are `proven` in both venues,
|
|
written by `upgrade-test.py --write-ladder`; C3, the harness's negative control, came back `failed`
|
|
first.
|
|
|
|
**Not measured, and stated in both records and on both app pages:** a household must bring a PAID
|
|
Usenet provider, and this session had none, so connecting to a provider, par2 repair, unpacking, the
|
|
finished file on the drive, and memory under that load are untested. The queue — the store an upgrade
|
|
must not lose — is measured in both apps, seeded through their own APIs with a hand-built NZB whose
|
|
articles do not exist. The operator was offered a trial account or a free text-only server and chose
|
|
to publish with the gap stated; adding the download measurement later is one bench phase.
|
|
|
|
## Nine defects, found by measuring
|
|
|
|
Four are lessons beyond these two apps. **`inet_exposure = 5` protected nobody** in SABnzbd: it asks
|
|
only an "external" visitor to log in, and the app's built-in LAN ranges include the 172.16/12 that
|
|
traefik arrives from — a request with no credentials at all answered 200 and served the Quick-Start
|
|
Wizard, until `local_ranges = 127.0.0.1` replaced those defaults (which also stops the app trusting
|
|
`X-Forwarded-For`). **NZBGet kept its queue, nzb files and temp dir under `MainDir`, which ships as
|
|
`/downloads`** — the household's drive, the one folder this catalog classifies "optional, fetchable
|
|
again", so a restore would have returned the finished files and lost what was downloading. **A
|
|
`backup` or `data_paths` entry must name a path the compose actually binds**, or the controller
|
|
rejects the block out loud and the data has no class at all (SABnzbd's first version bound two
|
|
subfolders and declared their parent). **An `after_install` readback must match the app's own JSON
|
|
spacing** — SABnzbd answers `"key":value`, the greps expected a space, so the marker never printed,
|
|
the install held and the box kept the app closed, which is the gate working exactly as designed.
|
|
|
|
The rest: NZBGet's image has no curl, so the healthcheck could never pass (busybox wget now, proven
|
|
both ways); its shipped config carries the documented default password in plain text and thereby
|
|
breaks the app's own CLI; it asks nzbget.com for new versions; SABnzbd's healthcheck dialled `/`,
|
|
which answers 303; and two of my own fixtures assumed tools inside containers that lack them.
|
|
|
|
**Two measurement artefacts, recorded as such.** NZBGet looked broken because my probe ran its CLI
|
|
with `docker exec`, which defaults to root in that image, and recreated the app's directories as
|
|
root. And the box fixture read the API key from `app.yaml`, where a deploy secret is stored
|
|
**encrypted**, so the app rightly answered "API Key Incorrect"; `walk.app_env`'s docstring now says
|
|
what an `ENC:` value does, since the next session would have made the same mistake.
|
|
|
|
## The documented drill route could not be followed — filed, not papered over
|
|
|
|
`09` §6.5 runs a new app's box walk from the drill catalog. `admin/app-catalog-drill` is **private**
|
|
(Gitea API: `private=true`; the live catalog is `private=false`) and **no controller.yaml on 9202,
|
|
current or any of its 30 saved copies, has ever carried `git.username`/`git.token`**, so the box's
|
|
clone fails with `fatal: could not read Username`, exit 128. The route worked for the campaigns of
|
|
2026-10-10 and the torrent pair earlier today, so the repository's visibility changed in between.
|
|
|
|
Rather than put a credential on a box or change a repository's visibility unasked, the two templates
|
|
were staged in the box's own catalog cache — where the sync copies a catalog change anyway — with the
|
|
sync interval raised to 12h for the duration and rescan used in place of sync. **R-992** asks the
|
|
operator to choose the real fix.
|
|
|
|
## Gates and CI
|
|
|
|
`catalog_gates.py --fast` (whole catalog): all OK. `catalog_gates.py sabnzbd nzbget`: the same but for
|
|
`image-resolvable` (needs network) and `volume-persistence` (refuses a host that is not a scratch
|
|
host) — the two documented periodic ones, both covered on the bench. `site_gates.py`: OK, including
|
|
the logo gate (64 catalog apps, each with its logo) and the sitemap. `repo_gates.py --fast` here still
|
|
reports `instructions` and `script-tests` failing and `wire-contract` inconclusive — the same
|
|
pre-existing, Windows-shaped results as this afternoon, none of them about this work; CI on the
|
|
DooPlex-shaped runner is the authority and this afternoon's run was green.
|
|
|
|
## Teardown — three layers, verified
|
|
|
|
Both apps removed **through the product** on 9202 (volumes gone, no containers, the two download
|
|
folders deleted from the scratch drive, the standing apps untouched); the staging undone (out of the
|
|
cache and out of `/opt/docker/stacks`, sync interval back to 15m), with the catalog state proven by
|
|
sha256 against the published `origin/main` plus a decoy that must differ; bench 9401 emptied —
|
|
including the three anonymous volumes it was left with, removed **by name**, never a prune — and
|
|
stopped as it was found; the drill catalog reset to live `main`; the DooPlex clone clean at the
|
|
published commit. Hub: nothing to undo. `media/torrents` and `media/transmission` exist again on the
|
|
scratch drive as empty directories, created by the product's own storage sync for published apps, not
|
|
by this campaign.
|
|
|
|
## Register
|
|
|
|
Rows before 117, after 120 - a parallel session filed three of its own (R-989, R-990, R-991) while
|
|
this one ran, which is also why the drill-catalog row is **R-992** and not R-989. This session opened
|
|
1 (**R-992**) and closed 1 (**R-988**, moved to `CLOSED-ITEMS.md` in the same commit). Fixed without a row: the nine defects above, the two fixture
|
|
defects, the stale category badges on the app page, and `walk.app_env`'s docstring.
|