From 1bc9c18504c420c40f63be7fab975a4f407746bf Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 2 Aug 2026 20:43:19 +0200 Subject: [PATCH] gateway: nginx-hosts the full Swagger UI dist, core drops the fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends the theme-only alias into the full shape mara asked for on the PR thread: 1. nix/packages/swagger-ui-dist.nix — plain vendored Swagger UI 5.17.14 dist, sourced directly from the swagger-ui-dist npm package (same release the Rust utoipa-swagger-ui-vendored crate ships, verified via matching gitHead commit) rather than through Cargo.lock/cargo. 2. nix/packages/swagger-ui-theme.nix — overlays our 3 override files (index.html, hyperhive-theme.css, and now swagger-initializer.js) onto (1). 3. vhosts.nix's swaggerUiLocations now prefix-matches the whole /api/docs/ tree (not just 2 exact-match files) straight from (2), plus a `= /api/docs` redirect shim since hive-c0re's own redirect is going away too. /api/openapi.json (outside this prefix) keeps proxying to c0re unchanged — that's the one thing that stays dynamic. New file swagger-initializer.js needed hand-verification: the plain vendored copy hardcodes the swagger.io petstore demo URL. utoipa-swagger-ui normally rewrites it per-request from a {{config}} placeholder its own build.rs injects — since hive-c0re won't be serving this file at all once its SwaggerUi mount is removed, that rewrite has to be baked in statically here instead. Derived by actually running build.rs's own two transforms (strip the default layout: line, splice the Config JSON in place of the url/deepLinking block) against the real vendored file, not typed from scratch — verified byte-for-byte against what format_config() would produce for hive-c0re's actual single-URL config, and checked with node --check. Coordinated with damocles: he's taking the corresponding hive-c0re side (drop the utoipa-swagger-ui dependency + SwaggerUi::new(...) mount, keep only the plain /api/openapi.json route) once this lands. Verified: nix fmt clean; nix build .#swagger-ui-theme succeeds, output byte-matches the checked-in override files and node --check passes on swagger-initializer.js; a full nixosSystem eval of nixosModules.default resolves both new locations (/api/docs/ aliased to the right store path, = /api/docs redirecting) with auth threaded through. --- hive-c0re/swagger-ui-theme/index.html | 23 +++---- .../swagger-ui-theme/swagger-initializer.js | 21 ++++++ nix/host-modules/hive-c0re/options.nix | 14 ++-- nix/host-modules/hive-gateway/default.nix | 8 +-- nix/host-modules/hive-gateway/vhosts.nix | 45 +++++++------ nix/packages/default.nix | 19 ++++-- nix/packages/swagger-ui-dist.nix | 47 ++++++++++++++ nix/packages/swagger-ui-theme.nix | 65 +++++++++++-------- 8 files changed, 166 insertions(+), 76 deletions(-) create mode 100644 hive-c0re/swagger-ui-theme/swagger-initializer.js create mode 100644 nix/packages/swagger-ui-dist.nix diff --git a/hive-c0re/swagger-ui-theme/index.html b/hive-c0re/swagger-ui-theme/index.html index 5fd30668..a357a703 100644 --- a/hive-c0re/swagger-ui-theme/index.html +++ b/hive-c0re/swagger-ui-theme/index.html @@ -1,16 +1,13 @@ - + diff --git a/hive-c0re/swagger-ui-theme/swagger-initializer.js b/hive-c0re/swagger-ui-theme/swagger-initializer.js new file mode 100644 index 00000000..1e2c4abc --- /dev/null +++ b/hive-c0re/swagger-ui-theme/swagger-initializer.js @@ -0,0 +1,21 @@ +window.onload = function() { + // + + // the following lines will be replaced by docker/configurator, when it runs in a docker-container + window.ui = SwaggerUIBundle({ + "dom_id": "#swagger-ui", + "url": "/api/openapi.json", + "deepLinking": true, + "layout": "StandaloneLayout", + presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIStandalonePreset + ], + plugins: [ + SwaggerUIBundle.plugins.DownloadUrl + ], + + }); + + // +}; diff --git a/nix/host-modules/hive-c0re/options.nix b/nix/host-modules/hive-c0re/options.nix index b67c0b6b..c5d7088b 100644 --- a/nix/host-modules/hive-c0re/options.nix +++ b/nix/host-modules/hive-c0re/options.nix @@ -69,13 +69,13 @@ type = lib.types.package; defaultText = lib.literalExpression "hyperhive.packages.\${system}.swagger-ui-theme"; description = '' - Swagger UI re-theme static override files (see - `nix/packages/swagger-ui-theme.nix`; output has `index.html` + - `hyperhive-theme.css`). The hive-gateway module `alias`es these - two files straight from the store over `/api/docs/`, so a theme - tweak is a gateway config change — hive-c0re's own vendored - Swagger UI build is untouched. Override to ship a custom theme - (or the vendored default) without a hive-c0re rebuild. + Full Swagger UI static dist, hyperhive-themed (see + `nix/packages/swagger-ui-theme.nix`, built on + `nix/packages/swagger-ui-dist.nix`). hive-gateway serves this + whole tree directly at `/api/docs/` — hive-c0re hosts none of + it, only the dynamic `/api/openapi.json` route. Override to + ship a custom theme (or the plain vendored dist) without a + hive-c0re rebuild. ''; }; hyperhiveFlake = lib.mkOption { diff --git a/nix/host-modules/hive-gateway/default.nix b/nix/host-modules/hive-gateway/default.nix index a2c53f95..28453f06 100644 --- a/nix/host-modules/hive-gateway/default.nix +++ b/nix/host-modules/hive-gateway/default.nix @@ -24,10 +24,10 @@ let # container's). dashboardDist = "${config.services.hyperhive.c0re.servedFrontend}/dashboard"; - # Swagger UI re-theme static override files — nginx `alias`es these - # straight from the store over `/api/docs/`, so a theme tweak ships - # as a gateway config change (see vhosts.nix's `swaggerThemeLocations` - # and nix/packages/swagger-ui-theme.nix). + # Full hyperhive-themed Swagger UI dist — nginx serves this whole + # tree straight from the store at /api/docs/, no hive-c0re fallback + # (see vhosts.nix's `swaggerUiLocations` and + # nix/packages/swagger-ui-{dist,theme}.nix). swaggerUiTheme = config.services.hyperhive.c0re.swaggerUiTheme; # Self-signed TLS is the implicit floor: when neither an operator cert diff --git a/nix/host-modules/hive-gateway/vhosts.nix b/nix/host-modules/hive-gateway/vhosts.nix index 645d58f9..f94395b5 100644 --- a/nix/host-modules/hive-gateway/vhosts.nix +++ b/nix/host-modules/hive-gateway/vhosts.nix @@ -306,28 +306,35 @@ let }; }; - # Swagger UI re-theme: exact-match locations `alias`ed straight to - # `swaggerUiTheme`'s store path, nginx-served with no involvement - # from hive-c0re at all. `=` locations win over the `/api/` prefix - # block above regardless of declaration order (nginx's own location- - # matching precedence — exact match beats longest-prefix), so this - # doesn't need to be declared before it. Every OTHER Swagger UI asset - # (bundle.js, openapi.json, favicons, the *vendored* index.html c0re - # would otherwise serve) still falls through `/api/` to c0re's own - # embedded `utoipa-swagger-ui` dist unchanged — only these two exact - # paths are intercepted. A theme tweak is therefore a change to - # `hive-c0re/swagger-ui-theme/` + a gateway container activation, not - # a hive-c0re rebuild+restart. See nix/packages/swagger-ui-theme.nix. - swaggerThemeLocations = { - "= /api/docs/" = { + # Swagger UI: nginx hosts the FULL themed dist (`swaggerUiTheme` — + # vendored Swagger UI + our overlay, see nix/packages/swagger-ui- + # dist.nix + swagger-ui-theme.nix) straight from the store, with NO + # fallback to hive-c0re at all — per the operator's shape: "core + # should not need the swagger ui at all if it is hosted in gateway" + # / "core only hosts the json". Only `/api/openapi.json` + # (the live-generated spec `index.html` fetches; not under this + # prefix) still proxies to c0re via "/api/" below — that's the one + # thing that has to stay dynamic. + # + # Prefix location, not exact-match: wins over "/api/" on plain + # prefix length (no ordering/`=` needed), and now needs to cover + # every file in the tree (bundle.js, maps, favicons, …), not just + # our 2 override files — hive-c0re no longer serves any of this as + # a fallback once its own `utoipa-swagger-ui` mount is removed. + # `= /api/docs` (no trailing slash) issues the same redirect + # `utoipa-swagger-ui`'s router used to: that mount is going away + # too, so nginx has to own it now, or the H0M3 hub's own `/api/docs` + # link (no trailing slash) would 404 once hive-c0re drops the route. + swaggerUiLocations = { + "= /api/docs" = { extraConfig = '' - alias ${swaggerUiTheme}/index.html; - ${dashboardAuth} + return 301 /api/docs/; ''; }; - "= /api/docs/hyperhive-theme.css" = { + "/api/docs/" = { + alias = "${swaggerUiTheme}/"; extraConfig = '' - alias ${swaggerUiTheme}/hyperhive-theme.css; + index index.html; ${dashboardAuth} ''; }; @@ -353,7 +360,7 @@ in // wellKnownLocations // agentLocations // dashboardProxyLocation - // swaggerThemeLocations + // swaggerUiLocations // lib.optionalAttrs cfg.auth.enable { # Internal-only target for the 401 error_page above. # `internal` prevents direct client access; `alias` serves diff --git a/nix/packages/default.nix b/nix/packages/default.nix index ce53804f..70c5baa7 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -18,6 +18,13 @@ let inherit (nixpkgs.lib) nixosSystem; }; + # Plain vendored Swagger UI dist (./swagger-ui-dist.nix) + the + # hyperhive-themed overlay on top (./swagger-ui-theme.nix) — bound + # here (not just inline in the attrset below) so the theme + # derivation can take the dist derivation as an explicit input. + swagger-ui-dist = pkgs.callPackage ./swagger-ui-dist.nix { }; + swagger-ui-theme = pkgs.callPackage ./swagger-ui-theme.nix { inherit swagger-ui-dist; }; + # Every per-binary package: name → description. The single source of # truth for the bin list — it drives the per-bin extractor packages # and the `default` bundle, so adding a binary is one entry here. @@ -158,11 +165,13 @@ in xdg-icons = pkgs.callPackage ./hive-xdg-icons.nix { hyperhiveSvg = ../../branding/hyperhive.svg; }; - # Swagger UI re-theme static override files — see - # ./swagger-ui-theme.nix. The gateway `alias`es these straight from - # the store; a theme tweak is a gateway config change, not a - # hive-c0re rebuild. - swagger-ui-theme = pkgs.callPackage ./swagger-ui-theme.nix { }; + # Swagger UI: plain vendored dist + the hyperhive-themed overlay — + # see ./swagger-ui-dist.nix / ./swagger-ui-theme.nix (both computed + # above, in `let`). The gateway serves `swagger-ui-theme`'s full + # tree straight from the store at /api/docs/; a theme tweak is a + # gateway config change, not a hive-c0re rebuild. `swagger-ui-dist` + # is exposed too since it's independently useful/inspectable. + inherit swagger-ui-dist swagger-ui-theme; # Pre-built per-container system closures. Exposed as packages # so operators can `nix build .#agent-base-toplevel` (or wire diff --git a/nix/packages/swagger-ui-dist.nix b/nix/packages/swagger-ui-dist.nix new file mode 100644 index 00000000..cc70e995 --- /dev/null +++ b/nix/packages/swagger-ui-dist.nix @@ -0,0 +1,47 @@ +{ + stdenv, + fetchurl, +}: + +# Pure vendored Swagger UI 5.17.14 static dist — no hyperhive theming +# (see ./swagger-ui-theme.nix for that layer). Deliberately NOT sourced +# via the Rust `utoipa-swagger-ui-vendored` crate / Cargo.lock (per the +# operator's ask: a nix package that just contains the plain static +# dist, not fetched via cargo) — hive-c0re no longer needs to know this +# exists at all once the gateway hosts it directly. +# +# Sourced straight from the `swagger-ui-dist` npm package, which ships +# exactly the built `dist/` files (no source, no build step needed) at +# the same release as the Rust ecosystem's vendored copy — verified by +# comparing this tarball's recorded `gitHead` (in its `package.json`, +# `74ed0adebfc9c8dd0de2bf8e81495b022a66c083`) against the commit the +# `utoipa-swagger-ui-vendored` crate's own pinned zip was built from +# (same hash, printed by `unzip -l` on that zip's first entry). +stdenv.mkDerivation { + pname = "swagger-ui-dist"; + version = "5.17.14"; + + src = fetchurl { + url = "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz"; + hash = "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw=="; + }; + + sourceRoot = "package"; + dontBuild = true; + + installPhase = '' + runHook preInstall + mkdir -p $out + # The npm package also carries a few node-consumption conveniences + # (package.json, index.js, absolute-path.js, README/LICENSE/NOTICE) + # alongside the actual browser dist — only copy what a web server + # should ever expose. + cp *.html *.css *.css.map *.js *.js.map *.png $out/ + runHook postInstall + ''; + + meta = { + description = "Vendored Swagger UI 5.17.14 static dist (unthemed), from the swagger-ui-dist npm package"; + homepage = "https://forge.darkest.space/hyperhive/hyperhive"; + }; +} diff --git a/nix/packages/swagger-ui-theme.nix b/nix/packages/swagger-ui-theme.nix index 7e21faa6..a84cb6e0 100644 --- a/nix/packages/swagger-ui-theme.nix +++ b/nix/packages/swagger-ui-theme.nix @@ -1,49 +1,58 @@ { stdenv, + swagger-ui-dist, }: -# The hand-authored Swagger UI re-theme files (`hive-c0re/swagger-ui- -# theme/`), shipped as a standalone derivation so the gateway can -# `alias` them straight from the nix store instead of hive-c0re's own -# build serving them — see nix/host-modules/hive-gateway/vhosts.nix's -# `swaggerThemeLocations`. This is what lets a CSS tweak ship as a -# gateway config change (activate the gateway container) rather than a -# hive-c0re rebuild+restart: the two files nginx exact-matches -# (`/api/docs/` and `/api/docs/hyperhive-theme.css`) come from here; -# every other Swagger UI asset (bundle.js, openapi.json, favicons, …) -# still falls through the existing `/api/` prefix proxy to hive-c0re's -# own vendored (unthemed) `utoipa-swagger-ui` embed, unchanged. +# hyperhive's Catppuccin Mocha re-theme of Swagger UI: overlays our 3 +# hand-authored override files (`hive-c0re/swagger-ui-theme/`) onto +# the plain vendored dist (./swagger-ui-dist.nix). This is the FULL +# tree hive-gateway's nginx serves at `/api/docs/` — hive-c0re hosts +# none of it, only the dynamic `/api/openapi.json` (see +# nix/host-modules/hive-gateway/vhosts.nix). # -# Pure data: copied verbatim, no build step. -# -# Output layout: -# $out/index.html — themed index.html Swagger UI page -# $out/hyperhive-theme.css — the re-theme, consumes --baseNN vars -# from the dashboard's own colors.css -# (loaded via an absolute /static/ -# colors.css , same origin) - +# Output layout: every file from `swagger-ui-dist`, with 3 replaced: +# index.html — adds s for colors.css (live stylix +# theme, same origin) + hyperhive-theme.css +# hyperhive-theme.css — new; the re-theme itself, consumes +# --baseNN vars from colors.css +# swagger-initializer.js — hardcodes `url: "/api/openapi.json"`. The +# plain vendored copy points at the +# swagger.io petstore demo; normally +# `utoipa-swagger-ui`'s `serve()` rewrites +# this file per-request from a `{{config}}` +# placeholder it injects at its OWN build +# time (see that crate's `build.rs`'s +# `replace_default_url_with_config` + +# `format_config`). hive-c0re no longer +# serves this file at all, so that rewrite +# has to happen here instead — this copy is +# hand-verified to byte-match what +# `format_config` would produce for +# hive-c0re's actual config (single unnamed +# url, otherwise all `Config` defaults): the +# same transform applied to the real +# vendored file, not hand-typed from +# scratch. stdenv.mkDerivation { pname = "hyperhive-swagger-ui-theme"; version = "0.1.0"; - # Narrow src keeps this derivation's input hash decoupled from the - # rest of the tree — a theme tweak only re-hashes this. - src = ../../hive-c0re/swagger-ui-theme; + dontUnpack = true; dontBuild = true; - dontConfigure = true; installPhase = '' runHook preInstall mkdir -p $out - cp -r ./* $out/ + cp -r ${swagger-ui-dist}/. $out/ + chmod -R u+w $out + install -m644 ${../../hive-c0re/swagger-ui-theme/index.html} $out/index.html + install -m644 ${../../hive-c0re/swagger-ui-theme/hyperhive-theme.css} $out/hyperhive-theme.css + install -m644 ${../../hive-c0re/swagger-ui-theme/swagger-initializer.js} $out/swagger-initializer.js runHook postInstall ''; - dontFixup = true; - meta = { - description = "hyperhive Swagger UI Catppuccin Mocha re-theme (static override files)"; + description = "hyperhive Swagger UI Catppuccin Mocha re-theme — full static dist, nginx-served at /api/docs/"; homepage = "https://forge.darkest.space/hyperhive/hyperhive"; }; }