feat(store): console plugin store, index repo, and the fixes on-glass found
apple / swift (push) Successful in 1m22s
release / apple (push) Successful in 9m59s
windows-host / package (push) Successful in 9m52s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m20s
apple / screenshots (push) Successful in 6m28s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m21s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m39s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m45s
audit / cargo-audit (push) Successful in 2m58s
audit / bun-audit (push) Successful in 13s
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 59s
android / android (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
decky / build-publish (push) Successful in 23s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 35s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 49s
flatpak / build-publish (push) Successful in 7m53s
docker / deploy-docs (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
deb / build-publish (push) Successful in 11m41s
deb / build-publish-host (push) Successful in 13m32s
apple / swift (push) Successful in 1m22s
release / apple (push) Successful in 9m59s
windows-host / package (push) Successful in 9m52s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m20s
apple / screenshots (push) Successful in 6m28s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m21s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m39s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 5m45s
audit / cargo-audit (push) Successful in 2m58s
audit / bun-audit (push) Successful in 13s
ci / web (push) Successful in 52s
ci / docs-site (push) Successful in 59s
android / android (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
decky / build-publish (push) Successful in 23s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 35s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 49s
flatpak / build-publish (push) Successful in 7m53s
docker / deploy-docs (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
deb / build-publish (push) Successful in 11m41s
deb / build-publish-host (push) Successful in 13m32s
Console: a Plugins section (Browse / Installed / Sources) on a static nav entry, with install friction proportional to trust — a plain confirm for a verified entry, a warning naming the curator for an external one, and a danger dialog that makes you retype the spec for a raw package. Tier badges are permanent and follow the plugin onto its own UI page. Index: unom/punktfunk-plugin-index published and served from Gitea's raw endpoint (real HTTPS, byte-exact, no vhost to stand up) — merge to main is publish, which resolves the design's open hosting question. Four things only running it could find: - runner discovery matched @punktfunk/plugin-* only, so a third-party scoped plugin (which D8 requires) would install and never run - ...and that convention also matches @punktfunk/plugin-kit, a plugin's own framework: it listed as installed and would have been imported as a unit. Both now key off the plugins dir's top-level dependencies, with an emptied dependency list meaning 'nothing installed' rather than falling back to the naming convention - the store must not pass new flags to the runner: the scripting package ships separately and an older one reads an unknown flag's value as a package name. The host writes the bunfig scope mapping itself - ureq reports only >= 400 as Err, so a conditional request's 304 arrives as Ok with an empty body — handled as an error it made every refresh after the first verify a signature over zero bytes and sit stale Also: the console's first Tabs use exposed an @unom/ui theme gap that rendered inactive tabs invisible (caught in a browser pass, not by types). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,9 +54,13 @@ pub(crate) fn fetch(source: &Source, etag: Option<&str>) -> Fetched {
|
||||
req = req.set("If-None-Match", tag);
|
||||
}
|
||||
let resp = match req.call() {
|
||||
// `ureq` only turns status >= 400 into `Err(Status)`, so a conditional request's 304
|
||||
// arrives here as **Ok with an empty body** — not as an error. Reading it as an error arm
|
||||
// (the intuitive reading) means every refresh after the first one verifies a signature
|
||||
// over zero bytes and "fails"; the catalog then sits permanently stale, serving cache and
|
||||
// never picking up a new entry. Found on-glass; pinned by `ureq_returns_304_as_ok`.
|
||||
Ok(r) if r.status() == 304 => return Fetched::NotModified,
|
||||
Ok(r) => r,
|
||||
// 304 is the happy "nothing changed" path, not a failure.
|
||||
Err(ureq::Error::Status(304, _)) => return Fetched::NotModified,
|
||||
Err(ureq::Error::Status(code, _)) => {
|
||||
return Fetched::Failed(format!("index fetch returned HTTP {code}"))
|
||||
}
|
||||
@@ -243,6 +247,37 @@ mod tests {
|
||||
assert!(!meta_path(dir.path(), "s").exists());
|
||||
}
|
||||
|
||||
/// Pins the HTTP-client assumption that [`fetch`]'s conditional-request handling rests on.
|
||||
///
|
||||
/// `ureq` converts only status >= 400 into `Err(Status)`. A 304 — which is exactly what a
|
||||
/// successful `If-None-Match` produces, i.e. the *steady state* of a healthy catalog — comes
|
||||
/// back as `Ok` with an empty body. Treating it as an error arm compiles, looks right, and
|
||||
/// silently breaks every refresh after the first: the empty body fails the signature check and
|
||||
/// the source sits stale forever. If a `ureq` upgrade ever changes this, fail here rather than
|
||||
/// on someone's host.
|
||||
#[test]
|
||||
fn ureq_returns_304_as_ok() {
|
||||
use std::io::Write as _;
|
||||
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
let server = std::thread::spawn(move || {
|
||||
if let Ok((mut sock, _)) = listener.accept() {
|
||||
let _ = sock.write_all(b"HTTP/1.1 304 Not Modified\r\nETag: \"x\"\r\n\r\n");
|
||||
let _ = sock.flush();
|
||||
}
|
||||
});
|
||||
|
||||
let resp = ureq::get(&format!("http://{addr}/index.json"))
|
||||
.set("If-None-Match", "\"x\"")
|
||||
.call();
|
||||
let _ = server.join();
|
||||
|
||||
match resp {
|
||||
Ok(r) => assert_eq!(r.status(), 304, "304 must arrive as Ok, and be checked for"),
|
||||
Err(e) => panic!("ureq now reports 304 as an error ({e}) — fetch() must be updated"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_https_source_never_reaches_the_network() {
|
||||
let s = Source {
|
||||
|
||||
Reference in New Issue
Block a user