Commit graph

140 commits

Author SHA1 Message Date
c18604c426
Stop the app from auto-reloading on new builds; update on next manual refresh instead 2026-07-10 09:04:31 +00:00
efe0fb0df9
Add a security-group quick-pick for the securitygroup extban (config-driven) 2026-07-10 07:01:13 +00:00
68c7560212
Add opt-in Google Analytics (gtag.js) with per-channel page views, DMs redacted 2026-07-10 04:32:33 +00:00
1a82247a7d
Enable cookieless analytics on the app (config.analytics endpoint) 2026-07-10 04:19:00 +00:00
ac79231d95
Fix PWA manifest: add app id, wide/narrow screenshots, drop the SVG install icon 2026-07-09 23:39:27 +00:00
05f7eeaea1
sw: derive cache name from the build commit so deploys always evict the old shell 2026-07-09 11:47:10 +00:00
c3b5788dc1
add meet-people lobby fields to the connect screen (sex/age/city + intent picker) 2026-07-09 09:39:59 +00:00
fd46a37969 chore: tidy comments and examples 2026-07-08 01:08:44 +00:00
f859ed373d navbar: add a brandable top navbar (built-in, in-page)
Ported from the classic webchat network navbar, themed to Orbit: a full-width bar
across the top with the network logo/name and a row of external portal links. New
'navbar' UI slot rendered in a flex shell above the app grid (collapses to just the
app when unused); the orbit-navbar plugin fills it from a 'navbar' config section
(brand + links), falling back to the branding name/icon. First-party, so it runs
in-page per the trust model.
2026-07-08 00:00:24 +00:00
96728bb9ea sandbox: move the guest bootstrap into typed core source
The guest (bridge + SDK) was hand-written vanilla JS in public/plugin-sandbox.html
— untyped, unlinted, and hand-duplicating protocol constants (drift risk that grew
with the API). Move it to src/modules/sandbox/guest/ as TypeScript that imports the
shared types from protocol.ts (rpc() is now typed against RpcMethod, so a method not
wired on the host won't compile). A small Vite plugin transpiles it into
plugin-sandbox.html: served on the fly in dev, emitted into the build otherwise —
kept unminified so the served security-boundary code stays auditable, and inline so
the response keeps its own header CSP (an external script can't use 'self' in an
opaque origin). Behavior-neutral: verified clock/radio/dice mount, radio opens/plays
identically, trigger centered.
2026-07-07 18:58:06 +00:00
b0b7812bf9 sandbox: add orbit.command + orbit.shortcut; harden ui.claim
Full sandbox re-audit: the isolation/capability model is sound (opaque origin,
fail-closed gate, irc-raw split, 'raw' withheld, namespaced storage, cloneable
event payloads). The gap was that sandboxed plugins couldn't register the slash
commands / shortcuts the registry already supports in-page.

- orbit.command(name, run, help): the host registers via the registry and relays
  (args, rest) to the guest; the plugin's action still goes through gated verbs.
- orbit.shortcut(combo, run): modifier REQUIRED — the shortcut loop fires while
  typing, so a bare-key combo would keylog and eat keystrokes; the host rejects it.
- Registration hooks are disposed on each handshake so the adoption reload can't
  duplicate them.
- ui.claim now validates the slot against the known set (bogus slot -> footer).

Verified live: /hello relays to the guest and posts to the channel. Template +
docs updated.
2026-07-07 18:32:44 +00:00
07d804530e sandbox: center the panel trigger so it can't slide onto the next tab
A <button> sizes to fit-content, and the panel root was a plain block, so when
the wider card opened the trigger left-aligned under it and slid onto the
neighbouring tab. Center the panel root (flex column, align-items center) so the
trigger stays over its own slot open or closed. Fixes it for every panel.
2026-07-07 18:20:19 +00:00
f04a30f7fb sandbox: add a plugin SDK (orbit.panel + orbit.el) so rich plugins just work
The pain of writing a sandboxed plugin came from re-solving the same hard parts
by hand: theming, the async frame-resize lag, upward growth, no half-drawn
flash, native-looking controls. Move all of it into the guest bootstrap:

- orbit.panel(opts): a nav tab + floating panel that opens upward, fully in
  view, no flash/grey/black, matching the native tabs — author just fills body.
- orbit.el.button/row/slider: pre-themed atoms.
- guest defaults: box-sizing, sane line-height, text defaults to --ink.

Rewrote the radio on top of it (208 -> 116 lines, all the fiddly logic gone),
added a ~15-line template (orbit-hello.js) and docs/PLUGIN-SDK.md.
2026-07-07 18:11:35 +00:00
80204727fa sandbox: hide guest scrollbars without overflow:hidden
overflow:hidden on the guest root paints an opaque backdrop and kills the
iframe transparency, so opening the radio flashed a black box before the card
appeared. Hide the scrollbars with scrollbar-width/::-webkit-scrollbar instead
— transparency stays intact.
2026-07-07 17:42:14 +00:00
56e263e7fe radio: keep the player card hidden until its frame has grown
On open the card is display:block but visibility:hidden; it is revealed only
once the guest viewport (frame) has grown to fit it, detected via the frame's
own resize event. Stops the half-drawn card flashing down by the composer on
the first click while the async frame resize catches up. Guest gets
overflow:hidden so a mid-resize frame never shows scrollbars.
2026-07-07 17:28:48 +00:00
958ad7ebb1 clock: fix clipped digits — line-height 1 measured too short for the glyphs 2026-07-07 17:06:07 +00:00
19c798c48c radio: align the nav tab with Home/Rooms/Friends and stop the load jump
Slot shares the nav row as an equal flex column so the Radio tab lines up
with the others; trigger mirrors the .tab hover/active effect. Frame stays
hidden until the guest reports its size, so it no longer flashes at screen
center before the slot CSS applies.
2026-07-07 16:54:58 +00:00
17802bd0c5 radio: open the player card upward deterministically, never off-screen
Absolutely position the nav slot's iframe and pin it to the bottom, so
growing its height (opening the card) can only extend upward. Replaces the
flex align trick that grew the card downward off-screen in some browsers.
Keep the tab label fixed so the centered frame never shifts sideways.
2026-07-07 16:38:31 +00:00
c51b93a579 sandbox: transparent iframe (color-scheme on body, not root — kills the grey canvas behind plugins) 2026-07-07 16:24:49 +00:00
4596ef799c radio: robust upward card (drop :has), solid dark card, kill the grey accent-soft fills 2026-07-07 15:22:43 +00:00
0b952f429a radio: move to a nav tab next to Friends (new nav_item slot), drop the grey bg 2026-07-07 15:07:38 +00:00
cd92bfc972 radio: footer trigger becomes a now-playing pill (station name + bars) 2026-07-07 14:41:36 +00:00
0c41b33fd3 radio: themed floating player card with equalizer + station list 2026-07-07 14:37:26 +00:00
84679568d5 plugins: add a sandboxed footer web-radio player (third/orbit-radio.js) 2026-07-07 14:17:05 +00:00
120806886c sandbox: add explicit "none" permission for zero-grant plugins 2026-07-07 14:03:17 +00:00
7bf51bdff8 plugins: consolidate under third/, run the clock fully sandboxed 2026-07-07 13:42:33 +00:00
6059ae321b auth: SASL SCRAM-SHA-256 for typed-password login, with PLAIN fallback 2026-07-07 04:05:53 +00:00
54dd2c3dc0 config: enable passkey sign-in on the tchatou deployment 2026-07-07 03:26:30 +00:00
efb73dfef3 sw: network-first for unhashed /app/ resources (plugins, icons); cache-first only for hashed /app/assets/ (was pinning stale plugins) 2026-07-07 01:08:41 +00:00
6f67e56ed4 fix invalid font shorthand (…/lh inherit) in clock/invite/games plugins 2026-07-07 01:02:29 +00:00
cb6c9ecf21 persistent session resume: reopen the tab straight back into your channels (opt-in; members re-auth via a fresh cookie-minted ticket, guests reconnect, no stored secret) 2026-07-06 23:44:52 +00:00
fa115e5bc3 Mirror orbit.server into the sandbox via the state snapshot 2026-07-06 17:52:06 +00:00
5c179eaa4a sandbox: accept the guest init (which evals plugin source) only from the host frame, once 2026-07-05 23:03:32 +00:00
0d89bc701a onboarding: honest TLS badge, localized hero + nick hint, channel picker with suggestions 2026-07-05 20:13:07 +00:00
b615339ae1 app: refresh in place on a new deploy instead of a hard reload
You had to reload the tab by hand to pick up a new build, and when the service
worker did reload it was an abrupt white flash. Now the build stamps version.json
with the commit and the running app (which already knows its own __GIT_COMMIT__)
polls it whenever the tab regains focus. When a newer build is live it cross-fades
a themed curtain (the theme's own --bg + accent spinner) and reloads, then holds
that curtain over the fresh load until the app mounts and fades it out - so it reads
as an in-place refresh, no flash, no manual reload.

If you're mid-message it waits until the composer is empty (or the tab is hidden)
before reloading, and a loop guard stops it re-reloading for a commit it already
tried. sw.js serves version.json network-only so the probe always sees the live id;
index.html restores the themed bg pre-paint so dark themes don't flash light.

Existing open tabs need one manual reload to pick up this machinery; after that it's
automatic.
2026-07-05 03:12:44 +00:00
e92e505302 Reported by Juest: fix dark flip/roll buttons in yomirc
The dice feature's buttons styled themselves with var(--panel) and var(--green-soft),
neither of which exists: --panel was never a token and --green-soft got renamed to
--accent-soft. So the buttons had no fill and the bare <button> picked up the OS dark
UA chrome (the sandbox iframe declared color-scheme: light dark, following the visitor's
OS, not the app). On a dark desktop the flip/roll buttons came out dark in a light theme.

Use the real, mirrored tokens (--accent-soft fill, --accent hover) so the buttons always
carry the theme's own accent, and pin the sandbox iframe's color-scheme to the app theme
(from its --bg) so no plugin's native controls track the OS instead of the skin. Drop the
dead --panel from the mirror list.
2026-07-05 02:40:34 +00:00
3998849930 multi-network: i18n the network UI (10 locales) + enable on production 2026-07-04 09:27:28 +00:00
b90d404438 multi-network: 2nd-network switcher, add-network modal, global-state sync + per-network storage (gated: features.multiNetwork) 2026-07-04 09:18:36 +00:00
75f69c6a66 chat: link-preview cards via the server unfurl endpoint (lazy, proxied image) 2026-07-04 08:10:36 +00:00
3a842d5099 sandbox: gate built-in features behind config.builtins (opt-in) 2026-07-04 06:38:59 +00:00
42657f352c sandbox: promote to a core subsystem the app mounts itself (bundled builtins) 2026-07-04 06:28:56 +00:00
8a5bc2781f Revert "chat: built-in /roll and /flip commands"
This reverts commit 5b989f48c0.
2026-07-04 06:19:31 +00:00
5b989f48c0 chat: built-in /roll and /flip commands 2026-07-04 06:16:39 +00:00
b3da7c29e9 sandbox: measure a wrapper sizer so a plugin restyling its root can't collapse the frame 2026-07-04 06:06:51 +00:00
29c6197aed plugins: orbit-dice, a real themed sandboxed plugin 2026-07-04 06:04:30 +00:00
2c6f6e18be sandbox: mirror the app theme vars into sandboxed plugins 2026-07-04 06:04:30 +00:00
221057cfa8 config: drop the sandbox demo from production 2026-07-04 06:04:30 +00:00
7e881d78d6 sandbox: re-handshake on iframe reload + size to content (fixes invisible UI) 2026-07-04 05:43:22 +00:00
f680484a0e config: enable the sandboxed demo plugin 2026-07-04 05:24:00 +00:00
86a7072581 sandbox: iframe host, guest bootstrap and loader routing 2026-07-04 05:12:13 +00:00