2025-09-19 - 2026-09-19
Overview
184 Pull requests merged by 2 users
Merged
#202 chore(tools): delete the cliloc converter the Asset Bridge replaced (Asset Bridge cutover, 2 of 5)
Merged
#201 chore(tools): delete the cliloc converter the Asset Bridge replaced (Phase 2)
Merged
#199 feat(events): the Event System — core (Phase 16b cutover, 2 of 6)
Merged
#200 fix(events): midnight in an announcement is 12:00 am on the Node we ship
Merged
#198 fix(events): the public calendar, a stranded revert, and three dropped facts (Phase 16a)
Merged
#197 fix(events): carry a module's own account of a successful step
Merged
#196 feat(events): the public calendar, event pages and participation history (Phase 14a)
Merged
#195 feat(events): the authoring UI proper (Phase 13)
Merged
#194 feat(events): targeted leases, value sets and searchable sources (Phase 12b)
Merged
#193 fix(events): give a lease's ledger row a reconcile path (Phase 11b)
Merged
#192 feat(events): the integrations — lifecycle triggers, participants, results (Phase 10)
Merged
#191 fix(engagement): the trigger manifest was stale, and its check was crying wolf
Merged
#190 feat(events): the resource ledger, leases and cleanup (Phase 8)
Merged
#189 feat(events): open the event contract to modules (Phase 7)
Merged
#188 feat(events): enablement, per-run caps and mayInvoke (Phase 6)
Merged
#187 feat(events): conditions, phase advancement and the diagnosis panel (Phase 5)
Merged
#186 feat(events): schedule, recurrence and the calendar (Phase 4)
Merged
#185 feat(events): the minimal admin surface (Phase 3)
Merged
#184 feat(events): the runner (Phase 2)
Merged
#183 feat(events): schema, CRUD and the core action registry (Phase 1)
Merged
#182 feat(engagement): retention — three sweeps and one recorded refusal (Phase 14)
Merged
#181 fix(engagement): claim the seed guard atomically, and let a rule name a digest body
Merged
#180 feat(engagement): the engagement system — cutover 3 of 7 (edge → main)
Merged
#179 fix(engagement): two defects the Phase 11b live walk found in core
Merged
#178 feat(engagement): let a module ship its own templates and rules (Phase 11b)
Merged
#177 feat(engagement): the admin ceiling and core's news.post emitter (Phase 11a)
Merged
#176 feat(engagement): deliverability — suppression, bounces and the verification gate (Phase 9)
Merged
#175 feat(engagement): the in-app channel, core and web (engagement Phase 7)
Merged
#174 feat(engagement): the email channel on the engine, and the Teams migration (engagement Phase 6)
Merged
#173 feat(engagement): the template editor, the trigger catalog and the send log (engagement Phase 5b)
Merged
#172 feat(engagement): templates — the email block family, renderer and seeded set (engagement Phase 5a)
Merged
#171 feat(engagement): Admin → Engagement → Rules and Audiences (engagement Phase 4b)
Merged
#170 feat(engagement): the rules engine, cooldowns and outbox (engagement Phase 4a)
Merged
#169 feat(notifications): per-channel preferences and the delivery-channel registry (engagement Phase 3)
Merged
#168 feat(modules): event triggers, audiences and the ceiling lattice (engagement Phase 2)
Merged
#167 feat(auth): unique, changeable, verifiable email addresses (engagement Phase 1b)
Merged
#166 refactor(api): collapse /admin/account and /player/account onto /auth/me/account
Merged
#165 feat(email): engagement Phase 1 — remove Gmail OAuth2, SMTP behind a transport registry
Merged
#164 fix(swagger): hoist the one inline predicate that makes the generator run away
Merged
#163 fix(env): the documented Compose deploy could not boot
Merged
#162 fix(admin): style the Teams admin screen with the site's own classes
Merged
#161 feat(teams): Teams as a platform primitive — MODULE_API 1.6.0 (Teams cutover 4/6)
Merged
#160 fix(modules): core offers a contribution, never a slot name
Merged
#159 feat(teams): phase 9 — one voice channel per Team, granted by a role
Merged
#158 feat(teams): phase 8 — the notifications bridge, and the gate §7.2 could not check
Merged
#157 feat(teams): phase 7 — the slash-command seam, and the bot's first tests
Merged
#156 feat(teams): phase 6 — notifications, and the email sink the web never had
Merged
#155 feat(teams): phase 5 — Forum 5b, discussion + moderation + reports
Merged
#154 fix(teams): four defects the live rig found in the phase 4 forum
Merged
#153 feat(teams): phase 4 — the forum access model, announcements and the operator's controls
Merged
#152 feat(teams): the activity feed, the roster projection, and the inverted slot
Merged
#151 feat(teams): Team core — the reconciler, the four authority paths, and the impersonation controls
Merged
#150 feat(modules)!: the module system cutover — a game-agnostic core reaches main
Merged
#149 chore(modules): declare the UO module for the UOMysticmoon instance
Merged
#148 feat(modules): PublicLayout takes a shell, MODULE_API_VERSION 1.5.0
Merged
#147 chore(modules): bump MODULE_API_VERSION to 1.4.0 — the sidecar rule
Merged
#146 fix(modules): stop a module before purging its tables
Merged
#145 test(login): stop the backoff-guard test racing its own one-second lock
Merged
#144 feat(modules): the declarative Docker path (phase 4, slice 3)
Merged
#143 feat(admin): the Modules screen (phase 4, slice 2)
Merged
#142 feat(modules): install, uninstall, purge and restart (phase 4, slice 1)
Merged
#141 feat(modules): merge module OpenAPI fragments into /api/docs.json (phase 3, slice 5)
Merged
#140 refactor(modules)!: de-UO core's copy, and enforce it (phase 3, slice 4)
Merged
#139 refactor(client): delete the UO client half (phase 3, slice 3)
Merged
#138 feat(modules): client extension slots (phase 3, slice 2)
Merged
#137 refactor(modules)!: move the UO server half out to module-uo (phase 3, slice 1)
Merged
#136 feat(modules): mount the modules directory as a volume (phase 2, PR 9)
Merged
#135 feat(modules): interleave module nav items and derive moderator confinement (phase 2, PR 8)
Merged
#134 feat(modules): the client registry, window.__rg and the chunk's script injection
Merged
#133 feat(modules): publish the installed-module list at /api/v1/public/modules
Merged
#132 feat(modules): boot/shutdown hook dispatch and the installed_modules reconcile
Merged
#131 feat(modules): the three de-entanglement registries, with core as the registrant
Merged
#130 feat(modules): replay module schema fragments after core's (phase 2, PR 3)
Merged
#129 feat(modules): the filesystem module loader (phase 2, PR 2)
Merged
#128 feat(modules): installed_modules and the module state machine (phase 2, PR 1)
Merged
#127 ci: run PR checks on pull requests into edge as well as main
Merged
#126 feat(theming): admin-configurable theme, brand assets and navigation (edge → main)
Merged
#125 feat(theming): dropdown sections and added links in the public header (phase 10)
Merged
#124 feat(theming): nav wiring and the admin nav builder (phases 6-8)
Merged
#123 feat(theming): brand-asset overrides and a cached, settings-aware HTML shell (phase 5)
Merged
#122 feat(theming): server-resolved theme engine and admin appearance UI (phases 3-4)
Merged
#121 feat(theming): settings-store, nav merge util and radius tokens (phases 0-2)
Merged
#120 docs(readme): say how to get a sidecar before explaining how it is used
Merged
#118 feat(shard)!: Protocol 3.0 cutover — visibility framework, spawn atlas, marketplace
Merged
#119 fix(shard): answer with the instance name when the shard is unnamed
Merged
#117 feat(shard)!: declare wire protocol 3
Merged
#116 feat(shard): the player-vendor marketplace
Merged
#115 feat(shard): resolve cliloc names for items and reward titles
Merged
#114 feat(shard): ingest points.board and publish the leaderboards
Merged
#113 feat(atlas): serve the spawn atlas and give operators a panel for it
Merged
#112 feat(atlas): derive a spawn atlas from the shard tree on every boot
Merged
#111 feat(shard): ingest world.ruleset and publish it at /site/rules
Merged
#110 fix(shard): enforce visibility on the REST reads that bypassed it
Merged
#109 feat(shard): admin-configurable visibility for every shard surface
Merged
#108 feat(auth): honor and establish trusted devices on the SSO login paths
Merged
#107 fix(shard): stop an undecryptable uo-link token 500ing every live-shard route
Merged
#106 refactor(server): split public, player and residual auth into capability routers (PR 5)
Merged
#105 refactor(server): split admin shard, uo-link, email, discord-bot, settings and dashboard into capability routers (PR 4)
Merged
#104 refactor(server): split admin posts, uploads, wiki and pages into capability routers (PR 3)
Merged
#103 refactor(server): split admin moderation, bot-activity and activity into capability routers (PR 2)
Merged
#101 build(swagger): normalize and sort generated OpenAPI path keys
Merged
#102 refactor(server): split admin users, account, invites and auth providers into capability routers
Merged
#100 feat(security): soak the tightened CSP on report-only, with a same-origin sink
Merged
#99 chore(server): freeze the URL surface with a generated route manifest (PR 0)
Merged
#98 ci(docs): auto-sync PROJECT_TREE.md to the docs repo on push to main
Merged
#97 fix(moderation): windowValue must not fall back to the 30d total on a null column
Merged
#96 fix(admin): restore digit match in discordId route validation
Merged
#95 fix(ntfy): publish ntfy host port so the external reverse proxy can reach it
Merged
#94 fix(player): open the player self-service surface to staff
Merged
#93 feat(auth): trusted devices, recovery codes, and admin MFA management
Merged
#92 docs(readme): add architecture mermaid diagram
Merged
#91 chore(dev): stub OAuth IdP tooling for local mobile SSO testing
Merged
#90 fix(footer): point Shard Status link to /site/shard
Merged
#89 refactor(server): dedupe shard-state shaping, upsert builder, and config DB models
Merged
#88 chore(quality): resolve SonarQube code smells across website
Merged
#87 ci(sonarqube): populate the "Unit Tests" measure via a test-execution report
Merged
#86 test: meaningful unit tests for server models/controllers + client logic
Merged
#85 ci(sonarqube): generate and report server test coverage
Merged
#84 fix(security): add SPA CSP, drop x-powered-by, strengthen dedupe hash
Merged
#83 ci(sonarqube): non-blocking SonarQube analysis on push to main
Merged
#82 fix(db): strip inline -- comments before splitting schema statements
Merged
#81 feat(mobile-sso): serve assetlinks.json + App Links redirect allowlist
Merged
#80 feat(auth): native SSO authorization bridge for the Android app (M9 Part 1)
Merged
#79 feat(settings): surface push.ntfyUrl in /public/settings for the app
Merged
#78 feat(push): M7 backend — opt-in push notifications via self-hosted ntfy
Merged
#77 feat(public): version/health surfacing + typed brand block
Merged
#76 feat(auth): role-agnostic self-service surface under /auth/me
Merged
#75 feat(auth): self-service password reset (backend + web)
Merged
#74 Moderation appeals (Phase 6c) + Discord auto-reversal (Phase 6d)
Merged
#73 docs: generalize deployment section to any reverse proxy
Merged
#72 fix(shard): restrict staff in-game location to admins/moderators
Merged
#71 chore: add open-source governance files (GPLv3 + contributing docs)
Merged
#70 fix(brand): link "Runic Gateway" footer badge to Gitea org
Merged
#69 feat(brand): default emblem — favicon, hero medallion, footer credit
Merged
#68 feat(brand): BRAND_* env scheme — instance branding without a rebuild
Merged
#67 docs: move design docs to RunicGateway/docs
Merged
#66 chore(org): retarget org paths to RunicGateway
Merged
#65 Protocol 2.0/2.1 uo-link integration — boards, cross-links, news gump, account provisioning
Merged
#64 ci(deploy): correct deploy runner label to uom-deploy-runner
Merged
#63 ci(deploy): auto-deploy prod stack after image build on merge to main
Merged
#62 fix(bot): retry boot-time config fetch so bot self-heals on cold start
Merged
#61 fix(public): always show real hero + drop nav from landing page
Merged
#58 feat(shard): admin write plane, help-page queue, and public champion board
Merged
#57 ci: gate PRs into main on server tests + client build
Merged
#56 feat(admin): view a user's shard footprint at /admin/users/:id
Merged
#55 deploy: split build into docker-compose.dev.yml (prod compose pulls only)
Merged
#54 deploy: pull prebuilt registry images in compose (IMAGE_TAG) + dev/prod split
Merged
#53 ci: build & publish app + bot images to Gitea registry on merge
Merged
#52 News post → town crier + Discord announcement pipeline
Merged
#51 Homepage teaser: rich text editor
Merged
#50 Frontend theme redo: player portal → Admin sidebar shell + stat-tile My Characters
Merged
#49 uo-link: staff-only public presence + admin character access
Merged
#47 CMS Page Builder (Wave 1): block-based Pages content type
Merged
#46 Modernize email: Gmail OAuth2 sending + admin sidebar redesign
Merged
#45 Redesign admin/staff sidebar: collapsible categories, icons, role-accurate nav
Merged
#44 Gate /admin to staff roles; role-aware login redirects for players
Merged
#43 Player accounts: self-service player role, registration, and portal
Merged
#42 Moderation dashboard: staff dashboard, user history, notes, event capture (Phase 6a + 6b)
Merged
#41 Fix bot container inheriting site PORT/LOG_FILE from shared .env
Merged
#40 Audit and fix Swagger/OpenAPI accuracy; regenerate served spec
Merged
#39 Enforce TOTP second factor on SSO login (#31)
Merged
#38 Fix SSO flow-token / session type confusion (#32)
Merged
#37 Implement web session/token revocation (#30)
Merged
#36 Isolate internal bot-config route from the public listener (#33)
Merged
#29 Add Discord bot: moderation, filters, scheduling, roles, invites, site integration
Merged
#28 Hero editor: fullscreen landing, remove two-card row, quick links into hero
Merged
#27 Add Swagger/OpenAPI API docs (swagger-ui + swagger-autogen)
Merged
#26 Hero editor: scale text-block fonts with the resize handle (#25)
Merged
#24 Add session abstraction, mobile bearer auth, and pluggable SSO (Google/Discord/OIDC)
Merged
#23 Add Bot Activity admin panel: banned-IP view + recent events + emergency unban
Merged
#22 Update README for today's security hardening and 2FA work
Merged
#21 Fail fast when JWT_SECRET is missing in production (closes #14)
Merged
#20 Make the hero Moon image configurable (src/alt), backwards-compatible
Merged
#19 Admin login hardening: RBAC-safe controls, optional TOTP, bot-scoring + IP ban (closes #9)
Merged
#18 Derive uploaded file extension from mimetype, not originalname (fixes #11)
Merged
#17 Validate and uniqueness-check username on user update (fixes #13)
Merged
#16 Re-validate JWT against the DB in isLoggedIn (fixes #12)
Merged
#15 Enforce role-based authorization on admin-only routes (fixes #10)
Merged
#8 Fix #6: larger RTE toolbar buttons + bigger, both-axis-scrolling editor
Merged
#7 RTE Posts upgrade: TipTap rich-text editing + sanitization for posts
Merged
#4 hero-feature
Merged
#3 Wiki upgrade: rich-text editing, categories, drafts, links/backlinks, tags, search, revisions
Merged
#2 Document full-stack setup; fix dev proxy; drop stray temp script
Merged
#1 Frontend update
18 Issues closed from 3 users
Closed
#35 [SECURITY AUDIT] Username enumeration via login timing side-channel (bcrypt runs only for existing users)
Closed
#60 side ways scrolling section on hero page.
Closed
#34 [SECURITY AUDIT] No Content-Security-Policy — stored-HTML XSS defense rests entirely on sanitization
Closed
#59 hero page layout
Closed
#48 Homepage Teaser
Closed
#31 [SECURITY AUDIT] SSO login bypasses TOTP two-factor for accounts that have 2FA enabled
Closed
#32 [SECURITY AUDIT] SSO flow token (sso_tx) validates as a session — token-type confusion in sessionFromDecoded
Closed
#30 [SECURITY AUDIT] Session/token revocation is a non-functional stub — logout and password change do not invalidate existing JWTs
Closed
#33 [SECURITY AUDIT] Decrypted Discord bot token served from an endpoint on the public API router, guarded only by a shared secret
Closed
#25 On the front page/hero page
Closed
#14 [Bug][Medium] Server boots with no JWT_SECRET (only a warning)
Closed
#5 Hero button bug
Closed
#9 Admin path security
Closed
#11 [Security][High] Uploaded file extension is attacker-controlled → stored XSS
Closed
#13 [Bug][Medium] username unvalidated and not uniqueness-checked on user update
Closed
#12 [Security][Medium] Stale JWT: demoted/deleted users keep access until token expiry
Closed
#10 [Security][High] No role-based authorization — editor role is never enforced
Closed
#6 wiki editor.
18 Issues created by 0 users
Opened
#5 Hero button bug
Opened
#6 wiki editor.
Opened
#9 Admin path security
Opened
#10 [Security][High] No role-based authorization — editor role is never enforced
Opened
#11 [Security][High] Uploaded file extension is attacker-controlled → stored XSS
Opened
#12 [Security][Medium] Stale JWT: demoted/deleted users keep access until token expiry
Opened
#13 [Bug][Medium] username unvalidated and not uniqueness-checked on user update
Opened
#14 [Bug][Medium] Server boots with no JWT_SECRET (only a warning)
Opened
#25 On the front page/hero page
Opened
#30 [SECURITY AUDIT] Session/token revocation is a non-functional stub — logout and password change do not invalidate existing JWTs
Opened
#31 [SECURITY AUDIT] SSO login bypasses TOTP two-factor for accounts that have 2FA enabled
Opened
#32 [SECURITY AUDIT] SSO flow token (sso_tx) validates as a session — token-type confusion in sessionFromDecoded
Opened
#33 [SECURITY AUDIT] Decrypted Discord bot token served from an endpoint on the public API router, guarded only by a shared secret
Opened
#34 [SECURITY AUDIT] No Content-Security-Policy — stored-HTML XSS defense rests entirely on sanitization
Opened
#35 [SECURITY AUDIT] Username enumeration via login timing side-channel (bcrypt runs only for existing users)
Opened
#48 Homepage Teaser
Opened
#59 hero page layout
Opened
#60 side ways scrolling section on hero page.