Route.lang is removed; Group.lang now drives the message language for
every route in the group (default en, custom via KV i18n:<lang>).
dispatch.ts loads translations per group and falls back to en for
groups without a lang. Admin UI: GroupEditor gains the language field,
RouteEditor/RouteCard drop theirs; docs and config example updated.
The root catch-all page ([...slug].vue) redirected every unknown URL to
/admin, and the worker fell back to the SPA for any path — so no matter
what page was opened, the URL ended up at baseurl/admin.
- Extract the console into ConsolePage.vue; the active tab now mirrors
the URL path: /admin (groups), /admin/groups, /admin/logs, /admin/audit
(tab switches use router.replace; unknown slugs render 404)
- admin.vue and admin/[slug].vue become thin wrappers
- Delete the root [...slug].vue catch-all redirect
- server.ts: notFound serves ASSETS (SPA + _nuxt chunks) only for
/admin-prefixed paths; every other unknown URL returns a JSON 404
Cloudflare KV's list operation is eventually consistent and can lag
behind a fresh write, so pending invites were invisible right after
creation (GET /admin/api/groups/:id/invites returned {invites: []}).
Keep a per-group token index (invite:group:{id}) updated on create,
revoke, accept and expiry; the members panel also inserts the freshly
created invite into the list immediately and copies the absolute link.
- New MembersPanel: role switching, add/remove members, invite-link
generation with copy/revoke, pending invite list
- New Audit tab (AuditLog.vue) with group filter
- Role-aware UI: viewer hides route/group edit actions (RouteCard readonly),
owner-only controls, role badge + member count on group cards
- GroupEditor: members managed via panel, owners field super-admin only
- en/zh i18n and CSS for the new panels
- Add groupId query param to GET /api/logs endpoint
- Add group filter dropdown in SendLogs component
- Pass groups list and filter state from admin.vue
- Update useLogs.ts to accept optional groupId parameter
- Add groupId to SendRecord type
- Add i18n keys and CSS for filter UI
- Change validateRoutes to per-group ID uniqueness instead of global
- Remove post-merge cross-group route ID uniqueness checks
- Include groupId in msg:* KV key to prevent collision
- Add group_id column to send_logs table (migration 0004)
- Record groupId in send_logs for accurate permission filtering
- Use groupId from log entries for admin log access checks
Add clickable commit links in check_suite formatter output with fallback
URL when html_url is unavailable. Remove check_run from checks template
since formatter only handles check_suite events.