Skip to content

feat(huds): import broadcast HUDs from the panel - #407

Open
LCrew wants to merge 1 commit into
5stackgg:mainfrom
LCrew:pr/broadcast-huds
Open

feat(huds): import broadcast HUDs from the panel#407
LCrew wants to merge 1 commit into
5stackgg:mainfrom
LCrew:pr/broadcast-huds

Conversation

@LCrew

@LCrew LCrew commented Sep 9, 2026

Copy link
Copy Markdown

The HUD burned into live streams, demo playback and batch highlights was a closed two-value choice. resolveHudMode read default_hud_mode, stamped HUD_MODE onto the pod, and the spec-server forwarded it as a ?variant= on the one bundle JTs Hud Manager ships -- horizontal and vertical were never separate HUDs, they are two layouts of default.

This adds the dimension that was missing: a hudId. JTs Hud Manager already knows how to hold more than one (~/jthm-huds, POST /api/huds/upload-zip, and an /api/overlay/start that has always taken a hudId the pod never varied), so a broadcast_huds row is an entry in that library and the two shipped layouts are seeded as rows -- the pickers become "list the library" without the familiar options disappearing.

The archive is stored whole and never extracted here: JTHud's own upload-zip does that inside the pod, signature verification included, and a second extractor would only be a second thing to keep in agreement with it. What we do own is refusing an archive it would mishandle -- its extract writes entries with path.join and no traversal guard, and takes the hud id straight out of the archive when hud.json sits one level deep. The panel is the only thing that ever uploads to it, so the panel is where a hostile bundle has to be stopped.

An imported HUD carries no variant of its own, and the empty string is the answer rather than a fallback layout: handing an imported bundle ?variant=horizontal names a layout its hud.json very likely does not declare. HUD_MODE keeps carrying a real layout, since an older game-streamer image reads that one.

GET /huds/:slug/bundle.zip is deliberately unauthenticated -- JTs Hud Manager inside the pod holds no 5stack session, and it serves nothing but an archive an administrator uploaded. /hud-data/:matchId stays cluster-internal as before.

Nothing regresses on an older game-streamer image: HUD_MODE is still sent carrying the variant, and setHudMode keeps its signature, with the three old layout names mapping onto the seeded builtin slugs.

Needs the matching game-streamer change to load an imported bundle, and the /huds ingress path in 5stack-panel for the browser-side import.

The HUD burned into live streams, demo playback and batch highlights was a
closed two-value choice. resolveHudMode read `default_hud_mode`, stamped
HUD_MODE onto the pod, and the spec-server forwarded it as a `?variant=` on the
one bundle JTs Hud Manager ships -- horizontal and vertical were never separate
HUDs, they are two layouts of `default`.

This adds the dimension that was missing: a hudId. JTs Hud Manager already knows
how to hold more than one (~/jthm-huds, POST /api/huds/upload-zip, and an
/api/overlay/start that has always taken a hudId the pod never varied), so a
broadcast_huds row is an entry in that library and the two shipped layouts are
seeded as rows -- the pickers become "list the library" without the familiar
options disappearing.

The archive is stored whole and never extracted here: JTHud's own upload-zip
does that inside the pod, signature verification included, and a second
extractor would only be a second thing to keep in agreement with it. What we do
own is refusing an archive it would mishandle -- its extract writes entries with
path.join and no traversal guard, and takes the hud id straight out of the
archive when hud.json sits one level deep. The panel is the only thing that ever
uploads to it, so the panel is where a hostile bundle has to be stopped.

An imported HUD carries no variant of its own, and the empty string is the
answer rather than a fallback layout: handing an imported bundle
`?variant=horizontal` names a layout its hud.json very likely does not declare.
HUD_MODE keeps carrying a real layout, since an older game-streamer image reads
that one.

GET /huds/:slug/bundle.zip is deliberately unauthenticated -- JTs Hud Manager
inside the pod holds no 5stack session, and it serves nothing but an archive an
administrator uploaded. /hud-data/:matchId stays cluster-internal as before.

Nothing regresses on an older game-streamer image: HUD_MODE is still sent
carrying the variant, and setHudMode keeps its signature, with the three old
layout names mapping onto the seeded builtin slugs.

Needs the matching game-streamer change to load an imported bundle, and the
/huds ingress path in 5stack-panel for the browser-side import.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant