`cargo leptos build --release` died with "queries overflow the depth
limit": every tile's Show/icon views inlined into one enormous
hydrate_async type for the whole call subtree. VideoTile, CallIcon and
CallActive now return AnyView, the same cut CallPanel got in 0.2.1. The
dev profile never tripped it, which is why 0.3.0 shipped broken.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L3sD29ozDvqA7jozeZXZoB
Screen sharing swaps the outgoing video track on every peer's sender with
replaceTrack (same m-line, no renegotiation); the camera returns when the
share stops, including via the browser's own "Stop sharing" bar. Mic and
camera toggles flip track.enabled. A new Status signal kind broadcasts
mic/cam/screen state so tiles can show badges; newcomers get it directed
when their Join arrives.
Tiles carry a name label, click to pin as a stage (a peer's screen share
pins itself), double-click for fullscreen. The call bar has an elapsed
timer and a participant count. Controls are icon-only inline SVGs on
currentColor: plain with a strike when off, a soft glow and ticking LED
when live. Red is reserved for leave.
Also fixed along the way: the peer map was a non-reactive StoredValue, so
the tile list never re-rendered when someone joined; ICE candidates that
arrive before the remote description are now buffered instead of
rejected; a peer whose connection fails or closes is dropped.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L3sD29ozDvqA7jozeZXZoB
The aarch64 release leg runs on the klokka host. Gate the sccache /
cargo-binstall / cargo-leptos installs to the ephemeral x86_64 container; on
the bare runner check-and-fail instead (the sccache tarball was x86_64-only
anyway, so it was both a host mutation and a wrong-arch binary). Switch
checkout to v4 builtin:checkout (native Go, no Node/download) in all jobs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
x86_64 uses /sccache (host dir bind-mounted into the job container by the
runner config); aarch64 on the klokka host uses a runner-owned dir. Both
persist across releases via RUSTC_WRAPPER=sccache.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLUwWE2KmFPzhKaf67tWbx
The runner's PKGEXT is .pkg.tar.xz, so the .zst glob never matched;
--packagelist yields the exact filename, and options=('!strip') lets the
foreign-arch binary be packaged on the aarch64 host without stripping.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLUwWE2KmFPzhKaf67tWbx
- PKGBUILD url/source now point at this instance's releases.
- Release uploads use the run's own ephemeral token instead of the
GITEA_TOKEN secret.
- The publish job also builds both architectures' packages (repack
PKGBUILD, CARCH override) and uploads them to the instance Arch
package registry (repository name: uhhm).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GLUwWE2KmFPzhKaf67tWbx
Palette override in a light media query; scanlines, vignette, card
shadow and signal glows moved to tokens/color-mix so both prints share
one set of rules. color-scheme on :root brings UA scrollbars and form
controls along.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every video tile is built client-side via document.createElement, never
parsed from HTML - browsers only seed the live .muted property from the
muted attribute for parser-inserted elements, so the attribute alone
never actually silenced the local preview. Result: your own mic played
back through your own speakers even with no other peers in the call.
Now sets el.set_muted(true) directly whenever the preview's srcObject
is (re)assigned.
The SSR branch rendered an empty call-panel div while the hydrate
branch expected a child button node. On any full load/refresh of the
lobby room, the mismatched hydration cursor hit tachys's
unreachable!() panic path, trapping the wasm instance and killing all
reactivity (routing, room switching, SSE) for the rest of the page
load, while the already-rendered SSR HTML stayed visually intact.
SSR now renders the same default join-button markup hydrate expects.
Building cargo-leptos from source pulls in swc/lightningcss/rhai and was
OOM-killing the aarch64 (Raspberry Pi) runner. cargo-leptos publishes
prebuilt aarch64-unknown-linux-gnu binaries, so binstall sidesteps the
compile entirely.
Mesh calling's nested Show/For inside ChatShell's own Show inlined as a
type parameter, blowing rustc's query recursion limit during the wasm
release build (CI: "queries overflow the depth limit!"). Splitting the
in-call view into its own component and type-erasing both CallPanel
branches with .into_any() keeps the type shallow instead of raising the
crate-wide limit.
Rooms can now require a Kanidm group (via the `groups` OIDC claim,
mapped by `oauth2 update-claim-map` server-side) - dev/ops require
`developers`, enforced at every message path (send, history, SSE).
Adds a minimal WebRTC mesh call feature scoped to the lobby room,
signaled over a separate `call.room.*` NATS subject kept out of the
chat archive: public STUN only, no TURN, no SFU - small groups on
friendly networks, by design.
async_nats::connect() silently drops user:pass embedded in NATS_URL,
so the server rejected every connection with an authorization violation.
Parse the URL and feed credentials through ConnectOptions instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirrors the gpupaper release convention: v* tags build x86_64/aarch64
tarballs (binary + leptos site + systemd unit), upload them as Gitea
release assets, push bendik/cnats to Docker Hub, and update the AUR
package with checksums from the release assets.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DATABASE_URL required at startup; schema self-initializes.
Compose gains a postgres service for standalone dev.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Initial import plus deployment packaging: multi-stage Dockerfile
(cargo-leptos build -> debian-slim runtime), .dockerignore, and a
dev-only docker-compose (app + local NATS). Production deployment
lives in the infrastructure repo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>