Cloudflare Workers Build runs "wrangler deploy" on a fresh checkout,
where admin/dist (a gitignored symlink) does not exist, so the deploy
failed with a missing assets.directory.
- add build.command to generate the Nuxt SPA before bundling
- point assets.directory at the real ./admin/.output/public output
instead of the gitignored admin/dist symlink
Serve a public landing page at / with buttons to the docs, GitHub repo,
Terms, Privacy and the admin login. Relocate the Nuxt admin console from
/ to /admin so the root is no longer the private console.
- add home-routes.ts (bilingual landing, auto dark mode, configurable
DOCS_URL / GITHUB_REPO_URL) mounted at /
- move console to admin/pages/admin.vue; redirect / and unknown SPA
routes to /admin
- point admin login/logout redirects at /admin
Introduce optional route groups so non-super admins can be delegated
edit/view access to a subset of routes and their send logs.
- add Group model and Route.groupId
- add groups.ts (load/save groups, resolveScope, permission helpers)
- scope /api/routes and /api/logs by the caller's accessible groups;
add /api/me and /api/groups (group management is super-admin only)
- require a groupId on every route in validateRoutes
- allow group admins (not just super admins) to sign in to the console
Add bilingual (zh/en) /terms and /privacy pages served by the Worker for
configuring the Discord application's Terms of Service and Privacy Policy
URLs. Contact line is configurable via optional LEGAL_CONTACT env var.
wrangler@4.118 requires @cloudflare/workers-types@^5, so a fresh
`npm install` (Cloudflare Workers Build CI) failed with ERESOLVE against
the old ^4 pin. Align to ^5; typecheck, lint and tests still pass.
Document the /gh login, /gh logout and /gh comment add|edit|del
commands plus the right-click message context-menu equivalents, and
require the applications.commands invite scope. Comments are posted as
the linked user's own GitHub account, so the old GitHub App identity,
Message Content intent and Read Message History requirements are gone.
Skip re-processing when the same X-GitHub-Delivery id is seen (KV, 300s TTL)
to stop double pushes when both an org and an App webhook target the worker.
Pass ExecutionContext through so dispatch runs via waitUntil instead of a
fire-and-forget that gets frozen. Cache the imported HMAC key per secret.
Replace the App-identity !gh text command with native slash and message
context-menu commands. /gh login|logout link a Discord user to their GitHub
account; /gh comment add|edit|del and the right-click 'GitHub' commands open
a modal and create/edit/delete comments using the user's own OAuth token,
delegating permission checks to GitHub (surfacing 401/403/404). The gateway
registers guild commands on connect and handles interactions in the DO.
Add an admin WebUI (Nuxt static SPA in admin/, served via the ASSETS
binding) for managing routes and viewing send logs. Access is gated by
GitHub OAuth plus an ADMIN_USER_IDS whitelist with cookie sessions
(admin-session.ts). Expose routes/logs CRUD API (admin-routes.ts), add a
discord-link mapping in token-store.ts, and mount admin routes with an
SPA assets fallback in the server.
Gateway is now an opt-in feature (DISCORD_GATEWAY_ENABLED); when disabled,
messages are delivered via the Discord REST API (discord-rest.ts) instead of
the Durable Object. Record per-route delivery results (send-log.ts) for the
WebUI. Configure assets binding, DO sqlite migration and cron trigger.
Remove hardcoded DEFAULT_ROUTES and Config.discord.defaultChannelId so
forwarding is driven entirely by user-defined routes (empty KV = no
forwarding). Add ADMIN_USER_IDS, DISCORD_GATEWAY_ENABLED and ASSETS to Env.