From 275608d9722229a8906c8e96a00b63c4afd7fb71 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sat, 14 Mar 2026 07:21:44 +0900 Subject: [PATCH 01/25] =?UTF-8?q?docs:=205.7.0=E3=83=AA=E3=83=AA=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E6=B8=88=E3=81=BF=E3=81=AB=E6=9B=B4=E6=96=B0=E3=80=81?= =?UTF-8?q?5.8.0=E3=81=AB=E3=82=BB=E3=82=AD=E3=83=A5=E3=83=AA=E3=83=86?= =?UTF-8?q?=E3=82=A3=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC=E6=8C=87=E6=91=98?= =?UTF-8?q?=E4=BA=8B=E9=A0=85=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- docs/CLAUDE.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index b5f67cffb..c66b4c24d 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -93,14 +93,18 @@ git diff Gemfile.lock - #4117 WebUI: 複雑なハンドラーパラメータ編集(CRUD一覧管理) — オブジェクト配列や深いネスト構造を持つパラメータの一覧管理UI - #4144 カスタムAPI/カスタムフィードを独立デーモンに分離 — Bundler二重管理・Open3.capture3の不安定さを解消。元の独立デーモン形式に戻す - #4146 PieFed対応をginseng-piefedに切り出し — tomato-shriekerとの共有が動機。#4145 完了が前提 +- #4157 Sentry: before_sendフィルタによる秘匿情報スクラビング — #4156 セキュリティレビューの指摘対応 +- #4158 bundler-auditの導入とCI統合 — #4156 セキュリティレビューの指摘対応 -## 予定: 5.7.0 +## リリース済み: 5.7.0(2026-03-14) -- **#4152 docs/api.md: Annict連携セクションの認証要件を実装に合わせて修正** — Codexレビュー(PR #4149)の指摘に対応。P4セクションとの重複記述を解消 -- **#4153 Misskey: 内部DMにlocalOnlyフラグを設定する** — コマンドトゥート、お知らせボット通知DM、ボットメンション時のDM強制変更でlocalOnly: trueを設定。capabilities/local_postで判定 -- **#4154 Sentry.ioによるエラートラッキングの導入** — sentry-ruby + sentry-sidekiq。既存のalertメソッドにSentry.capture_exceptionを統合。DSNはconfig/local.yamlの/sentry/dsnで設定(デプロイ時にSentryプロジェクト作成 → chubo2#13) -- #4140 config.slim のフォーム処理ロジックを外部 JS に抽出 — #4131 後続。データ変換ロジックの抽出とブラウザテスト追加 -- #4141 テンプレート内 JS の段階的なモジュール抽出 — 各テンプレートから純粋関数を外部モジュールへ段階的に移行 +全5 Issue クローズ。Sentry エラートラッキング導入、Misskey localOnly フラグ、フロントエンド JS モジュール抽出。セキュリティレビュー(#4156)実施済み。 + +- **#4154 Sentry.ioによるエラートラッキングの導入** — sentry-ruby + sentry-sidekiq。既存のalertメソッドにSentry.capture_exceptionを統合。DSNはconfig/local.yamlの`/sentry/dsn`で設定 +- **#4153 Misskey: 内部DMにlocalOnlyフラグを設定する** — コマンドトゥート、お知らせボット通知DM、ボットメンション時のDM強制変更でlocalOnly: trueを設定 +- **#4140 config.slimのフォーム処理ロジックを外部JSに抽出** — config_form.jsに10個の純粋関数を抽出、27テストケース追加 +- **#4141 テンプレート内JSの段階的なモジュール抽出** — webui_utils.jsに6個の純粋関数を抽出、18テストケース追加 +- #4152 Annict連携セクションの認証要件をドキュメントで修正 ## リリース済み: 5.6.0(2026-03-11) From 5b02c2a3fd3dc2a185c65a75ff31f6008eb01216 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sat, 14 Mar 2026 07:31:16 +0900 Subject: [PATCH 02/25] =?UTF-8?q?fix:=20config=5Fform=5Ftest=E3=81=AE?= =?UTF-8?q?=E3=82=A2=E3=82=B5=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=EF=BC=88visibility=20label=E9=A0=86=E5=BA=8F=E3=80=81?= =?UTF-8?q?minutes=20null=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- public/mulukhiya/script/test/config_form_test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/mulukhiya/script/test/config_form_test.js b/public/mulukhiya/script/test/config_form_test.js index d8795b251..c14bb4da3 100644 --- a/public/mulukhiya/script/test/config_form_test.js +++ b/public/mulukhiya/script/test/config_form_test.js @@ -82,7 +82,7 @@ describe('config_form', () => { const options = extractVisibilityOptions(data) assert.equal(options.length, 2) assert.equal(options[0].value, 'public') - assert.equal(options[0].label, '公開 (public)') + assert.equal(options[0].label, 'public (公開)') assert.equal(options[1].value, 'unlisted') }) @@ -177,7 +177,7 @@ describe('config_form', () => { const form = {tags: 'tag1', program: {minutes: null}, decoration: {id: null}} const cmd = buildTagsCommand(form) assert.deepEqual(cmd.tagging.user_tags, ['tag1']) - assert.isUndefined(cmd.tagging.minutes) + assert.isNull(cmd.tagging.minutes) }) }) From 410a004baec6cd4d5544c837ee69812732ee4166 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sat, 14 Mar 2026 16:53:54 +0900 Subject: [PATCH 03/25] =?UTF-8?q?fix:=20OAuth=E3=82=B3=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=83=90=E3=83=83=E3=82=AF=E3=81=AE=E3=83=91=E3=83=A9=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E6=AC=A0=E8=90=BD=E6=99=82=E3=81=ABSentry?= =?UTF-8?q?=E3=81=B8=E9=80=9A=E7=9F=A5=E3=81=97=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit state/codeパラメータなしのアクセスは不正リクエストであり アプリケーション異常ではないため、alertを経由せず400を返す Co-Authored-By: Claude Opus 4.6 --- app/lib/mulukhiya/controller/ui_controller.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/lib/mulukhiya/controller/ui_controller.rb b/app/lib/mulukhiya/controller/ui_controller.rb index 2c675fbe0..56aee1bd6 100644 --- a/app/lib/mulukhiya/controller/ui_controller.rb +++ b/app/lib/mulukhiya/controller/ui_controller.rb @@ -19,8 +19,13 @@ class UIController < Controller end get '/oauth/callback' do - raise Ginseng::AuthError, 'Missing state' unless params[:state] - raise Ginseng::AuthError, 'Missing code' unless params[:code] + unless params[:state] && params[:code] + @renderer = SlimRenderer.new + @renderer.template = 'token_error' + @renderer[:error] = 'Missing required OAuth parameters' + @renderer.status = 400 + return @renderer.to_s + end result = sns.auth_with_pkce(params[:code], params[:state]) raise Ginseng::AuthError, 'Token exchange failed' unless result parsed = result.parsed_response From e4b9ce07d1711b23f39c29ac773062219d550a3f Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sat, 14 Mar 2026 16:55:44 +0900 Subject: [PATCH 04/25] =?UTF-8?q?docs:=205.8.0=E3=83=9E=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=BC=E3=83=B3=E3=81=AB#4159=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- docs/CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index c66b4c24d..d2c2aca36 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -95,6 +95,7 @@ git diff Gemfile.lock - #4146 PieFed対応をginseng-piefedに切り出し — tomato-shriekerとの共有が動機。#4145 完了が前提 - #4157 Sentry: before_sendフィルタによる秘匿情報スクラビング — #4156 セキュリティレビューの指摘対応 - #4158 bundler-auditの導入とCI統合 — #4156 セキュリティレビューの指摘対応 +- #4159 フロントJSテストのアサーション修正 — #4156 セキュリティレビューの指摘対応 ## リリース済み: 5.7.0(2026-03-14) From 10362aa6db49a9e05cdecf703b69f3415c65cd2e Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 09:53:04 +0900 Subject: [PATCH 05/25] =?UTF-8?q?fix:=20=E4=B8=8D=E6=AD=A3=E3=83=88?= =?UTF-8?q?=E3=83=BC=E3=82=AF=E3=83=B3=E3=81=AB=E3=82=88=E3=82=8B401?= =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E6=99=82=E3=81=ABSentry=E3=81=B8?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E3=81=97=E3=81=AA=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit curlによる不正アクセス試行(無効トークンでのメディアアップロード等)で GatewayError 401が発生した際、alertを経由してSentryに通知されていた。 401はアプリケーション異常ではないためalertをスキップする。 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/controller/mastodon_controller.rb | 12 ++++++------ app/lib/mulukhiya/controller/misskey_controller.rb | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index 99bc82907..a719552a3 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -14,7 +14,7 @@ class MastodonController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -33,7 +33,7 @@ class MastodonController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -48,7 +48,7 @@ class MastodonController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -63,7 +63,7 @@ class MastodonController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -78,7 +78,7 @@ class MastodonController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -93,7 +93,7 @@ class MastodonController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s diff --git a/app/lib/mulukhiya/controller/misskey_controller.rb b/app/lib/mulukhiya/controller/misskey_controller.rb index d024f03c3..83ab3b73d 100644 --- a/app/lib/mulukhiya/controller/misskey_controller.rb +++ b/app/lib/mulukhiya/controller/misskey_controller.rb @@ -14,7 +14,7 @@ class MisskeyController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -32,7 +32,7 @@ class MisskeyController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -56,7 +56,7 @@ class MisskeyController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -75,7 +75,7 @@ class MisskeyController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -89,7 +89,7 @@ class MisskeyController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s @@ -103,7 +103,7 @@ class MisskeyController < Controller @renderer.status = reporter.response.code return @renderer.to_s rescue Ginseng::GatewayError => e - e.alert + e.alert unless e.source_status == 401 @renderer.message = {error: e.message} @renderer.status = e.source_status return @renderer.to_s From 77df388b6930d474feb5353cc256d1782b38c665 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 17:05:30 +0900 Subject: [PATCH 06/25] =?UTF-8?q?docs:=20=E3=82=BB=E3=83=83=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E9=96=8B=E5=A7=8B=E6=99=82=E3=81=AE=E5=90=8C?= =?UTF-8?q?=E6=9C=9F=E6=89=8B=E9=A0=86=E3=82=92CLAUDE.md=E3=81=AB=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/CLAUDE.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index d2c2aca36..c60fe1fd7 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -182,6 +182,51 @@ git diff Gemfile.lock - #4082 Sidekiqワーカーテスト、#4099 Worker個別コンテキストログ、#4103 テストの外部API依存解消 - #4105 FreeBSD rc.d 起動ブロック原因切り分け(Mastodon streaming が主犯 → [pooza/mastodon#900](https://github.com/pooza/mastodon/issues/900)) +## セッション開始時の同期手順 + +会話の最初に「進捗を同期してください」等の指示があった場合、以下の手順を実行する。 + +### 1. プロジェクトガイドの読み込み + +- `docs/CLAUDE.md` を読む(プロジェクトのルール・構造・履歴の正本) +- `MEMORY.md` は自動ロードされるので、両者の整合性を意識する + +### 2. ローカルの状態確認 + +- `git log --oneline -10` — 直近のコミット履歴 +- `gh issue list --state open` — open Issue一覧 +- `gh pr list --state open` — open PR一覧 + +### 3. Dependabotセキュリティアラート + +- `gh api repos/pooza/mulukhiya-toot-proxy/dependabot/alerts` で open アラートを確認 +- 0件なら対応不要、あれば提案 + +### 4. Codexレビューコメントの確認 + +- 最近マージされたPR(`gh pr list --state merged --limit 5`)を取得 +- 各PRに対して `gh api repos/pooza/mulukhiya-toot-proxy/pulls/{number}/comments` でCodex(`chatgpt-codex-connector[bot]`)のコメントを確認 +- 未返信のコメントがあれば内容を確認し、対応が必要か判断 + +### 5. 外部リポジトリの同期確認(chubo2) + +- `cd ~/repos/chubo2 && git fetch origin` + `git log HEAD..origin/main --oneline` でリモートとの差分を確認 +- `docs/infra-note.md` に変更があれば MEMORY.md のインフラセクションに反映が必要か判断 +- `gh issue list --state open` で open Issue の変動を確認 + +### 6. マイルストーンの状態確認 + +- `docs/CLAUDE.md` と MEMORY.md に記載された次期マイルストーンの Issue が、実際の GitHub 上の状態(open/closed)と一致しているか確認 +- クローズ済みの Issue があれば MEMORY.md から除外し、`docs/CLAUDE.md` も必要に応じて更新 + +### 7. MEMORY.md の更新 + +- 上記で検出した差分(Issue 状態、リリース日の誤り、件数のズレ等)を反映 + +### 8. 同期結果の報告 + +- 現在のブランチ・状態、マイルストーンの状況、各確認項目の結果をまとめて報告する + ## 情報の記載先ルール - **課題・タスク** → GitHub Issue で管理(インフラ面の課題は `pooza/chubo2` の Issue として起票) From 792922d2073967f6b2762b5eb33c4a9ca2225f34 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 17:13:25 +0900 Subject: [PATCH 07/25] =?UTF-8?q?feat:=20about=20API=E3=81=A7=E3=83=96?= =?UTF-8?q?=E3=83=BC=E3=82=B9=E3=83=88/=E3=83=AA=E3=83=8E=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=81=AE=E3=82=AB=E3=82=B9=E3=82=BF=E3=83=A0=E3=83=A9?= =?UTF-8?q?=E3=83=99=E3=83=AB=E3=82=92=E8=BF=94=E3=81=99=20(#4161)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/config.rb | 1 + app/lib/mulukhiya/controller_methods.rb | 4 ++++ config/application.yaml | 2 ++ 3 files changed, 7 insertions(+) diff --git a/app/lib/mulukhiya/config.rb b/app/lib/mulukhiya/config.rb index d9c2a1fac..5882f6d64 100644 --- a/app/lib/mulukhiya/config.rb +++ b/app/lib/mulukhiya/config.rb @@ -31,6 +31,7 @@ def about controller: self['/controller'], status: Environment.status_class.default.merge( label: controller.status_label, + reblog_label: controller.reblog_label, max_length: controller.max_length, ), capabilities: sub_hash("/#{name}/capabilities"), diff --git a/app/lib/mulukhiya/controller_methods.rb b/app/lib/mulukhiya/controller_methods.rb index 877af46f1..e80849403 100644 --- a/app/lib/mulukhiya/controller_methods.rb +++ b/app/lib/mulukhiya/controller_methods.rb @@ -175,6 +175,10 @@ def status_label return config["/#{name}/status/label"] end + def reblog_label + return config["/#{name}/status/reblog_label"] + end + def status_delete_limit return config["/#{name}/status/delete/limit"] rescue nil end diff --git a/config/application.yaml b/config/application.yaml index 8e6852c56..04033f4f5 100644 --- a/config/application.yaml +++ b/config/application.yaml @@ -323,6 +323,7 @@ mastodon: limit: 30 key: id label: 投稿 + reblog_label: ブースト parser: toot spoiler_text: null streaming: @@ -377,6 +378,7 @@ misskey: default_max_length: 3000 key: noteId label: ノート + reblog_label: リノート parser: note spoiler_text: null streaming: From a2c6cc557af24d81a2e8bfae639bad750eb6aa37 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 17:33:42 +0900 Subject: [PATCH 08/25] =?UTF-8?q?docs:=20=E3=82=BB=E3=83=83=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E9=96=8B=E5=A7=8B=E6=99=82=E3=81=AE=E5=90=8C?= =?UTF-8?q?=E6=9C=9F=E6=89=8B=E9=A0=86=E3=81=ABgit=20fetch=E3=83=BB?= =?UTF-8?q?=E3=83=AA=E3=83=A2=E3=83=BC=E3=83=88=E4=B9=96=E9=9B=A2=E7=A2=BA?= =?UTF-8?q?=E8=AA=8D=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MEMORY.mdの「リモートが正本」ルールが同期手順に反映されておらず、 端末間で前提が共有されないことがあったため明示的に追加。 Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/CLAUDE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index c60fe1fd7..78cda10d9 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -191,8 +191,10 @@ git diff Gemfile.lock - `docs/CLAUDE.md` を読む(プロジェクトのルール・構造・履歴の正本) - `MEMORY.md` は自動ロードされるので、両者の整合性を意識する -### 2. ローカルの状態確認 +### 2. リモートとの同期・状態確認 +- `git fetch origin` — **最初に必ず実行**。リモートが正本であり、ローカルの状態を信用しない +- `git log HEAD..origin/develop --oneline` — リモートに未取り込みのコミットがないか確認。差分があればpullを検討 - `git log --oneline -10` — 直近のコミット履歴 - `gh issue list --state open` — open Issue一覧 - `gh pr list --state open` — open PR一覧 From e2d0250be72c9fe9831c9eb94d9bf2d314b4fa56 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 17:44:19 +0900 Subject: [PATCH 09/25] =?UTF-8?q?docs:=205.8.0=E3=80=9C5.10.0=E3=81=AE?= =?UTF-8?q?=E3=83=9E=E3=82=A4=E3=83=AB=E3=82=B9=E3=83=88=E3=83=BC=E3=83=B3?= =?UTF-8?q?=E3=82=92=E5=86=8D=E7=B7=A8=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 5.8.0: セキュリティレビュー対応に絞り軽量化 - 5.9.0: アーキテクチャ整理(#4144, #4146) - 5.10.0: WebUI拡張(#4117, #4118) - マイルストーン管理の原則にボリューム考慮の記載を追加 Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/CLAUDE.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 78cda10d9..fd036687b 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -88,14 +88,24 @@ git diff Gemfile.lock # 5. 問題なければコミット ``` -## 予定: 5.8.0 +## 予定: 5.8.0 — セキュリティレビュー対応 -- #4117 WebUI: 複雑なハンドラーパラメータ編集(CRUD一覧管理) — オブジェクト配列や深いネスト構造を持つパラメータの一覧管理UI -- #4144 カスタムAPI/カスタムフィードを独立デーモンに分離 — Bundler二重管理・Open3.capture3の不安定さを解消。元の独立デーモン形式に戻す -- #4146 PieFed対応をginseng-piefedに切り出し — tomato-shriekerとの共有が動機。#4145 完了が前提 +- #4155 Wiki: Sentry.ioの設定項目をドキュメントに追加 - #4157 Sentry: before_sendフィルタによる秘匿情報スクラビング — #4156 セキュリティレビューの指摘対応 - #4158 bundler-auditの導入とCI統合 — #4156 セキュリティレビューの指摘対応 -- #4159 フロントJSテストのアサーション修正 — #4156 セキュリティレビューの指摘対応 +- #4156 セキュリティレビュー — 上記完了でクローズ +- ~~#4159 フロントJSテストのアサーション修正~~ — クローズ済み +- ~~#4161 about APIでブースト/リノートのカスタムラベルを返す~~ — クローズ済み + +## 予定: 5.9.0 — アーキテクチャ整理 + +- #4144 カスタムAPI/カスタムフィードを独立デーモンに分離 — Bundler二重管理・Open3.capture3の不安定さを解消。元の独立デーモン形式に戻す +- #4146 PieFed対応をginseng-piefedに切り出し — tomato-shriekerとの共有が動機。#4145 完了が前提 + +## 予定: 5.10.0 — WebUI拡張 + +- #4117 WebUI: 複雑なハンドラーパラメータ編集(CRUD一覧管理) — オブジェクト配列や深いネスト構造を持つパラメータの一覧管理UI +- #4118 WebUI: サービス連携・システム設定の編集と不要設定の自動検出 ## リリース済み: 5.7.0(2026-03-14) @@ -310,7 +320,7 @@ test/ ### マイルストーン管理 -- 1マイルストーンあたり10件前後で区切る +- 1マイルストーンあたり10件前後で区切る(平均的なボリュームのIssueを基準とし、粒度の大きなIssueがある場合は件数を減らして調整する) - 優先度の低いIssueは次のマイナーバージョンへ送る - 計画書は作成せず、Issue+マイルストーンで管理する - セキュリティレビュー([#4156](https://github.com/pooza/mulukhiya-toot-proxy/issues/4156))は各マイルストーンの Issue をすべて消化した後、リリース直前に毎度実施する From 69bc8a6462b71c19f101d9c2b36b0d93c28ff676 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 17:47:02 +0900 Subject: [PATCH 10/25] =?UTF-8?q?feat:=20bundler-audit=E3=81=AE=E5=B0=8E?= =?UTF-8?q?=E5=85=A5=E3=81=A8rake=20lint=E7=B5=B1=E5=90=88=20(#4158)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Gemfileにbundler-audit追加 - bundler_audit:check rakeタスク作成、lint taskに統合 - sinatra CVE-2025-61921 (ReDoS) をignore(rack 3.2問題のため4.1.1固定中) - CLAUDE.mdにbundler-audit運用ルールを追記 Co-Authored-By: Claude Opus 4.6 (1M context) --- .bundler-audit.yml | 6 ++++++ Gemfile | 1 + Gemfile.lock | 11 ++++++++--- app/task/bundler_audit.rb | 11 +++++++++++ app/task/lint.rb | 2 +- docs/CLAUDE.md | 1 + 6 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 .bundler-audit.yml create mode 100644 app/task/bundler_audit.rb diff --git a/.bundler-audit.yml b/.bundler-audit.yml new file mode 100644 index 000000000..fccaeeae6 --- /dev/null +++ b/.bundler-audit.yml @@ -0,0 +1,6 @@ +--- +ignore: + # Sinatra ReDoS (ETag header) - sinatra 4.2.0で修正だが、 + # rack 3.2 + Sinatra 4.2.0でトークン汚染インシデント発生のため + # sinatra 4.1.1に固定中。docs/postmortem-2025-10-rack32.md 参照 + - GHSA-mr3q-g2mv-mr4q diff --git a/Gemfile b/Gemfile index 3add20c14..9bf9e270b 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,7 @@ gem 'sentry-sidekiq' gem 'sidekiq', '~>8.1' gem 'sidekiq-scheduler', '~>6.0.1' group :development do + gem 'bundler-audit' gem 'ostruct' # gli < 2.22の未宣言依存 gem 'rack-test' gem 'rails-erb-lint' diff --git a/Gemfile.lock b/Gemfile.lock index 9b5870b02..fc2d59be4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -125,6 +125,9 @@ GEM base64 (0.3.0) bigdecimal (4.0.1) builder (3.3.0) + bundler-audit (0.9.3) + bundler (>= 1.2.0) + thor (~> 1.0) cgi (0.5.1) concurrent-ruby (1.3.6) connection_pool (3.0.2) @@ -205,7 +208,7 @@ GEM multi_xml (>= 0.5.2) i18n (1.14.8) concurrent-ruby (~> 1.0) - json (2.19.0) + json (2.19.1) json-schema (6.2.0) addressable (~> 2.8) bigdecimal (>= 3.1, < 5) @@ -346,7 +349,7 @@ GEM rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.49.0) + rubocop-ast (1.49.1) parser (>= 3.3.7.2) prism (~> 1.7) rubocop-minitest (0.39.1) @@ -417,11 +420,12 @@ GEM temple (0.10.4) test-unit (3.7.7) power_assert + thor (1.5.0) tilt (2.1.0) time (0.4.2) date timecop (0.9.10) - timeout (0.6.0) + timeout (0.6.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (3.2.0) @@ -449,6 +453,7 @@ PLATFORMS x86_64-linux DEPENDENCIES + bundler-audit concurrent-ruby dry-validation faye-websocket! diff --git a/app/task/bundler_audit.rb b/app/task/bundler_audit.rb new file mode 100644 index 000000000..166d340c7 --- /dev/null +++ b/app/task/bundler_audit.rb @@ -0,0 +1,11 @@ +module Mulukhiya + extend Rake::DSL + + namespace :bundler_audit do + desc 'bundler-audit' + task :check do + Dir.chdir(Environment.dir) + sh 'bundler-audit check --update' + end + end +end diff --git a/app/task/lint.rb b/app/task/lint.rb index f5ee27e24..d0638cd5a 100644 --- a/app/task/lint.rb +++ b/app/task/lint.rb @@ -2,5 +2,5 @@ module Mulukhiya extend Rake::DSL desc 'lint all' - task lint: ['erb:lint', 'slim:lint', 'rubocop:lint', 'yaml:lint'] + task lint: ['erb:lint', 'slim:lint', 'rubocop:lint', 'yaml:lint', 'bundler_audit:check'] end diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index fd036687b..95b5a5b0d 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -339,6 +339,7 @@ test/ - 未対応 → PRをマージ - セキュリティアラートはリリース時の Gemfile.lock 更新で自動クローズされる - `target-branch`: v4(4.x向け)と develop(5.x向け)の2エントリ +- **bundler-audit**: `rake lint` に統合済み。RubyGems ソースの gem の既知脆弱性を自動スキャンする。`ginseng-*` 系 gem は git ソースのため対象外。`ginseng-*` の依存 gem に脆弱性がある場合は、該当 gem のリポジトリで `bundle update` して対応する ### Codexレビュー確認 From 1e2727dcbdf8c3dcbc621afc26b066ab281e4466 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 17:51:19 +0900 Subject: [PATCH 11/25] =?UTF-8?q?feat:=20Sentry=20before=5Fsend=E3=83=95?= =?UTF-8?q?=E3=82=A3=E3=83=AB=E3=82=BF=E3=81=AB=E3=82=88=E3=82=8B=E7=A7=98?= =?UTF-8?q?=E5=8C=BF=E6=83=85=E5=A0=B1=E3=82=B9=E3=82=AF=E3=83=A9=E3=83=93?= =?UTF-8?q?=E3=83=B3=E3=82=B0=20(#4157)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sentry.initにbefore_sendコールバックを追加 - 例外メッセージからトークンパターン(20文字以上の英数字列)と 内部パス(/home/*, /Users/*)をマスク - スクラビングパターンはconfig/application.yamlの/sentry/scrub_patternsで設定可能 - テスト4件追加 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya.rb | 12 ++++++++++ config/application.yaml | 4 ++++ test/unit/lib/sentry_scrub.rb | 43 +++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 test/unit/lib/sentry_scrub.rb diff --git a/app/lib/mulukhiya.rb b/app/lib/mulukhiya.rb index e41e11f8f..23288a3a8 100644 --- a/app/lib/mulukhiya.rb +++ b/app/lib/mulukhiya.rb @@ -38,11 +38,23 @@ def self.setup_sentry config.release = Package.version config.environment = Environment.type config.traces_sample_rate = Config.instance['/sentry/traces_sample_rate'] || 0 + config.before_send = method(:scrub_sentry_event) end rescue => e warn "Sentry initialization skipped: #{e.message}" end + def self.scrub_sentry_event(event, _hint) + patterns = (Config.instance['/sentry/scrub_patterns'] || []).map {|p| Regexp.new(p)} + return event if patterns.empty? + event.exception&.values&.each do |ex| # rubocop:disable Style/HashEachMethods + patterns.each do |pattern| + ex.value = ex.value&.gsub(pattern, '[FILTERED]') + end + end + return event + end + def self.setup_debug Ricecream.disable return unless Environment.development? diff --git a/config/application.yaml b/config/application.yaml index 04033f4f5..9001c3bd6 100644 --- a/config/application.yaml +++ b/config/application.yaml @@ -451,6 +451,10 @@ redis: sentry: dsn: null traces_sample_rate: 0 + scrub_patterns: + - '[a-zA-Z0-9_\-]{20,}' + - '/home/[^\s]+' + - '/Users/[^\s]+' ruby: bundler: install: false diff --git a/test/unit/lib/sentry_scrub.rb b/test/unit/lib/sentry_scrub.rb new file mode 100644 index 000000000..d0e1900df --- /dev/null +++ b/test/unit/lib/sentry_scrub.rb @@ -0,0 +1,43 @@ +module Mulukhiya + class SentryScrubTest < TestCase + def build_event(message) + config = Sentry::Configuration.new + event = Sentry::ErrorEvent.new(configuration: config) + exc = RuntimeError.new(message) + exc.set_backtrace(caller) + mechanism = Sentry::Mechanism.new(type: 'generic', handled: true) + event.add_exception_interface(exc, mechanism: mechanism) + return event + end + + def test_scrub_token + event = build_event('Token abc123XYZ456defGHI789jkl failed') + result = Mulukhiya.scrub_sentry_event(event, {}) + + assert_not_match(/abc123XYZ456defGHI789jkl/, result.exception.values.first.value) + assert_match(/\[FILTERED\]/, result.exception.values.first.value) + end + + def test_scrub_path + event = build_event('Error at /home/mastodon/mulukhiya-toot-proxy/app/lib/foo.rb') + result = Mulukhiya.scrub_sentry_event(event, {}) + + assert_not_match(%r{/home/mastodon}, result.exception.values.first.value) + end + + def test_scrub_preserves_short_strings + event = build_event('Something went wrong') + result = Mulukhiya.scrub_sentry_event(event, {}) + + assert_match(/Something went wrong/, result.exception.values.first.value) + end + + def test_scrub_no_exception + config = Sentry::Configuration.new + event = Sentry::ErrorEvent.new(configuration: config) + result = Mulukhiya.scrub_sentry_event(event, {}) + + assert_not_nil(result) + end + end +end From 402c2d4b30bebcc92a8694d5a96b8df9a51513f2 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 18:09:49 +0900 Subject: [PATCH 12/25] =?UTF-8?q?chore:=20=E3=83=90=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=82=925.8.0=E3=81=AB=E3=83=90=E3=83=B3?= =?UTF-8?q?=E3=83=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- config/application.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/application.yaml b/config/application.yaml index 9001c3bd6..25e44c51d 100644 --- a/config/application.yaml +++ b/config/application.yaml @@ -406,7 +406,7 @@ package: - tkoishi@b-shock.co.jp license: MIT url: https://github.com/pooza/mulukhiya-toot-proxy - version: 5.7.0 + version: 5.8.0 parser: note: fields: From 0a3faf5022f4c8abd61acf18562ed90d0f9a8120 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 18:16:30 +0900 Subject: [PATCH 13/25] =?UTF-8?q?docs:=20about=20API=E3=83=AC=E3=82=B9?= =?UTF-8?q?=E3=83=9D=E3=83=B3=E3=82=B9=E4=BE=8B=E3=81=ABreblog=5Flabel?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/api.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index 8d0891156..aa246bd24 100644 --- a/docs/api.md +++ b/docs/api.md @@ -228,12 +228,13 @@ URL 正規化、短縮 URL 展開、NowPlaying 検出(iTunes/Spotify/YouTube "email": ["author@example.com"], "license": "MIT", "url": "https://github.com/pooza/mulukhiya-toot-proxy", - "version": "5.2.1" + "version": "5.8.0" }, "config": { "controller": "mastodon", "status": { "label": "投稿", + "reblog_label": "ブースト", "max_length": 2400, "spoiler": {"text": null, "emoji": null, "shortcode": null}, "default_hashtag": "precure_fun" From 9be2e46077d6af02b06c0eebe82ee5c31e1968d3 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 18:18:27 +0900 Subject: [PATCH 14/25] =?UTF-8?q?docs:=205.8.0=E3=82=92=E3=83=AA=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=82=B9=E5=BE=85=E3=81=A1=E7=8A=B6=E6=85=8B=E3=81=AB?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/CLAUDE.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 95b5a5b0d..1bcdf950c 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -88,12 +88,14 @@ git diff Gemfile.lock # 5. 問題なければコミット ``` -## 予定: 5.8.0 — セキュリティレビュー対応 +## 予定: 5.8.0 — セキュリティレビュー対応(リリース待ち) -- #4155 Wiki: Sentry.ioの設定項目をドキュメントに追加 -- #4157 Sentry: before_sendフィルタによる秘匿情報スクラビング — #4156 セキュリティレビューの指摘対応 -- #4158 bundler-auditの導入とCI統合 — #4156 セキュリティレビューの指摘対応 -- #4156 セキュリティレビュー — 上記完了でクローズ +全Issue クローズ済み。ステージング全4台(dev04/dev15/dev22/dev23)デプロイ・動作確認済み。リリース作業のみ残。 + +- ~~#4155 Wiki: Sentry.ioの設定項目をドキュメントに追加~~ — クローズ済み +- ~~#4157 Sentry: before_sendフィルタによる秘匿情報スクラビング~~ — クローズ済み +- ~~#4158 bundler-auditの導入とCI統合~~ — クローズ済み。sinatra CVE-2025-61921 は rack 3.2問題のため ignore 設定 +- ~~#4156 セキュリティレビュー~~ — クローズ済み - ~~#4159 フロントJSテストのアサーション修正~~ — クローズ済み - ~~#4161 about APIでブースト/リノートのカスタムラベルを返す~~ — クローズ済み From 82ec6ba43f0debe4e306c678e46ae25fd3f2db58 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 21:58:03 +0900 Subject: [PATCH 15/25] =?UTF-8?q?feat:=20PUT=20/api/v1/statuses/:id=20?= =?UTF-8?q?=E3=83=91=E3=82=B9=E3=82=B9=E3=83=AB=E3=83=BC=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mastodon の投稿編集 API(media_attributes によるメディア説明更新等)を モロヘイヤ経由で利用できるようにする。 既存の POST /api/:version/statuses ルートのみでは PUT リクエストが 405 Method Not Allowed になっていた。 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/controller/mastodon_controller.rb | 13 +++++++++++++ docs/api.md | 1 + 2 files changed, 14 insertions(+) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index a719552a3..4a5161c3c 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -54,6 +54,19 @@ class MastodonController < Controller return @renderer.to_s end + put '/api/:version/statuses/:id' do + verify_token_integrity! + reporter.response = sns.update_status(params[:id], params, {headers: @headers}) + @renderer.message = reporter.response.parsed_response + @renderer.status = reporter.response.code + return @renderer.to_s + rescue Ginseng::GatewayError => e + e.alert unless e.source_status == 401 + @renderer.message = {error: e.message} + @renderer.status = e.source_status + return @renderer.to_s + end + post '/api/:version/statuses/:id/favourite' do verify_token_integrity! reporter.response = sns.fav(params[:id]) diff --git a/docs/api.md b/docs/api.md index aa246bd24..a267710da 100644 --- a/docs/api.md +++ b/docs/api.md @@ -182,6 +182,7 @@ URL 正規化、短縮 URL 展開、NowPlaying 検出(iTunes/Spotify/YouTube | エンドポイント | メソッド | 処理内容 | |---------------|---------|---------| | `/api/v{version}/statuses` | POST | 投稿作成(pre_toot → SNS → post_toot) | +| `/api/v{version}/statuses/{id}` | PUT | 投稿編集(パススルー) | | `/api/v{version}/media` | POST | メディアアップロード(pre_upload → SNS → post_upload) | | `/api/v{version}/media/{id}` | PUT | メディア更新(サムネイル変換) | | `/api/v{version}/statuses/{id}/favourite` | POST | お気に入り(SNS → post_fav) | From ed57563f51d5d6a8844134ace5a21edc71f5a63e Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 22:05:44 +0900 Subject: [PATCH 16/25] =?UTF-8?q?docs:=205.8.0=E3=81=AB#4162=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=97=E3=82=B9=E3=83=86=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=83=B3=E3=82=B0=E5=86=8D=E6=A4=9C=E8=A8=BC=E3=81=8C=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E3=81=AA=E7=8A=B6=E6=85=8B=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/CLAUDE.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 1bcdf950c..2e7e4e04d 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -88,9 +88,9 @@ git diff Gemfile.lock # 5. 問題なければコミット ``` -## 予定: 5.8.0 — セキュリティレビュー対応(リリース待ち) +## 予定: 5.8.0 — セキュリティレビュー対応 -全Issue クローズ済み。ステージング全4台(dev04/dev15/dev22/dev23)デプロイ・動作確認済み。リリース作業のみ残。 +セキュリティ関連 Issue 全クローズ済み。#4162 追加によりステージング再検証が必要。 - ~~#4155 Wiki: Sentry.ioの設定項目をドキュメントに追加~~ — クローズ済み - ~~#4157 Sentry: before_sendフィルタによる秘匿情報スクラビング~~ — クローズ済み @@ -98,6 +98,7 @@ git diff Gemfile.lock - ~~#4156 セキュリティレビュー~~ — クローズ済み - ~~#4159 フロントJSテストのアサーション修正~~ — クローズ済み - ~~#4161 about APIでブースト/リノートのカスタムラベルを返す~~ — クローズ済み +- #4162 PUT /api/v1/statuses/:id パススルーを追加 — capsicum#30(投稿編集API)対応。ステージング検証未実施 ## 予定: 5.9.0 — アーキテクチャ整理 From bc0c683f2f95421178ad53822128965ba48f2260 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 22:24:19 +0900 Subject: [PATCH 17/25] =?UTF-8?q?refactor:=20PUT=20/api/v1/statuses/:id=20?= =?UTF-8?q?=E3=82=92=20media=5Fattributes=20=E3=81=AE=E3=81=BF=E8=A8=B1?= =?UTF-8?q?=E5=8F=AF=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 投稿本文(status)の事後編集を防ぎつつ、メディア説明(ALT)の 更新のみを許可するフィルタリングを実装。 - コントローラー: params から media_attributes のみ抽出して転送 - media_attributes がない場合は 422 を返す - nginx: PUT を reject せずモロヘイヤに転送(フィルタリングはアプリ層で実施) - api.md: エンドポイントの説明を更新 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/controller/mastodon_controller.rb | 8 +++++++- config/sample/mastodon/mulukhiya.nginx | 5 +---- docs/api.md | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index 4a5161c3c..10f8ad0bd 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -56,10 +56,16 @@ class MastodonController < Controller put '/api/:version/statuses/:id' do verify_token_integrity! - reporter.response = sns.update_status(params[:id], params, {headers: @headers}) + body = {media_attributes: params[:media_attributes]}.compact + raise Ginseng::ValidateError, 'media_attributes is required' if body.empty? + reporter.response = sns.update_status(params[:id], body, {headers: @headers}) @renderer.message = reporter.response.parsed_response @renderer.status = reporter.response.code return @renderer.to_s + rescue Ginseng::ValidateError => e + @renderer.message = {error: e.message} + @renderer.status = 422 + return @renderer.to_s rescue Ginseng::GatewayError => e e.alert unless e.source_status == 401 @renderer.message = {error: e.message} diff --git a/config/sample/mastodon/mulukhiya.nginx b/config/sample/mastodon/mulukhiya.nginx index 8f0285c7b..e9065b857 100644 --- a/config/sample/mastodon/mulukhiya.nginx +++ b/config/sample/mastodon/mulukhiya.nginx @@ -8,7 +8,7 @@ map "${request_method}:${http_x_mulukhiya}" $media_put_backend { default http://localhost:3000; } map "${request_method}:${http_x_mulukhiya}" $status_put_backend { - "~^PUT:$" reject; + "~^PUT:$" http://localhost:3008; default http://localhost:3000; } @@ -31,9 +31,6 @@ location ~ ^/api/v[0-9]+/statuses/[0-9]+$ { if ($http_x_mulukhiya_purpose != '') { proxy_pass http://localhost:3008; } - if ($status_put_backend = reject) { - return 405; - } proxy_pass $status_put_backend; } location = /api/v1/timelines/public { diff --git a/docs/api.md b/docs/api.md index a267710da..9035e508d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -182,7 +182,7 @@ URL 正規化、短縮 URL 展開、NowPlaying 検出(iTunes/Spotify/YouTube | エンドポイント | メソッド | 処理内容 | |---------------|---------|---------| | `/api/v{version}/statuses` | POST | 投稿作成(pre_toot → SNS → post_toot) | -| `/api/v{version}/statuses/{id}` | PUT | 投稿編集(パススルー) | +| `/api/v{version}/statuses/{id}` | PUT | メディア説明更新(`media_attributes` のみ許可、本文編集は不可) | | `/api/v{version}/media` | POST | メディアアップロード(pre_upload → SNS → post_upload) | | `/api/v{version}/media/{id}` | PUT | メディア更新(サムネイル変換) | | `/api/v{version}/statuses/{id}/favourite` | POST | お気に入り(SNS → post_fav) | From 8b1a2c2d220c070859cc81a0aebdfb9b6c8c674f Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 22:42:34 +0900 Subject: [PATCH 18/25] =?UTF-8?q?refactor:=20PUT=20/api/v1/statuses/:id=20?= =?UTF-8?q?=E3=81=AB=20X-Mulukhiya-Purpose=20=E3=83=99=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=81=AE=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E5=B0=8E=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit デフォルト(Purpose なし)は media_attributes のみ許可。 Purpose: tag で status パラメータも許可(#3877 ハッシュタグ付け替え用)。 不明な Purpose は 422 で拒否。 nginx サンプルから冗長な if ブロックを削除。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../mulukhiya/controller/mastodon_controller.rb | 10 +++++++++- config/sample/mastodon/mulukhiya.nginx | 3 --- docs/api.md | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index 10f8ad0bd..4dff6f034 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -56,7 +56,15 @@ class MastodonController < Controller put '/api/:version/statuses/:id' do verify_token_integrity! - body = {media_attributes: params[:media_attributes]}.compact + purpose = request.env['HTTP_X_MULUKHIYA_PURPOSE'] + body = case purpose + when nil, '' + {media_attributes: params[:media_attributes]}.compact + when 'tag' + {status: params[:status], media_attributes: params[:media_attributes]}.compact + else + raise Ginseng::ValidateError, "unknown purpose: #{purpose}" + end raise Ginseng::ValidateError, 'media_attributes is required' if body.empty? reporter.response = sns.update_status(params[:id], body, {headers: @headers}) @renderer.message = reporter.response.parsed_response diff --git a/config/sample/mastodon/mulukhiya.nginx b/config/sample/mastodon/mulukhiya.nginx index e9065b857..b77914f15 100644 --- a/config/sample/mastodon/mulukhiya.nginx +++ b/config/sample/mastodon/mulukhiya.nginx @@ -28,9 +28,6 @@ location ~ ^/api/v[0-9]+/media/[0-9]+$ { } location ~ ^/api/v[0-9]+/statuses/[0-9]+$ { include /path/to/mulukhiya_proxy.conf; - if ($http_x_mulukhiya_purpose != '') { - proxy_pass http://localhost:3008; - } proxy_pass $status_put_backend; } location = /api/v1/timelines/public { diff --git a/docs/api.md b/docs/api.md index 9035e508d..0cdead852 100644 --- a/docs/api.md +++ b/docs/api.md @@ -159,6 +159,20 @@ HTTP ステータス 200 なら全サービス正常、503 なら一部サービ - モロヘイヤが SNS に転送する際に自動的に `X-Mulukhiya: {パッケージ名}` を付与する - クライアントがこのヘッダを送信する必要はない +### X-Mulukhiya-Purpose ヘッダ + +`PUT /api/v{version}/statuses/{id}` で本文更新の可否を制御するヘッダ。 +SNS における「発言の責任」の観点から、本文の自由な編集はデフォルトで禁止している。 + +| X-Mulukhiya-Purpose | 許可されるパラメータ | 用途 | +| --- | --- | --- | +| (なし / 空) | `media_attributes` のみ | メディア説明(ALT)の編集 | +| `tag` | `status`, `media_attributes` | ハッシュタグの付け替え(モロヘイヤ内部用) | + +- Purpose ヘッダなし: クライアントからの通常リクエスト。`media_attributes` 以外は除去される +- Purpose が `tag`: モロヘイヤ自身がハッシュタグを書き換える際に使用(将来の #3877 対応) +- 不明な Purpose: 422 Unprocessable Entity を返す + ### パイプライン処理 以下の処理が**透過的に**適用される。クライアントは標準 API を呼ぶだけでよい。 @@ -182,7 +196,7 @@ URL 正規化、短縮 URL 展開、NowPlaying 検出(iTunes/Spotify/YouTube | エンドポイント | メソッド | 処理内容 | |---------------|---------|---------| | `/api/v{version}/statuses` | POST | 投稿作成(pre_toot → SNS → post_toot) | -| `/api/v{version}/statuses/{id}` | PUT | メディア説明更新(`media_attributes` のみ許可、本文編集は不可) | +| `/api/v{version}/statuses/{id}` | PUT | 投稿更新(`X-Mulukhiya-Purpose` ヘッダで許可範囲を制御、下記参照) | | `/api/v{version}/media` | POST | メディアアップロード(pre_upload → SNS → post_upload) | | `/api/v{version}/media/{id}` | PUT | メディア更新(サムネイル変換) | | `/api/v{version}/statuses/{id}/favourite` | POST | お気に入り(SNS → post_fav) | From 71094040b5cabeef45568b9f9f571ef8ef92a2f8 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 22:43:21 +0900 Subject: [PATCH 19/25] =?UTF-8?q?docs:=205.8.0=E3=81=AE=E3=82=B9=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E3=82=B9=E3=82=92=E6=9B=B4=E6=96=B0=EF=BC=88?= =?UTF-8?q?#4162=20=E3=82=B9=E3=83=86=E3=83=BC=E3=82=B8=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E6=A4=9C=E8=A8=BC=E4=B8=AD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/CLAUDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 2e7e4e04d..93a794983 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -90,7 +90,7 @@ git diff Gemfile.lock ## 予定: 5.8.0 — セキュリティレビュー対応 -セキュリティ関連 Issue 全クローズ済み。#4162 追加によりステージング再検証が必要。 +全 Issue クローズ済み。ステージング検証中(dev04 先行)。 - ~~#4155 Wiki: Sentry.ioの設定項目をドキュメントに追加~~ — クローズ済み - ~~#4157 Sentry: before_sendフィルタによる秘匿情報スクラビング~~ — クローズ済み @@ -98,7 +98,7 @@ git diff Gemfile.lock - ~~#4156 セキュリティレビュー~~ — クローズ済み - ~~#4159 フロントJSテストのアサーション修正~~ — クローズ済み - ~~#4161 about APIでブースト/リノートのカスタムラベルを返す~~ — クローズ済み -- #4162 PUT /api/v1/statuses/:id パススルーを追加 — capsicum#30(投稿編集API)対応。ステージング検証未実施 +- ~~#4162 PUT /api/v1/statuses/:id パススルーを追加~~ — X-Mulukhiya-Purpose ヘッダで許可範囲を制御。ステージング検証中 ## 予定: 5.9.0 — アーキテクチャ整理 From b3199a40c56783cfbbde012a2fed46c51fb0253b Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 23:20:55 +0900 Subject: [PATCH 20/25] =?UTF-8?q?feat:=20X-Mulukhiya-Purpose:=20media=5Fup?= =?UTF-8?q?date=20=E3=82=92=E3=82=B5=E3=83=9D=E3=83=BC=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit クライアント(capsicum)からの ALT 編集リクエスト用。 nginx が Purpose ヘッダの有無でルーティングするため、 クライアントは media_update を指定して PUT を送る。 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/controller/mastodon_controller.rb | 2 +- docs/api.md | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index 4dff6f034..07377a551 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -58,7 +58,7 @@ class MastodonController < Controller verify_token_integrity! purpose = request.env['HTTP_X_MULUKHIYA_PURPOSE'] body = case purpose - when nil, '' + when nil, '', 'media_update' {media_attributes: params[:media_attributes]}.compact when 'tag' {status: params[:status], media_attributes: params[:media_attributes]}.compact diff --git a/docs/api.md b/docs/api.md index 0cdead852..6efb4b2d3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -166,10 +166,12 @@ SNS における「発言の責任」の観点から、本文の自由な編集 | X-Mulukhiya-Purpose | 許可されるパラメータ | 用途 | | --- | --- | --- | -| (なし / 空) | `media_attributes` のみ | メディア説明(ALT)の編集 | +| (なし / 空) | `media_attributes` のみ | メディア説明(ALT)の編集(直接アクセス時) | +| `media_update` | `media_attributes` のみ | メディア説明(ALT)の編集(クライアントから) | | `tag` | `status`, `media_attributes` | ハッシュタグの付け替え(モロヘイヤ内部用) | -- Purpose ヘッダなし: クライアントからの通常リクエスト。`media_attributes` 以外は除去される +- Purpose ヘッダなし: 直接アクセス時。`media_attributes` 以外は除去される +- Purpose が `media_update`: クライアント(capsicum 等)からの ALT 編集リクエスト。nginx が Purpose ヘッダの有無でルーティングするため、クライアントはこの値を指定する - Purpose が `tag`: モロヘイヤ自身がハッシュタグを書き換える際に使用(将来の #3877 対応) - 不明な Purpose: 422 Unprocessable Entity を返す From 9ed2467f0baf4fda1a16db8534af43c2f1adccfb Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 23:23:19 +0900 Subject: [PATCH 21/25] =?UTF-8?q?refactor:=20nginx=20=E3=82=B5=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=AB=E3=82=92=20X-Mulukhiya-Purpose=20=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purpose ヘッダなしの PUT /statuses/:id を 405 で拒否し、 ヘッダありの場合のみモロヘイヤにルーティングする。 if is evil 問題を回避するため map で一括振り分け。 Co-Authored-By: Claude Opus 4.6 (1M context) --- config/sample/mastodon/mulukhiya.nginx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/config/sample/mastodon/mulukhiya.nginx b/config/sample/mastodon/mulukhiya.nginx index b77914f15..760558496 100644 --- a/config/sample/mastodon/mulukhiya.nginx +++ b/config/sample/mastodon/mulukhiya.nginx @@ -7,9 +7,10 @@ map "${request_method}:${http_x_mulukhiya}" $media_put_backend { "~^PUT:$" http://localhost:3008; default http://localhost:3000; } -map "${request_method}:${http_x_mulukhiya}" $status_put_backend { - "~^PUT:$" http://localhost:3008; - default http://localhost:3000; +map "${request_method}:${http_x_mulukhiya}:${http_x_mulukhiya_purpose}" $status_put_backend { + "~^PUT::.+" http://localhost:3008; + "~^PUT::$" reject; + default http://localhost:3000; } # === server context に追加 === @@ -27,6 +28,9 @@ location ~ ^/api/v[0-9]+/media/[0-9]+$ { proxy_pass $media_put_backend; } location ~ ^/api/v[0-9]+/statuses/[0-9]+$ { + if ($status_put_backend = reject) { + return 405; + } include /path/to/mulukhiya_proxy.conf; proxy_pass $status_put_backend; } From ced00a77e6e1f4c246e2562cace1cb70bd85416a Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Sun, 15 Mar 2026 23:32:22 +0900 Subject: [PATCH 22/25] =?UTF-8?q?fix:=20media=5Fupdate=20=E6=99=82?= =?UTF-8?q?=E3=81=AB=E5=85=83=E3=81=AE=E6=8A=95=E7=A8=BF=E6=9C=AC=E6=96=87?= =?UTF-8?q?=E3=82=92=E8=87=AA=E5=8B=95=E8=A3=9C=E5=AE=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mastodon の PUT /api/v1/statuses/:id は status パラメータが必須。 media_update 時は fetch_status で元の投稿を取得し、本文(text)を そのまま再送することで、クライアントに本文編集を許可せずに media_attributes の更新を実現する。 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/controller/mastodon_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index 07377a551..3e44c941c 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -59,7 +59,8 @@ class MastodonController < Controller purpose = request.env['HTTP_X_MULUKHIYA_PURPOSE'] body = case purpose when nil, '', 'media_update' - {media_attributes: params[:media_attributes]}.compact + original = sns.fetch_status(params[:id], {headers: @headers}) + {status: original['text'], media_attributes: params[:media_attributes]}.compact when 'tag' {status: params[:status], media_attributes: params[:media_attributes]}.compact else From 223dcbc6853b09f6c1f81de18a13cb2c9faec074 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Mon, 16 Mar 2026 00:03:25 +0900 Subject: [PATCH 23/25] =?UTF-8?q?fix:=20media=5Fupdate=20=E6=99=82?= =?UTF-8?q?=E3=81=AB=20/source=20=E3=82=A8=E3=83=B3=E3=83=89=E3=83=9D?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=83=88=E3=81=A7=E3=82=BD=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88=E3=82=92=E5=8F=96=E5=BE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GET /api/v1/statuses/:id は text フィールドを返さないため、 /api/v1/statuses/:id/source を使ってソーステキストを取得する。 Co-Authored-By: Claude Opus 4.6 (1M context) --- app/lib/mulukhiya/controller/mastodon_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lib/mulukhiya/controller/mastodon_controller.rb b/app/lib/mulukhiya/controller/mastodon_controller.rb index 3e44c941c..189ed7b0a 100644 --- a/app/lib/mulukhiya/controller/mastodon_controller.rb +++ b/app/lib/mulukhiya/controller/mastodon_controller.rb @@ -59,8 +59,8 @@ class MastodonController < Controller purpose = request.env['HTTP_X_MULUKHIYA_PURPOSE'] body = case purpose when nil, '', 'media_update' - original = sns.fetch_status(params[:id], {headers: @headers}) - {status: original['text'], media_attributes: params[:media_attributes]}.compact + source = sns.fetch_status_source(params[:id], {headers: @headers}) + {status: source['text'], media_attributes: params[:media_attributes]}.compact when 'tag' {status: params[:status], media_attributes: params[:media_attributes]}.compact else From 8aeda04f35e24620df1c13d79649b714dbaf3449 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Mon, 16 Mar 2026 00:44:59 +0900 Subject: [PATCH 24/25] =?UTF-8?q?chore:=20nginx=20=E3=82=B5=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=AB=E3=82=92=E7=B0=A1=E7=B4=A0=E5=8C=96=E3=81=97?= =?UTF-8?q?=205.8.0=20=E3=82=B9=E3=83=86=E3=83=BC=E3=82=BF=E3=82=B9?= =?UTF-8?q?=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - nginx の status_put_backend map から Purpose ヘッダ分岐を削除 (Mastodon ALT 編集は一旦見送りのため不要) - 5.8.0 をリリース待ち状態に更新、#4162 を予定リストから削除 Co-Authored-By: Claude Opus 4.6 (1M context) --- config/sample/mastodon/mulukhiya.nginx | 10 +++------- docs/CLAUDE.md | 5 ++--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/config/sample/mastodon/mulukhiya.nginx b/config/sample/mastodon/mulukhiya.nginx index 760558496..b77914f15 100644 --- a/config/sample/mastodon/mulukhiya.nginx +++ b/config/sample/mastodon/mulukhiya.nginx @@ -7,10 +7,9 @@ map "${request_method}:${http_x_mulukhiya}" $media_put_backend { "~^PUT:$" http://localhost:3008; default http://localhost:3000; } -map "${request_method}:${http_x_mulukhiya}:${http_x_mulukhiya_purpose}" $status_put_backend { - "~^PUT::.+" http://localhost:3008; - "~^PUT::$" reject; - default http://localhost:3000; +map "${request_method}:${http_x_mulukhiya}" $status_put_backend { + "~^PUT:$" http://localhost:3008; + default http://localhost:3000; } # === server context に追加 === @@ -28,9 +27,6 @@ location ~ ^/api/v[0-9]+/media/[0-9]+$ { proxy_pass $media_put_backend; } location ~ ^/api/v[0-9]+/statuses/[0-9]+$ { - if ($status_put_backend = reject) { - return 405; - } include /path/to/mulukhiya_proxy.conf; proxy_pass $status_put_backend; } diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 93a794983..1bcdf950c 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -88,9 +88,9 @@ git diff Gemfile.lock # 5. 問題なければコミット ``` -## 予定: 5.8.0 — セキュリティレビュー対応 +## 予定: 5.8.0 — セキュリティレビュー対応(リリース待ち) -全 Issue クローズ済み。ステージング検証中(dev04 先行)。 +全Issue クローズ済み。ステージング全4台(dev04/dev15/dev22/dev23)デプロイ・動作確認済み。リリース作業のみ残。 - ~~#4155 Wiki: Sentry.ioの設定項目をドキュメントに追加~~ — クローズ済み - ~~#4157 Sentry: before_sendフィルタによる秘匿情報スクラビング~~ — クローズ済み @@ -98,7 +98,6 @@ git diff Gemfile.lock - ~~#4156 セキュリティレビュー~~ — クローズ済み - ~~#4159 フロントJSテストのアサーション修正~~ — クローズ済み - ~~#4161 about APIでブースト/リノートのカスタムラベルを返す~~ — クローズ済み -- ~~#4162 PUT /api/v1/statuses/:id パススルーを追加~~ — X-Mulukhiya-Purpose ヘッダで許可範囲を制御。ステージング検証中 ## 予定: 5.9.0 — アーキテクチャ整理 From f038be5c774810b6bdb3c4f749b56da1365ded94 Mon Sep 17 00:00:00 2001 From: Tatsuya Koishi Date: Mon, 16 Mar 2026 07:11:07 +0900 Subject: [PATCH 25/25] bundle update --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index fc2d59be4..f227a10c8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -42,7 +42,7 @@ GIT GIT remote: https://github.com/pooza/ginseng-fediverse.git - revision: d780863b197b054aa91e15dfe9acacd7c022e41b + revision: 3a30745ecc8661a22fdf5cb5c4cc0bc1fe756cb5 branch: main specs: ginseng-fediverse (1.8.21)