Kanidm group-gated rooms and minimal mesh calling

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.
This commit is contained in:
2026-07-27 23:52:27 +02:00
parent 46bdad1629
commit 650ed50c21
12 changed files with 875 additions and 26 deletions
+73
View File
@@ -197,6 +197,22 @@ body::before {
text-transform: uppercase;
}
/* brand mark - height:1em scales it to whatever font-size the surrounding
heading uses, so the same element/class works at sidebar (1.6rem) and
gate-title (up to 4.5rem) scale with no per-placement sizing rules. */
.pulse-mark {
display: block;
height: 1em;
width: auto;
color: var(--signal);
margin-bottom: 0.3em;
}
.gate-tagline {
font-size: 0.75rem;
margin-top: 0.6rem;
}
.rail-label {
font-family: var(--mono);
font-size: 0.6rem;
@@ -480,6 +496,63 @@ body::before {
.composer-send:hover { filter: brightness(1.15); }
.composer-send:disabled { filter: grayscale(0.6) brightness(0.7); cursor: wait; }
/* call */
.call-panel {
padding: 0.9rem 1.6rem;
border-bottom: 1px solid var(--line);
background: var(--ink-1);
}
.call-join {
font-family: var(--mono);
font-weight: 600;
font-size: 0.78rem;
letter-spacing: 0.08em;
color: var(--ink-0);
background: var(--signal);
border: none;
padding: 0.55rem 1rem;
cursor: pointer;
transition: filter 120ms;
}
.call-join:hover { filter: brightness(1.15); }
.call-active { display: flex; flex-direction: column; gap: 0.8rem; }
.video-grid {
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
}
.video-tile {
width: 200px;
height: 150px;
background: var(--ink-0);
border: 1px solid var(--line-hot);
object-fit: cover;
}
.video-tile-local { border-color: var(--signal-dim); }
.call-leave {
align-self: flex-start;
font-family: var(--mono);
font-weight: 600;
font-size: 0.78rem;
letter-spacing: 0.08em;
color: var(--text);
background: none;
border: 1px solid var(--alarm);
padding: 0.5rem 0.9rem;
cursor: pointer;
transition: background 120ms;
}
.call-leave:hover { background: rgba(255, 90, 90, 0.12); }
/* motion */
@keyframes rise {