かめぱわぁ〜るどガイドのAstroサイト、WYSIWYGエディター、Discord権限連携APIです。原稿は KamePowerWorld/kpw-docs で管理します。
本番URL: https://docs.kamesuta.com
kpw-webとkpw-docsを同じ親ディレクトリへ置きます。
npm ci
npm run dev別の場所に原稿がある場合はKPW_DOCS_DIR=/path/to/kpw-docs npm run devを使用します。
- トップページは
kpw-docs/pages/index/index.mdで、URLは/に固定されます。 - 通常ページはGitHub上では
pages/<slug>/へフラットに置き、navigation.ymlのツリーから公開URLを組み立てます。 - URLは末尾スラッシュなしです。古い階層や過去slugは現在の正規URLへリダイレクトされます。
- エディターでは複数ページとツリー変更をブラウザに保持し、GitHub Appを使った1つのGit commitへまとめて保存します。
- 子を持つページは削除できません。先にページエクスプローラーで子を移動します。
既存のDiscord ApplicationへBotを追加し、次を設定します。
- OAuth2 Redirect URL:
https://<公開ドメイン>/api/auth/callback - OAuth2 scope:
identify(アプリ側がログイン時に指定) - Botを編集者が所属するDiscordサーバーへインストール
- Developer PortalのBot設定で
Server Members Intentを有効化 DISCORD_ADMIN_ROLE_IDに指定したロールは全ページの編集・構造変更・権限設定が可能
ページ権限はDiscordのロールまたは個人へ付与します。編集権限と子ページ作成権限は別々です。子ページ作成は次のどちらかを選びます。
inherit: 作成したページも親の権限をライブ継承する。作成者はそのページを編集できるが、権限設定はできない。custom: 作成者がそのページ以下を管理し、権限を自由に設定できる。adminは常に管理可能。
未設定の既存ページはadminのみ編集できます。ロールはAPI呼び出しごとにDiscordから再確認するため、Discord側でロールを外すと権限も失われます。 個人権限は内部では変更されにくいDiscord IDで保持し、画面では現在のアバター、サーバーニックネーム、Discordユーザー名を表示します。
GitHub Appを作成し、次を設定します。
- Repository permissions: Metadata read、Contents read and write
- Installation:
KamePowerWorld/kpw-docsだけを選択 - App IDを
GITHUB_APP_IDへ設定 - ダウンロードしたPrivate Key(PEM全文)を
GITHUB_APP_PRIVATE_KEYSecretへ設定 - Installation IDは
GITHUB_INSTALLATION_IDへ任意設定。省略時はリポジトリから自動取得
GitHubユーザーのOAuth認証やPersonal Access Tokenは使用しません。
このリポジトリのwrangler.jsoncには本番のKV SESSIONSとD1 kpw-web-authが設定済みです。
- CloudflareのWorker設定で通常の環境変数
DISCORD_CLIENT_ID、DISCORD_GUILD_ID、DISCORD_ADMIN_ROLE_ID、GITHUB_APP_IDを設定する。 npx wrangler secret put DISCORD_CLIENT_SECRETを実行する。npx wrangler secret put DISCORD_BOT_TOKENを実行する。npx wrangler secret put GITHUB_APP_PRIVATE_KEYを実行し、PEM全文を登録する。npx wrangler d1 migrations apply kpw-web-auth --remoteで未適用のD1 migrationを反映する。- GitHub Organization Secretに
CLOUDFLARE_API_TOKENとCLOUDFLARE_ACCOUNT_IDを登録する。 npm run deployで配備する。
Cloudflare Dashboardで環境変数を管理するため、デプロイには--keep-varsを付けています。ローカルでは.dev.vars.exampleを.dev.varsへコピーして値を設定します。秘密値をリポジトリへcommitしないでください。
- DiscordセッションはHttpOnly・Secure・SameSite Cookieで管理し、保存と権限変更はOrigin、CSRF token、現在のDiscord所属・ロールを検証します。
- GitHub AppのInstallation tokenはサーバー内で短時間だけ使用し、ブラウザへ渡しません。
- 原稿commitのAuthor名は編集者のDiscordユーザー名、CommitterはGitHub Appになります。
- Markdownと画像はデータとして扱い、HTML、SVG、危険なパス、過大ファイルを拒否します。
- GitHub保存は開始時commit SHAを照合し、競合時に
masterを上書きしません。 - 権限変更はD1のrevisionで競合を検出し、操作履歴を
audit_eventsへ記録します。