From bc0c53b92b0ceba7617d9d02f54bbf7ccfc933d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 21 Oct 2024 11:44:57 +0900
Subject: [PATCH 001/125] =?UTF-8?q?fix(frontend):=20Captcha=20=E3=81=AE?=
 =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA?=
 =?UTF-8?q?=E3=83=B3=E3=82=B0=20(#14811)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): Captcha のエラーハンドリングを修正 (MisskeyIO#768)

(cherry picked from commit 88912d0f8c63a762fbb1d43e5c1abf4fd9fc05d4)

* Update Changelog

* typo

---------

Co-authored-by: riku6460 <17585784+riku6460@users.noreply.github.com>
---
 CHANGELOG.md                                   | 2 ++
 packages/frontend/src/components/MkCaptcha.vue | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04ae102227..c815e65ab3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
 - Enhance: ドライブでソートができるように 
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
+- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
+  (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
 
 ### Server
 -
diff --git a/packages/frontend/src/components/MkCaptcha.vue b/packages/frontend/src/components/MkCaptcha.vue
index 82fc89e51c..264cf9af06 100644
--- a/packages/frontend/src/components/MkCaptcha.vue
+++ b/packages/frontend/src/components/MkCaptcha.vue
@@ -117,8 +117,8 @@ async function requestRender() {
 			sitekey: props.sitekey,
 			theme: defaultStore.state.darkMode ? 'dark' : 'light',
 			callback: callback,
-			'expired-callback': callback,
-			'error-callback': callback,
+			'expired-callback': () => callback(undefined),
+			'error-callback': () => callback(undefined),
 		});
 	} else if (props.provider === 'mcaptcha' && props.instanceUrl && props.sitekey) {
 		const { default: Widget } = await import('@mcaptcha/vanilla-glue');

From 5c79d8db208da1fd7c5bc4900090c3d7b9512196 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 21 Oct 2024 12:49:29 +0900
Subject: [PATCH 002/125] =?UTF-8?q?feat:=20=E3=83=8E=E3=83=BC=E3=83=88?=
 =?UTF-8?q?=E3=81=AE=E9=96=B2=E8=A6=A7=E3=81=AB=E3=83=AD=E3=82=B0=E3=82=A4?=
 =?UTF-8?q?=E3=83=B3=E5=BF=85=E9=A0=88=E3=81=AB=E3=81=99=E3=82=8B=E8=A8=AD?=
 =?UTF-8?q?=E5=AE=9A=20(#14799)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* wip

* wip

* wip

* Update packages/frontend/src/pages/note.vue

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>

* wip

* Update WebhookTestService.ts

* Update privacy.vue

* wip

* rename

* Update locales/ja-JP.yml

Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>

* :art:

* wip

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
---
 CHANGELOG.md                                  |  2 +-
 locales/index.d.ts                            | 26 +++++++++++++++++++
 locales/ja-JP.yml                             |  8 ++++++
 ...333924409-signinRequiredForShowContents.js | 16 ++++++++++++
 .../backend/src/core/WebhookTestService.ts    |  1 +
 .../src/core/activitypub/ApRendererService.ts |  1 +
 .../src/core/activitypub/misc/contexts.ts     |  1 +
 .../activitypub/models/ApPersonService.ts     |  1 +
 packages/backend/src/core/activitypub/type.ts |  1 +
 .../src/core/entities/NoteEntityService.ts    |  4 +++
 .../src/core/entities/UserEntityService.ts    |  1 +
 packages/backend/src/models/User.ts           |  5 ++++
 .../backend/src/models/json-schema/user.ts    |  4 +++
 .../backend/src/server/api/GetterService.ts   | 11 ++++++++
 .../src/server/api/endpoints/i/update.ts      |  2 ++
 .../src/server/api/endpoints/notes/show.ts    | 12 ++++++++-
 .../src/server/api/endpoints/users/notes.ts   |  6 +++++
 .../src/server/web/ClientServerService.ts     | 11 +++++---
 .../src/components/MkFollowButton.vue         |  4 +--
 packages/frontend/src/components/MkNote.vue   |  8 +++---
 .../src/components/MkNoteDetailed.vue         | 10 +++----
 packages/frontend/src/components/MkPoll.vue   |  6 ++---
 packages/frontend/src/os.ts                   | 18 +++++++------
 packages/frontend/src/pages/not-found.vue     |  2 +-
 packages/frontend/src/pages/note.vue          |  6 +++++
 .../frontend/src/pages/settings/privacy.vue   | 19 +++++++++++++-
 packages/frontend/src/scripts/please-login.ts | 14 ++++++----
 packages/misskey-js/src/autogen/types.ts      |  2 ++
 28 files changed, 167 insertions(+), 35 deletions(-)
 create mode 100644 packages/backend/migration/1729333924409-signinRequiredForShowContents.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c815e65ab3..4d8c8ded3a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,7 @@
 ## Unreleased
 
 ### General
--
+- Feat: コンテンツの表示にログインを必須にできるように
 
 ### Client
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  
diff --git a/locales/index.d.ts b/locales/index.d.ts
index fb010d9353..e002540307 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -5190,6 +5190,32 @@ export interface Locale extends ILocale {
      * 名前に禁止されている文字列が含まれています。この名前を使用したい場合は、サーバー管理者にお問い合わせください。
      */
     "yourNameContainsProhibitedWordsDescription": string;
+    /**
+     * 投稿者により、表示にはログインが必要と設定されています
+     */
+    "thisContentsAreMarkedAsSigninRequiredByAuthor": string;
+    /**
+     * ロックダウン
+     */
+    "lockdown": string;
+    "_accountSettings": {
+        /**
+         * コンテンツの表示にログインを必須にする
+         */
+        "requireSigninToViewContents": string;
+        /**
+         * あなたが作成した全てのノートなどのコンテンツを表示するのにログインを必須にします。クローラーから情報を収集されるのを防ぐ効果が期待できます。
+         */
+        "requireSigninToViewContentsDescription1": string;
+        /**
+         * URLプレビュー(OGP)、Webページへの埋め込み、ノートの引用に対応していないサーバーからの表示も不可になります。
+         */
+        "requireSigninToViewContentsDescription2": string;
+        /**
+         * リモートサーバーに連合されたコンテンツでは、これらの制限が適用されない場合があります。
+         */
+        "requireSigninToViewContentsDescription3": string;
+    };
     "_abuseUserReport": {
         /**
          * 転送
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index c241a9e560..f3f7e5c77f 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1293,6 +1293,14 @@ prohibitedWordsForNameOfUser: "禁止ワード(ユーザーの名前)"
 prohibitedWordsForNameOfUserDescription: "このリストに含まれる文字列がユーザーの名前に含まれる場合、ユーザーの名前の変更を拒否します。モデレーター権限を持つユーザーはこの制限の影響を受けません。"
 yourNameContainsProhibitedWords: "変更しようとした名前に禁止された文字列が含まれています"
 yourNameContainsProhibitedWordsDescription: "名前に禁止されている文字列が含まれています。この名前を使用したい場合は、サーバー管理者にお問い合わせください。"
+thisContentsAreMarkedAsSigninRequiredByAuthor: "投稿者により、表示にはログインが必要と設定されています"
+lockdown: "ロックダウン"
+
+_accountSettings:
+  requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
+  requireSigninToViewContentsDescription1: "あなたが作成した全てのノートなどのコンテンツを表示するのにログインを必須にします。クローラーから情報を収集されるのを防ぐ効果が期待できます。"
+  requireSigninToViewContentsDescription2: "URLプレビュー(OGP)、Webページへの埋め込み、ノートの引用に対応していないサーバーからの表示も不可になります。"
+  requireSigninToViewContentsDescription3: "リモートサーバーに連合されたコンテンツでは、これらの制限が適用されない場合があります。"
 
 _abuseUserReport:
   forward: "転送"
diff --git a/packages/backend/migration/1729333924409-signinRequiredForShowContents.js b/packages/backend/migration/1729333924409-signinRequiredForShowContents.js
new file mode 100644
index 0000000000..5d4d1fcce2
--- /dev/null
+++ b/packages/backend/migration/1729333924409-signinRequiredForShowContents.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class SigninRequiredForShowContents1729333924409 {
+    name = 'SigninRequiredForShowContents1729333924409'
+
+    async up(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "user" ADD "requireSigninToViewContents" boolean NOT NULL DEFAULT false`);
+    }
+
+    async down(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "requireSigninToViewContents"`);
+    }
+}
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index 55c8a52705..254d961040 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -83,6 +83,7 @@ function generateDummyUser(override?: Partial<MiUser>): MiUser {
 		isExplorable: true,
 		isHibernated: false,
 		isDeleted: false,
+		requireSigninToViewContents: false,
 		emojis: [],
 		score: 0,
 		host: null,
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index fba8947f03..8235d7ba30 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -495,6 +495,7 @@ export class ApRendererService {
 			summary: profile.description ? this.mfmService.toHtml(mfm.parse(profile.description)) : null,
 			_misskey_summary: profile.description,
 			_misskey_followedMessage: profile.followedMessage,
+			_misskey_requireSigninToViewContents: user.requireSigninToViewContents,
 			icon: avatar ? this.renderImage(avatar) : null,
 			image: banner ? this.renderImage(banner) : null,
 			tag,
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 3dd85b9b86..447f7ef3db 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -555,6 +555,7 @@ const extension_context_definition = {
 	'_misskey_votes': 'misskey:_misskey_votes',
 	'_misskey_summary': 'misskey:_misskey_summary',
 	'_misskey_followedMessage': 'misskey:_misskey_followedMessage',
+	'_misskey_requireSigninToViewContents': 'misskey:_misskey_requireSigninToViewContents',
 	'isCat': 'misskey:isCat',
 	// vcard
 	vcard: 'http://www.w3.org/2006/vcard/ns#',
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 73281078e5..c7915ed94f 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -356,6 +356,7 @@ export class ApPersonService implements OnModuleInit {
 					tags,
 					isBot,
 					isCat: (person as any).isCat === true,
+					requireSigninToViewContents: (person as any).requireSigninToViewContents === true,
 					emojis,
 				})) as MiRemoteUser;
 
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 154965b9d5..8a860335fa 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -14,6 +14,7 @@ export interface IObject {
 	summary?: string;
 	_misskey_summary?: string;
 	_misskey_followedMessage?: string | null;
+	_misskey_requireSigninToViewContents?: boolean;
 	published?: string;
 	cc?: ApObject;
 	to?: ApObject;
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 3e1f094fce..62016936a2 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -149,6 +149,10 @@ export class NoteEntityService implements OnModuleInit {
 			}
 		}
 
+		if (packedNote.user.requireSigninToViewContents && meId == null) {
+			hide = true;
+		}
+
 		if (hide) {
 			packedNote.visibleUserIds = undefined;
 			packedNote.fileIds = [];
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index c9939adf11..747ffc780f 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -490,6 +490,7 @@ export class UserEntityService implements OnModuleInit {
 			}))) : [],
 			isBot: user.isBot,
 			isCat: user.isCat,
+			requireSigninToViewContents: user.requireSigninToViewContents === false ? undefined : true,
 			instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? {
 				name: instance.name,
 				softwareName: instance.softwareName,
diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts
index 805a1e75ae..6fcff77854 100644
--- a/packages/backend/src/models/User.ts
+++ b/packages/backend/src/models/User.ts
@@ -202,6 +202,11 @@ export class MiUser {
 	})
 	public isHibernated: boolean;
 
+	@Column('boolean', {
+		default: false,
+	})
+	public requireSigninToViewContents: boolean;
+
 	// アカウントが削除されたかどうかのフラグだが、完全に削除される際は物理削除なので実質削除されるまでの「削除が進行しているかどうか」のフラグ
 	@Column('boolean', {
 		default: false,
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index 9cffd680f2..817f8e9292 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -115,6 +115,10 @@ export const packedUserLiteSchema = {
 			type: 'boolean',
 			nullable: false, optional: true,
 		},
+		requireSigninToViewContents: {
+			type: 'boolean',
+			nullable: false, optional: true,
+		},
 		instance: {
 			type: 'object',
 			nullable: false, optional: true,
diff --git a/packages/backend/src/server/api/GetterService.ts b/packages/backend/src/server/api/GetterService.ts
index bff3ab96f3..444e6db744 100644
--- a/packages/backend/src/server/api/GetterService.ts
+++ b/packages/backend/src/server/api/GetterService.ts
@@ -39,6 +39,17 @@ export class GetterService {
 		return note;
 	}
 
+	@bindThis
+	public async getNoteWithUser(noteId: MiNote['id']) {
+		const note = await this.notesRepository.findOne({ where: { id: noteId }, relations: ['user'] });
+
+		if (note == null) {
+			throw new IdentifiableError('9725d0ce-ba28-4dde-95a7-2cbb2c15de24', 'No such note.');
+		}
+
+		return note;
+	}
+
 	/**
 	 * Get user for API processing
 	 */
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 0b35005a87..6680c96f3f 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -179,6 +179,7 @@ export const paramDef = {
 		autoAcceptFollowed: { type: 'boolean' },
 		noCrawle: { type: 'boolean' },
 		preventAiLearning: { type: 'boolean' },
+		requireSigninToViewContents: { type: 'boolean' },
 		isBot: { type: 'boolean' },
 		isCat: { type: 'boolean' },
 		injectFeaturedNote: { type: 'boolean' },
@@ -334,6 +335,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			if (typeof ps.autoAcceptFollowed === 'boolean') profileUpdates.autoAcceptFollowed = ps.autoAcceptFollowed;
 			if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
 			if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning;
+			if (typeof ps.requireSigninToViewContents === 'boolean') updates.requireSigninToViewContents = ps.requireSigninToViewContents;
 			if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
 			if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
 			if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts
index adcda30a7d..11839bce36 100644
--- a/packages/backend/src/server/api/endpoints/notes/show.ts
+++ b/packages/backend/src/server/api/endpoints/notes/show.ts
@@ -26,6 +26,12 @@ export const meta = {
 			code: 'NO_SUCH_NOTE',
 			id: '24fcbfc6-2e37-42b6-8388-c29b3861a08d',
 		},
+
+		signinRequired: {
+			message: 'Signin required.',
+			code: 'SIGNIN_REQUIRED',
+			id: '8e75455b-738c-471d-9f80-62693f33372e',
+		},
 	},
 } as const;
 
@@ -44,11 +50,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 		private getterService: GetterService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const note = await this.getterService.getNote(ps.noteId).catch(err => {
+			const note = await this.getterService.getNoteWithUser(ps.noteId).catch(err => {
 				if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
 				throw err;
 			});
 
+			if (note.user!.requireSigninToViewContents && me == null) {
+				throw new ApiError(meta.errors.signinRequired);
+			}
+
 			return await this.noteEntityService.pack(note, me, {
 				detail: true,
 			});
diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts
index 7fc11ba369..e9c334057e 100644
--- a/packages/backend/src/server/api/endpoints/users/notes.ts
+++ b/packages/backend/src/server/api/endpoints/users/notes.ts
@@ -42,6 +42,12 @@ export const meta = {
 			code: 'BOTH_WITH_REPLIES_AND_WITH_FILES',
 			id: '91c8cb9f-36ed-46e7-9ca2-7df96ed6e222',
 		},
+
+		signinRequired: {
+			message: 'Signin required.',
+			code: 'SIGNIN_REQUIRED',
+			id: 'd1588a9e-4b4d-4c07-807f-16f1486577a2',
+		},
 	},
 } as const;
 
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index c9c29e42a8..4860ef3e12 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -601,12 +601,15 @@ export class ClientServerService {
 		fastify.get<{ Params: { note: string; } }>('/notes/:note', async (request, reply) => {
 			vary(reply.raw, 'Accept');
 
-			const note = await this.notesRepository.findOneBy({
-				id: request.params.note,
-				visibility: In(['public', 'home']),
+			const note = await this.notesRepository.findOne({
+				where: {
+					id: request.params.note,
+					visibility: In(['public', 'home']),
+				},
+				relations: ['user'],
 			});
 
-			if (note) {
+			if (note && !note.user!.requireSigninToViewContents) {
 				const _note = await this.noteEntityService.pack(note);
 				const profile = await this.userProfilesRepository.findOneByOrFail({ userId: note.userId });
 				reply.header('Cache-Control', 'public, max-age=15');
diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue
index ccea7cd453..cc07175907 100644
--- a/packages/frontend/src/components/MkFollowButton.vue
+++ b/packages/frontend/src/components/MkFollowButton.vue
@@ -37,13 +37,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { onBeforeUnmount, onMounted, ref } from 'vue';
 import * as Misskey from 'misskey-js';
+import { host } from '@@/js/config.js';
 import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { useStream } from '@/stream.js';
 import { i18n } from '@/i18n.js';
 import { claimAchievement } from '@/scripts/achievements.js';
 import { pleaseLogin } from '@/scripts/please-login.js';
-import { host } from '@@/js/config.js';
 import { $i } from '@/account.js';
 import { defaultStore } from '@/store.js';
 
@@ -80,7 +80,7 @@ function onFollowChange(user: Misskey.entities.UserDetailed) {
 }
 
 async function onClick() {
-	pleaseLogin(undefined, { type: 'web', path: `/@${props.user.username}@${props.user.host ?? host}` });
+	pleaseLogin({ openOnRemote: { type: 'web', path: `/@${props.user.username}@${props.user.host ?? host}` } });
 
 	wait.value = true;
 
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 828ad2e872..425c4992da 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -419,7 +419,7 @@ if (!props.mock) {
 }
 
 function renote(viaKeyboard = false) {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 
 	const { menu } = getRenoteMenu({ note: note.value, renoteButton, mock: props.mock });
@@ -429,7 +429,7 @@ function renote(viaKeyboard = false) {
 }
 
 function reply(): void {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	if (props.mock) {
 		return;
 	}
@@ -442,7 +442,7 @@ function reply(): void {
 }
 
 function react(): void {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 	if (appearNote.value.reactionAcceptance === 'likeOnly') {
 		sound.playMisskeySfx('reaction');
@@ -563,7 +563,7 @@ function showRenoteMenu(): void {
 	}
 
 	if (isMyRenote) {
-		pleaseLogin(undefined, pleaseLoginContext.value);
+		pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 		os.popupMenu([
 			getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote),
 			{ type: 'divider' },
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 6d53685651..e0473dce5e 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -207,6 +207,7 @@ import { computed, inject, onMounted, provide, ref, shallowRef } from 'vue';
 import * as mfm from 'mfm-js';
 import * as Misskey from 'misskey-js';
 import { isLink } from '@@/js/is-link.js';
+import { host } from '@@/js/config.js';
 import MkNoteSub from '@/components/MkNoteSub.vue';
 import MkNoteSimple from '@/components/MkNoteSimple.vue';
 import MkReactionsViewer from '@/components/MkReactionsViewer.vue';
@@ -230,7 +231,6 @@ import { reactionPicker } from '@/scripts/reaction-picker.js';
 import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm.js';
 import { $i } from '@/account.js';
 import { i18n } from '@/i18n.js';
-import { host } from '@@/js/config.js';
 import { getNoteClipMenu, getNoteMenu, getRenoteMenu } from '@/scripts/get-note-menu.js';
 import { useNoteCapture } from '@/scripts/use-note-capture.js';
 import { deepClone } from '@/scripts/clone.js';
@@ -404,7 +404,7 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') {
 }
 
 function renote() {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 
 	const { menu } = getRenoteMenu({ note: note.value, renoteButton });
@@ -412,7 +412,7 @@ function renote() {
 }
 
 function reply(): void {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 	os.post({
 		reply: appearNote.value,
@@ -423,7 +423,7 @@ function reply(): void {
 }
 
 function react(): void {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 	if (appearNote.value.reactionAcceptance === 'likeOnly') {
 		sound.playMisskeySfx('reaction');
@@ -499,7 +499,7 @@ async function clip(): Promise<void> {
 
 function showRenoteMenu(): void {
 	if (!isMyRenote) return;
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	os.popupMenu([{
 		text: i18n.ts.unrenote,
 		icon: 'ti ti-trash',
diff --git a/packages/frontend/src/components/MkPoll.vue b/packages/frontend/src/components/MkPoll.vue
index 48913004e0..e70ac7ff1a 100644
--- a/packages/frontend/src/components/MkPoll.vue
+++ b/packages/frontend/src/components/MkPoll.vue
@@ -29,14 +29,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { computed, ref } from 'vue';
 import * as Misskey from 'misskey-js';
+import { host } from '@@/js/config.js';
+import { useInterval } from '@@/js/use-interval.js';
 import type { OpenOnRemoteOptions } from '@/scripts/please-login.js';
 import { sum } from '@/scripts/array.js';
 import { pleaseLogin } from '@/scripts/please-login.js';
 import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
-import { host } from '@@/js/config.js';
-import { useInterval } from '@@/js/use-interval.js';
 
 const props = defineProps<{
 	noteId: string;
@@ -85,7 +85,7 @@ if (props.poll.expiresAt) {
 const vote = async (id) => {
 	if (props.readOnly || closed.value || isVoted.value) return;
 
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 
 	const { canceled } = await os.confirm({
 		type: 'question',
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 4d41cf5bc0..07d91a0644 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -688,14 +688,16 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
 }
 
 export function post(props: Record<string, any> = {}): Promise<void> {
-	pleaseLogin(undefined, (props.initialText || props.initialNote ? {
-		type: 'share',
-		params: {
-			text: props.initialText ?? props.initialNote.text,
-			visibility: props.initialVisibility ?? props.initialNote?.visibility,
-			localOnly: (props.initialLocalOnly || props.initialNote?.localOnly) ? '1' : '0',
-		},
-	} : undefined));
+	pleaseLogin({
+		openOnRemote: (props.initialText || props.initialNote ? {
+			type: 'share',
+			params: {
+				text: props.initialText ?? props.initialNote.text,
+				visibility: props.initialVisibility ?? props.initialNote?.visibility,
+				localOnly: (props.initialLocalOnly || props.initialNote?.localOnly) ? '1' : '0',
+			},
+		} : undefined),
+	});
 
 	showMovedDialog();
 	return new Promise(resolve => {
diff --git a/packages/frontend/src/pages/not-found.vue b/packages/frontend/src/pages/not-found.vue
index 93a792c42f..6a2d01b6fa 100644
--- a/packages/frontend/src/pages/not-found.vue
+++ b/packages/frontend/src/pages/not-found.vue
@@ -24,7 +24,7 @@ const props = defineProps<{
 }>();
 
 if (props.showLoginPopup) {
-	pleaseLogin('/');
+	pleaseLogin({ path: '/' });
 }
 
 const headerActions = computed(() => []);
diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue
index 448244204d..454ee3c6bc 100644
--- a/packages/frontend/src/pages/note.vue
+++ b/packages/frontend/src/pages/note.vue
@@ -61,6 +61,7 @@ import { i18n } from '@/i18n.js';
 import { dateString } from '@/filters/date.js';
 import MkClipPreview from '@/components/MkClipPreview.vue';
 import { defaultStore } from '@/store.js';
+import { pleaseLogin } from '@/scripts/please-login.js';
 
 const props = defineProps<{
 	noteId: string;
@@ -128,6 +129,11 @@ function fetchNote() {
 			});
 		}
 	}).catch(err => {
+		if (err.id === '8e75455b-738c-471d-9f80-62693f33372e') {
+			pleaseLogin({
+				message: i18n.ts.thisContentsAreMarkedAsSigninRequiredByAuthor,
+			});
+		}
 		error.value = err;
 	});
 }
diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue
index d418be624e..e277dfad71 100644
--- a/packages/frontend/src/pages/settings/privacy.vue
+++ b/packages/frontend/src/pages/settings/privacy.vue
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<template #caption>{{ i18n.ts.noCrawleDescription }}</template>
 	</MkSwitch>
 	<MkSwitch v-model="preventAiLearning" @update:modelValue="save()">
-		{{ i18n.ts.preventAiLearning }}<span class="_beta">{{ i18n.ts.beta }}</span>
+		{{ i18n.ts.preventAiLearning }}
 		<template #caption>{{ i18n.ts.preventAiLearningDescription }}</template>
 	</MkSwitch>
 	<MkSwitch v-model="isExplorable" @update:modelValue="save()">
@@ -44,6 +44,21 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<template #caption>{{ i18n.ts.makeExplorableDescription }}</template>
 	</MkSwitch>
 
+	<FormSection>
+		<template #label>{{ i18n.ts.lockdown }}</template>
+
+		<div class="_gaps_m">
+			<MkSwitch v-model="requireSigninToViewContents" @update:modelValue="save()">
+				{{ i18n.ts._accountSettings.requireSigninToViewContents }}<span class="_beta">{{ i18n.ts.beta }}</span>
+				<template #caption>
+					<div>{{ i18n.ts._accountSettings.requireSigninToViewContentsDescription1 }}</div>
+					<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription2 }}</div>
+					<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription3 }}</div>
+				</template>
+			</MkSwitch>
+		</div>
+	</FormSection>
+
 	<FormSection>
 		<div class="_gaps_m">
 			<MkSwitch v-model="rememberNoteVisibility" @update:modelValue="save()">{{ i18n.ts.rememberNoteVisibility }}</MkSwitch>
@@ -90,6 +105,7 @@ const autoAcceptFollowed = ref($i.autoAcceptFollowed);
 const noCrawle = ref($i.noCrawle);
 const preventAiLearning = ref($i.preventAiLearning);
 const isExplorable = ref($i.isExplorable);
+const requireSigninToViewContents = ref($i.requireSigninToViewContents ?? false);
 const hideOnlineStatus = ref($i.hideOnlineStatus);
 const publicReactions = ref($i.publicReactions);
 const followingVisibility = ref($i.followingVisibility);
@@ -107,6 +123,7 @@ function save() {
 		noCrawle: !!noCrawle.value,
 		preventAiLearning: !!preventAiLearning.value,
 		isExplorable: !!isExplorable.value,
+		requireSigninToViewContents: !!requireSigninToViewContents.value,
 		hideOnlineStatus: !!hideOnlineStatus.value,
 		publicReactions: !!publicReactions.value,
 		followingVisibility: followingVisibility.value,
diff --git a/packages/frontend/src/scripts/please-login.ts b/packages/frontend/src/scripts/please-login.ts
index 18f05bc7f4..43dcf11936 100644
--- a/packages/frontend/src/scripts/please-login.ts
+++ b/packages/frontend/src/scripts/please-login.ts
@@ -44,17 +44,21 @@ export type OpenOnRemoteOptions = {
 	params: Record<string, string>;
 };
 
-export function pleaseLogin(path?: string, openOnRemote?: OpenOnRemoteOptions) {
+export function pleaseLogin(opts: {
+	path?: string;
+	message?: string;
+	openOnRemote?: OpenOnRemoteOptions;
+} = {}) {
 	if ($i) return;
 
 	const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
 		autoSet: true,
-		message: openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired,
-		openOnRemote,
+		message: opts.message ?? (opts.openOnRemote ? i18n.ts.signinOrContinueOnRemote : i18n.ts.signinRequired),
+		openOnRemote: opts.openOnRemote,
 	}, {
 		cancelled: () => {
-			if (path) {
-				window.location.href = path;
+			if (opts.path) {
+				window.location.href = opts.path;
 			}
 		},
 		closed: () => dispose(),
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 698c08826a..8f84aa37ff 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -3736,6 +3736,7 @@ export type components = {
         }[];
       isBot?: boolean;
       isCat?: boolean;
+      requireSigninToViewContents?: boolean;
       instance?: {
         name: string | null;
         softwareName: string | null;
@@ -19844,6 +19845,7 @@ export type operations = {
           autoAcceptFollowed?: boolean;
           noCrawle?: boolean;
           preventAiLearning?: boolean;
+          requireSigninToViewContents?: boolean;
           isBot?: boolean;
           isCat?: boolean;
           injectFeaturedNote?: boolean;

From 2f9c04b23ba357088ebb7c261c86387fd535e0ad Mon Sep 17 00:00:00 2001
From: Yuba <m.takuma@gmail.com>
Date: Mon, 21 Oct 2024 12:51:45 +0900
Subject: [PATCH 003/125] =?UTF-8?q?refs#10866=20=E6=8A=95=E7=A8=BF?=
 =?UTF-8?q?=E3=83=80=E3=82=A4=E3=82=A2=E3=83=AD=E3=82=B0=E3=81=A7Esc?=
 =?UTF-8?q?=E3=82=AD=E3=83=BC=E3=81=8C=E6=8A=BC=E3=81=95=E3=82=8C=E3=81=9F?=
 =?UTF-8?q?=E3=81=A8=E3=81=8DIME=E5=85=A5=E5=8A=9B=E4=B8=AD=E3=81=AA?=
 =?UTF-8?q?=E3=82=89=E3=83=80=E3=82=A4=E3=82=A2=E3=83=AD=E3=82=B0=E3=81=AF?=
 =?UTF-8?q?=E9=96=89=E3=81=98=E3=81=AA=E3=81=84=20(#14787)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                                    |  1 +
 packages/frontend/src/components/MkPostForm.vue | 14 +++++++++++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d8c8ded3a..3878b52cb7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
+- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )  
 
 ### Server
 -
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 76a6e4212a..b6b80082d3 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -65,10 +65,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 	</div>
 	<MkInfo v-if="hasNotSpecifiedMentions" warn :class="$style.hasNotSpecifiedMentions">{{ i18n.ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ i18n.ts.add }}</button></MkInfo>
-	<input v-show="useCw" ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown">
+	<input v-show="useCw" ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown" @keyup="onKeyup" @compositionend="onCompositionEnd">
 	<div :class="[$style.textOuter, { [$style.withCw]: useCw }]">
 		<div v-if="channel" :class="$style.colorBar" :style="{ background: channel.color }"></div>
-		<textarea ref="textareaEl" v-model="text" :class="[$style.text]" :disabled="posting || posted" :readonly="textAreaReadOnly" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/>
+		<textarea ref="textareaEl" v-model="text" :class="[$style.text]" :disabled="posting || posted" :readonly="textAreaReadOnly" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @keyup="onKeyup" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/>
 		<div v-if="maxTextLength - textLength < 100" :class="['_acrylic', $style.textCount, { [$style.textOver]: textLength > maxTextLength }]">{{ maxTextLength - textLength }}</div>
 	</div>
 	<input v-show="withHashtags" ref="hashtagsInputEl" v-model="hashtags" :class="$style.hashtags" :placeholder="i18n.ts.hashtags" list="hashtags">
@@ -201,6 +201,7 @@ const recentHashtags = ref(JSON.parse(miLocalStorage.getItem('hashtags') ?? '[]'
 const imeText = ref('');
 const showingOptions = ref(false);
 const textAreaReadOnly = ref(false);
+const justEndedComposition = ref(false);
 
 const draftKey = computed((): string => {
 	let key = props.channel ? `channel:${props.channel.id}` : '';
@@ -573,7 +574,13 @@ function clear() {
 function onKeydown(ev: KeyboardEvent) {
 	if (ev.key === 'Enter' && (ev.ctrlKey || ev.metaKey) && canPost.value) post();
 
-	if (ev.key === 'Escape') emit('esc');
+	// justEndedComposition.value is for Safari, which keyDown occurs after compositionend.
+	// ev.isComposing is for another browsers.
+	if (ev.key === 'Escape' && !justEndedComposition.value && !ev.isComposing) emit('esc');
+}
+
+function onKeyup(ev: KeyboardEvent) {
+	justEndedComposition.value = false;
 }
 
 function onCompositionUpdate(ev: CompositionEvent) {
@@ -582,6 +589,7 @@ function onCompositionUpdate(ev: CompositionEvent) {
 
 function onCompositionEnd(ev: CompositionEvent) {
 	imeText.value = '';
+	justEndedComposition.value = true;
 }
 
 async function onPaste(ev: ClipboardEvent) {

From 5f12bc515d8ff59183ac465a815ee3885d79b8c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 21 Oct 2024 13:11:11 +0900
Subject: [PATCH 004/125] Update CHANGELOG.md

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3878b52cb7..6b12ed5991 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,10 +7,10 @@
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
 - Enhance: ドライブでソートができるように 
+- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )  
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
-- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )  
 
 ### Server
 -

From bc1fce9af6e5a29c660174a16246c95624a68418 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 21 Oct 2024 13:22:21 +0900
Subject: [PATCH 005/125] =?UTF-8?q?fix(frontend):=20=E3=83=87=E3=83=83?=
 =?UTF-8?q?=E3=82=AD=E3=81=AE=E3=82=BF=E3=82=A4=E3=83=A0=E3=83=A9=E3=82=A4?=
 =?UTF-8?q?=E3=83=B3=E3=82=AB=E3=83=A9=E3=83=A0=E3=81=A7withSensitive?=
 =?UTF-8?q?=E3=81=8C=E5=88=A9=E7=94=A8=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84?=
 =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#14772)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): デッキのタイムラインカラムでwithSensitiveが利用できない問題を修正

* Update Changelog

* Update Changelog

* Update packages/frontend/src/ui/deck/tl-column.vue
---
 CHANGELOG.md                                    |  1 +
 packages/frontend/src/components/MkNote.vue     |  3 ++-
 packages/frontend/src/components/MkTimeline.vue |  5 +++++
 packages/frontend/src/pages/timeline.vue        |  6 +-----
 packages/frontend/src/ui/deck/deck-store.ts     |  1 +
 packages/frontend/src/ui/deck/tl-column.vue     | 12 ++++++++++++
 6 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b12ed5991..421237c32d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
+- Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
 
 ### Server
 -
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 425c4992da..be1339ecc4 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -227,6 +227,7 @@ const emit = defineEmits<{
 }>();
 
 const inTimeline = inject<boolean>('inTimeline', false);
+const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(false));
 const inChannel = inject('inChannel', null);
 const currentClip = inject<Ref<Misskey.entities.Clip> | null>('currentClip', null);
 
@@ -299,7 +300,7 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
 
 	if (checkOnly) return false;
 
-	if (inTimeline && !defaultStore.state.tl.filter.withSensitive && noteToCheck.files?.some((v) => v.isSensitive)) return 'sensitiveMute';
+	if (inTimeline && !tl_withSensitive.value && noteToCheck.files?.some((v) => v.isSensitive)) return 'sensitiveMute';
 	return false;
 }
 
diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue
index ca87316bf7..226faac291 100644
--- a/packages/frontend/src/components/MkTimeline.vue
+++ b/packages/frontend/src/components/MkTimeline.vue
@@ -38,6 +38,7 @@ const props = withDefaults(defineProps<{
 	sound?: boolean;
 	withRenotes?: boolean;
 	withReplies?: boolean;
+	withSensitive?: boolean;
 	onlyFiles?: boolean;
 }>(), {
 	withRenotes: true,
@@ -51,6 +52,7 @@ const emit = defineEmits<{
 }>();
 
 provide('inTimeline', true);
+provide('tl_withSensitive', computed(() => props.withSensitive));
 provide('inChannel', computed(() => props.src === 'channel'));
 
 type TimelineQueryType = {
@@ -248,6 +250,9 @@ function refreshEndpointAndChannel() {
 // IDが切り替わったら切り替え先のTLを表示させたい
 watch(() => [props.list, props.antenna, props.channel, props.role, props.withRenotes], refreshEndpointAndChannel);
 
+// withSensitiveはクライアントで完結する処理のため、単にリロードするだけでOK
+watch(() => props.withSensitive, reloadTimeline);
+
 // 初回表示用
 refreshEndpointAndChannel();
 
diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue
index 4feba54104..7a3195304b 100644
--- a/packages/frontend/src/pages/timeline.vue
+++ b/packages/frontend/src/pages/timeline.vue
@@ -22,6 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 						:list="src.split(':')[1]"
 						:withRenotes="withRenotes"
 						:withReplies="withReplies"
+						:withSensitive="withSensitive"
 						:onlyFiles="onlyFiles"
 						:sound="true"
 						@queue="queueUpdated"
@@ -121,11 +122,6 @@ watch(src, () => {
 	queue.value = 0;
 });
 
-watch(withSensitive, () => {
-	// これだけはクライアント側で完結する処理なので手動でリロード
-	tlComponent.value?.reloadTimeline();
-});
-
 function queueUpdated(q: number): void {
 	queue.value = q;
 }
diff --git a/packages/frontend/src/ui/deck/deck-store.ts b/packages/frontend/src/ui/deck/deck-store.ts
index eb587554b9..3186982349 100644
--- a/packages/frontend/src/ui/deck/deck-store.ts
+++ b/packages/frontend/src/ui/deck/deck-store.ts
@@ -49,6 +49,7 @@ export type Column = {
 	tl?: BasicTimelineType;
 	withRenotes?: boolean;
 	withReplies?: boolean;
+	withSensitive?: boolean;
 	onlyFiles?: boolean;
 	soundSetting: SoundStore;
 };
diff --git a/packages/frontend/src/ui/deck/tl-column.vue b/packages/frontend/src/ui/deck/tl-column.vue
index 01da92f731..74c4fb504b 100644
--- a/packages/frontend/src/ui/deck/tl-column.vue
+++ b/packages/frontend/src/ui/deck/tl-column.vue
@@ -24,6 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		:src="column.tl"
 		:withRenotes="withRenotes"
 		:withReplies="withReplies"
+		:withSensitive="withSensitive"
 		:onlyFiles="onlyFiles"
 		@note="onNote"
 	/>
@@ -54,6 +55,7 @@ const timeline = shallowRef<InstanceType<typeof MkTimeline>>();
 const soundSetting = ref<SoundStore>(props.column.soundSetting ?? { type: null, volume: 1 });
 const withRenotes = ref(props.column.withRenotes ?? true);
 const withReplies = ref(props.column.withReplies ?? false);
+const withSensitive = ref(props.column.withSensitive ?? true);
 const onlyFiles = ref(props.column.onlyFiles ?? false);
 
 watch(withRenotes, v => {
@@ -68,6 +70,12 @@ watch(withReplies, v => {
 	});
 });
 
+watch(withSensitive, v => {
+	updateColumn(props.column.id, {
+		withSensitive: v,
+	});
+});
+
 watch(onlyFiles, v => {
 	updateColumn(props.column.id, {
 		onlyFiles: v,
@@ -144,6 +152,10 @@ const menu = computed<MenuItem[]>(() => {
 		text: i18n.ts.fileAttachedOnly,
 		ref: onlyFiles,
 		disabled: hasWithReplies(props.column.tl) ? withReplies : false,
+	}, {
+		type: 'switch',
+		text: i18n.ts.withSensitive,
+		ref: withSensitive,
 	});
 
 	return menuItems;

From 9d0f7eeb9c20fed9921c806dd007496b1d76e7cc Mon Sep 17 00:00:00 2001
From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com>
Date: Mon, 21 Oct 2024 15:12:28 +0900
Subject: [PATCH 006/125] =?UTF-8?q?docs:=20ActivityPub=E5=B1=A4=E3=81=AE?=
 =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=82=92=E5=90=AB=E3=82=80=E5=A0=B4=E5=90=88?=
 =?UTF-8?q?=E3=81=AB=E3=82=84=E3=82=8B=E3=81=B9=E3=81=8D=E3=81=93=E3=81=A8?=
 =?UTF-8?q?=E3=82=92=E6=98=8E=E6=96=87=E5=8C=96=20(#14812)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CONTRIBUTING.md | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fc72cf42ea..3bc0faf96d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -64,6 +64,22 @@ Thank you for your PR! Before creating a PR, please check the following:
 
 Thanks for your cooperation 🤗
 
+### Additional things for ActivityPub payload changes
+*This section is specific to misskey-dev implementation. Other fork or implementation may take different way. A significant difference is that non-"misskey-dev" extension is not described in the misskey-hub's document.*
+
+If PR includes changes to ActivityPub payload, please reflect it in [misskey-hub's document](https://github.com/misskey-dev/misskey-hub-next/blob/master/content/ns.md) by sending PR.
+
+The name of purporsed extension property (referred as "extended property" in later) to ActivityPub shall be prefixed by `_misskey_`. (i.e. `_misskey_quote`)
+
+The extended property in `packages/backend/src/core/activitypub/type.ts` **must** be declared as optional because ActivityPub payloads that comes from older Misskey or other implementation may not contain it.
+
+The extended property must be included in the context definition. Context is defined in `packages/backend/src/core/activitypub/misc/contexts.ts`.
+The key shall be same as the name of extended property, and the value shall be same as "short IRI".
+
+"Short IRI" is defined in misskey-hub's document, but usually takes form of `misskey:<name of extended property>`. (i.e. `misskey:_misskey_quote`)
+
+One should not add property that has defined before by other implementation, or add custom variant value to "well-known" property.
+
 ## Reviewers guide
 Be willing to comment on the good points and not just the things you want fixed 💯
 

From c4f1ca2fd9cb1c9b6035f4efb3fa9e46f7be9d64 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 21 Oct 2024 19:14:02 +0900
Subject: [PATCH 007/125] =?UTF-8?q?fix(frontend):=20MkSelect=E3=81=A7model?=
 =?UTF-8?q?Value=E3=81=8C=E6=9B=B4=E6=96=B0=E3=81=95=E3=82=8C=E3=81=AA?=
 =?UTF-8?q?=E3=81=84=E9=99=90=E3=82=8A=E5=80=A4=E3=82=92=E6=9B=B4=E6=96=B0?=
 =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/components/MkSelect.vue | 80 +++++++++----------
 1 file changed, 38 insertions(+), 42 deletions(-)

diff --git a/packages/frontend/src/components/MkSelect.vue b/packages/frontend/src/components/MkSelect.vue
index a2ec384ac5..8bd02000e6 100644
--- a/packages/frontend/src/components/MkSelect.vue
+++ b/packages/frontend/src/components/MkSelect.vue
@@ -16,9 +16,8 @@ SPDX-License-Identifier: AGPL-3.0-only
 		@keydown.space.enter="show"
 	>
 		<div ref="prefixEl" :class="$style.prefix"><slot name="prefix"></slot></div>
-		<select
+		<div
 			ref="inputEl"
-			v-model="v"
 			v-adaptive-border
 			tabindex="-1"
 			:class="$style.inputCore"
@@ -26,27 +25,25 @@ SPDX-License-Identifier: AGPL-3.0-only
 			:required="required"
 			:readonly="readonly"
 			:placeholder="placeholder"
-			@input="onInput"
 			@mousedown.prevent="() => {}"
 			@keydown.prevent="() => {}"
 		>
-			<slot></slot>
-		</select>
+			<div style="pointer-events: none;">{{ currentValueText ?? '' }}</div>
+			<div style="display: none;">
+				<slot></slot>
+			</div>
+		</div>
 		<div ref="suffixEl" :class="$style.suffix"><i class="ti ti-chevron-down" :class="[$style.chevron, { [$style.chevronOpening]: opening }]"></i></div>
 	</div>
 	<div :class="$style.caption"><slot name="caption"></slot></div>
-
-	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
 </div>
 </template>
 
 <script lang="ts" setup>
 import { onMounted, nextTick, ref, watch, computed, toRefs, VNode, useSlots, VNodeChild } from 'vue';
-import MkButton from '@/components/MkButton.vue';
-import * as os from '@/os.js';
 import { useInterval } from '@@/js/use-interval.js';
-import { i18n } from '@/i18n.js';
 import type { MenuItem } from '@/types/menu.js';
+import * as os from '@/os.js';
 
 const props = defineProps<{
 	modelValue: string | null;
@@ -56,25 +53,20 @@ const props = defineProps<{
 	placeholder?: string;
 	autofocus?: boolean;
 	inline?: boolean;
-	manualSave?: boolean;
 	small?: boolean;
 	large?: boolean;
 }>();
 
 const emit = defineEmits<{
-	(ev: 'changeByUser', value: string | null): void;
-	(ev: 'update:modelValue', value: string | null): void;
+	(ev: 'update:modelValue', value: string | number | null): void;
 }>();
 
 const slots = useSlots();
 
 const { modelValue, autofocus } = toRefs(props);
-const v = ref(modelValue.value);
 const focused = ref(false);
 const opening = ref(false);
-const changed = ref(false);
-const invalid = ref(false);
-const filled = computed(() => v.value !== '' && v.value != null);
+const currentValueText = ref<string | null>(null);
 const inputEl = ref<HTMLObjectElement | null>(null);
 const prefixEl = ref<HTMLElement | null>(null);
 const suffixEl = ref<HTMLElement | null>(null);
@@ -85,26 +77,6 @@ const height =
 	36;
 
 const focus = () => container.value?.focus();
-const onInput = (ev) => {
-	changed.value = true;
-};
-
-const updated = () => {
-	changed.value = false;
-	emit('update:modelValue', v.value);
-};
-
-watch(modelValue, newValue => {
-	v.value = newValue;
-});
-
-watch(v, () => {
-	if (!props.manualSave) {
-		updated();
-	}
-
-	invalid.value = inputEl.value?.validity.badInput ?? true;
-});
 
 // このコンポーネントが作成された時、非表示状態である場合がある
 // 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
@@ -134,6 +106,31 @@ onMounted(() => {
 	});
 });
 
+watch(modelValue, () => {
+	const scanOptions = (options: VNodeChild[]) => {
+		for (const vnode of options) {
+			if (typeof vnode !== 'object' || vnode === null || Array.isArray(vnode)) continue;
+			if (vnode.type === 'optgroup') {
+				const optgroup = vnode;
+				if (Array.isArray(optgroup.children)) scanOptions(optgroup.children);
+			} else if (Array.isArray(vnode.children)) { // 何故かフラグメントになってくることがある
+				const fragment = vnode;
+				if (Array.isArray(fragment.children)) scanOptions(fragment.children);
+			} else if (vnode.props == null) { // v-if で条件が false のときにこうなる
+				// nop?
+			} else {
+				const option = vnode;
+				if (option.props?.value === modelValue.value) {
+					currentValueText.value = option.children as string;
+					break;
+				}
+			}
+		}
+	};
+
+	scanOptions(slots.default!());
+}, { immediate: true });
+
 function show() {
 	if (opening.value) return;
 	focus();
@@ -146,11 +143,9 @@ function show() {
 	const pushOption = (option: VNode) => {
 		menu.push({
 			text: option.children as string,
-			active: computed(() => v.value === option.props?.value),
+			active: computed(() => modelValue.value === option.props?.value),
 			action: () => {
-				v.value = option.props?.value;
-				changed.value = true;
-				emit('changeByUser', v.value);
+				emit('update:modelValue', option.props?.value);
 			},
 		});
 	};
@@ -248,7 +243,8 @@ function show() {
 .inputCore {
 	appearance: none;
 	-webkit-appearance: none;
-	display: block;
+	display: flex;
+	align-items: center;
 	height: v-bind("height + 'px'");
 	width: 100%;
 	margin: 0;

From 70b2a8f72e7efc488b8c286e2da8cffa11331eab Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 21 Oct 2024 19:59:20 +0900
Subject: [PATCH 008/125] =?UTF-8?q?fix(frontend):=20/i=E3=81=AE=E3=83=AC?=
 =?UTF-8?q?=E3=82=B9=E3=83=9D=E3=83=B3=E3=82=B9=E3=81=AB=E5=90=AB=E3=81=BE?=
 =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=84=E3=83=97=E3=83=AD=E3=83=91=E3=83=86?=
 =?UTF-8?q?=E3=82=A3=E3=81=8C=E6=B6=88=E3=81=88=E3=81=9A=E3=81=AB=E6=AE=8B?=
 =?UTF-8?q?=E3=82=8A=E7=B6=9A=E3=81=91=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/account.ts              | 17 ++++++++++---
 packages/frontend/src/boot/main-boot.ts       | 24 +++++++++----------
 .../src/components/MkAnnouncementDialog.vue   |  4 ++--
 packages/frontend/src/pages/announcement.vue  |  4 ++--
 packages/frontend/src/pages/announcements.vue |  4 ++--
 packages/frontend/src/pages/settings/2fa.vue  |  4 ++--
 6 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts
index b91834b94f..f5a74a0581 100644
--- a/packages/frontend/src/account.ts
+++ b/packages/frontend/src/account.ts
@@ -5,12 +5,12 @@
 
 import { defineAsyncComponent, reactive, ref } from 'vue';
 import * as Misskey from 'misskey-js';
+import { apiUrl } from '@@/js/config.js';
+import type { MenuItem, MenuButton } from '@/types/menu.js';
 import { showSuspendedDialog } from '@/scripts/show-suspended-dialog.js';
 import { i18n } from '@/i18n.js';
 import { miLocalStorage } from '@/local-storage.js';
-import type { MenuItem, MenuButton } from '@/types/menu.js';
 import { del, get, set } from '@/scripts/idb-proxy.js';
-import { apiUrl } from '@@/js/config.js';
 import { waiting, popup, popupMenu, success, alert } from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { unisonReload, reloadChannel } from '@/scripts/unison-reload.js';
@@ -165,7 +165,18 @@ function fetchAccount(token: string, id?: string, forceShowDialog?: boolean): Pr
 	});
 }
 
-export function updateAccount(accountData: Partial<Account>) {
+export function updateAccount(accountData: Account) {
+	if (!$i) return;
+	for (const key of Object.keys($i)) {
+		delete $i[key];
+	}
+	for (const [key, value] of Object.entries(accountData)) {
+		$i[key] = value;
+	}
+	miLocalStorage.setItem('account', JSON.stringify($i));
+}
+
+export function updateAccountPartial(accountData: Partial<Account>) {
 	if (!$i) return;
 	for (const [key, value] of Object.entries(accountData)) {
 		$i[key] = value;
diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts
index 76459ab330..2392381b64 100644
--- a/packages/frontend/src/boot/main-boot.ts
+++ b/packages/frontend/src/boot/main-boot.ts
@@ -4,14 +4,14 @@
  */
 
 import { createApp, defineAsyncComponent, markRaw } from 'vue';
+import { ui } from '@@/js/config.js';
 import { common } from './common.js';
 import type * as Misskey from 'misskey-js';
-import { ui } from '@@/js/config.js';
 import { i18n } from '@/i18n.js';
 import { alert, confirm, popup, post, toast } from '@/os.js';
 import { useStream } from '@/stream.js';
 import * as sound from '@/scripts/sound.js';
-import { $i, signout, updateAccount } from '@/account.js';
+import { $i, signout, updateAccountPartial } from '@/account.js';
 import { instance } from '@/instance.js';
 import { ColdDeviceStorage, defaultStore } from '@/store.js';
 import { reactionPicker } from '@/scripts/reaction-picker.js';
@@ -291,11 +291,11 @@ export async function mainBoot() {
 
 		// 自分の情報が更新されたとき
 		main.on('meUpdated', i => {
-			updateAccount(i);
+			updateAccountPartial(i);
 		});
 
 		main.on('readAllNotifications', () => {
-			updateAccount({
+			updateAccountPartial({
 				hasUnreadNotification: false,
 				unreadNotificationsCount: 0,
 			});
@@ -303,39 +303,39 @@ export async function mainBoot() {
 
 		main.on('unreadNotification', () => {
 			const unreadNotificationsCount = ($i?.unreadNotificationsCount ?? 0) + 1;
-			updateAccount({
+			updateAccountPartial({
 				hasUnreadNotification: true,
 				unreadNotificationsCount,
 			});
 		});
 
 		main.on('unreadMention', () => {
-			updateAccount({ hasUnreadMentions: true });
+			updateAccountPartial({ hasUnreadMentions: true });
 		});
 
 		main.on('readAllUnreadMentions', () => {
-			updateAccount({ hasUnreadMentions: false });
+			updateAccountPartial({ hasUnreadMentions: false });
 		});
 
 		main.on('unreadSpecifiedNote', () => {
-			updateAccount({ hasUnreadSpecifiedNotes: true });
+			updateAccountPartial({ hasUnreadSpecifiedNotes: true });
 		});
 
 		main.on('readAllUnreadSpecifiedNotes', () => {
-			updateAccount({ hasUnreadSpecifiedNotes: false });
+			updateAccountPartial({ hasUnreadSpecifiedNotes: false });
 		});
 
 		main.on('readAllAntennas', () => {
-			updateAccount({ hasUnreadAntenna: false });
+			updateAccountPartial({ hasUnreadAntenna: false });
 		});
 
 		main.on('unreadAntenna', () => {
-			updateAccount({ hasUnreadAntenna: true });
+			updateAccountPartial({ hasUnreadAntenna: true });
 			sound.playMisskeySfx('antenna');
 		});
 
 		main.on('readAllAnnouncements', () => {
-			updateAccount({ hasUnreadAnnouncement: false });
+			updateAccountPartial({ hasUnreadAnnouncement: false });
 		});
 
 		// 個人宛てお知らせが発行されたとき
diff --git a/packages/frontend/src/components/MkAnnouncementDialog.vue b/packages/frontend/src/components/MkAnnouncementDialog.vue
index 1adb244c9e..3045a47585 100644
--- a/packages/frontend/src/components/MkAnnouncementDialog.vue
+++ b/packages/frontend/src/components/MkAnnouncementDialog.vue
@@ -29,7 +29,7 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
 import MkModal from '@/components/MkModal.vue';
 import MkButton from '@/components/MkButton.vue';
 import { i18n } from '@/i18n.js';
-import { $i, updateAccount } from '@/account.js';
+import { $i, updateAccountPartial } from '@/account.js';
 
 const props = withDefaults(defineProps<{
 	announcement: Misskey.entities.Announcement;
@@ -51,7 +51,7 @@ async function ok() {
 
 	modal.value?.close();
 	misskeyApi('i/read-announcement', { announcementId: props.announcement.id });
-	updateAccount({
+	updateAccountPartial({
 		unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== props.announcement.id),
 	});
 }
diff --git a/packages/frontend/src/pages/announcement.vue b/packages/frontend/src/pages/announcement.vue
index 3840e6a494..01c29cf02d 100644
--- a/packages/frontend/src/pages/announcement.vue
+++ b/packages/frontend/src/pages/announcement.vue
@@ -55,7 +55,7 @@ import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { $i, updateAccount } from '@/account.js';
+import { $i, updateAccountPartial } from '@/account.js';
 import { defaultStore } from '@/store.js';
 
 const props = defineProps<{
@@ -90,7 +90,7 @@ async function read(target: Misskey.entities.Announcement): Promise<void> {
 	target.isRead = true;
 	await misskeyApi('i/read-announcement', { announcementId: target.id });
 	if ($i) {
-		updateAccount({
+		updateAccountPartial({
 			unreadAnnouncements: $i.unreadAnnouncements.filter((a: { id: string; }) => a.id !== target.id),
 		});
 	}
diff --git a/packages/frontend/src/pages/announcements.vue b/packages/frontend/src/pages/announcements.vue
index 688a542988..75c0fd98dc 100644
--- a/packages/frontend/src/pages/announcements.vue
+++ b/packages/frontend/src/pages/announcements.vue
@@ -56,7 +56,7 @@ import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { $i, updateAccount } from '@/account.js';
+import { $i, updateAccountPartial } from '@/account.js';
 
 const paginationCurrent = {
 	endpoint: 'announcements' as const,
@@ -94,7 +94,7 @@ async function read(target) {
 		return a;
 	});
 	misskeyApi('i/read-announcement', { announcementId: target.id });
-	updateAccount({
+	updateAccountPartial({
 		unreadAnnouncements: $i!.unreadAnnouncements.filter(a => a.id !== target.id),
 	});
 }
diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue
index a76b748ac1..776f59dda3 100644
--- a/packages/frontend/src/pages/settings/2fa.vue
+++ b/packages/frontend/src/pages/settings/2fa.vue
@@ -84,7 +84,7 @@ import FormSection from '@/components/form/section.vue';
 import MkFolder from '@/components/MkFolder.vue';
 import MkLink from '@/components/MkLink.vue';
 import * as os from '@/os.js';
-import { signinRequired, updateAccount } from '@/account.js';
+import { signinRequired, updateAccountPartial } from '@/account.js';
 import { i18n } from '@/i18n.js';
 
 const $i = signinRequired();
@@ -123,7 +123,7 @@ async function unregisterTOTP(): Promise<void> {
 		password: auth.result.password,
 		token: auth.result.token,
 	}).then(res => {
-		updateAccount({
+		updateAccountPartial({
 			twoFactorEnabled: false,
 		});
 	}).catch(error => {

From 952fec5665ce0712a78f3ee68f5c46554426dfb4 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 22 Oct 2024 17:08:53 +0900
Subject: [PATCH 009/125] =?UTF-8?q?feat:=20=E9=81=8E=E5=8E=BB=E3=81=AE?=
 =?UTF-8?q?=E3=83=8E=E3=83=BC=E3=83=88=E3=82=92=E9=9D=9E=E5=85=AC=E9=96=8B?=
 =?UTF-8?q?=E5=8C=96/=E3=83=95=E3=82=A9=E3=83=AD=E3=83=AF=E3=83=BC?=
 =?UTF-8?q?=E3=81=AE=E3=81=BF=E8=A1=A8=E7=A4=BA=E5=8F=AF=E8=83=BD=E3=81=AB?=
 =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E6=A9=9F=E8=83=BD=20(#14814)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* wip

* Update CHANGELOG.md

* wip

* wip

* wip

* Update privacy.vue

* wip
---
 CHANGELOG.md                                  |   1 +
 locales/index.d.ts                            |  42 ++++++-
 locales/ja-JP.yml                             |  12 +-
 .../1729486255072-makeNotesHiddenBefore.js    |  18 +++
 .../backend/src/core/WebhookTestService.ts    |   2 +
 .../src/core/activitypub/ApRendererService.ts |   2 +
 .../src/core/activitypub/misc/contexts.ts     |   2 +
 .../activitypub/models/ApPersonService.ts     |   2 +
 packages/backend/src/core/activitypub/type.ts |   2 +
 .../src/core/entities/NoteEntityService.ts    | 101 ++++++++++------
 .../src/core/entities/UserEntityService.ts    |   2 +
 packages/backend/src/models/User.ts           |  12 ++
 .../backend/src/models/json-schema/user.ts    |   8 ++
 .../src/server/api/endpoints/i/update.ts      |   4 +
 packages/frontend/src/components/MkSelect.vue |   2 +-
 .../frontend/src/pages/settings/privacy.vue   | 109 +++++++++++++++++-
 packages/misskey-js/src/autogen/types.ts      |   4 +
 17 files changed, 282 insertions(+), 43 deletions(-)
 create mode 100644 packages/backend/migration/1729486255072-makeNotesHiddenBefore.js

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 421237c32d..d56abb29b4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように
+- Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
 
 ### Client
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  
diff --git a/locales/index.d.ts b/locales/index.d.ts
index e002540307..8350297a79 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -3806,6 +3806,18 @@ export interface Locale extends ILocale {
      * 1ヶ月
      */
     "oneMonth": string;
+    /**
+     * 3ヶ月
+     */
+    "threeMonths": string;
+    /**
+     * 1年
+     */
+    "oneYear": string;
+    /**
+     * 3日
+     */
+    "threeDays": string;
     /**
      * 反映されるまで時間がかかる場合があります。
      */
@@ -5204,7 +5216,7 @@ export interface Locale extends ILocale {
          */
         "requireSigninToViewContents": string;
         /**
-         * あなたが作成した全てのノートなどのコンテンツを表示するのにログインを必須にします。クローラーから情報を収集されるのを防ぐ効果が期待できます。
+         * あなたが作成した全てのノートなどのコンテンツを表示するのにログインを必須にします。クローラーに情報が収集されるのを防ぐ効果が期待できます。
          */
         "requireSigninToViewContentsDescription1": string;
         /**
@@ -5215,6 +5227,34 @@ export interface Locale extends ILocale {
          * リモートサーバーに連合されたコンテンツでは、これらの制限が適用されない場合があります。
          */
         "requireSigninToViewContentsDescription3": string;
+        /**
+         * 過去のノートをフォロワーのみ表示可能にする
+         */
+        "makeNotesFollowersOnlyBefore": string;
+        /**
+         * この機能が有効になっている間、設定された日時より過去、または設定された時間を経過しているノートがフォロワーのみ表示可能になります。無効に戻すと、ノートの公開状態も元に戻ります。
+         */
+        "makeNotesFollowersOnlyBeforeDescription": string;
+        /**
+         * 過去のノートを非公開化する
+         */
+        "makeNotesHiddenBefore": string;
+        /**
+         * この機能が有効になっている間、設定された日時より過去、または設定された時間を経過しているノートが自分のみ表示可能(非公開化)になります。無効に戻すと、ノートの公開状態も元に戻ります。
+         */
+        "makeNotesHiddenBeforeDescription": string;
+        /**
+         * リモートサーバーに連合されたノートには効果が及ばない場合があります。
+         */
+        "mayNotEffectForFederatedNotes": string;
+        /**
+         * 指定した時間を経過しているノート
+         */
+        "notesHavePassedSpecifiedPeriod": string;
+        /**
+         * 指定した日時より前のノート
+         */
+        "notesOlderThanSpecifiedDateAndTime": string;
     };
     "_abuseUserReport": {
         /**
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index f3f7e5c77f..93ed879a08 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -947,6 +947,9 @@ oneHour: "1時間"
 oneDay: "1日"
 oneWeek: "1週間"
 oneMonth: "1ヶ月"
+threeMonths: "3ヶ月"
+oneYear: "1年"
+threeDays: "3日"
 reflectMayTakeTime: "反映されるまで時間がかかる場合があります。"
 failedToFetchAccountInformation: "アカウント情報の取得に失敗しました"
 rateLimitExceeded: "レート制限を超えました"
@@ -1298,9 +1301,16 @@ lockdown: "ロックダウン"
 
 _accountSettings:
   requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
-  requireSigninToViewContentsDescription1: "あなたが作成した全てのノートなどのコンテンツを表示するのにログインを必須にします。クローラーから情報を収集されるのを防ぐ効果が期待できます。"
+  requireSigninToViewContentsDescription1: "あなたが作成した全てのノートなどのコンテンツを表示するのにログインを必須にします。クローラーに情報が収集されるのを防ぐ効果が期待できます。"
   requireSigninToViewContentsDescription2: "URLプレビュー(OGP)、Webページへの埋め込み、ノートの引用に対応していないサーバーからの表示も不可になります。"
   requireSigninToViewContentsDescription3: "リモートサーバーに連合されたコンテンツでは、これらの制限が適用されない場合があります。"
+  makeNotesFollowersOnlyBefore: "過去のノートをフォロワーのみ表示可能にする"
+  makeNotesFollowersOnlyBeforeDescription: "この機能が有効になっている間、設定された日時より過去、または設定された時間を経過しているノートがフォロワーのみ表示可能になります。無効に戻すと、ノートの公開状態も元に戻ります。"
+  makeNotesHiddenBefore: "過去のノートを非公開化する"
+  makeNotesHiddenBeforeDescription: "この機能が有効になっている間、設定された日時より過去、または設定された時間を経過しているノートが自分のみ表示可能(非公開化)になります。無効に戻すと、ノートの公開状態も元に戻ります。"
+  mayNotEffectForFederatedNotes: "リモートサーバーに連合されたノートには効果が及ばない場合があります。"
+  notesHavePassedSpecifiedPeriod: "指定した時間を経過しているノート"
+  notesOlderThanSpecifiedDateAndTime: "指定した日時より前のノート"
 
 _abuseUserReport:
   forward: "転送"
diff --git a/packages/backend/migration/1729486255072-makeNotesHiddenBefore.js b/packages/backend/migration/1729486255072-makeNotesHiddenBefore.js
new file mode 100644
index 0000000000..5fe4886b04
--- /dev/null
+++ b/packages/backend/migration/1729486255072-makeNotesHiddenBefore.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class MakeNotesHiddenBefore1729486255072 {
+    name = 'MakeNotesHiddenBefore1729486255072'
+
+    async up(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "user" ADD "makeNotesFollowersOnlyBefore" integer`);
+        await queryRunner.query(`ALTER TABLE "user" ADD "makeNotesHiddenBefore" integer`);
+    }
+
+    async down(queryRunner) {
+        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "makeNotesHiddenBefore"`);
+        await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "makeNotesFollowersOnlyBefore"`);
+    }
+}
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index 254d961040..c826a28963 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -84,6 +84,8 @@ function generateDummyUser(override?: Partial<MiUser>): MiUser {
 		isHibernated: false,
 		isDeleted: false,
 		requireSigninToViewContents: false,
+		makeNotesFollowersOnlyBefore: null,
+		makeNotesHiddenBefore: null,
 		emojis: [],
 		score: 0,
 		host: null,
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index 8235d7ba30..5617a29bab 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -496,6 +496,8 @@ export class ApRendererService {
 			_misskey_summary: profile.description,
 			_misskey_followedMessage: profile.followedMessage,
 			_misskey_requireSigninToViewContents: user.requireSigninToViewContents,
+			_misskey_makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore,
+			_misskey_makeNotesHiddenBefore: user.makeNotesHiddenBefore,
 			icon: avatar ? this.renderImage(avatar) : null,
 			image: banner ? this.renderImage(banner) : null,
 			tag,
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 447f7ef3db..94cb0785cb 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -556,6 +556,8 @@ const extension_context_definition = {
 	'_misskey_summary': 'misskey:_misskey_summary',
 	'_misskey_followedMessage': 'misskey:_misskey_followedMessage',
 	'_misskey_requireSigninToViewContents': 'misskey:_misskey_requireSigninToViewContents',
+	'_misskey_makeNotesFollowersOnlyBefore': 'misskey:_misskey_makeNotesFollowersOnlyBefore',
+	'_misskey_makeNotesHiddenBefore': 'misskey:_misskey_makeNotesHiddenBefore',
 	'isCat': 'misskey:isCat',
 	// vcard
 	vcard: 'http://www.w3.org/2006/vcard/ns#',
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index c7915ed94f..0e2934301b 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -357,6 +357,8 @@ export class ApPersonService implements OnModuleInit {
 					isBot,
 					isCat: (person as any).isCat === true,
 					requireSigninToViewContents: (person as any).requireSigninToViewContents === true,
+					makeNotesFollowersOnlyBefore: (person as any).makeNotesFollowersOnlyBefore ?? null,
+					makeNotesHiddenBefore: (person as any).makeNotesHiddenBefore ?? null,
 					emojis,
 				})) as MiRemoteUser;
 
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index 8a860335fa..7496315f09 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -15,6 +15,8 @@ export interface IObject {
 	_misskey_summary?: string;
 	_misskey_followedMessage?: string | null;
 	_misskey_requireSigninToViewContents?: boolean;
+	_misskey_makeNotesFollowersOnlyBefore?: number | null;
+	_misskey_makeNotesHiddenBefore?: number | null;
 	published?: string;
 	cc?: ApObject;
 	to?: ApObject;
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 62016936a2..96cc6b028e 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -102,57 +102,83 @@ export class NoteEntityService implements OnModuleInit {
 	}
 
 	@bindThis
-	private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null) {
+	private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null): Promise<void> {
+		// FIXME: このvisibility変更処理が当関数にあるのは若干不自然かもしれない(関数名を treatVisibility とかに変える手もある)
+		if (packedNote.visibility === 'public' || packedNote.visibility === 'home') {
+			const followersOnlyBefore = packedNote.user.makeNotesFollowersOnlyBefore;
+			if ((followersOnlyBefore != null)
+				&& (
+					(followersOnlyBefore <= 0 && (Date.now() - new Date(packedNote.createdAt).getTime() > 0 - (followersOnlyBefore * 1000)))
+					|| (followersOnlyBefore > 0 && (new Date(packedNote.createdAt).getTime() < followersOnlyBefore * 1000))
+				)
+			) {
+				packedNote.visibility = 'followers';
+			}
+		}
+
+		if (meId === packedNote.userId) return;
+
 		// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
 		let hide = false;
 
-		// visibility が specified かつ自分が指定されていなかったら非表示
-		if (packedNote.visibility === 'specified') {
-			if (meId == null) {
-				hide = true;
-			} else if (meId === packedNote.userId) {
-				hide = false;
-			} else {
-				// 指定されているかどうか
-				const specified = packedNote.visibleUserIds!.some(id => meId === id);
+		if (packedNote.user.requireSigninToViewContents && meId == null) {
+			hide = true;
+		}
 
-				if (specified) {
-					hide = false;
-				} else {
+		if (!hide) {
+			const hiddenBefore = packedNote.user.makeNotesHiddenBefore;
+			if ((hiddenBefore != null)
+				&& (
+					(hiddenBefore <= 0 && (Date.now() - new Date(packedNote.createdAt).getTime() > 0 - (hiddenBefore * 1000)))
+					|| (hiddenBefore > 0 && (new Date(packedNote.createdAt).getTime() < hiddenBefore * 1000))
+				)
+			) {
+				hide = true;
+			}
+		}
+
+		// visibility が specified かつ自分が指定されていなかったら非表示
+		if (!hide) {
+			if (packedNote.visibility === 'specified') {
+				if (meId == null) {
 					hide = true;
+				} else {
+					// 指定されているかどうか
+					const specified = packedNote.visibleUserIds!.some(id => meId === id);
+
+					if (!specified) {
+						hide = true;
+					}
 				}
 			}
 		}
 
 		// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
-		if (packedNote.visibility === 'followers') {
-			if (meId == null) {
-				hide = true;
-			} else if (meId === packedNote.userId) {
-				hide = false;
-			} else if (packedNote.reply && (meId === packedNote.reply.userId)) {
-				// 自分の投稿に対するリプライ
-				hide = false;
-			} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
-				// 自分へのメンション
-				hide = false;
-			} else {
-				// フォロワーかどうか
-				const isFollowing = await this.followingsRepository.exists({
-					where: {
-						followeeId: packedNote.userId,
-						followerId: meId,
-					},
-				});
+		if (!hide) {
+			if (packedNote.visibility === 'followers') {
+				if (meId == null) {
+					hide = true;
+				} else if (packedNote.reply && (meId === packedNote.reply.userId)) {
+					// 自分の投稿に対するリプライ
+					hide = false;
+				} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
+					// 自分へのメンション
+					hide = false;
+				} else {
+					// フォロワーかどうか
+					// TODO: 当関数呼び出しごとにクエリが走るのは重そうだからなんとかする
+					const isFollowing = await this.followingsRepository.exists({
+						where: {
+							followeeId: packedNote.userId,
+							followerId: meId,
+						},
+					});
 
-				hide = !isFollowing;
+					hide = !isFollowing;
+				}
 			}
 		}
 
-		if (packedNote.user.requireSigninToViewContents && meId == null) {
-			hide = true;
-		}
-
 		if (hide) {
 			packedNote.visibleUserIds = undefined;
 			packedNote.fileIds = [];
@@ -161,6 +187,7 @@ export class NoteEntityService implements OnModuleInit {
 			packedNote.poll = undefined;
 			packedNote.cw = null;
 			packedNote.isHidden = true;
+			// TODO: hiddenReason みたいなのを提供しても良さそう
 		}
 	}
 
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index 747ffc780f..d3c087a153 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -491,6 +491,8 @@ export class UserEntityService implements OnModuleInit {
 			isBot: user.isBot,
 			isCat: user.isCat,
 			requireSigninToViewContents: user.requireSigninToViewContents === false ? undefined : true,
+			makeNotesFollowersOnlyBefore: user.makeNotesFollowersOnlyBefore ?? undefined,
+			makeNotesHiddenBefore: user.makeNotesHiddenBefore ?? undefined,
 			instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? {
 				name: instance.name,
 				softwareName: instance.softwareName,
diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts
index 6fcff77854..96de30c4c2 100644
--- a/packages/backend/src/models/User.ts
+++ b/packages/backend/src/models/User.ts
@@ -207,6 +207,18 @@ export class MiUser {
 	})
 	public requireSigninToViewContents: boolean;
 
+	// in sec, マイナスで相対時間
+	@Column('integer', {
+		nullable: true,
+	})
+	public makeNotesFollowersOnlyBefore: number | null;
+
+	// in sec, マイナスで相対時間
+	@Column('integer', {
+		nullable: true,
+	})
+	public makeNotesHiddenBefore: number | null;
+
 	// アカウントが削除されたかどうかのフラグだが、完全に削除される際は物理削除なので実質削除されるまでの「削除が進行しているかどうか」のフラグ
 	@Column('boolean', {
 		default: false,
diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts
index 817f8e9292..38631f907d 100644
--- a/packages/backend/src/models/json-schema/user.ts
+++ b/packages/backend/src/models/json-schema/user.ts
@@ -119,6 +119,14 @@ export const packedUserLiteSchema = {
 			type: 'boolean',
 			nullable: false, optional: true,
 		},
+		makeNotesFollowersOnlyBefore: {
+			type: 'number',
+			nullable: true, optional: true,
+		},
+		makeNotesHiddenBefore: {
+			type: 'number',
+			nullable: true, optional: true,
+		},
 		instance: {
 			type: 'object',
 			nullable: false, optional: true,
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 6680c96f3f..2183beac7c 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -180,6 +180,8 @@ export const paramDef = {
 		noCrawle: { type: 'boolean' },
 		preventAiLearning: { type: 'boolean' },
 		requireSigninToViewContents: { type: 'boolean' },
+		makeNotesFollowersOnlyBefore: { type: 'integer', nullable: true },
+		makeNotesHiddenBefore: { type: 'integer', nullable: true },
 		isBot: { type: 'boolean' },
 		isCat: { type: 'boolean' },
 		injectFeaturedNote: { type: 'boolean' },
@@ -336,6 +338,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
 			if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning;
 			if (typeof ps.requireSigninToViewContents === 'boolean') updates.requireSigninToViewContents = ps.requireSigninToViewContents;
+			if ((typeof ps.makeNotesFollowersOnlyBefore === 'number') || (ps.makeNotesFollowersOnlyBefore === null)) updates.makeNotesFollowersOnlyBefore = ps.makeNotesFollowersOnlyBefore;
+			if ((typeof ps.makeNotesHiddenBefore === 'number') || (ps.makeNotesHiddenBefore === null)) updates.makeNotesHiddenBefore = ps.makeNotesHiddenBefore;
 			if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
 			if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
 			if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
diff --git a/packages/frontend/src/components/MkSelect.vue b/packages/frontend/src/components/MkSelect.vue
index 8bd02000e6..eeadd49936 100644
--- a/packages/frontend/src/components/MkSelect.vue
+++ b/packages/frontend/src/components/MkSelect.vue
@@ -46,7 +46,7 @@ import type { MenuItem } from '@/types/menu.js';
 import * as os from '@/os.js';
 
 const props = defineProps<{
-	modelValue: string | null;
+	modelValue: string | number | null;
 	required?: boolean;
 	readonly?: boolean;
 	disabled?: boolean;
diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue
index e277dfad71..da3d36b31a 100644
--- a/packages/frontend/src/pages/settings/privacy.vue
+++ b/packages/frontend/src/pages/settings/privacy.vue
@@ -45,17 +45,89 @@ SPDX-License-Identifier: AGPL-3.0-only
 	</MkSwitch>
 
 	<FormSection>
-		<template #label>{{ i18n.ts.lockdown }}</template>
+		<template #label>{{ i18n.ts.lockdown }}<span class="_beta">{{ i18n.ts.beta }}</span></template>
 
 		<div class="_gaps_m">
 			<MkSwitch v-model="requireSigninToViewContents" @update:modelValue="save()">
-				{{ i18n.ts._accountSettings.requireSigninToViewContents }}<span class="_beta">{{ i18n.ts.beta }}</span>
+				{{ i18n.ts._accountSettings.requireSigninToViewContents }}
 				<template #caption>
 					<div>{{ i18n.ts._accountSettings.requireSigninToViewContentsDescription1 }}</div>
 					<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription2 }}</div>
 					<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.requireSigninToViewContentsDescription3 }}</div>
 				</template>
 			</MkSwitch>
+
+			<FormSlot>
+				<template #label>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBefore }}</template>
+
+				<div class="_gaps_s">
+					<MkSelect :modelValue="makeNotesFollowersOnlyBefore_type" @update:modelValue="makeNotesFollowersOnlyBefore = $event === 'relative' ? -604800 : $event === 'absolute' ? Math.floor(Date.now() / 1000) : null">
+						<option :value="null">{{ i18n.ts.none }}</option>
+						<option value="relative">{{ i18n.ts._accountSettings.notesHavePassedSpecifiedPeriod }}</option>
+						<option value="absolute">{{ i18n.ts._accountSettings.notesOlderThanSpecifiedDateAndTime }}</option>
+					</MkSelect>
+
+					<MkSelect v-if="makeNotesFollowersOnlyBefore_type === 'relative'" v-model="makeNotesFollowersOnlyBefore">
+						<option :value="-3600">{{ i18n.ts.oneHour }}</option>
+						<option :value="-86400">{{ i18n.ts.oneDay }}</option>
+						<option :value="-259200">{{ i18n.ts.threeDays }}</option>
+						<option :value="-604800">{{ i18n.ts.oneWeek }}</option>
+						<option :value="-2592000">{{ i18n.ts.oneMonth }}</option>
+						<option :value="-7776000">{{ i18n.ts.threeMonths }}</option>
+						<option :value="-31104000">{{ i18n.ts.oneYear }}</option>
+					</MkSelect>
+
+					<MkInput
+						v-if="makeNotesFollowersOnlyBefore_type === 'absolute'"
+						:modelValue="formatDateTimeString(new Date(makeNotesFollowersOnlyBefore * 1000), 'yyyy-MM-dd')"
+						type="date"
+						:manualSave="true"
+						@update:modelValue="makeNotesFollowersOnlyBefore = Math.floor(new Date($event).getTime() / 1000)"
+					>
+					</MkInput>
+				</div>
+
+				<template #caption>
+					<div>{{ i18n.ts._accountSettings.makeNotesFollowersOnlyBeforeDescription }}</div>
+					<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div>
+				</template>
+			</FormSlot>
+
+			<FormSlot>
+				<template #label>{{ i18n.ts._accountSettings.makeNotesHiddenBefore }}</template>
+
+				<div class="_gaps_s">
+					<MkSelect :modelValue="makeNotesHiddenBefore_type" @update:modelValue="makeNotesHiddenBefore = $event === 'relative' ? -604800 : $event === 'absolute' ? Math.floor(Date.now() / 1000) : null">
+						<option :value="null">{{ i18n.ts.none }}</option>
+						<option value="relative">{{ i18n.ts._accountSettings.notesHavePassedSpecifiedPeriod }}</option>
+						<option value="absolute">{{ i18n.ts._accountSettings.notesOlderThanSpecifiedDateAndTime }}</option>
+					</MkSelect>
+
+					<MkSelect v-if="makeNotesHiddenBefore_type === 'relative'" v-model="makeNotesHiddenBefore">
+						<option :value="-3600">{{ i18n.ts.oneHour }}</option>
+						<option :value="-86400">{{ i18n.ts.oneDay }}</option>
+						<option :value="-259200">{{ i18n.ts.threeDays }}</option>
+						<option :value="-604800">{{ i18n.ts.oneWeek }}</option>
+						<option :value="-2592000">{{ i18n.ts.oneMonth }}</option>
+						<option :value="-7776000">{{ i18n.ts.threeMonths }}</option>
+						<option :value="-31104000">{{ i18n.ts.oneYear }}</option>
+					</MkSelect>
+
+					<MkInput
+						v-if="makeNotesHiddenBefore_type === 'absolute'"
+						:modelValue="formatDateTimeString(new Date(makeNotesHiddenBefore * 1000), 'yyyy-MM-dd')"
+						type="date"
+						:manualSave="true"
+						@update:modelValue="makeNotesHiddenBefore = Math.floor(new Date($event).getTime() / 1000)"
+					>
+					</MkInput>
+				</div>
+
+				<template #caption>
+					<div>{{ i18n.ts._accountSettings.makeNotesHiddenBeforeDescription }}</div>
+					<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._accountSettings.mayNotEffectForFederatedNotes }}</div>
+				</template>
+			</FormSlot>
 		</div>
 	</FormSection>
 
@@ -87,7 +159,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue';
+import { ref, computed, watch } from 'vue';
 import MkSwitch from '@/components/MkSwitch.vue';
 import MkSelect from '@/components/MkSelect.vue';
 import FormSection from '@/components/form/section.vue';
@@ -97,6 +169,9 @@ import { defaultStore } from '@/store.js';
 import { i18n } from '@/i18n.js';
 import { signinRequired } from '@/account.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
+import FormSlot from '@/components/form/slot.vue';
+import { formatDateTimeString } from '@/scripts/format-time-string.js';
+import MkInput from '@/components/MkInput.vue';
 
 const $i = signinRequired();
 
@@ -106,6 +181,8 @@ const noCrawle = ref($i.noCrawle);
 const preventAiLearning = ref($i.preventAiLearning);
 const isExplorable = ref($i.isExplorable);
 const requireSigninToViewContents = ref($i.requireSigninToViewContents ?? false);
+const makeNotesFollowersOnlyBefore = ref($i.makeNotesFollowersOnlyBefore ?? null);
+const makeNotesHiddenBefore = ref($i.makeNotesHiddenBefore ?? null);
 const hideOnlineStatus = ref($i.hideOnlineStatus);
 const publicReactions = ref($i.publicReactions);
 const followingVisibility = ref($i.followingVisibility);
@@ -116,6 +193,30 @@ const defaultNoteLocalOnly = computed(defaultStore.makeGetterSetter('defaultNote
 const rememberNoteVisibility = computed(defaultStore.makeGetterSetter('rememberNoteVisibility'));
 const keepCw = computed(defaultStore.makeGetterSetter('keepCw'));
 
+const makeNotesFollowersOnlyBefore_type = computed(() => {
+	if (makeNotesFollowersOnlyBefore.value == null) {
+		return null;
+	} else if (makeNotesFollowersOnlyBefore.value >= 0) {
+		return 'absolute';
+	} else {
+		return 'relative';
+	}
+});
+
+const makeNotesHiddenBefore_type = computed(() => {
+	if (makeNotesHiddenBefore.value == null) {
+		return null;
+	} else if (makeNotesHiddenBefore.value >= 0) {
+		return 'absolute';
+	} else {
+		return 'relative';
+	}
+});
+
+watch([makeNotesFollowersOnlyBefore, makeNotesHiddenBefore], () => {
+	save();
+});
+
 function save() {
 	misskeyApi('i/update', {
 		isLocked: !!isLocked.value,
@@ -124,6 +225,8 @@ function save() {
 		preventAiLearning: !!preventAiLearning.value,
 		isExplorable: !!isExplorable.value,
 		requireSigninToViewContents: !!requireSigninToViewContents.value,
+		makeNotesFollowersOnlyBefore: makeNotesFollowersOnlyBefore.value,
+		makeNotesHiddenBefore: makeNotesHiddenBefore.value,
 		hideOnlineStatus: !!hideOnlineStatus.value,
 		publicReactions: !!publicReactions.value,
 		followingVisibility: followingVisibility.value,
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 8f84aa37ff..560960f018 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -3737,6 +3737,8 @@ export type components = {
       isBot?: boolean;
       isCat?: boolean;
       requireSigninToViewContents?: boolean;
+      makeNotesFollowersOnlyBefore?: number | null;
+      makeNotesHiddenBefore?: number | null;
       instance?: {
         name: string | null;
         softwareName: string | null;
@@ -19846,6 +19848,8 @@ export type operations = {
           noCrawle?: boolean;
           preventAiLearning?: boolean;
           requireSigninToViewContents?: boolean;
+          makeNotesFollowersOnlyBefore?: number | null;
+          makeNotesHiddenBefore?: number | null;
           isBot?: boolean;
           isCat?: boolean;
           injectFeaturedNote?: boolean;

From 8b6d321a76877a422b268e77cf930be7d1967213 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Tue, 22 Oct 2024 08:45:08 +0000
Subject: [PATCH 010/125] Bump version to 2024.10.2-alpha.0

---
 CHANGELOG.md                     | 2 +-
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d56abb29b4..fde4901241 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## Unreleased
+## 2024.10.2
 
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように
diff --git a/package.json b/package.json
index 8bf96d916d..444af2409b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.10.1",
+	"version": "2024.10.2-alpha.0",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index a0a46a1162..d6c760ad83 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.10.1",
+	"version": "2024.10.2-alpha.0",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 48d1539f3be895b7aa8ecdd6c581e47a55cc9264 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A5=BA=E5=AD=90w=20=28Yumechi=29?=
 <35571479+eternal-flame-AD@users.noreply.github.com>
Date: Tue, 22 Oct 2024 04:17:56 -0500
Subject: [PATCH 011/125] Merge commit from fork

[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
---
 CHANGELOG.md                                     | 4 ++--
 packages/backend/src/server/FileServerService.ts | 6 ++++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fde4901241..7e25ef3355 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,8 +15,8 @@
 - Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
 
 ### Server
--
-
+- Fix: Nested proxy requestsを検出した際にブロックするように
+  [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
 
 ## 2024.10.1
 
diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts
index 41b6d2e83d..bf0a011699 100644
--- a/packages/backend/src/server/FileServerService.ts
+++ b/packages/backend/src/server/FileServerService.ts
@@ -319,6 +319,12 @@ export class FileServerService {
 			);
 		}
 
+		if (!request.headers['user-agent']) {
+			throw new StatusError('User-Agent is required', 400, 'User-Agent is required');
+		} else if (request.headers['user-agent'].toLowerCase().indexOf('misskey/') !== -1) {
+			throw new StatusError('Refusing to proxy a request from another proxy', 403, 'Proxy is recursive');
+		}
+
 		// Create temp file
 		const file = await this.getStreamAndTypeFromUrl(url);
 		if (file === '404') {

From 15ae1605ec199792cd651073b1c6de480a7eeabe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 23 Oct 2024 14:23:29 +0900
Subject: [PATCH 012/125] =?UTF-8?q?enhance(frontend):=20=E3=80=8C=E5=8D=98?=
 =?UTF-8?q?=E3=81=AA=E3=82=8B=E3=83=A9=E3=83=83=E3=82=AD=E3=83=BC=E3=80=8D?=
 =?UTF-8?q?=E3=81=AE=E8=AA=BF=E6=95=B4=20(#14807)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(frontend): 「単なるラッキー」の調整

* refactor

* comment

* Update Changelog

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 CHANGELOG.md                            |  3 ++-
 packages/frontend/src/boot/main-boot.ts | 34 +++++++++++++++++++++++--
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e25ef3355..c85dc00011 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,8 @@
 ### Client
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
-- Enhance: ドライブでソートができるように 
+- Enhance: ドライブでソートができるように
+- Enhance: 「単なるラッキー」の取得条件を変更
 - Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )  
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts
index 2392381b64..2bf9029479 100644
--- a/packages/frontend/src/boot/main-boot.ts
+++ b/packages/frontend/src/boot/main-boot.ts
@@ -231,11 +231,41 @@ export async function mainBoot() {
 		}
 
 		if (!claimedAchievements.includes('justPlainLucky')) {
-			window.setInterval(() => {
+			let justPlainLuckyTimer: number | null = null;
+			let lastVisibilityChangedAt = Date.now();
+
+			function claimPlainLucky() {
+				if (document.visibilityState !== 'visible') {
+					if (justPlainLuckyTimer != null) window.clearTimeout(justPlainLuckyTimer);
+					return;
+				}
+
 				if (Math.floor(Math.random() * 20000) === 0) {
 					claimAchievement('justPlainLucky');
+				} else {
+					justPlainLuckyTimer = window.setTimeout(claimPlainLucky, 1000 * 10);
 				}
-			}, 1000 * 10);
+			}
+
+			window.addEventListener('visibilitychange', () => {
+				const now = Date.now();
+
+				if (document.visibilityState === 'visible') {
+					// タブを高速で切り替えたら取得処理が何度も走るのを防ぐ
+					if ((now - lastVisibilityChangedAt) < 1000 * 10) {
+						justPlainLuckyTimer = window.setTimeout(claimPlainLucky, 1000 * 10);
+					} else {
+						claimPlainLucky();
+					}
+				} else if (justPlainLuckyTimer != null) {
+					window.clearTimeout(justPlainLuckyTimer);
+					justPlainLuckyTimer = null;
+				}
+
+				lastVisibilityChangedAt = now;
+			}, { passive: true });
+
+			claimPlainLucky();
 		}
 
 		if (!claimedAchievements.includes('client30min')) {

From 076cc953e2bcd9f7335e2d9799cdf902829816cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 25 Oct 2024 14:20:33 +0900
Subject: [PATCH 013/125] =?UTF-8?q?enhance(frontend):=20=E5=A4=96=E9=83=A8?=
 =?UTF-8?q?=E3=82=A2=E3=83=97=E3=83=AA=E8=AA=8D=E8=A8=BC=E7=94=BB=E9=9D=A2?=
 =?UTF-8?q?=E3=81=AE=E6=94=B9=E8=89=AF=20(#14828)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(frontend): 外部アプリ認証画面の改良

* :art:

* lint

* Update Changelog

* indent

* lint

* enhance: miauthのリダイレクト先をUI内でも表示するように

* :art:

* fix

* fix
---
 CHANGELOG.md                                  |   3 +
 locales/index.d.ts                            |  16 +
 locales/ja-JP.yml                             |   4 +
 packages/frontend/src/_boot_.ts               |   2 +-
 packages/frontend/src/account.ts              |  70 ++-
 .../components/MkAuthConfirm.stories.impl.ts  |   7 +
 .../frontend/src/components/MkAuthConfirm.vue | 450 ++++++++++++++++++
 .../frontend/src/components/MkModalWindow.vue |  10 +-
 .../src/components/MkSignupDialog.vue         |  10 +-
 packages/frontend/src/pages/miauth.vue        | 145 +++---
 packages/frontend/src/pages/oauth.vue         | 111 +++--
 .../frontend/src/pages/settings/accounts.vue  |  20 +-
 12 files changed, 697 insertions(+), 151 deletions(-)
 create mode 100644 packages/frontend/src/components/MkAuthConfirm.stories.impl.ts
 create mode 100644 packages/frontend/src/components/MkAuthConfirm.vue

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c85dc00011..6e5747f3d8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,9 @@
 - Enhance: ドライブでソートができるように
 - Enhance: 「単なるラッキー」の取得条件を変更
 - Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )  
+- Enhance: MiAuth, OAuthの認可画面の改善
+  - どのアカウントで認証しようとしているのかがわかるように
+  - 認証するアカウントを切り替えられるように
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 8350297a79..80adf69232 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -5210,6 +5210,10 @@ export interface Locale extends ILocale {
      * ロックダウン
      */
     "lockdown": string;
+    /**
+     * アカウントを選択してください
+     */
+    "pleaseSelectAccount": string;
     "_accountSettings": {
         /**
          * コンテンツの表示にログインを必須にする
@@ -8448,14 +8452,26 @@ export interface Locale extends ILocale {
          * アプリケーションに戻っています
          */
         "callback": string;
+        /**
+         * アクセスを許可しました
+         */
+        "accepted": string;
         /**
          * アクセスを拒否しました
          */
         "denied": string;
+        /**
+         * 以下のユーザーとして操作しています
+         */
+        "scopeUser": string;
         /**
          * アプリケーションにアクセス許可を与えるには、ログインが必要です。
          */
         "pleaseLogin": string;
+        /**
+         * アクセスを許可すると、自動で以下のURLに遷移します
+         */
+        "byClickingYouWillBeRedirectedToThisUrl": string;
     };
     "_antennaSources": {
         /**
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 93ed879a08..d545425cbd 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1298,6 +1298,7 @@ yourNameContainsProhibitedWords: "変更しようとした名前に禁止され
 yourNameContainsProhibitedWordsDescription: "名前に禁止されている文字列が含まれています。この名前を使用したい場合は、サーバー管理者にお問い合わせください。"
 thisContentsAreMarkedAsSigninRequiredByAuthor: "投稿者により、表示にはログインが必要と設定されています"
 lockdown: "ロックダウン"
+pleaseSelectAccount: "アカウントを選択してください"
 
 _accountSettings:
   requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
@@ -2217,8 +2218,11 @@ _auth:
   permissionAsk: "このアプリは次の権限を要求しています"
   pleaseGoBack: "アプリケーションに戻ってやっていってください"
   callback: "アプリケーションに戻っています"
+  accepted: "アクセスを許可しました"
   denied: "アクセスを拒否しました"
+  scopeUser: "以下のユーザーとして操作しています"
   pleaseLogin: "アプリケーションにアクセス許可を与えるには、ログインが必要です。"
+  byClickingYouWillBeRedirectedToThisUrl: "アクセスを許可すると、自動で以下のURLに遷移します"
 
 _antennaSources:
   all: "全てのノート"
diff --git a/packages/frontend/src/_boot_.ts b/packages/frontend/src/_boot_.ts
index 13a97e433c..c90cc6bdd0 100644
--- a/packages/frontend/src/_boot_.ts
+++ b/packages/frontend/src/_boot_.ts
@@ -12,7 +12,7 @@ import '@/style.scss';
 import { mainBoot } from '@/boot/main-boot.js';
 import { subBoot } from '@/boot/sub-boot.js';
 
-const subBootPaths = ['/share', '/auth', '/miauth', '/signup-complete'];
+const subBootPaths = ['/share', '/auth', '/miauth', '/oauth', '/signup-complete'];
 
 if (subBootPaths.some(i => location.pathname === i || location.pathname.startsWith(i + '/'))) {
 	subBoot();
diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts
index f5a74a0581..36186ecac1 100644
--- a/packages/frontend/src/account.ts
+++ b/packages/frontend/src/account.ts
@@ -235,26 +235,6 @@ export async function openAccountMenu(opts: {
 }, ev: MouseEvent) {
 	if (!$i) return;
 
-	function showSigninDialog() {
-		const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
-			done: (res: Misskey.entities.SigninFlowResponse & { finished: true }) => {
-				addAccount(res.id, res.i);
-				success();
-			},
-			closed: () => dispose(),
-		});
-	}
-
-	function createAccount() {
-		const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
-			done: (res: Misskey.entities.SignupResponse) => {
-				addAccount(res.id, res.token);
-				switchAccountWithToken(res.token);
-			},
-			closed: () => dispose(),
-		});
-	}
-
 	async function switchAccount(account: Misskey.entities.UserDetailed) {
 		const storedAccounts = await getAccounts();
 		const found = storedAccounts.find(x => x.id === account.id);
@@ -323,10 +303,22 @@ export async function openAccountMenu(opts: {
 			text: i18n.ts.addAccount,
 			children: [{
 				text: i18n.ts.existingAccount,
-				action: () => { showSigninDialog(); },
+				action: () => {
+					getAccountWithSigninDialog().then(res => {
+						if (res != null) {
+							success();
+						}
+					});
+				},
 			}, {
 				text: i18n.ts.createAccount,
-				action: () => { createAccount(); },
+				action: () => {
+					getAccountWithSignupDialog().then(res => {
+						if (res != null) {
+							switchAccountWithToken(res.token);
+						}
+					});
+				},
 			}],
 		}, {
 			type: 'link',
@@ -347,6 +339,40 @@ export async function openAccountMenu(opts: {
 	});
 }
 
+export function getAccountWithSigninDialog(): Promise<{ id: string, token: string } | null> {
+	return new Promise((resolve) => {
+		const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
+			done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => {
+				await addAccount(res.id, res.i);
+				resolve({ id: res.id, token: res.i });
+			},
+			cancelled: () => {
+				resolve(null);
+			},
+			closed: () => {
+				dispose();
+			},
+		});
+	});
+}
+
+export function getAccountWithSignupDialog(): Promise<{ id: string, token: string } | null> {
+	return new Promise((resolve) => {
+		const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
+			done: async (res: Misskey.entities.SignupResponse) => {
+				await addAccount(res.id, res.token);
+				resolve({ id: res.id, token: res.token });
+			},
+			cancelled: () => {
+				resolve(null);
+			},
+			closed: () => {
+				dispose();
+			},
+		});
+	});
+}
+
 if (_DEV_) {
 	(window as any).$i = $i;
 }
diff --git a/packages/frontend/src/components/MkAuthConfirm.stories.impl.ts b/packages/frontend/src/components/MkAuthConfirm.stories.impl.ts
new file mode 100644
index 0000000000..0adc44e204
--- /dev/null
+++ b/packages/frontend/src/components/MkAuthConfirm.stories.impl.ts
@@ -0,0 +1,7 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import MkAuthConfirm from './MkAuthConfirm.vue';
+void MkAuthConfirm;
diff --git a/packages/frontend/src/components/MkAuthConfirm.vue b/packages/frontend/src/components/MkAuthConfirm.vue
new file mode 100644
index 0000000000..f5f6d7f6cc
--- /dev/null
+++ b/packages/frontend/src/components/MkAuthConfirm.vue
@@ -0,0 +1,450 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<div :class="$style.wrapper">
+	<Transition
+		mode="out-in"
+		:enterActiveClass="$style.transition_enterActive"
+		:leaveActiveClass="$style.transition_leaveActive"
+		:enterFromClass="$style.transition_enterFrom"
+		:leaveToClass="$style.transition_leaveTo"
+
+		:inert="_waiting"
+	>
+		<div v-if="phase === 'accountSelect'" key="accountSelect" :class="$style.root" class="_gaps">
+			<div :class="$style.header" class="_gaps_s">
+				<div :class="$style.iconFallback">
+					<i class="ti ti-user"></i>
+				</div>
+				<div :class="$style.headerText">{{ i18n.ts.pleaseSelectAccount }}</div>
+			</div>
+			<div :class="$style.accountSelectorRoot">
+				<div :class="$style.accountSelectorLabel">{{ i18n.ts.selectAccount }}</div>
+				<div :class="$style.accountSelectorList">
+					<template v-for="[id, user] in users">
+						<input :id="'account-' + id" v-model="selectedUser" type="radio" name="accountSelector" :value="id" :class="$style.accountSelectorRadio"/>
+						<label :for="'account-' + id" :class="$style.accountSelectorItem">
+							<MkAvatar :user="user" :class="$style.accountSelectorAvatar"/>
+							<div :class="$style.accountSelectorBody">
+								<MkUserName :user="user" :class="$style.accountSelectorName"/>
+								<MkAcct :user="user" :class="$style.accountSelectorAcct"/>
+							</div>
+						</label>
+					</template>
+					<button class="_button" :class="[$style.accountSelectorItem, $style.accountSelectorAddAccountRoot]" @click="clickAddAccount">
+						<div :class="[$style.accountSelectorAvatar, $style.accountSelectorAddAccountAvatar]">
+							<i class="ti ti-user-plus"></i>
+						</div>
+						<div :class="[$style.accountSelectorBody, $style.accountSelectorName]">{{ i18n.ts.addAccount }}</div>
+					</button>
+				</div>
+			</div>
+			<div class="_buttonsCenter">
+				<MkButton rounded gradate :disabled="selectedUser === null" @click="clickChooseAccount">{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
+			</div>
+		</div>
+		<div v-else-if="phase === 'consent'" key="consent" :class="$style.root" class="_gaps">
+			<div :class="$style.header" class="_gaps_s">
+				<img v-if="icon" :class="$style.icon" :src="getProxiedImageUrl(icon, 'preview')"/>
+				<div v-else :class="$style.iconFallback">
+					<i class="ti ti-apps"></i>
+				</div>
+				<div :class="$style.headerText">{{ name ? i18n.tsx._auth.shareAccess({ name }) : i18n.ts._auth.shareAccessAsk }}</div>
+			</div>
+			<div v-if="permissions && permissions.length > 0" class="_gaps_s" :class="$style.permissionRoot">
+				<div>{{ name ? i18n.tsx._auth.permission({ name }) : i18n.ts._auth.permissionAsk }}</div>
+				<div :class="$style.permissionListWrapper">
+					<ul :class="$style.permissionList">
+						<li v-for="p in permissions" :key="p">{{ i18n.ts._permissions[p] }}</li>
+					</ul>
+				</div>
+			</div>
+			<slot name="consentAdditionalInfo"></slot>
+			<div :class="$style.accountSelectorRoot">
+				<div :class="$style.accountSelectorLabel">
+					{{ i18n.ts._auth.scopeUser }} <button class="_textButton" @click="clickBackToAccountSelect">{{ i18n.ts.switchAccount }}</button>
+				</div>
+				<div :class="$style.accountSelectorList">
+					<div :class="[$style.accountSelectorItem, $style.static]">
+						<MkAvatar :user="users.get(selectedUser!)!" :class="$style.accountSelectorAvatar"/>
+						<div :class="$style.accountSelectorBody">
+							<MkUserName :user="users.get(selectedUser!)!" :class="$style.accountSelectorName"/>
+							<MkAcct :user="users.get(selectedUser!)!" :class="$style.accountSelectorAcct"/>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div class="_buttonsCenter">
+				<MkButton rounded @click="clickCancel">{{ i18n.ts.reject }}</MkButton>
+				<MkButton rounded gradate @click="clickAccept">{{ i18n.ts.accept }}</MkButton>
+			</div>
+		</div>
+		<div v-else-if="phase === 'success'" key="success" :class="$style.root" class="_gaps_s">
+			<div :class="$style.header" class="_gaps_s">
+				<div :class="$style.iconFallback">
+					<i class="ti ti-check"></i>
+				</div>
+				<div :class="$style.headerText">{{ i18n.ts._auth.accepted }}</div>
+				<div :class="$style.headerTextSub">{{ i18n.ts._auth.pleaseGoBack }}</div>
+			</div>
+		</div>
+		<div v-else-if="phase === 'denied'" key="denied" :class="$style.root" class="_gaps_s">
+			<div :class="$style.header" class="_gaps_s">
+				<div :class="$style.iconFallback">
+					<i class="ti ti-x"></i>
+				</div>
+				<div :class="$style.headerText">{{ i18n.ts._auth.denied }}</div>
+			</div>
+		</div>
+		<div v-else-if="phase === 'failed'" key="failed" :class="$style.root" class="_gaps_s">
+			<div :class="$style.header" class="_gaps_s">
+				<div :class="$style.iconFallback">
+					<i class="ti ti-x"></i>
+				</div>
+				<div :class="$style.headerText">{{ i18n.ts.somethingHappened }}</div>
+			</div>
+		</div>
+	</Transition>
+	<div v-if="_waiting" :class="$style.waitingRoot">
+		<MkLoading/>
+	</div>
+</div>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue';
+import * as Misskey from 'misskey-js';
+
+import MkButton from '@/components/MkButton.vue';
+
+import { $i, getAccounts, getAccountWithSigninDialog, getAccountWithSignupDialog } from '@/account.js';
+import { i18n } from '@/i18n.js';
+import * as os from '@/os.js';
+import { getProxiedImageUrl } from '@/scripts/media-proxy.js';
+import { misskeyApi } from '@/scripts/misskey-api.js';
+
+const props = defineProps<{
+	name?: string;
+	icon?: string;
+	permissions?: (typeof Misskey.permissions[number])[];
+	manualWaiting?: boolean;
+	waitOnDeny?: boolean;
+}>();
+
+const emit = defineEmits<{
+	(ev: 'accept', token: string): void;
+	(ev: 'deny', token: string): void;
+}>();
+
+const waiting = ref(true);
+const _waiting = computed(() => waiting.value || props.manualWaiting);
+const phase = ref<'accountSelect' | 'consent' | 'success' | 'denied' | 'failed'>('accountSelect');
+
+const selectedUser = ref<string | null>(null);
+
+const users = ref(new Map<string, Misskey.entities.UserDetailed & { token: string; }>());
+
+async function init() {
+	waiting.value = true;
+
+	users.value.clear();
+
+	if ($i) {
+		users.value.set($i.id, $i);
+	}
+
+	const accounts = await getAccounts();
+
+	const accountIdsToFetch = accounts.map(a => a.id).filter(id => !users.value.has(id));
+
+	if (accountIdsToFetch.length > 0) {
+		const usersRes = await misskeyApi('users/show', {
+			userIds: accountIdsToFetch,
+		});
+
+		for (const user of usersRes) {
+			if (users.value.has(user.id)) continue;
+
+			users.value.set(user.id, {
+				...user,
+				token: accounts.find(a => a.id === user.id)!.token,
+			});
+		}
+	}
+
+	waiting.value = false;
+}
+
+init();
+
+function clickAddAccount(ev: MouseEvent) {
+	selectedUser.value = null;
+
+	os.popupMenu([{
+		text: i18n.ts.existingAccount,
+		action: () => {
+			getAccountWithSigninDialog().then(async (res) => {
+				if (res != null) {
+					os.success();
+					await init();
+					if (users.value.has(res.id)) {
+						selectedUser.value = res.id;
+					}
+				}
+			});
+		},
+	}, {
+		text: i18n.ts.createAccount,
+		action: () => {
+			getAccountWithSignupDialog().then(async (res) => {
+				if (res != null) {
+					os.success();
+					await init();
+					if (users.value.has(res.id)) {
+						selectedUser.value = res.id;
+					}
+				}
+			});
+		},
+	}], ev.currentTarget ?? ev.target);
+}
+
+function clickChooseAccount() {
+	if (selectedUser.value === null) return;
+
+	phase.value = 'consent';
+}
+
+function clickBackToAccountSelect() {
+	selectedUser.value = null;
+	phase.value = 'accountSelect';
+}
+
+function clickCancel() {
+	if (selectedUser.value === null) return;
+
+	const user = users.value.get(selectedUser.value)!;
+
+	const token = user.token;
+
+	if (props.waitOnDeny) {
+		waiting.value = true;
+	}
+	emit('deny', token);
+}
+
+async function clickAccept() {
+	if (selectedUser.value === null) return;
+
+	const user = users.value.get(selectedUser.value)!;
+
+	const token = user.token;
+
+	waiting.value = true;
+	emit('accept', token);
+}
+
+function showUI(state: 'success' | 'denied' | 'failed') {
+	phase.value = state;
+	waiting.value = false;
+}
+
+defineExpose({
+	showUI,
+});
+</script>
+
+<style lang="scss" module>
+.transition_enterActive,
+.transition_leaveActive {
+	transition: opacity 0.3s cubic-bezier(0,0,.35,1), transform 0.3s cubic-bezier(0,0,.35,1);
+}
+.transition_enterFrom {
+	opacity: 0;
+	transform: translateX(50px);
+}
+.transition_leaveTo {
+	opacity: 0;
+	transform: translateX(-50px);
+}
+
+.wrapper {
+	overflow-x: hidden;
+	overflow-x: clip;
+
+	position: relative;
+	width: 100%;
+	height: 100%;
+}
+
+.waitingRoot {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	background-color: color-mix(in srgb, var(--MI_THEME-panel), transparent 50%);
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	z-index: 1;
+	cursor: wait;
+}
+
+.root {
+	position: relative;
+	box-sizing: border-box;
+	width: 100%;
+	padding: 48px 24px;
+}
+
+.header {
+	margin: 0 auto;
+	max-width: 320px;
+}
+
+.icon,
+.iconFallback {
+	display: block;
+	margin: 0 auto;
+	width: 54px;
+	height: 54px;
+}
+
+.icon {
+	border-radius: 50%;
+	border: 1px solid var(--MI_THEME-divider);
+	background-color: #fff;
+	object-fit: contain;
+}
+
+.iconFallback {
+	border-radius: 50%;
+	background-color: var(--MI_THEME-accentedBg);
+	color: var(--MI_THEME-accent);
+	text-align: center;
+	line-height: 54px;
+	font-size: 18px;
+}
+
+.headerText,
+.headerTextSub {
+	text-align: center;
+	word-break: normal;
+	word-break: auto-phrase;
+}
+
+.headerText {
+	font-size: 16px;
+	font-weight: 700;
+}
+
+.permissionRoot {
+	padding: 16px;
+	border-radius: var(--MI-radius);
+	background-color: var(--MI_THEME-bg);
+}
+
+.permissionListWrapper {
+	max-height: 350px;
+	overflow-y: auto;
+	padding: 12px;
+	border-radius: var(--MI-radius);
+	background-color: var(--MI_THEME-panel);
+}
+
+.permissionList {
+	margin: 0 0 0 1.5em;
+	padding: 0;
+	font-size: 90%;
+}
+
+.accountSelectorLabel {
+	font-size: 0.85em;
+	opacity: 0.7;
+	margin-bottom: 8px;
+}
+
+.accountSelectorList {
+	border-radius: var(--MI-radius);
+	border: 1px solid var(--MI_THEME-divider);
+	overflow: hidden;
+	overflow: clip;
+}
+
+.accountSelectorRadio {
+	position: absolute;
+	clip: rect(0, 0, 0, 0);
+	pointer-events: none;
+
+	&:focus-visible + .accountSelectorItem {
+		outline: 2px solid var(--MI_THEME-accent);
+		outline-offset: -4px;
+	}
+
+	&:checked:focus-visible + .accountSelectorItem {
+		outline-color: #fff;
+	}
+
+	&:checked + .accountSelectorItem {
+		background: var(--MI_THEME-accent);
+		color: #fff;
+	}
+}
+
+.accountSelectorItem {
+	display: flex;
+	align-items: center;
+	padding: 8px;
+	font-size: 14px;
+	-webkit-tap-highlight-color: transparent;
+	cursor: pointer;
+
+	&:hover {
+		background: var(--MI_THEME-buttonHoverBg);
+	}
+
+	&.static {
+		cursor: unset;
+
+		&:hover {
+			background: none;
+		}
+	}
+}
+
+.accountSelectorAddAccountRoot {
+	width: 100%;
+}
+
+.accountSelectorBody {
+	padding: 0 8px;
+	min-width: 0;
+}
+
+.accountSelectorAvatar {
+	width: 45px;
+	height: 45px;
+}
+
+.accountSelectorAddAccountAvatar {
+	background-color: var(--MI_THEME-accentedBg);
+	color: var(--MI_THEME-accent);
+	font-size: 16px;
+	line-height: 45px;
+	text-align: center;
+	border-radius: 50%;
+}
+
+.accountSelectorName {
+	display: block;
+	font-weight: bold;
+}
+
+.accountSelectorAcct {
+	opacity: 0.5;
+}
+</style>
diff --git a/packages/frontend/src/components/MkModalWindow.vue b/packages/frontend/src/components/MkModalWindow.vue
index fe9e1ce088..f06cfffee4 100644
--- a/packages/frontend/src/components/MkModalWindow.vue
+++ b/packages/frontend/src/components/MkModalWindow.vue
@@ -26,11 +26,11 @@ import { onMounted, onUnmounted, shallowRef, ref } from 'vue';
 import MkModal from './MkModal.vue';
 
 const props = withDefaults(defineProps<{
-	withOkButton: boolean;
-	withCloseButton: boolean;
-	okButtonDisabled: boolean;
-	width: number;
-	height: number;
+	withOkButton?: boolean;
+	withCloseButton?: boolean;
+	okButtonDisabled?: boolean;
+	width?: number;
+	height?: number;
 }>(), {
 	withOkButton: false,
 	withCloseButton: true,
diff --git a/packages/frontend/src/components/MkSignupDialog.vue b/packages/frontend/src/components/MkSignupDialog.vue
index f240e6dc46..4f75a36fbe 100644
--- a/packages/frontend/src/components/MkSignupDialog.vue
+++ b/packages/frontend/src/components/MkSignupDialog.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	ref="dialog"
 	:width="500"
 	:height="600"
-	@close="dialog?.close()"
+	@close="onClose"
 	@closed="$emit('closed')"
 >
 	<template #header>{{ i18n.ts.signup }}</template>
@@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			:leaveToClass="$style.transition_x_leaveTo"
 		>
 			<template v-if="!isAcceptedServerRule">
-				<XServerRules @done="isAcceptedServerRule = true" @cancel="dialog?.close()"/>
+				<XServerRules @done="isAcceptedServerRule = true" @cancel="onClose"/>
 			</template>
 			<template v-else>
 				<XSignup :autoSet="autoSet" @signup="onSignup" @signupEmailPending="onSignupEmailPending"/>
@@ -48,6 +48,7 @@ const props = withDefaults(defineProps<{
 
 const emit = defineEmits<{
 	(ev: 'done', res: Misskey.entities.SignupResponse): void;
+	(ev: 'cancelled'): void;
 	(ev: 'closed'): void;
 }>();
 
@@ -55,6 +56,11 @@ const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
 
 const isAcceptedServerRule = ref(false);
 
+function onClose() {
+	emit('cancelled');
+	dialog.value?.close();
+}
+
 function onSignup(res: Misskey.entities.SignupResponse) {
 	emit('done', res);
 	dialog.value?.close();
diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue
index ffaf739ed0..283f66ac45 100644
--- a/packages/frontend/src/pages/miauth.vue
+++ b/packages/frontend/src/pages/miauth.vue
@@ -4,95 +4,79 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<MkStickyContainer>
-	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
-	<MkSpacer :contentMax="800">
-		<div v-if="$i">
-			<div v-if="state == 'waiting'">
-				<MkLoading/>
-			</div>
-			<div v-if="state == 'denied'">
-				<p>{{ i18n.ts._auth.denied }}</p>
-			</div>
-			<div v-else-if="state == 'accepted'" class="accepted">
-				<p v-if="callback">{{ i18n.ts._auth.callback }}<MkEllipsis/></p>
-				<p v-else>{{ i18n.ts._auth.pleaseGoBack }}</p>
-			</div>
-			<div v-else>
-				<div v-if="_permissions.length > 0">
-					<p v-if="name">{{ i18n.tsx._auth.permission({ name }) }}</p>
-					<p v-else>{{ i18n.ts._auth.permissionAsk }}</p>
-					<ul>
-						<li v-for="p in _permissions" :key="p">{{ i18n.ts._permissions[p] }}</li>
-					</ul>
-				</div>
-				<div v-if="name">{{ i18n.tsx._auth.shareAccess({ name }) }}</div>
-				<div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div>
-				<div :class="$style.buttons">
-					<MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton>
-					<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton>
-				</div>
-			</div>
+<div>
+	<MkAnimBg style="position: fixed; top: 0;"/>
+	<div :class="$style.formContainer">
+		<div :class="$style.form">
+			<MkAuthConfirm
+				ref="authRoot"
+				:name="name"
+				:icon="icon || undefined"
+				:permissions="_permissions"
+				@accept="onAccept"
+				@deny="onDeny"
+			>
+				<template #consentAdditionalInfo>
+					<div v-if="callback != null" :class="$style.redirectRoot">
+						<div>{{ i18n.ts._auth.byClickingYouWillBeRedirectedToThisUrl }}</div>
+						<div class="_monospace" :class="$style.redirectUrl">{{ callback }}</div>
+					</div>
+				</template>
+			</MkAuthConfirm>
 		</div>
-		<div v-else>
-			<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p>
-			<MkSignin @login="onLogin"/>
-		</div>
-	</MkSpacer>
-</MkStickyContainer>
+	</div>
+</div>
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue';
-import MkSignin from '@/components/MkSignin.vue';
-import MkButton from '@/components/MkButton.vue';
-import { misskeyApi } from '@/scripts/misskey-api.js';
-import { $i, login } from '@/account.js';
+import { computed, useTemplateRef } from 'vue';
+import * as Misskey from 'misskey-js';
+
+import MkAnimBg from '@/components/MkAnimBg.vue';
+import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
+
 import { i18n } from '@/i18n.js';
+import { misskeyApi } from '@/scripts/misskey-api.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 
 const props = defineProps<{
 	session: string;
 	callback?: string;
-	name: string;
-	icon: string;
-	permission: string; // コンマ区切り
+	name?: string;
+	icon?: string;
+	permission?: string; // コンマ区切り
 }>();
 
-const _permissions = props.permission ? props.permission.split(',') : [];
+const _permissions = computed(() => {
+	return (props.permission ? props.permission.split(',').filter((p): p is typeof Misskey.permissions[number] => (Misskey.permissions as readonly string[]).includes(p)) : []);
+});
 
-const state = ref<string | null>(null);
+const authRoot = useTemplateRef('authRoot');
 
-async function accept(): Promise<void> {
-	state.value = 'waiting';
+async function onAccept(token: string) {
 	await misskeyApi('miauth/gen-token', {
 		session: props.session,
 		name: props.name,
 		iconUrl: props.icon,
-		permission: _permissions,
+		permission: _permissions.value,
+	}, token).catch(() => {
+		authRoot.value?.showUI('failed');
 	});
 
-	state.value = 'accepted';
-	if (props.callback) {
+	if (props.callback && props.callback !== '') {
 		const cbUrl = new URL(props.callback);
 		if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(cbUrl.protocol)) throw new Error('invalid url');
 		cbUrl.searchParams.set('session', props.session);
-		location.href = cbUrl.href;
+		location.href = cbUrl.toString();
+	} else {
+		authRoot.value?.showUI('success');
 	}
 }
 
-function deny(): void {
-	state.value = 'denied';
+function onDeny() {
+	authRoot.value?.showUI('denied');
 }
 
-function onLogin(res): void {
-	login(res.i);
-}
-
-const headerActions = computed(() => []);
-
-const headerTabs = computed(() => []);
-
 definePageMetadata(() => ({
 	title: 'MiAuth',
 	icon: 'ti ti-apps',
@@ -100,15 +84,38 @@ definePageMetadata(() => ({
 </script>
 
 <style lang="scss" module>
-.buttons {
-	margin-top: 16px;
-	display: flex;
-	gap: 8px;
-	flex-wrap: wrap;
+.formContainer {
+	min-height: 100svh;
+	padding: 32px 32px calc(env(safe-area-inset-bottom, 0px) + 32px) 32px;
+	box-sizing: border-box;
+	display: grid;
+	place-content: center;
 }
 
-.loginMessage {
-	text-align: center;
-	margin: 8px 0 24px;
+.form {
+	position: relative;
+	z-index: 10;
+	border-radius: var(--MI-radius);
+	background-color: var(--MI_THEME-panel);
+	box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
+	overflow: clip;
+	max-width: 500px;
+	width: calc(100vw - 64px);
+	height: min(65svh, calc(100svh - calc(env(safe-area-inset-bottom, 0px) + 64px)));
+	overflow-y: scroll;
+}
+
+.redirectRoot {
+	padding: 16px;
+	border-radius: var(--MI-radius);
+	background-color: var(--MI_THEME-bg);
+}
+
+.redirectUrl {
+	font-size: 90%;
+	padding: 12px;
+	border-radius: var(--MI-radius);
+	background-color: var(--MI_THEME-panel);
+	overflow-x: scroll;
 }
 </style>
diff --git a/packages/frontend/src/pages/oauth.vue b/packages/frontend/src/pages/oauth.vue
index 733e34eb2c..8719a769e5 100644
--- a/packages/frontend/src/pages/oauth.vue
+++ b/packages/frontend/src/pages/oauth.vue
@@ -4,40 +4,28 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<MkStickyContainer>
-	<template #header><MkPageHeader/></template>
-	<MkSpacer :contentMax="800">
-		<div v-if="$i">
-			<div v-if="permissions.length > 0">
-				<p v-if="name">{{ i18n.tsx._auth.permission({ name }) }}</p>
-				<p v-else>{{ i18n.ts._auth.permissionAsk }}</p>
-				<ul>
-					<li v-for="p in permissions" :key="p">{{ i18n.ts._permissions[p] }}</li>
-				</ul>
-			</div>
-			<div v-if="name">{{ i18n.tsx._auth.shareAccess({ name }) }}</div>
-			<div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div>
-			<form :class="$style.buttons" action="/oauth/decision" accept-charset="utf-8" method="post">
-				<input name="login_token" type="hidden" :value="$i.token"/>
-				<input name="transaction_id" type="hidden" :value="transactionIdMeta?.content"/>
-				<MkButton inline name="cancel" value="cancel">{{ i18n.ts.cancel }}</MkButton>
-				<MkButton inline primary>{{ i18n.ts.accept }}</MkButton>
-			</form>
+<div>
+	<MkAnimBg style="position: fixed; top: 0;"/>
+	<div :class="$style.formContainer">
+		<div :class="$style.form">
+			<MkAuthConfirm
+				ref="authRoot"
+				:name="name"
+				:permissions="permissions"
+				:waitOnDeny="true"
+				@accept="onAccept"
+				@deny="onDeny"
+			/>
 		</div>
-		<div v-else>
-			<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p>
-			<MkSignin @login="onLogin"/>
-		</div>
-	</MkSpacer>
-</MkStickyContainer>
+	</div>
+</div>
 </template>
 
 <script lang="ts" setup>
-import MkSignin from '@/components/MkSignin.vue';
-import MkButton from '@/components/MkButton.vue';
-import { $i, login } from '@/account.js';
-import { i18n } from '@/i18n.js';
+import * as Misskey from 'misskey-js';
+import MkAnimBg from '@/components/MkAnimBg.vue';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
+import MkAuthConfirm from '@/components/MkAuthConfirm.vue';
 
 const transactionIdMeta = document.querySelector<HTMLMetaElement>('meta[name="misskey:oauth:transaction-id"]');
 if (transactionIdMeta) {
@@ -45,10 +33,44 @@ if (transactionIdMeta) {
 }
 
 const name = document.querySelector<HTMLMetaElement>('meta[name="misskey:oauth:client-name"]')?.content;
-const permissions = document.querySelector<HTMLMetaElement>('meta[name="misskey:oauth:scope"]')?.content.split(' ') ?? [];
+const permissions = document.querySelector<HTMLMetaElement>('meta[name="misskey:oauth:scope"]')?.content.split(' ').filter((p): p is typeof Misskey.permissions[number] => (Misskey.permissions as readonly string[]).includes(p)) ?? [];
 
-function onLogin(res): void {
-	login(res.i);
+function doPost(token: string, decision: 'accept' | 'deny') {
+	const form = document.createElement('form');
+	form.action = '/oauth/decision';
+	form.method = 'post';
+	form.acceptCharset = 'utf-8';
+
+	const loginToken = document.createElement('input');
+	loginToken.type = 'hidden';
+	loginToken.name = 'login_token';
+	loginToken.value = token;
+	form.appendChild(loginToken);
+
+	const transactionId = document.createElement('input');
+	transactionId.type = 'hidden';
+	transactionId.name = 'transaction_id';
+	transactionId.value = transactionIdMeta?.content ?? '';
+	form.appendChild(transactionId);
+
+	if (decision === 'deny') {
+		const cancel = document.createElement('input');
+		cancel.type = 'hidden';
+		cancel.name = 'cancel';
+		cancel.value = 'cancel';
+		form.appendChild(cancel);
+	}
+
+	document.body.appendChild(form);
+	form.submit();
+}
+
+function onAccept(token: string) {
+	doPost(token, 'accept');
+}
+
+function onDeny(token: string) {
+	doPost(token, 'deny');
 }
 
 definePageMetadata(() => ({
@@ -58,15 +80,24 @@ definePageMetadata(() => ({
 </script>
 
 <style lang="scss" module>
-.buttons {
-	margin-top: 16px;
-	display: flex;
-	gap: 8px;
-	flex-wrap: wrap;
+.formContainer {
+	min-height: 100svh;
+	padding: 32px 32px calc(env(safe-area-inset-bottom, 0px) + 32px) 32px;
+	box-sizing: border-box;
+	display: grid;
+	place-content: center;
 }
 
-.loginMessage {
-	text-align: center;
-	margin: 8px 0 24px;
+.form {
+	position: relative;
+	z-index: 10;
+	border-radius: var(--MI-radius);
+	background-color: var(--MI_THEME-panel);
+	box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
+	overflow: clip;
+	max-width: 500px;
+	width: calc(100vw - 64px);
+	height: min(65svh, calc(100svh - calc(env(safe-area-inset-bottom, 0px) + 64px)));
+	overflow-y: scroll;
 }
 </style>
diff --git a/packages/frontend/src/pages/settings/accounts.vue b/packages/frontend/src/pages/settings/accounts.vue
index 1bbedb817e..16f0716a12 100644
--- a/packages/frontend/src/pages/settings/accounts.vue
+++ b/packages/frontend/src/pages/settings/accounts.vue
@@ -19,13 +19,13 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-import { defineAsyncComponent, ref, computed } from 'vue';
+import { ref, computed } from 'vue';
 import type * as Misskey from 'misskey-js';
 import FormSuspense from '@/components/form/suspense.vue';
 import MkButton from '@/components/MkButton.vue';
 import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
-import { getAccounts, addAccount as addAccounts, removeAccount as _removeAccount, login, $i } from '@/account.js';
+import { getAccounts, removeAccount as _removeAccount, login, $i, getAccountWithSigninDialog, getAccountWithSignupDialog } from '@/account.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 import MkUserCardMini from '@/components/MkUserCardMini.vue';
@@ -74,23 +74,19 @@ async function removeAccount(account: Misskey.entities.UserDetailed) {
 }
 
 function addExistingAccount() {
-	const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, {
-		done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => {
-			await addAccounts(res.id, res.i);
+	getAccountWithSigninDialog().then((res) => {
+		if (res != null) {
 			os.success();
 			init();
-		},
-		closed: () => dispose(),
+		}
 	});
 }
 
 function createAccount() {
-	const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, {
-		done: async (res: Misskey.entities.SignupResponse) => {
-			await addAccounts(res.id, res.token);
+	getAccountWithSignupDialog().then((res) => {
+		if (res != null) {
 			switchAccountWithToken(res.token);
-		},
-		closed: () => dispose(),
+		}
 	});
 }
 

From 07b2c3e5b2facb7e5a3c69dc3d2384531a847c4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 25 Oct 2024 15:09:07 +0900
Subject: [PATCH 014/125] =?UTF-8?q?fix(frontend):=20=E7=AE=A1=E7=90=86?=
 =?UTF-8?q?=E7=94=BB=E9=9D=A2=E3=81=AE=E3=83=AA=E3=83=B3=E3=82=AF=E5=88=87?=
 =?UTF-8?q?=E3=82=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#14831)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): 管理画面のリンク切れを修正

* Update Changelog
---
 CHANGELOG.md                                | 1 +
 packages/frontend/src/pages/admin/index.vue | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e5747f3d8..2bb021317d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
 - Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
+- Fix: リンク切れを修正
 
 ### Server
 - Fix: Nested proxy requestsを検出した際にブロックするように
diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue
index 8a206a2f79..fd15ae1d66 100644
--- a/packages/frontend/src/pages/admin/index.vue
+++ b/packages/frontend/src/pages/admin/index.vue
@@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<div class="_gaps_s">
 					<MkInfo v-if="thereIsUnresolvedAbuseReport" warn>{{ i18n.ts.thereIsUnresolvedAbuseReportWarning }} <MkA to="/admin/abuses" class="_link">{{ i18n.ts.check }}</MkA></MkInfo>
 					<MkInfo v-if="noMaintainerInformation" warn>{{ i18n.ts.noMaintainerInformationWarning }} <MkA to="/admin/settings" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
-					<MkInfo v-if="noInquiryUrl" warn>{{ i18n.ts.noInquiryUrlWarning }} <MkA to="/admin/moderation" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
+					<MkInfo v-if="noInquiryUrl" warn>{{ i18n.ts.noInquiryUrlWarning }} <MkA to="/admin/settings" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
 					<MkInfo v-if="noBotProtection" warn>{{ i18n.ts.noBotProtectionWarning }} <MkA to="/admin/security" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
 					<MkInfo v-if="noEmailServer" warn>{{ i18n.ts.noEmailServerWarning }} <MkA to="/admin/email-settings" class="_link">{{ i18n.ts.configure }}</MkA></MkInfo>
 				</div>

From eeea4ec00b4ed1aeabee85d2761699765f9b2af9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 25 Oct 2024 15:09:37 +0900
Subject: [PATCH 015/125] =?UTF-8?q?fix(backend):=20=E6=8B=9B=E5=BE=85?=
 =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E7=99=BA=E8=A1=8C=E5=8F=AF=E8=83=BD?=
 =?UTF-8?q?=E6=AE=8B=E3=82=8A=E6=95=B0=E7=AE=97=E5=87=BA=E3=81=AB=E4=BD=BF?=
 =?UTF-8?q?=E7=94=A8=E3=81=99=E3=81=B9=E3=81=8D=E3=83=AD=E3=83=BC=E3=83=AB?=
 =?UTF-8?q?=E3=83=9D=E3=83=AA=E3=82=B7=E3=83=BC=E3=81=AE=E5=80=A4=E3=81=8C?=
 =?UTF-8?q?=E9=81=95=E3=81=86=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1483?=
 =?UTF-8?q?4)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: should use invite limit cycle to calculate invite/limit

* Update Changelog

* Update changelog

---------

Co-authored-by: Lhc_fl <lhcfl@outlook.com>
---
 CHANGELOG.md                                              | 2 ++
 packages/backend/src/server/api/endpoints/invite/limit.ts | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2bb021317d..c35aa3679f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,8 @@
 ### Server
 - Fix: Nested proxy requestsを検出した際にブロックするように
   [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
+- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
 
 ## 2024.10.1
 
diff --git a/packages/backend/src/server/api/endpoints/invite/limit.ts b/packages/backend/src/server/api/endpoints/invite/limit.ts
index 2786bd98d5..2ffd41ae28 100644
--- a/packages/backend/src/server/api/endpoints/invite/limit.ts
+++ b/packages/backend/src/server/api/endpoints/invite/limit.ts
@@ -49,7 +49,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			const policies = await this.roleService.getUserPolicies(me.id);
 
 			const count = policies.inviteLimit ? await this.registrationTicketsRepository.countBy({
-				id: MoreThan(this.idService.gen(Date.now() - (policies.inviteExpirationTime * 60 * 1000))),
+				id: MoreThan(this.idService.gen(Date.now() - (policies.inviteLimitCycle * 60 * 1000))),
 				createdById: me.id,
 			}) : null;
 

From db95b6b0d6988c5caadb2bdd9586525a81ad7fda Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 25 Oct 2024 19:37:01 +0900
Subject: [PATCH 016/125] :art:
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

https://github.com/misskey-dev/misskey/pull/14828 のデザイン修正
---
 packages/frontend/src/pages/miauth.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue
index 283f66ac45..e89dd5c4a5 100644
--- a/packages/frontend/src/pages/miauth.vue
+++ b/packages/frontend/src/pages/miauth.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				@deny="onDeny"
 			>
 				<template #consentAdditionalInfo>
-					<div v-if="callback != null" :class="$style.redirectRoot">
+					<div v-if="callback != null" class="_gaps_s" :class="$style.redirectRoot">
 						<div>{{ i18n.ts._auth.byClickingYouWillBeRedirectedToThisUrl }}</div>
 						<div class="_monospace" :class="$style.redirectUrl">{{ callback }}</div>
 					</div>

From ded6ef207b888c14f425d46a341a35feab76be86 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Fri, 25 Oct 2024 13:16:43 +0000
Subject: [PATCH 017/125] Bump version to 2024.10.2-alpha.1

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 444af2409b..6c598e11a3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.10.2-alpha.0",
+	"version": "2024.10.2-alpha.1",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index d6c760ad83..ef3d84ee96 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.10.2-alpha.0",
+	"version": "2024.10.2-alpha.1",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From a6a1e3d733e192504986e6e91b5aca9211c331ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 26 Oct 2024 22:07:26 +0900
Subject: [PATCH 018/125] =?UTF-8?q?enhance(frontend):=20Self-XSS=E9=98=B2?=
 =?UTF-8?q?=E6=AD=A2=E7=94=A8=E3=81=AE=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?=
 =?UTF-8?q?=E3=82=B8=E3=82=92=E8=BF=BD=E5=8A=A0=20(#14839)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(frontend): Self-XSS防止用のメッセージを追加

* Update Changelog

* embedにも同様の記述を追加
---
 CHANGELOG.md                         |  1 +
 locales/index.d.ts                   | 22 ++++++++++++++++++++++
 locales/ja-JP.yml                    |  7 +++++++
 packages/frontend-embed/src/boot.ts  | 22 ++++++++++++++++++++++
 packages/frontend/src/boot/common.ts | 23 ++++++++++++++++++++++-
 5 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c35aa3679f..40ad0b639b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@
 - Enhance: MiAuth, OAuthの認可画面の改善
   - どのアカウントで認証しようとしているのかがわかるように
   - 認証するアカウントを切り替えられるように
+- Enhance: Self-XSS防止用の警告を追加
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 80adf69232..9058c70496 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -10553,6 +10553,28 @@ export interface Locale extends ILocale {
          */
         "codeGeneratedDescription": string;
     };
+    "_selfXssPrevention": {
+        /**
+         * 警告
+         */
+        "warning": string;
+        /**
+         * 「この画面に何か貼り付けろ」はすべて詐欺です。
+         */
+        "title": string;
+        /**
+         * ここに何かを貼り付けると、悪意のあるユーザーにアカウントを乗っ取られたり、個人情報を盗まれたりする可能性があります。
+         */
+        "description1": string;
+        /**
+         * 貼り付けようとしているものが何なのかを正確に理解していない場合は、%c今すぐ作業を中止してこのウィンドウを閉じてください。
+         */
+        "description2": string;
+        /**
+         * 詳しくはこちらをご確認ください。 {link}
+         */
+        "description3": ParameterizedString<"link">;
+    };
 }
 declare const locales: {
     [lang: string]: Locale;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index d545425cbd..1d426f1705 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -2811,3 +2811,10 @@ _embedCodeGen:
   generateCode: "埋め込みコードを作成"
   codeGenerated: "コードが生成されました"
   codeGeneratedDescription: "生成されたコードをウェブサイトに貼り付けてご利用ください。"
+
+_selfXssPrevention:
+  warning: "警告"
+  title: "「この画面に何か貼り付けろ」はすべて詐欺です。"
+  description1: "ここに何かを貼り付けると、悪意のあるユーザーにアカウントを乗っ取られたり、個人情報を盗まれたりする可能性があります。"
+  description2: "貼り付けようとしているものが何なのかを正確に理解していない場合は、%c今すぐ作業を中止してこのウィンドウを閉じてください。"
+  description3: "詳しくはこちらをご確認ください。 {link}"
diff --git a/packages/frontend-embed/src/boot.ts b/packages/frontend-embed/src/boot.ts
index 00c7944eb3..8ab4ab32e6 100644
--- a/packages/frontend-embed/src/boot.ts
+++ b/packages/frontend-embed/src/boot.ts
@@ -21,6 +21,7 @@ import { url } from '@@/js/config.js';
 import { parseEmbedParams } from '@@/js/embed-page.js';
 import { postMessageToParentWindow, setIframeId } from '@/post-message.js';
 import { serverContext } from '@/server-context.js';
+import { i18n } from '@/i18n.js';
 
 import type { Theme } from '@/theme.js';
 
@@ -127,6 +128,27 @@ window.onunhandledrejection = null;
 
 removeSplash();
 
+//#region Self-XSS 対策メッセージ
+console.log(
+	`%c${i18n.ts._selfXssPrevention.warning}`,
+	'color: #f00; background-color: #ff0; font-size: 36px; padding: 4px;',
+);
+console.log(
+	`%c${i18n.ts._selfXssPrevention.title}`,
+	'color: #f00; font-weight: 900; font-family: "Hiragino Sans W9", "Hiragino Kaku Gothic ProN", sans-serif; font-size: 24px;',
+);
+console.log(
+	`%c${i18n.ts._selfXssPrevention.description1}`,
+	'font-size: 16px; font-weight: 700;',
+);
+console.log(
+	`%c${i18n.ts._selfXssPrevention.description2}`,
+	'font-size: 16px;',
+	'font-size: 20px; font-weight: 700; color: #f00;',
+);
+console.log(i18n.tsx._selfXssPrevention.description3({ link: 'https://misskey-hub.net/docs/for-users/resources/self-xss/' }));
+//#endregion
+
 function removeSplash() {
 	const splash = document.getElementById('splash');
 	if (splash) {
diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts
index 1145891b71..90ae49ee59 100644
--- a/packages/frontend/src/boot/common.ts
+++ b/packages/frontend/src/boot/common.ts
@@ -11,7 +11,7 @@ import directives from '@/directives/index.js';
 import components from '@/components/index.js';
 import { applyTheme } from '@/scripts/theme.js';
 import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js';
-import { updateI18n } from '@/i18n.js';
+import { updateI18n, i18n } from '@/i18n.js';
 import { $i, refreshAccount, login } from '@/account.js';
 import { defaultStore, ColdDeviceStorage } from '@/store.js';
 import { fetchInstance, instance } from '@/instance.js';
@@ -269,6 +269,27 @@ export async function common(createVue: () => App<Element>) {
 
 	removeSplash();
 
+	//#region Self-XSS 対策メッセージ
+	console.log(
+		`%c${i18n.ts._selfXssPrevention.warning}`,
+		'color: #f00; background-color: #ff0; font-size: 36px; padding: 4px;',
+	);
+	console.log(
+		`%c${i18n.ts._selfXssPrevention.title}`,
+		'color: #f00; font-weight: 900; font-family: "Hiragino Sans W9", "Hiragino Kaku Gothic ProN", sans-serif; font-size: 24px;',
+	);
+	console.log(
+		`%c${i18n.ts._selfXssPrevention.description1}`,
+		'font-size: 16px; font-weight: 700;',
+	);
+	console.log(
+		`%c${i18n.ts._selfXssPrevention.description2}`,
+		'font-size: 16px;',
+		'font-size: 20px; font-weight: 700; color: #f00;',
+	);
+	console.log(i18n.tsx._selfXssPrevention.description3({ link: 'https://misskey-hub.net/docs/for-users/resources/self-xss/' }));
+	//#endregion
+
 	return {
 		isClientUpdated,
 		app,

From ec4358d1e8c9a59a0702d19182c37d91510b3736 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 28 Oct 2024 11:43:05 +0900
Subject: [PATCH 019/125] =?UTF-8?q?fix(misskey-js):=20WebSocket=E3=81=AE?=
 =?UTF-8?q?=E5=9E=8B=E5=AE=9A=E7=BE=A9=E3=82=92ReconnectingWebsocket?=
 =?UTF-8?q?=E3=81=AB=E4=BE=9D=E5=AD=98=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?=
 =?UTF-8?q?=E3=81=AB=20(#14850)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(misskey-js): WebSocketの型定義をReconnectingWebsocketに依存するように

* Update Changelog

* run api extractor

* fix

* fix
---
 CHANGELOG.md                                   | 3 +++
 packages/backend/test-federation/test/utils.ts | 2 --
 packages/misskey-js/etc/misskey-js.api.md      | 3 ++-
 packages/misskey-js/src/streaming.ts           | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40ad0b639b..90ad015dab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,9 @@
 - Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
 
+### Misskey.js
+- Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
+
 ## 2024.10.1
 
 ### Note
diff --git a/packages/backend/test-federation/test/utils.ts b/packages/backend/test-federation/test/utils.ts
index 483bf4b254..093277cdb4 100644
--- a/packages/backend/test-federation/test/utils.ts
+++ b/packages/backend/test-federation/test/utils.ts
@@ -232,7 +232,6 @@ export async function isFired<C extends keyof Misskey.Channels, T extends keyof
 	params?: Misskey.Channels[C]['params'],
 ): Promise<boolean> {
 	return new Promise<boolean>(async (resolve, reject) => {
-		// @ts-expect-error TODO: why?
 		const stream = new Misskey.Stream(`wss://${host}`, { token: user.i }, { WebSocket });
 		const connection = stream.useChannel(channel, params);
 		connection.on(type as any, ((msg: any) => {
@@ -266,7 +265,6 @@ export async function isNoteUpdatedEventFired(
 	cond: (msg: Parameters<Misskey.StreamEvents['noteUpdated']>[0]) => boolean,
 ): Promise<boolean> {
 	return new Promise<boolean>(async (resolve, reject) => {
-		// @ts-expect-error TODO: why?
 		const stream = new Misskey.Stream(`wss://${host}`, { token: user.i }, { WebSocket });
 		stream.send('s', { id: noteId });
 		stream.on('noteUpdated', msg => {
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index 72c236373d..61de8b8c7e 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -7,6 +7,7 @@
 import type { AuthenticationResponseJSON } from '@simplewebauthn/types';
 import { EventEmitter } from 'eventemitter3';
 import type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/types';
+import _ReconnectingWebsocket from 'reconnecting-websocket';
 
 // Warning: (ae-forgotten-export) The symbol "components" needs to be exported by the entry point index.d.ts
 //
@@ -3137,7 +3138,7 @@ export class Stream extends EventEmitter<StreamEvents> implements IStream {
     constructor(origin: string, user: {
         token: string;
     } | null, options?: {
-        WebSocket?: WebSocket;
+        WebSocket?: _ReconnectingWebsocket.Options['WebSocket'];
     });
     // (undocumented)
     close(): void;
diff --git a/packages/misskey-js/src/streaming.ts b/packages/misskey-js/src/streaming.ts
index ffb46c77f6..6e34ec1508 100644
--- a/packages/misskey-js/src/streaming.ts
+++ b/packages/misskey-js/src/streaming.ts
@@ -51,7 +51,7 @@ export default class Stream extends EventEmitter<StreamEvents> implements IStrea
 	private idCounter = 0;
 
 	constructor(origin: string, user: { token: string; } | null, options?: {
-		WebSocket?: WebSocket;
+		WebSocket?: _ReconnectingWebsocket.Options['WebSocket'];
 	}) {
 		super();
 

From 93a03e6b6d1af511c2d52fbc2230d81f94451e19 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 28 Oct 2024 11:43:55 +0900
Subject: [PATCH 020/125] New Crowdin updates (#14767)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Japanese, Kansai)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Japanese, Kansai)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (Japanese, Kansai)

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Hungarian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)
---
 locales/ca-ES.yml | 115 ++++++++++++++++++++++++++++++++++++++++++++--
 locales/en-US.yml |  31 ++++++++++++-
 locales/es-ES.yml |  18 ++++++++
 locales/hu-HU.yml |   2 +-
 locales/id-ID.yml |  28 +++++++++++
 locales/it-IT.yml |  85 ++++++++++++++++++++++------------
 locales/ja-KS.yml |  92 ++++++++++++++++++++++++++++++++++++-
 locales/ko-GS.yml |   4 +-
 locales/ru-RU.yml |   8 ++++
 locales/th-TH.yml |  79 +++++++++++++++++++++++++++++++
 locales/zh-CN.yml |  37 +++++++++++++--
 locales/zh-TW.yml |  29 +++++++++++-
 12 files changed, 485 insertions(+), 43 deletions(-)

diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index b9f3fecc76..748f6f03c0 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -2,7 +2,7 @@
 _lang_: "Català"
 headlineMisskey: "Una xarxa connectada per notes"
 introMisskey: "Benvingut! Misskey és un servei de microblogging descentralitzat de codi obert.\nCrea \"notes\" per compartir els teus pensaments amb tots els que t'envolten. 📡\nAmb \"reaccions\", també pots expressar ràpidament els teus sentiments sobre les notes de tothom. 👍\nExplorem un món nou! 🚀"
-poweredByMisskeyDescription: "{name} És un del serveis (anomenats instàncies de Misskey) que utilitzen la plataforma de codi obert <b>Misskey</b>."
+poweredByMisskeyDescription: "{name} És un dels serveis (anomenats instàncies de Misskey) que utilitzen la plataforma de codi obert <b>Misskey</b>."
 monthAndDay: "{day}/{month}"
 search: "Cercar"
 notifications: "Notificacions"
@@ -10,6 +10,7 @@ username: "Nom d'usuari"
 password: "Contrasenya"
 initialPasswordForSetup: "Contrasenya inicial per la configuració inicial"
 initialPasswordIsIncorrect: "La contrasenya no és correcta."
+initialPasswordForSetupDescription: "Fes servir la contrasenya que has fet servir al fitxer de configuració, si tu mateix has instal·lat Misskey.\nSi fas servir una empresa d'allotjament de Misskey, fes servir la contrasenya que t'han donat.\nSi no has posat cap contrasenya deixar l'espai en blanc."
 forgotPassword: "Contrasenya oblidada"
 fetchingAsApObject: "Cercant en el Fediverse..."
 ok: "OK"
@@ -17,7 +18,7 @@ gotIt: "Ho he entès!"
 cancel: "Cancel·lar"
 noThankYou: "No, gràcies"
 enterUsername: "Introdueix el teu nom d'usuari"
-renotedBy: "Impulsat per {usuari}"
+renotedBy: "Impulsat per {user}"
 noNotes: "Cap nota"
 noNotifications: "Cap notificació"
 instance: "Servidor"
@@ -946,6 +947,9 @@ oneHour: "1 hora"
 oneDay: "Un dia"
 oneWeek: "Una setmana"
 oneMonth: "Un mes"
+threeMonths: "3 mesos"
+oneYear: "1 any"
+threeDays: "3 dies"
 reflectMayTakeTime: "Això pot trigar una estona a tenir efecte"
 failedToFetchAccountInformation: "No es pot obtenir la informació del compte"
 rateLimitExceeded: "S'ha arribat al màxim de peticions"
@@ -1086,6 +1090,7 @@ retryAllQueuesConfirmTitle: "Tornar a intentar-ho tot?"
 retryAllQueuesConfirmText: "Això farà que la càrrega del servidor augmenti temporalment."
 enableChartsForRemoteUser: "Generar gràfiques d'usuaris remots"
 enableChartsForFederatedInstances: "Generar gràfiques d'instàncies remotes"
+enableStatsForFederatedInstances: "Activa les estadístiques de les instàncies remotes federades"
 showClipButtonInNoteFooter: "Afegir \"Retall\" al menú d'acció de la nota"
 reactionsDisplaySize: "Mida de les reaccions"
 limitWidthOfReaction: "Limitar l'amplada màxima de la reacció i mostrar-les en una mida reduïda "
@@ -1287,6 +1292,25 @@ passkeyVerificationSucceededButPasswordlessLoginDisabled: "La verificació de la
 messageToFollower: "Missatge als meus seguidors"
 target: "Assumpte "
 testCaptchaWarning: "És una característica dissenyada per a la prova de CAPTCHA. <strong>No l'utilitzes en l'entorn real.</strong>"
+prohibitedWordsForNameOfUser: "Noms prohibits per escollir noms d'usuari "
+prohibitedWordsForNameOfUserDescription: "Si qualsevol d'aquestes paraules es troben a un nom d'usuari la creació de l'usuari no es durà a terme. Als moderadors no els afecta aquesta restricció."
+yourNameContainsProhibitedWords: "El nom conté paraules prohibides "
+yourNameContainsProhibitedWordsDescription: "Si de veritat vols fer servir aquest nom posat en contacte amb l'administrador."
+thisContentsAreMarkedAsSigninRequiredByAuthor: "L'autor requereix l'inici de sessió per poder veure"
+lockdown: "Bloquejat"
+pleaseSelectAccount: "Seleccionar un compte"
+_accountSettings:
+  requireSigninToViewContents: "És obligatori l'inici de sessió per poder veure el contingut"
+  requireSigninToViewContentsDescription1: "Es requereix l'inici de sessió per poder veure totes les notes i el contingut que has creat. Amb això esperem evitar que els rastrejadors recopilin informació."
+  requireSigninToViewContentsDescription2: "També es desactivaran les vistes prèvies d'URLS (OGP), la incrustació a pàgines web i la visualització des de servidors que no admetin la citació de notes."
+  requireSigninToViewContentsDescription3: "Aquestes restriccions pot ser que no s'apliquin als continguts federats en servidors remots."
+  makeNotesFollowersOnlyBefore: "Permetre que les notes antigues només es mostrin als seguidors."
+  makeNotesFollowersOnlyBeforeDescription: "Mentre aquesta funció estigui activada, les notes que hagin passat la data i hora fixada o hagi passat els temps establert seran visibles només per als teus seguidors. Quan es desactivi, també es restableix l'estat públic de la nota."
+  makeNotesHiddenBefore: "Fes que les notes antigues siguin privades"
+  makeNotesHiddenBeforeDescription: "Mentres aquesta funció estigui activada les notes que hagin superat una data i hora fixada o hagi passat el temps establert només seran visibles per a tu. Si la desactives es restablirà també l'estat públic de les notes."
+  mayNotEffectForFederatedNotes: "Això pot ser que no afecti les notes federades."
+  notesHavePassedSpecifiedPeriod: "Notes publicades durant un període de temps especificat."
+  notesOlderThanSpecifiedDateAndTime: "Notes més antigues de la data i temps especificat "
 _abuseUserReport:
   forward: "Reenviar "
   forwardDescription: "Reenvia l'informe a una altra instància com un compte del sistema anònima."
@@ -2151,8 +2175,11 @@ _auth:
   permissionAsk: "Aquesta aplicació demana els següents permisos"
   pleaseGoBack: "Si us plau, torna a l'aplicació"
   callback: "Tornant a l'aplicació"
+  accepted: "Accés garantit"
   denied: "Accés denegat"
+  scopeUser: "Opera com si fossis aquest usuari"
   pleaseLogin: "Si us plau, identificat per autoritzar l'aplicació."
+  byClickingYouWillBeRedirectedToThisUrl: "Si es garanteix l'accés, seràs redirigit automàticament a la següent adreça URL"
 _antennaSources:
   all: "Totes les publicacions"
   homeTimeline: "Publicacions dels usuaris seguits"
@@ -2402,7 +2429,8 @@ _notification:
   renotedBySomeUsers: "L'han impulsat {n} usuaris"
   followedBySomeUsers: "Et segueixen {n} usuaris"
   flushNotification: "Netejar notificacions"
-  exportOfXCompleted: "Completada l'exportació de {n}"
+  exportOfXCompleted: "Completada l'exportació de {x}"
+  login: "Algú ha iniciat sessió "
   _types:
     all: "Tots"
     note: "Notes noves"
@@ -2485,6 +2513,8 @@ _webhookSettings:
     abuseReport: "Quan reps un nou informe de moderació "
     abuseReportResolved: "Quan resols un informe de moderació "
     userCreated: "Quan es crea un usuari"
+    inactiveModeratorsWarning: "Quan el compte d'un moderador no té activitat durant un temps"
+    inactiveModeratorsInvitationOnlyChanged: "Quan el compte d'un moderador no té activitat durant un temps, i el servidor es canvia a registre per invitacions"
   deleteConfirm: "Segur que vols esborrar el webhook?"
   testRemarks: "Si feu clic al botó a la dreta de l'interruptor, podeu enviar un webhook de prova amb dades dummy."
 _abuseReport:
@@ -2612,8 +2642,81 @@ _dataSaver:
     description: "Les imatges en miniatura que serveixen com a vista prèvia de les URLs no es tornaran a carregar."
   _code:
     title: "Ressaltat del codi "
+    description: "Quan s'utilitza codi MFM, no es llegeix fins que es copiï. En els punts destacats del codi s'han de llegir els fitxers definits per a cada llengua que resulti alt, però no es poden llegir automàticament, per la qual cosa es poden reduir les quantitats de comunicació."
+_hemisphere:
+  N: "Hemisferi Nord "
+  S: "Hemisferi Sud"
+  caption: "El fan servir alguns clients per determinar l'estació de l'any."
 _reversi:
+  reversi: "Reversi"
+  gameSettings: "Opcions del joc"
+  chooseBoard: "Escull un taulell"
+  blackOrWhite: "Negres/Blanques"
+  blackIs: "{name} juga amb negres "
+  rules: "Regles"
+  thisGameIsStartedSoon: "El joc començarà en breu"
+  waitingForOther: "Esperant la tirada de l'oponent "
+  waitingForMe: "Esperant el teu torn"
+  waitingBoth: "Prepara't "
+  ready: "Preparat "
+  cancelReady: " No preparat "
+  opponentTurn: "Torn de l'oponent "
+  myTurn: "El teu torn"
+  turnOf: "Li toca a {name}"
+  pastTurnOf: "Torn de {name}"
+  surrender: "Rendeix-te"
+  surrendered: "T'has rendit"
+  timeout: "Temps esgotat"
+  drawn: "Empat"
+  won: "{name} ha guanyat"
+  black: "Negres"
+  white: "Blanques"
   total: "Total"
+  turnCount: "Torn {count}"
+  myGames: "Jugades"
+  allGames: "Totes les jugades"
+  ended: "Acabat"
+  playing: "Jugant"
+  isLlotheo: "Qui tingui menys pedres guanya (Llotheo)"
+  loopedMap: "Mapa de recursiu"
+  canPutEverywhere: "Les fitxes es poden posar a qualsevol lloc"
+  timeLimitForEachTurn: "Temps límit per jugada"
+  freeMatch: "Partida lliure"
+  lookingForPlayer: "Buscant contrincant..."
+  gameCanceled: "La partida s'ha cancel·lat "
+  shareToTlTheGameWhenStart: "Compartir la partida a la línia de temps quan comenci"
+  iStartedAGame: "La partida ha començat! #MisskeyReversi"
+  opponentHasSettingsChanged: "L'oponent h canviat la seva configuració "
+  allowIrregularRules: "Regles irregulars (totalment lliure)"
+  disallowIrregularRules: "Sense regles irregulars"
+  showBoardLabels: "Mostrar el número de línia i columna al tauler de joc"
+  useAvatarAsStone: "Fer servir els avatars dels usuaris com a fitxes"
+_offlineScreen:
+  title: "Fora de línia - No es pot connectar amb el servidor"
+  header: "Impossible connectar amb el servidor"
+_urlPreviewSetting:
+  title: "Configuració per a la previsualització de l'URL"
+  enable: "Activa la previsualització de l'URL"
+  timeout: "Temps màxim per carregar la previsualització de l'URL (ms)"
+  timeoutDescription: "Si l'obtenció de la previsualització triga més que el temps establert, no es generarà la vista prèvia."
+  maximumContentLength: "Longitud màxima del contingut (bytes)"
+  maximumContentLengthDescription: "Si la màxima longitud és més gran que aquest valor, la previsualització no es generarà."
+  requireContentLength: "Generar la previsualització només si es pot obtenir la longitud màxima "
+  requireContentLengthDescription: "Si l'altre servidor no proporciona la longitud màxima, la previsualització no es generarà."
+  userAgent: "User-Agent"
+  userAgentDescription: "Estableix l'User-Agent que és farà servir per a la recuperació de la vista prèvia. Si és deixa en blanc es farà servir l'User-Agent per defecte."
+  summaryProxy: "Proxy endpoints per generar vistes prèvies"
+  summaryProxyDescription: "La vista prèvia es genera fent servir Summaly proxy, no la genera el mateix Misskey."
+  summaryProxyDescription2: "Els següents paràmetres són passats al proxy com cadenes de consulta. Si el proxy no els admet, s'ignoren els valors configurats."
+_mediaControls:
+  pip: "Imatge sobre impressionada "
+  playbackRate: "Velocitat de reproducció "
+  loop: "Reproducció en bucle"
+_contextMenu:
+  title: "Menú contextual"
+  app: "Aplicació "
+  appWithShift: "Aplicació amb la tecla shift"
+  native: "Interfície del navegador"
 _embedCodeGen:
   title: "Personalitza el codi per incrustar"
   header: "Mostrar la capçalera"
@@ -2628,3 +2731,9 @@ _embedCodeGen:
   generateCode: "Crea el codi per incrustar"
   codeGenerated: "Codi generat"
   codeGeneratedDescription: "Si us plau, enganxeu el codi generat al lloc web."
+_selfXssPrevention:
+  warning: "Advertència "
+  title: "\"Enganxa qualsevol cosa en aquesta finestra\"  És tot un engany."
+  description1: "Si posa alguna cosa al seu compte, un usuari malintencionat podria segrestar-la o robar-li les dades."
+  description2: "Si no entens que estàs fent %cpara ara mateix i tanca la finestra."
+  description3: "Per obtenir més informació. {link}"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 6ea7fb4f8d..8570addfa2 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -331,7 +331,6 @@ selectFile: "Select a file"
 selectFiles: "Select files"
 selectFolder: "Select a folder"
 selectFolders: "Select folders"
-fileNotSelected: ""
 renameFile: "Rename file"
 folderName: "Folder name"
 createFolder: "Create a folder"
@@ -947,6 +946,9 @@ oneHour: "One hour"
 oneDay: "One day"
 oneWeek: "One week"
 oneMonth: "One month"
+threeMonths: "3 months"
+oneYear: "1 year"
+threeDays: "3 days"
 reflectMayTakeTime: "It may take some time for this to be reflected."
 failedToFetchAccountInformation: "Could not fetch account information"
 rateLimitExceeded: "Rate limit exceeded"
@@ -1087,6 +1089,7 @@ retryAllQueuesConfirmTitle: "Really retry all?"
 retryAllQueuesConfirmText: "This will temporarily increase the server load."
 enableChartsForRemoteUser: "Generate remote user data charts"
 enableChartsForFederatedInstances: "Generate remote instance data charts"
+enableStatsForFederatedInstances: "Receive remote server stats"
 showClipButtonInNoteFooter: "Add \"Clip\" to note action menu"
 reactionsDisplaySize: "Reaction display size"
 limitWidthOfReaction: "Limit the maximum width of reactions and display them in reduced size."
@@ -1287,6 +1290,26 @@ passkeyVerificationFailed: "Passkey verification has failed."
 passkeyVerificationSucceededButPasswordlessLoginDisabled: "Passkey verification has succeeded but password-less login is disabled."
 messageToFollower: "Message to followers"
 target: "Target"
+testCaptchaWarning: "This function is intended for CAPTCHA testing purposes.\n<strong>Do not use in a production environment.</strong>"
+prohibitedWordsForNameOfUser: "Prohibited words for user names"
+prohibitedWordsForNameOfUserDescription: "If any of the strings in this list are included in the user's name, the name will be denied. Users with moderator privileges are not affected by this restriction."
+yourNameContainsProhibitedWords: "Your name contains prohibited words"
+yourNameContainsProhibitedWordsDescription: "If you wish to use this name, please contact your server administrator."
+thisContentsAreMarkedAsSigninRequiredByAuthor: "Set by the author to require login to view"
+lockdown: "Lockdown"
+pleaseSelectAccount: "Select an account"
+_accountSettings:
+  requireSigninToViewContents: "Require sign-in to view contents"
+  requireSigninToViewContentsDescription1: "Require login to view all notes and other content you have created. This will have the effect of preventing crawlers from collecting your information."
+  requireSigninToViewContentsDescription2: "Content will not be displayed in URL previews (OGP), embedded in web pages, or on servers that don't support note quotes."
+  requireSigninToViewContentsDescription3: "These restrictions may not apply to federated content from other remote servers."
+  makeNotesFollowersOnlyBefore: "Make past notes to be displayed only to followers"
+  makeNotesFollowersOnlyBeforeDescription: "While this feature is enabled, only followers can see notes past the set date and time or have been visible for a set time. When it is deactivated, the note publication status will also be restored."
+  makeNotesHiddenBefore: "Make past notes private"
+  makeNotesHiddenBeforeDescription: "While this feature is enabled, notes that are past the set date and time or have been visible only to you. When it is deactivated, the note publication status will also be restored."
+  mayNotEffectForFederatedNotes: "Notes federated to a remote server may not be effective."
+  notesHavePassedSpecifiedPeriod: "Note that the specified time has passed"
+  notesOlderThanSpecifiedDateAndTime: "Notes before the specified date and time"
 _abuseUserReport:
   forward: "Forward"
   forwardDescription: "Forward the report to a remote server as an anonymous system account."
@@ -1431,6 +1454,7 @@ _serverSettings:
   reactionsBufferingDescription: "When enabled, performance during reaction creation will be greatly improved, reducing the load on the database. However, Redis memory usage will increase."
   inquiryUrl: "Inquiry URL"
   inquiryUrlDescription: "Specify a URL for the inquiry form to the server maintainer or a web page for the contact information."
+  thisSettingWillAutomaticallyOffWhenModeratorsInactive: "If no moderator activity is detected for a while, this setting will be automatically turned off to prevent spam."
 _accountMigration:
   moveFrom: "Migrate another account to this one"
   moveFromSub: "Create alias to another account"
@@ -2150,8 +2174,11 @@ _auth:
   permissionAsk: "This application requests the following permissions"
   pleaseGoBack: "Please go back to the application"
   callback: "Returning to the application"
+  accepted: "Access granted"
   denied: "Access denied"
+  scopeUser: "Operate as the following user"
   pleaseLogin: "Please log in to authorize applications."
+  byClickingYouWillBeRedirectedToThisUrl: "When access is granted, you will automatically be redirected to the following URL"
 _antennaSources:
   all: "All notes"
   homeTimeline: "Notes from followed users"
@@ -2485,6 +2512,8 @@ _webhookSettings:
     abuseReport: "When received a new report"
     abuseReportResolved: "When resolved report"
     userCreated: "When user is created"
+    inactiveModeratorsWarning: "When moderators have been inactive for a while"
+    inactiveModeratorsInvitationOnlyChanged: "When a moderator has been inactive for a while, and the server is changed to invitation-only"
   deleteConfirm: "Are you sure you want to delete the Webhook?"
   testRemarks: "Click the button to the right of the switch to send a test Webhook with dummy data."
 _abuseReport:
diff --git a/locales/es-ES.yml b/locales/es-ES.yml
index d574999e40..7731598152 100644
--- a/locales/es-ES.yml
+++ b/locales/es-ES.yml
@@ -8,6 +8,8 @@ search: "Buscar"
 notifications: "Notificaciones"
 username: "Nombre de usuario"
 password: "Contraseña"
+initialPasswordForSetup: "Contraseña para iniciar la inicialización"
+initialPasswordIsIncorrect: "La contraseña para iniciar la configuración inicial es incorrecta."
 forgotPassword: "Olvidé mi contraseña"
 fetchingAsApObject: "Buscando en el fediverso"
 ok: "OK"
@@ -502,6 +504,8 @@ uiLanguage: "Idioma de visualización de la interfaz"
 aboutX: "Acerca de {x}"
 emojiStyle: "Estilo de emoji"
 native: "Nativo"
+menuStyle: "Diseño del menú"
+style: "Diseño"
 showNoteActionsOnlyHover: "Mostrar acciones de la nota sólo al pasar el cursor"
 showReactionsCount: "Mostrar el número de reacciones en las notas"
 noHistory: "No hay datos en el historial"
@@ -925,6 +929,9 @@ oneHour: "1 hora"
 oneDay: "1 día"
 oneWeek: "1 semana"
 oneMonth: "1 mes"
+threeMonths: "Tres meses"
+oneYear: "Un año"
+threeDays: "Tres días"
 reflectMayTakeTime: "Puede pasar un tiempo hasta que se reflejen los cambios"
 failedToFetchAccountInformation: "No se pudo obtener información de la cuenta"
 rateLimitExceeded: "Se excedió el límite de peticiones"
@@ -1240,6 +1247,14 @@ useNativeUIForVideoAudioPlayer: "Usar la interfaz del navegador cuando se reprod
 keepOriginalFilename: "Mantener el nombre original del archivo"
 noDescription: "No hay descripción"
 alwaysConfirmFollow: "Confirmar siempre cuando se sigue a alguien"
+inquiry: "Contacto"
+tryAgain: "Por favor , inténtalo de nuevo"
+performance: "Rendimiento"
+unknownWebAuthnKey: "Esto no se ha registrado llave maestra."
+messageToFollower: "Mensaje a seguidores"
+_abuseUserReport:
+  accept: "Acepte"
+  reject: "repudio"
 _delivery:
   stop: "Suspendido"
   _type:
@@ -2340,6 +2355,7 @@ _notification:
     roleAssigned: "Rol asignado"
     achievementEarned: "Logro desbloqueado"
     login: "Iniciar sesión"
+    test: "Pruebas de nofiticaciones"
     app: "Notificaciones desde aplicaciones"
   _actions:
     followBack: "Te sigue de vuelta"
@@ -2398,6 +2414,8 @@ _webhookSettings:
     renote: "Cuando reciba un \"re-note\""
     reaction: "Cuando se recibe una reacción"
     mention: "Cuando hay una mención"
+  _systemEvents:
+    userCreated: "Cuando se crea el usuario."
 _abuseReport:
   _notificationRecipient:
     _recipientType:
diff --git a/locales/hu-HU.yml b/locales/hu-HU.yml
index acc27ed092..d0fdc027e9 100644
--- a/locales/hu-HU.yml
+++ b/locales/hu-HU.yml
@@ -1,5 +1,5 @@
 ---
-_lang_: "Japán"
+_lang_: "Magyar"
 monthAndDay: "{month}.{day}."
 search: "Keresés"
 notifications: "Értesítések"
diff --git a/locales/id-ID.yml b/locales/id-ID.yml
index ce3958b167..5d51d2dc78 100644
--- a/locales/id-ID.yml
+++ b/locales/id-ID.yml
@@ -196,6 +196,7 @@ followConfirm: "Apakah kamu yakin ingin mengikuti {name}?"
 proxyAccount: "Akun proksi"
 proxyAccountDescription: "Akun proksi merupakan sebuah akun yang bertindak sebagai pengikut instansi luar untuk pengguna dalam kondisi tertentu. Sebagai contoh, ketika pengguna menambahkan seorang pengguna instansi luar ke dalam daftar, aktivitas dari pengguna instansi luar tidak akan disampaikan ke instansi apabila tidak ada pengguna lokal yang mengikuti pengguna tersebut, dengan begitu akun proksilah yang akan mengikutinya."
 host: "Host"
+selectSelf: "Pilih diri sendiri"
 selectUser: "Pilih pengguna"
 recipient: "Penerima"
 annotation: "Keterangan konten"
@@ -232,6 +233,7 @@ blockedInstances: "Instansi terblokir"
 blockedInstancesDescription: "Daftar nama host dari instansi yang diperlukan untuk diblokir. Instansi yang didaftarkan tidak akan dapat berkomunikasi dengan instansi ini."
 silencedInstances: "Instansi yang disenyapkan"
 silencedInstancesDescription: "Daftar nama host dari instansi yang ingin kamu senyapkan. Semua akun dari instansi yang terdaftar akan diperlakukan sebagai disenyapkan. Hal ini membuat akun hanya dapat membuat permintaan mengikuti, dan tidak dapat menyebutkan akun lokal apabila tidak mengikuti. Hal ini tidak akan mempengaruhi instansi yang diblokir."
+federationAllowedHosts: "Server yang membolehkan federasi"
 muteAndBlock: "Bisukan / Blokir"
 mutedUsers: "Pengguna yang dibisukan"
 blockedUsers: "Pengguna yang diblokir"
@@ -330,6 +332,7 @@ renameFolder: "Ubah nama folder"
 deleteFolder: "Hapus folder"
 folder: "Folder"
 addFile: "Tambahkan berkas"
+showFile: "Tampilkan berkas"
 emptyDrive: "Drive kosong"
 emptyFolder: "Folder kosong"
 unableToDelete: "Tidak dapat menghapus"
@@ -504,6 +507,8 @@ uiLanguage: "Bahasa antarmuka pengguna"
 aboutX: "Tentang {x}"
 emojiStyle: "Gaya emoji"
 native: "Native"
+menuStyle: "Gaya menu"
+style: "Gaya"
 showNoteActionsOnlyHover: "Hanya tampilkan aksi catatan saat ditunjuk"
 showReactionsCount: "Lihat jumlah reaksi dalam catatan"
 noHistory: "Tidak ada riwayat"
@@ -927,6 +932,9 @@ oneHour: "1 Jam"
 oneDay: "1 Hari"
 oneWeek: "1 Bulan"
 oneMonth: "satu bulan"
+threeMonths: "3 bulan"
+oneYear: "1 tahun"
+threeDays: "3 hari"
 reflectMayTakeTime: "Mungkin perlu beberapa saat untuk dicerminkan."
 failedToFetchAccountInformation: "Gagal untuk mendapatkan informasi akun"
 rateLimitExceeded: "Batas sudah terlampaui"
@@ -1101,6 +1109,7 @@ preservedUsernames: "Nama pengguna tercadangkan"
 preservedUsernamesDescription: "Daftar nama pengguna yang dicadangkan dipisah dengan baris baru. Nama pengguna berikut akan tidak dapat dipakai pada pembuatan akun normal, namun dapat digunakan oleh admin untuk membuat akun baru. Akun yang sudah ada dengan menggunakan nama pengguna ini tidak akan terpengaruh."
 createNoteFromTheFile: "Buat catatan dari berkas ini"
 archive: "Arsipkan"
+archived: "Diarsipkan"
 channelArchiveConfirmTitle: "Yakin untuk mengarsipkan {name}?"
 channelArchiveConfirmDescription: "Kanal yang diarsipkan tidak akan muncul pada daftar kanal atau hasil pencarian. Postingan baru juga tidak dapat ditambahkan lagi."
 thisChannelArchived: "Kanal ini telah diarsipkan."
@@ -1111,6 +1120,7 @@ preventAiLearning: "Tolak penggunaan Pembelajaran Mesin (AI Generatif)"
 preventAiLearningDescription: "Minta perayap web untuk tidak menggunakan materi teks atau gambar yang telah diposting ke dalam set data Pembelajaran Mesin (Prediktif / Generatif). Hal ini dicapai dengan menambahkan flag HTML-Response \"noai\" ke masing-masing konten. Pencegahan penuh mungkin tidak dapat dicapai dengan flag ini, karena juga dapat diabaikan begitu saja."
 options: "Opsi peran"
 specifyUser: "Pengguna spesifik"
+openTagPageConfirm: "Apakah ingin membuka laman tagar?"
 failedToPreviewUrl: "Tidak dapat dipratinjau"
 update: "Perbarui"
 rolesThatCanBeUsedThisEmojiAsReaction: "Peran yang dapat menggunakan emoji ini sebagai reaksi"
@@ -1243,6 +1253,18 @@ noDescription: "Tidak ada deskripsi"
 alwaysConfirmFollow: "Selalu konfirmasi ketika mengikuti"
 inquiry: "Hubungi kami"
 tryAgain: "Silahkan coba lagi."
+createdLists: "Senarai yang dibuat"
+createdAntennas: "Antena yang dibuat"
+fromX: "Dari {x}"
+noteOfThisUser: "Catatan oleh pengguna ini"
+clipNoteLimitExceeded: "Klip ini tak bisa ditambahi lagi catatan."
+performance: "Kinerja"
+modified: "Diubah"
+thereAreNChanges: "Ada {n} perubahan"
+prohibitedWordsForNameOfUser: "Kata yang dilarang untuk nama pengguna"
+_abuseUserReport:
+  accept: "Setuju"
+  reject: "Tolak"
 _delivery:
   status: "Status pengiriman"
   stop: "Ditangguhkan"
@@ -1707,6 +1729,8 @@ _role:
     canSearchNotes: "Penggunaan pencarian catatan"
     canUseTranslator: "Penggunaan penerjemah"
     avatarDecorationLimit: "Jumlah maksimum dekorasi avatar yang dapat diterapkan"
+    canImportAntennas: "Izinkan mengimpor antena"
+    canImportUserLists: "Izinkan mengimpor senarai"
   _condition:
     roleAssignedTo: "Ditugaskan ke peran manual"
     isLocal: "Pengguna lokal"
@@ -1943,6 +1967,7 @@ _soundSettings:
   driveFileTypeWarnDescription: "Pilih berkas audio"
   driveFileDurationWarn: "Audio ini terlalu panjang"
   driveFileDurationWarnDescription: "Audio panjang dapat mengganggu penggunaan Misskey. Masih ingin melanjutkan?"
+  driveFileError: "Tak bisa memuat audio. Mohon ubah pengaturan"
 _ago:
   future: "Masa depan"
   justNow: "Baru saja"
@@ -2415,6 +2440,8 @@ _abuseReport:
   _notificationRecipient:
     _recipientType:
       mail: "Surel"
+      webhook: "Webhook"
+    keywords: "Kata kunci"
 _moderationLogTypes:
   createRole: "Peran telah dibuat"
   deleteRole: "Peran telah dihapus"
@@ -2452,6 +2479,7 @@ _moderationLogTypes:
   deleteAvatarDecoration: "Hapus dekorasi avatar"
   unsetUserAvatar: "Hapus avatar pengguna"
   unsetUserBanner: "Hapus banner pengguna"
+  deleteAccount: "Akun dihapus"
 _fileViewer:
   title: "Rincian berkas"
   type: "Jenis berkas"
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index bcabf1bdb6..8fb6dcd6f2 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -68,7 +68,7 @@ reply: "Rispondi"
 loadMore: "Mostra di più"
 showMore: "Espandi"
 showLess: "Comprimi"
-youGotNewFollower: "Adesso ti segue"
+youGotNewFollower: "Hai un nuovo Follower"
 receiveFollowRequest: "Hai ricevuto una richiesta di follow"
 followRequestAccepted: "Ha accettato la tua richiesta di follow"
 mention: "Menzioni"
@@ -80,14 +80,14 @@ export: "Esporta"
 files: "Allegati"
 download: "Scarica"
 driveFileDeleteConfirm: "Vuoi davvero eliminare il file \"{name}\", e le Note a cui è stato allegato?"
-unfollowConfirm: "Vuoi davvero smettere di seguire {name}?"
+unfollowConfirm: "Vuoi davvero togliere il Following a {name}?"
 exportRequested: "Hai richiesto un'esportazione, e potrebbe volerci tempo. Quando sarà compiuta, il file verrà aggiunto direttamente al Drive."
 importRequested: "Hai richiesto un'importazione. Potrebbe richiedere un po' di tempo."
 lists: "Liste"
 noLists: "Nessuna lista"
 note: "Nota"
 notes: "Note"
-following: "Follow"
+following: "Following"
 followers: "Follower"
 followsYou: "Follower"
 createList: "Aggiungi una nuova lista"
@@ -106,7 +106,7 @@ defaultNoteVisibility: "Privacy predefinita delle note"
 follow: "Segui"
 followRequest: "Richiesta di follow"
 followRequests: "Richieste di follow"
-unfollow: "Smetti di seguire"
+unfollow: "Togli Following"
 followRequestPending: "Richiesta in approvazione"
 enterEmoji: "Inserisci emoji"
 renote: "Rinota"
@@ -195,7 +195,7 @@ setWallpaper: "Imposta sfondo"
 removeWallpaper: "Elimina lo sfondo"
 searchWith: "Cerca: {q}"
 youHaveNoLists: "Non hai ancora creato nessuna lista"
-followConfirm: "Vuoi seguire {name}?"
+followConfirm: "Confermi il Following a {name}?"
 proxyAccount: "Profilo proxy"
 proxyAccountDescription: "Un profilo proxy funziona come follower per i profili remoti, sotto certe condizioni. Ad esempio, quando un profilo locale ne inserisce uno remoto in una lista (senza seguirlo), se nessun altro segue quel profilo remoto, le attività non possono essere distribuite. Dunque, il profilo proxy le seguirà per tutti."
 host: "Host"
@@ -263,7 +263,7 @@ all: "Tutte"
 subscribing: "Iscrizione"
 publishing: "Pubblicazione"
 notResponding: "Nessuna risposta"
-instanceFollowing: "Seguiti dall'istanza"
+instanceFollowing: "Istanza Following"
 instanceFollowers: "Follower dell'istanza"
 instanceUsers: "Profili nell'istanza"
 changePassword: "Aggiorna Password"
@@ -615,7 +615,7 @@ unsetUserBannerConfirm: "Vuoi davvero rimuovere l'intestazione dal profilo?"
 deleteAllFiles: "Elimina tutti i file"
 deleteAllFilesConfirm: "Vuoi davvero eliminare tutti i file?"
 removeAllFollowing: "Annulla tutti i follow"
-removeAllFollowingDescription: "Cancella tutti i follows del server {host}. Per favore, esegui se, ad esempio, l'istanza non esiste più."
+removeAllFollowingDescription: "Togli il Following a tutti i profili su {host}. Utile, ad esempio, quando l'istanza non esiste più."
 userSuspended: "L'utente è in sospensione"
 userSilenced: "Profilo silenziato"
 yourAccountSuspendedTitle: "Questo profilo è sospeso"
@@ -688,7 +688,7 @@ hardWordMute: "Filtro parole forte"
 regexpError: "errore regex"
 regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:"
 instanceMute: "Silenziare l'istanza"
-userSaysSomething: "{name} ha parlato"
+userSaysSomething: "{name} ha detto qualcosa"
 makeActive: "Attiva"
 display: "Visualizza"
 copy: "Copia"
@@ -703,7 +703,7 @@ notificationSetting: "Impostazioni notifiche"
 notificationSettingDesc: "Seleziona il tipo di notifiche da visualizzare."
 useGlobalSetting: "Usa impostazioni generali"
 useGlobalSettingDesc: "Quando attiva, verranno utilizzate le impostazioni notifiche del profilo. Altrimenti si possono segliere impostazioni personalizzate."
-other: "Ulteriori"
+other: "Eccetera"
 regenerateLoginToken: "Genera di nuovo un token di connessione"
 regenerateLoginTokenDescription: "Genera un nuovo token di autenticazione. Solitamente questa operazione non è necessaria: quando si genera un nuovo token, tutti i dispositivi vanno disconnessi."
 theKeywordWhenSearchingForCustomEmoji: "Questa sarà la parola chiave durante la ricerca di emoji personalizzate"
@@ -747,7 +747,7 @@ repliesCount: "Numero di risposte inviate"
 renotesCount: "Numero di note che hai ricondiviso"
 repliedCount: "Numero di risposte ricevute"
 renotedCount: "Numero delle tue note ricondivise"
-followingCount: "Numero di profili seguiti"
+followingCount: "Numero di Following"
 followersCount: "Numero di profili che ti seguono"
 sentReactionsCount: "Numero di reazioni inviate"
 receivedReactionsCount: "Numero di reazioni ricevute"
@@ -901,8 +901,8 @@ pubSub: "Publish/Subscribe del profilo"
 lastCommunication: "La comunicazione più recente"
 resolved: "Risolto"
 unresolved: "Non risolto"
-breakFollow: "Impedire di seguirmi"
-breakFollowConfirm: "Vuoi davvero che questo profilo smetta di seguirti?"
+breakFollow: "Rimuovi Follower"
+breakFollowConfirm: "Vuoi davvero togliere questo Follower?"
 itsOn: "Abilitato"
 itsOff: "Disabilitato"
 on: "Acceso"
@@ -917,7 +917,7 @@ makeReactionsPublicDescription: "La lista delle reazioni che avete fatto è a di
 classic: "Classico"
 muteThread: "Silenziare conversazione"
 unmuteThread: "Riattiva la conversazione"
-followingVisibility: "Visibilità dei profili seguiti"
+followingVisibility: "Visibilità dei Following"
 followersVisibility: "Visibilità dei profili che ti seguono"
 continueThread: "Altre conversazioni"
 deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?"
@@ -947,6 +947,9 @@ oneHour: "1 ora"
 oneDay: "1 giorno"
 oneWeek: "1 settimana"
 oneMonth: "Un mese"
+threeMonths: "3 mesi"
+oneYear: "1 anno"
+threeDays: "3 giorni"
 reflectMayTakeTime: "Potrebbe essere necessario un po' di tempo perché ciò abbia effetto."
 failedToFetchAccountInformation: "Impossibile recuperare le informazioni sul profilo"
 rateLimitExceeded: "Superato il limite di richieste."
@@ -965,7 +968,7 @@ driveCapOverrideLabel: "Modificare la capienza del Drive per questo profilo"
 driveCapOverrideCaption: "Se viene specificato meno di 0, viene annullato."
 requireAdminForView: "Per visualizzarli, è necessario aver effettuato l'accesso con un profilo amministratore."
 isSystemAccount: "Questi profili vengono creati e gestiti automaticamente dal sistema"
-typeToConfirm: "Per eseguire questa operazione, digitare {x}"
+typeToConfirm: "Digita {x} per continuare"
 deleteAccount: "Eliminazione profilo"
 document: "Documento"
 numberOfPageCache: "Numero di pagine cache"
@@ -1020,7 +1023,7 @@ neverShow: "Non mostrare più"
 remindMeLater: "Rimanda"
 didYouLikeMisskey: "Ti piace Misskey?"
 pleaseDonate: "Misskey è il software libero utilizzato su {host}. Offrendo una donazione è più facile continuare a svilupparlo!"
-correspondingSourceIsAvailable: ""
+correspondingSourceIsAvailable: "Il codice sorgente corrispondente è disponibile su {anchor}."
 roles: "Ruoli"
 role: "Ruolo"
 noRole: "Ruolo non trovato"
@@ -1130,7 +1133,7 @@ channelArchiveConfirmDescription: "Un canale archiviato non compare nell'elenco
 thisChannelArchived: "Questo canale è stato archiviato."
 displayOfNote: "Visualizzazione delle Note"
 initialAccountSetting: "Impostazioni iniziali del profilo"
-youFollowing: "Seguiti"
+youFollowing: "Following"
 preventAiLearning: "Impedisci l'apprendimento della IA"
 preventAiLearningDescription: "Aggiungendo il campo \"noai\" alla risposta HTML, si indica ai Robot esterni di non usare testi e allegati per addestrare sistemi di Machine Learning (IA predittiva/generativa). Anche se è impossibile sapere se la richiesta venga onorata o semplicemente ignorata."
 options: "Opzioni del ruolo"
@@ -1293,6 +1296,21 @@ prohibitedWordsForNameOfUser: "Parole proibite (nome utente)"
 prohibitedWordsForNameOfUserDescription: "Il sistema rifiuta di rinominare un utente, se il nome contiene qualsiasi parola nell'elenco. Sono esenti i profili con privilegi di moderazione."
 yourNameContainsProhibitedWords: "Il nome che hai scelto contiene una o più parole vietate"
 yourNameContainsProhibitedWordsDescription: "Se desideri comunque utilizzare questo nome, contatta l''amministrazione."
+thisContentsAreMarkedAsSigninRequiredByAuthor: "L'autore richiede di iscriversi per vedere il contenuto"
+lockdown: "Isolamento"
+pleaseSelectAccount: "Per favore, seleziona un profilo"
+_accountSettings:
+  requireSigninToViewContents: "Per vedere il contenuto, è necessaria l'iscrizione"
+  requireSigninToViewContentsDescription1: "Richiedere l'iscrizione per visualizzare tutte le Note e gli altri contenuti che hai creato. Probabilmente l'effetto è impedire la raccolta di informazioni da parte dei bot crawler."
+  requireSigninToViewContentsDescription2: "La visualizzazione verrà disabilitata a server che non supportano l'anteprima URL (OGP), all'incorporamento nelle pagine Web e alla citazione delle Note."
+  requireSigninToViewContentsDescription3: "Queste restrizioni potrebbero non applicarsi al contenuto federato su server remoti."
+  makeNotesFollowersOnlyBefore: "Rendi visibili solo ai Follower le Note pubblicate in precedenza"
+  makeNotesFollowersOnlyBeforeDescription: "Mentre questa funzione è abilitata, le Note antecedenti al momento impostato, saranno visibili solo ai profili Follower. Disabilitandola nuovamente, verrà ripristinata anche la visibilità pubblica della Nota."
+  makeNotesHiddenBefore: "Nascondi le Note pubblicate in precedenza"
+  makeNotesHiddenBeforeDescription: "Mentre questa funzione è abilitata, le Note antecedenti al momento impostato, saranno visibili soltanto a te (private). Disabilitandola nuovamente, verrà ripristinata anche la visibilità pubblica della Nota."
+  mayNotEffectForFederatedNotes: "Le Note già federate su server remoti potrebbero non essere modificate."
+  notesHavePassedSpecifiedPeriod: "Note antecedenti al periodo specificato"
+  notesOlderThanSpecifiedDateAndTime: "Note antecedenti al momento specificato"
 _abuseUserReport:
   forward: "Inoltra"
   forwardDescription: "Inoltra il report al server remoto, per mezzo di account di sistema, anonimo."
@@ -1378,7 +1396,7 @@ _initialTutorial:
   _timeline:
     title: "Come funziona la Timeline"
     description1: "Misskey fornisce alcune Timeline (sequenze cronologiche di Note). Una di queste potrebbe essere stata disattivata dagli amministratori."
-    home: "le Note provenienti dai profili che segui (follow)."
+    home: "le Note provenienti dai profili che segui (Following)."
     local: "tutte le Note pubblicate dai profili di questa istanza."
     social: "sia le Note della Timeline Home che quelle della Timeline Locale, insieme!"
     global: "le Note da pubblicate da tutte le altre istanze federate con la nostra."
@@ -1416,7 +1434,7 @@ _initialTutorial:
     title: "Il tutorial è finito! 🎉"
     description: "Queste sono solamente alcune delle funzionalità principali di Misskey. Per ulteriori informazioni, {link}."
 _timelineDescription:
-  home: "Nella Timeline Home, la tua cronologia principale, puoi vedere le Note provenienti dai profili che segui (follow)."
+  home: "Nella Timeline Home, la tua cronologia principale, puoi vedere le Note provenienti dai profili che segui (Following)."
   local: "La Timeline Locale, è una cronologia di Note pubblicate da tutti i profili iscritti su questo server."
   social: "La Timeline Sociale, unisce in ordine cronologico l'elenco di Note presenti nella Timeline Home e quella Locale."
   global: "La Timeline Federata ti consente di vedere le Note pubblicate dai profili di tutti gli altri server federati a questo."
@@ -1442,7 +1460,7 @@ _accountMigration:
   moveFrom: "Migra un altro profilo dentro a questo"
   moveFromSub: "Crea un alias verso un altro profilo remoto"
   moveFromLabel: "Profilo da cui migrare #{n}"
-  moveFromDescription: "Se desideri spostare i profili follower da un altro profilo a questo, devi prima creare un alias qui. Assicurati averlo creato PRIMA di eseguire l'attività! Inserisci l'indirizzo del profilo mittente in questo modo: @persona@istanza.it"
+  moveFromDescription: "Se desideri spostare i Follower da un altro profilo a questo, devi prima creare un alias qui. Assicurati averlo creato PRIMA di eseguire l'attività! Inserisci l'indirizzo del profilo mittente in questo modo: @persona@istanza.it"
   moveTo: "Migrare questo profilo verso un un altro"
   moveToLabel: "Profilo verso cui migrare"
   moveCannotBeUndone: "La migrazione è irreversibile, non può essere interrotta o annullata."
@@ -1451,7 +1469,7 @@ _accountMigration:
   startMigration: "Avvia la migrazione"
   migrationConfirm: "Vuoi davvero migrare questo profilo su {account}? L'azione è irreversibile e non potrai più utilizzare questo profilo nel suo stato originale.\nInoltre, assicurati di aver già creato un alias sull'account a cui ti stai trasferendo."
   movedAndCannotBeUndone: "Il tuo profilo è stato migrato.\nLa migrazione non può essere annullata."
-  postMigrationNote: "Questo profilo smetterà di seguire gli altri profili remoti a 24 ore dal termine della migrazione.\nSia i Follow che i Follower scenderanno a zero. I tuoi follower saranno comunque in grado di vedere le Note per soli follower, poiché non smetteranno di seguirti."
+  postMigrationNote: "Questo profilo smetterà di seguire gli altri profili remoti a 24 ore dal termine della migrazione.\nSia i Following che i Follower scenderanno a zero. I tuoi Follower saranno comunque in grado di vedere le Note per soli Follower, poiché non smetteranno di seguirti."
   movedTo: "Profilo verso cui migrare"
 _achievements:
   earnedAt: "Data di conseguimento"
@@ -1844,7 +1862,7 @@ _gallery:
   unlike: "Non mi piace più"
 _email:
   _follow:
-    title: "Adesso ti segue"
+    title: "Follower aggiuntivo"
   _receiveFollowRequest:
     title: "Hai ricevuto una richiesta di follow"
 _plugin:
@@ -1908,7 +1926,7 @@ _channel:
   removeBanner: "Rimuovi intestazione"
   featured: "Di tendenza"
   owned: "I miei canali"
-  following: "Seguiti"
+  following: "Following"
   usersCount: "{n} partecipanti"
   notesCount: "{n} note"
   nameAndDescription: "Nome e descrizione"
@@ -2074,7 +2092,7 @@ _permissions:
   "read:favorites": "Visualizza i tuoi preferiti"
   "write:favorites": "Gestisci i tuoi preferiti"
   "read:following": "Vedi le informazioni di follow"
-  "write:following": "Following di altri profili"
+  "write:following": "Aggiungere e togliere Following"
   "read:messaging": "Visualizzare la chat"
   "write:messaging": "Gestire la chat"
   "read:mutes": "Vedi i profili silenziati"
@@ -2157,11 +2175,14 @@ _auth:
   permissionAsk: "Questa app richiede le seguenti autorizzazioni:"
   pleaseGoBack: "Si prega di ritornare sulla app"
   callback: "Ritornando sulla app"
+  accepted: "Accesso concesso"
   denied: "Accesso negato"
+  scopeUser: "Sto funzionando per il seguente profilo"
   pleaseLogin: "Per favore accedi al tuo account per cambiare i permessi dell'applicazione"
+  byClickingYouWillBeRedirectedToThisUrl: "Consentendo l'accesso, si verrà reindirizzati presso questo indirizzo URL"
 _antennaSources:
   all: "Tutte le note"
-  homeTimeline: "Note dagli utenti che segui"
+  homeTimeline: "Note dai tuoi Following"
   users: "Note dagli utenti selezionati"
   userList: "Note dagli utenti della lista selezionata"
   userBlacklist: "Tutte le Note tranne quelle di uno o più profili specificati"
@@ -2274,7 +2295,7 @@ _exportOrImport:
   allNotes: "Tutte le note"
   favoritedNotes: "Note preferite"
   clips: "Clip"
-  followingList: "Follow"
+  followingList: "Following"
   muteList: "Elenco profili silenziati"
   blockingList: "Elenco profili bloccati"
   userLists: "Liste"
@@ -2390,7 +2411,7 @@ _notification:
   youGotReply: "{name} ti ha risposto"
   youGotQuote: "{name} ha citato la tua Nota e ha detto"
   youRenoted: "{name} ha rinotato"
-  youWereFollowed: "Adesso ti segue"
+  youWereFollowed: "Follower aggiuntivo"
   youReceivedFollowRequest: "Hai ricevuto una richiesta di follow"
   yourFollowRequestAccepted: "La tua richiesta di follow è stata accettata"
   pollEnded: "Risultati del sondaggio."
@@ -2413,7 +2434,7 @@ _notification:
   _types:
     all: "Tutto"
     note: "Nuove Note"
-    follow: "Nuovi profili follower"
+    follow: "Follower"
     mention: "Menzioni"
     reply: "Risposte"
     renote: "Rinota"
@@ -2429,7 +2450,7 @@ _notification:
     test: "Prova la notifica"
     app: "Notifiche da applicazioni"
   _actions:
-    followBack: "Segui"
+    followBack: "Following ricambiato"
     reply: "Rispondi"
     renote: "Rinota"
 _deck:
@@ -2481,7 +2502,7 @@ _webhookSettings:
   trigger: "Trigger"
   active: "Attivo"
   _events:
-    follow: "Quando segui un profilo"
+    follow: "Quando aggiungi Following"
     followed: "Quando ti segue un profilo"
     note: "Quando pubblichi una Nota"
     reply: "Quando rispondono ad una Nota"
@@ -2710,3 +2731,9 @@ _embedCodeGen:
   generateCode: "Crea il codice di incorporamento"
   codeGenerated: "Codice generato"
   codeGeneratedDescription: "Incolla il codice appena generato sul tuo sito web."
+_selfXssPrevention:
+  warning: "Avviso"
+  title: "\"Incolla qualcosa su questa schermata\" è tutta una truffa."
+  description1: "Incollando qualcosa qui, malintenzionati potrebbero prendere il controllo del tuo profilo o rubare i tuoi dati personali."
+  description2: "Se non sai esattamente cosa stai facendo, %c smetti subito e chiudi questa finestra."
+  description3: "Per favore, controlla questo collegamento per avere maggiori dettagli. {link}"
diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml
index 0a8b3828f2..50132c0645 100644
--- a/locales/ja-KS.yml
+++ b/locales/ja-KS.yml
@@ -8,6 +8,9 @@ search: "探す"
 notifications: "通知"
 username: "ユーザー名"
 password: "パスワード"
+initialPasswordForSetup: "初期設定開始用パスワード"
+initialPasswordIsIncorrect: "初期設定開始用のパスワードがちゃうで。"
+initialPasswordForSetupDescription: "Miskkeyを自分でインストールしたんやったら、設定ファイルに入れたパスワードを使ってや。\nホスティングサービスを使っとるんやったら、サービスから言われたやつを使うんやで。\n別に何も設定しとらんのやったら、何も入れずに空けといてな。"
 forgotPassword: "パスワード忘れたん?"
 fetchingAsApObject: "今ちと連合に照会しとるで"
 ok: "ええで"
@@ -236,6 +239,8 @@ silencedInstances: "サーバーサイレンスされてんねん"
 silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定すんで。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなんねん。ブロックしたインスタンスには影響せーへんで。"
 mediaSilencedInstances: "メディアサイレンスしたサーバー"
 mediaSilencedInstancesDescription: "メディアサイレンスしたいサーバーのホストを改行で区切って設定するで。メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われてな、カスタム絵文字が使えへんようになるで。ブロックしたインスタンスには影響せえへんで。"
+federationAllowedHosts: "連合を許すサーバー"
+federationAllowedHostsDescription: "連合してもいいサーバーのホストを行ごとに区切って設定してや。"
 muteAndBlock: "ミュートとブロック"
 mutedUsers: "ミュートしとるユーザー"
 blockedUsers: "ブロックしとるユーザー"
@@ -334,6 +339,7 @@ renameFolder: "フォルダー名を変える"
 deleteFolder: "フォルダーをほかす"
 folder: "フォルダー"
 addFile: "ファイルを追加"
+showFile: "ファイル出す"
 emptyDrive: "ドライブは空っぽや"
 emptyFolder: "このフォルダーは空や"
 unableToDelete: "消せんかったわ"
@@ -448,6 +454,7 @@ totpDescription: "認証アプリ使うてワンタイムパスワードを入
 moderator: "モデレーター"
 moderation: "モデレーション"
 moderationNote: "モデレーションノート"
+moderationNoteDescription: "モデレーターの中だけで共有するメモを入れれるで。"
 addModerationNote: "モデレーションノートを追加するで"
 moderationLogs: "モデログ"
 nUsersMentioned: "{n}人が投稿"
@@ -509,6 +516,10 @@ uiLanguage: "UIの表示言語"
 aboutX: "{x}について"
 emojiStyle: "絵文字のスタイル"
 native: "ネイティブ"
+menuStyle: "メニューのスタイル"
+style: "スタイル"
+drawer: "ドロワー"
+popup: "ポップアップ"
 showNoteActionsOnlyHover: "ノートの操作部をホバー時のみ表示するで"
 showReactionsCount: "ノートのリアクション数を表示する"
 noHistory: "履歴はないわ。"
@@ -591,6 +602,8 @@ ascendingOrder: "小さい順"
 descendingOrder: "大きい順"
 scratchpad: "スクラッチパッド"
 scratchpadDescription: "スクラッチパッドではAiScriptを色々試すことができるんや。Misskeyに対して色々できるコードを書いて動かしてみたり、結果を見たりできるで。"
+uiInspector: "UIインスペクター"
+uiInspectorDescription: "メモリ上にあるUIコンポーネントのインスタンス一覧を見れるで。UIコンポーネントはUi:C:系関数で生成されるで。"
 output: "出力"
 script: "スクリプト"
 disablePagesScript: "Pagesのスクリプトを無効にしてや"
@@ -909,6 +922,7 @@ followersVisibility: "フォロワーの公開範囲"
 continueThread: "さらにスレッドを見るで"
 deleteAccountConfirm: "アカウントを消すで?ええんか?"
 incorrectPassword: "パスワードがちゃうわ。"
+incorrectTotp: "ワンタイムパスワードが間違っとるか、期限が切れとるみたいやな。"
 voteConfirm: "「{choice}」に投票するんか?"
 hide: "隠す"
 useDrawerReactionPickerForMobile: "ケータイとかのときドロワーで表示するで"
@@ -1073,6 +1087,7 @@ retryAllQueuesConfirmTitle: "もっかいやってみるか?"
 retryAllQueuesConfirmText: "一時的にサーバー重なるかもしれへんで。"
 enableChartsForRemoteUser: "リモートユーザーのチャートを作る"
 enableChartsForFederatedInstances: "リモートサーバーのチャートを作る"
+enableStatsForFederatedInstances: "リモートサーバの情報を取得"
 showClipButtonInNoteFooter: "ノートのアクションにクリップを追加"
 reactionsDisplaySize: "ツッコミの表示のでかさ"
 limitWidthOfReaction: "ツッコミの最大横幅を制限して、ちっさく表示するで"
@@ -1259,6 +1274,32 @@ confirmWhenRevealingSensitiveMedia: "センシティブなメディアを表示
 sensitiveMediaRevealConfirm: "センシティブなメディアやで。表示するんか?"
 createdLists: "作成したリスト"
 createdAntennas: "作成したアンテナ"
+fromX: "{x}から"
+genEmbedCode: "埋め込みコードを作る"
+noteOfThisUser: "このユーザーのノート全部"
+clipNoteLimitExceeded: "これ以上このクリップにノート追加でけへんわ。"
+performance: "パフォーマンス"
+modified: "変更あり"
+discard: "やめる"
+thereAreNChanges: "{n}個の変更があるみたいや"
+signinWithPasskey: "パスキーでログイン"
+unknownWebAuthnKey: "登録されてへんパスキーやな。"
+passkeyVerificationFailed: "パスキーの検証に失敗したで。"
+passkeyVerificationSucceededButPasswordlessLoginDisabled: "パスキーの検証は成功したんやけど、パスワードレスログインが無効になっとるわ。"
+messageToFollower: "フォロワーへのメッセージ"
+target: "対象"
+testCaptchaWarning: "CAPTCHAのテストを目的としてるで。<strong>絶対に本番環境で使わんといてな。絶対やで。</strong>"
+prohibitedWordsForNameOfUser: "禁止ワード(ユーザー名)"
+prohibitedWordsForNameOfUserDescription: "このリストの中にある文字列がユーザー名に入っとったら、その名前に変更できひんようになるで。モデレーター権限があるユーザーは除外や。"
+yourNameContainsProhibitedWords: "その名前は禁止した文字列が含まれとるで"
+yourNameContainsProhibitedWordsDescription: "その名前は禁止した文字列が含まれとるわ。どうしてもって言うなら、サーバー管理者に言うしかないで。"
+_abuseUserReport:
+  forward: "転送"
+  forwardDescription: "匿名のシステムアカウントってことにして、リモートサーバーに通報を転送するで。"
+  resolve: "解決"
+  accept: "ええよ"
+  reject: "あかんよ"
+  resolveTutorial: "内容がええなら「ええよ」を選ぶんや。肯定的に解決されたことにして記録するで。\n逆に、内容がだめなら「あかんよ」を選びいや。否定的に解決されたって記録しとくで。"
 _delivery:
   status: "配信状態"
   stop: "配信せぇへん"
@@ -1393,8 +1434,10 @@ _serverSettings:
   fanoutTimelineDescription: "入れると、おのおのタイムラインを取得するときにめちゃめちゃ動きが良うなって、データベースが軽くなるわ。でも、Redisのメモリ使う量が増えるから注意な。サーバーのメモリが足りんときとか、動きが変なときは切れるで。"
   fanoutTimelineDbFallback: "データベースにフォールバックする"
   fanoutTimelineDbFallbackDescription: "有効にしたら、タイムラインがキャッシュん中に入ってないときにDBにもっかい問い合わせるフォールバック処理ってのをやっとくで。切ったらフォールバック処理をやらんからサーバーはもっと軽くなんねんけど、タイムラインの取得範囲がちょっと減るで。"
+  reactionsBufferingDescription: "有効にしたら、リアクション作るときのパフォーマンスがすっごい上がって、データベースへの負荷が減るで。代わりに、Redisのメモリ使用は増えるで。"
   inquiryUrl: "問い合わせ先URL"
   inquiryUrlDescription: "サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定するで。"
+  thisSettingWillAutomaticallyOffWhenModeratorsInactive: "一定期間モデレーターがおらんかったら、スパムを防ぐためにこの設定は勝手に切られるで。"
 _accountMigration:
   moveFrom: "別のアカウントからこのアカウントに引っ越す"
   moveFromSub: "別のアカウントへエイリアスを作る"
@@ -1726,6 +1769,11 @@ _role:
     canSearchNotes: "ノート探せるかどうか"
     canUseTranslator: "翻訳使えるかどうか"
     avatarDecorationLimit: "アイコンデコのいっちばんつけれる数"
+    canImportAntennas: "アンテナのインポートを許す"
+    canImportBlocking: "ブロックのインポートを許す"
+    canImportFollowing: "フォローのインポートを許す"
+    canImportMuting: "ミュートのインポートを許す"
+    canImportUserLists: "リストのインポートを許す"
   _condition:
     roleAssignedTo: "マニュアルロールにアサイン済み"
     isLocal: "ローカルユーザー"
@@ -2219,6 +2267,9 @@ _profile:
   changeBanner: "バナー画像を変更するで"
   verifiedLinkDescription: "内容をURLに設定すると、リンク先のwebサイトに自分のプロフのリンクが含まれてる場合に所有者確認済みアイコンを表示させることができるで。"
   avatarDecorationMax: "最大{max}つまでデコつけれんで"
+  followedMessage: "フォローされたら返すメッセージ"
+  followedMessageDescription: "フォローされたときに相手に返す短めのメッセージを決めれるで。"
+  followedMessageDescriptionForLockedAccount: "フォローが承認制なら、フォローリクエストをOKしたときに見せるで。"
 _exportOrImport:
   allNotes: "全てのノート"
   favoritedNotes: "お気に入りにしたノート"
@@ -2311,6 +2362,7 @@ _pages:
   eyeCatchingImageSet: "アイキャッチ画像を設定"
   eyeCatchingImageRemove: "アイキャッチ画像を削除"
   chooseBlock: "ブロックを追加"
+  enterSectionTitle: "セクションタイトルを入れる"
   selectType: "種類を選択"
   contentBlocks: "コンテンツ"
   inputBlocks: "入力"
@@ -2356,13 +2408,15 @@ _notification:
   renotedBySomeUsers: "{n}人がリノートしたで"
   followedBySomeUsers: "{n}人にフォローされたで"
   flushNotification: "通知の履歴をリセットする"
+  exportOfXCompleted: "{x}のエクスポートが終わったわ"
+  login: "ログインしとったで"
   _types:
     all: "すべて"
     note: "あんたらの新規投稿"
     follow: "フォロー"
     mention: "メンション"
     reply: "リプライ"
-    renote: "Renote"
+    renote: "リノート"
     quote: "引用"
     reaction: "ツッコミ"
     pollEnded: "アンケートが終了したで"
@@ -2370,12 +2424,14 @@ _notification:
     followRequestAccepted: "フォローが受理されたで"
     roleAssigned: "ロールが付与された"
     achievementEarned: "実績の獲得"
+    exportCompleted: "エクスポート終わった"
     login: "ログイン"
+    test: "通知テスト"
     app: "連携アプリからの通知や"
   _actions:
     followBack: "フォローバック"
     reply: "返事"
-    renote: "Renote"
+    renote: "リノート"
 _deck:
   alwaysShowMainColumn: "いつもメインカラムを表示"
   columnAlign: "カラムの寄せ"
@@ -2436,7 +2492,10 @@ _webhookSettings:
     abuseReport: "ユーザーから通報があったとき"
     abuseReportResolved: "ユーザーからの通報を処理したとき"
     userCreated: "ユーザーが作成されたとき"
+    inactiveModeratorsWarning: "モデレーターがしばらくおらんかったとき"
+    inactiveModeratorsInvitationOnlyChanged: "モデレーターがしばらくおらんかったから、システムが招待制に変えたとき"
   deleteConfirm: "ほんまにWebhookをほかしてもええんか?"
+  testRemarks: "スイッチ右のボタンを押すとダミーデータを使ったテスト用Webhookを送れるで。"
 _abuseReport:
   _notificationRecipient:
     createRecipient: "通報の通知先を追加"
@@ -2480,6 +2539,8 @@ _moderationLogTypes:
   markSensitiveDriveFile: "ファイルをセンシティブ付与"
   unmarkSensitiveDriveFile: "ファイルをセンシティブ解除"
   resolveAbuseReport: "苦情を解決"
+  forwardAbuseReport: "通報を転送"
+  updateAbuseReportNote: "通報のモデレーションノート更新"
   createInvitation: "招待コード作る"
   createAd: "広告を作んで"
   deleteAd: "広告ほかす"
@@ -2491,6 +2552,14 @@ _moderationLogTypes:
   unsetUserBanner: "この子のバナー元に戻す"
   createSystemWebhook: "SystemWebhookを作成"
   updateSystemWebhook: "SystemWebhookを更新"
+  deleteSystemWebhook: "SystemWebhookを削除"
+  createAbuseReportNotificationRecipient: "通報の通知先作る"
+  updateAbuseReportNotificationRecipient: "通報の通知先更新"
+  deleteAbuseReportNotificationRecipient: "通報の通知先消す"
+  deleteAccount: "アカウント消す"
+  deletePage: "ページ消す"
+  deleteFlash: "Playをほかす"
+  deleteGalleryPost: "ギャラリーの投稿をほかす"
 _fileViewer:
   title: "ファイルの詳しい情報"
   type: "ファイルの種類"
@@ -2622,3 +2691,22 @@ _mediaControls:
   pip: "ピクチャインピクチャ"
   playbackRate: "再生速度"
   loop: "ループ再生"
+_contextMenu:
+  title: "コンテキストメニュー"
+  app: "アプリ"
+  appWithShift: "Shiftキーでアプリ"
+  native: "ブラウザのUI"
+_embedCodeGen:
+  title: "埋め込みコードをカスタム"
+  header: "ヘッダー出す"
+  autoload: "勝手に続きを読み込む(非推奨)"
+  maxHeight: "高さの最大値"
+  maxHeightDescription: "0は最大値を指定せえへんけど、ウィジェットが伸び続けるから絶対1以上にしといてや。"
+  maxHeightWarn: "高さの最大値が無効になっとるで。意図してへん変更なら、普通の値に戻してや。"
+  previewIsNotActual: "プレビュー画面で出せる範囲をはみ出したから、ホンマの表示とはちゃうとおもうで。"
+  rounded: "角丸める"
+  border: "外枠に枠線つける"
+  applyToPreview: "プレビューに反映"
+  generateCode: "埋め込みコード作る"
+  codeGenerated: "コード作ったで"
+  codeGeneratedDescription: "作ったコードはウェブサイトに貼っつけて使ってや。"
diff --git a/locales/ko-GS.yml b/locales/ko-GS.yml
index 6c667b48da..1f7faba23a 100644
--- a/locales/ko-GS.yml
+++ b/locales/ko-GS.yml
@@ -468,7 +468,7 @@ tooShort: "억수로 짜립니다"
 tooLong: "억수로 집니다"
 passwordMatched: "맞십니다"
 passwordNotMatched: "안 맞십니다"
-signinWith: "{n}서 로그인"
+signinWith: "{x} 서 로그인"
 signinFailed: "로그인 몬 했십니다. 고 이름이랑 비밀번호 제대로 썼는가 확인해 주이소."
 or: "아니면"
 language: "언어"
@@ -809,11 +809,13 @@ _notification:
   _types:
     follow: "팔로잉"
     mention: "멘션"
+    renote: "리노트"
     quote: "따오기"
     reaction: "반엉"
     login: "로그인"
   _actions:
     reply: "답하기"
+    renote: "리노트"
 _deck:
   _columns:
     notifications: "알림"
diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml
index 70178ec2fd..8174675880 100644
--- a/locales/ru-RU.yml
+++ b/locales/ru-RU.yml
@@ -8,6 +8,9 @@ search: "Поиск"
 notifications: "Уведомления"
 username: "Имя пользователя"
 password: "Пароль"
+initialPasswordForSetup: "Пароль для начала настройки"
+initialPasswordIsIncorrect: "Пароль для запуска настройки неверен"
+initialPasswordForSetupDescription: "Если вы установили Misskey самостоятельно, используйте пароль, который вы указали в файле конфигурации.\nЕсли вы используете что-то вроде хостинга Misskey, используйте предоставленный пароль.\nЕсли вы не установили пароль, оставьте его пустым и продолжайте."
 forgotPassword: "Забыли пароль?"
 fetchingAsApObject: "Приём с других сайтов"
 ok: "Подтвердить"
@@ -232,6 +235,7 @@ clearCachedFilesConfirm: "Удалить все закэшированные ф
 blockedInstances: "Заблокированные инстансы"
 blockedInstancesDescription: "Введите список инстансов, которые хотите заблокировать. Они больше не смогут обмениваться с вашим инстансом."
 silencedInstances: "Заглушённые инстансы"
+federationAllowedHosts: "Серверы, поддерживающие федерацию"
 muteAndBlock: "Скрытие и блокировка"
 mutedUsers: "Скрытые пользователи"
 blockedUsers: "Заблокированные пользователи"
@@ -330,6 +334,7 @@ renameFolder: "Переименовать папку"
 deleteFolder: "Удалить папку"
 folder: "Папка"
 addFile: "Добавить файл"
+showFile: "Посмотреть файл"
 emptyDrive: "Диск пуст"
 emptyFolder: "Папка пуста"
 unableToDelete: "Удаление невозможно"
@@ -443,6 +448,7 @@ totp: "Приложение-аутентификатор"
 totpDescription: "Описание приложения-аутентификатора"
 moderator: "Модератор"
 moderation: "Модерация"
+moderationNote: "Примечания модератора"
 moderationLogs: "Журнал модерации"
 nUsersMentioned: "Упомянуло пользователей: {n}"
 securityKeyAndPasskey: "Ключ безопасности и парольная фраза"
@@ -503,6 +509,8 @@ uiLanguage: "Язык интерфейса"
 aboutX: "Описание {x}"
 emojiStyle: "Стиль эмодзи"
 native: "Системные"
+menuStyle: "Стиль меню"
+style: "Стиль"
 showNoteActionsOnlyHover: "Показывать кнопки у заметок только при наведении"
 showReactionsCount: "Видеть количество реакций на заметках"
 noHistory: "История пока пуста"
diff --git a/locales/th-TH.yml b/locales/th-TH.yml
index c70d448e2b..58cf8f068c 100644
--- a/locales/th-TH.yml
+++ b/locales/th-TH.yml
@@ -8,6 +8,9 @@ search: "ค้นหา"
 notifications: "เเจ้งเตือน"
 username: "ชื่อผู้ใช้"
 password: "รหัสผ่าน"
+initialPasswordForSetup: "รหัสผ่านเริ่มต้นสำหรับการตั้งค่า"
+initialPasswordIsIncorrect: "รหัสผ่านเริ่มต้นสำหรับตั้งค่านั้นไม่ถูกต้องค่ะ"
+initialPasswordForSetupDescription: "ถ้าหากคุณติดตั้ง Misskey เอง ให้ใช้รหัสผ่านที่คุณป้อนในไฟล์กำหนดค่า \nถ้าหากคุณกำลังใช้บริการโฮสต์ Misskey ให้ใช้รหัสผ่านที่ได้รับมา\nถ้ายังไม่มีรหัสผ่าน ให้ข้ามช่องรหัสผ่านไป แล้วกดต่อไป"
 forgotPassword: "ลืมรหัสผ่าน"
 fetchingAsApObject: "กำลังดึงข้อมูลจากสหพันธ์..."
 ok: "ตกลง"
@@ -236,6 +239,8 @@ silencedInstances: "ปิดปากเซิร์ฟเวอร์นี้
 silencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปาก คั่นด้วยการขึ้นบรรทัดใหม่, บัญชีทั้งหมดของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปากเช่นกัน ทำได้เฉพาะคำขอติดตามเท่านั้น และไม่สามารถกล่าวถึงบัญชีในเซิร์ฟเวอร์นี้ได้หากไม่ได้ถูกติดตามกลับ | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก"
 mediaSilencedInstances: "เซิร์ฟเวอร์ที่ถูกปิดปากสื่อ"
 mediaSilencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปากสื่อ คั่นด้วยการขึ้นบรรทัดใหม่, ไฟล์ที่ถูกส่งจากบัญชีของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปาก แล้วจะถูกติดเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน และเอโมจิแบบกำหนดเองก็จะใช้ไม่ได้ด้วย | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก"
+federationAllowedHosts: "เซิร์ฟเวอร์ที่เปิดให้บริการแบบเฟเดอเรชั่น"
+federationAllowedHostsDescription: "ระบุชื่อโฮสต์ของเซิร์ฟเวอร์ที่คุณต้องการอนุญาตให้เชื่อมต่อแบบเฟเดอเรชั่น โดยต้องเว้นวรรคแต่ละบรรทัด"
 muteAndBlock: "ปิดเสียงและบล็อก"
 mutedUsers: "ผู้ใช้ที่ถูกปิดเสียง"
 blockedUsers: "ผู้ใช้ที่ถูกบล็อก"
@@ -334,6 +339,7 @@ renameFolder: "เปลี่ยนชื่อโฟลเดอร์"
 deleteFolder: "ลบโฟลเดอร์"
 folder: "โฟลเดอร์"
 addFile: "เพิ่มไฟล์"
+showFile: "แสดงไฟล์"
 emptyDrive: "ไดรฟ์ของคุณว่างเปล่านะ"
 emptyFolder: "โฟลเดอร์นี้ว่างเปล่า"
 unableToDelete: "ไม่สามารถลบออกได้"
@@ -448,6 +454,7 @@ totpDescription: "ใช้แอปยืนยันตัวตนเพื
 moderator: "ผู้ควบคุม"
 moderation: "การกลั่นกรอง"
 moderationNote: "โน้ตการกลั่นกรอง"
+moderationNoteDescription: "คุณสามารถใส่โน้ตส่วนตัวที่เฉพาะผู้ดูแลระบบเท่านั้นที่สามารถเข้าถึงได้"
 addModerationNote: "เพิ่มโน้ตการกลั่นกรอง"
 moderationLogs: "ปูมการควบคุมดูแล"
 nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} ราย"
@@ -509,6 +516,10 @@ uiLanguage: "ภาษาอินเทอร์เฟซผู้ใช้ง
 aboutX: "เกี่ยวกับ {x}"
 emojiStyle: "สไตล์ของเอโมจิ"
 native: "ภาษาแม่"
+menuStyle: "สไตล์เมนู"
+style: "สไตล์"
+drawer: "ตัววาด"
+popup: "ป๊อปอัพ"
 showNoteActionsOnlyHover: "แสดงการดำเนินการโน้ตเมื่อโฮเวอร์(วางเมาส์เหนือ)เท่านั้น"
 showReactionsCount: "แสดงจำนวนรีแอกชั่นในโน้ต"
 noHistory: "ไม่มีประวัติ"
@@ -591,6 +602,8 @@ ascendingOrder: "เรียงลำดับขึ้น"
 descendingOrder: "เรียงลำดับลง"
 scratchpad: "Scratchpad"
 scratchpadDescription: "Scratchpad ให้สภาพแวดล้อมสำหรับการทดลอง AiScript คุณสามารถเขียนโค้ด/สั่งดำเนินการ/ตรวจสอบผลลัพธ์ ของการโต้ตอบกับ Misskey ได้"
+uiInspector: "ตัวตรวจสอบ UI"
+uiInspectorDescription: "คุณสามารถตรวจสอบรายชื่อเซิร์ฟเวอร์ที่เกี่ยวข้องกับส่วนประกอบอินเตอร์เฟซผู้ใช้ (UI) บนหน่วยความจำของระบบ ส่วนประกอบ UI เหล่านี้จะถูกสร้างขึ้นโดยฟังก์ชัน Ui:C:"
 output: "เอาท์พุต"
 script: "สคริปต์"
 disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ"
@@ -909,6 +922,7 @@ followersVisibility: "การมองเห็นผู้ที่กำล
 continueThread: "ดูความต่อเนื่องเธรด"
 deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
 incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
+incorrectTotp: "รหัสยืนยันตัวตนแบบใช้ครั้งเดียวที่ท่านได้ระบุมานั้น ไม่ถูกต้องหรือหมดอายุลงแล้วค่ะ"
 voteConfirm: "ต้องการโหวต “{choice}” ใช่ไหม?"
 hide: "ซ่อน"
 useDrawerReactionPickerForMobile: "แสดง ตัวจิ้มรีแอคชั่น เป็นแบบลิ้นชัก เมื่อใช้บนมือถือ"
@@ -1073,6 +1087,7 @@ retryAllQueuesConfirmTitle: "ลองใหม่ทั้งหมดจริ
 retryAllQueuesConfirmText: "สิ่งนี้จะเพิ่มการโหลดเซิร์ฟเวอร์ชั่วคราวนะ"
 enableChartsForRemoteUser: "สร้างแผนภูมิข้อมูลผู้ใช้ระยะไกล"
 enableChartsForFederatedInstances: "สร้างแผนภูมิของเซิร์ฟเวอร์ระยะไกล"
+enableStatsForFederatedInstances: "ดึงข้อมูลสถิติจากเซิร์ฟเวอร์ที่อยู่ห่างไกล"
 showClipButtonInNoteFooter: "เพิ่ม “คลิป” ไปยังเมนูสั่งการของโน้ต"
 reactionsDisplaySize: "ขนาดของรีแอคชั่น"
 limitWidthOfReaction: "จำกัดความกว้างสูงสุดของรีแอคชั่นและแสดงให้เล็กลง"
@@ -1259,6 +1274,32 @@ confirmWhenRevealingSensitiveMedia: "ตรวจสอบก่อนแสด
 sensitiveMediaRevealConfirm: "สื่อนี้มีเนื้อหาละเอียดอ่อน, ต้องการแสดงใช่ไหม?"
 createdLists: "รายชื่อที่ถูกสร้าง"
 createdAntennas: "เสาอากาศที่ถูกสร้าง"
+fromX: "จาก {x}"
+genEmbedCode: "สร้างรหัสฝัง"
+noteOfThisUser: "โน้ตโดยผู้ใช้นี้"
+clipNoteLimitExceeded: "ไม่สามารถเพิ่มโน้ตเพิ่มเติมในคลิปนี้ได้อีกแล้ว"
+performance: "ประสิทธิภาพ​"
+modified: "แก้ไข"
+discard: "ละทิ้ง"
+thereAreNChanges: "มีอยู่ {n} เปลี่ยนแปลง(s)"
+signinWithPasskey: "ลงชื่อเข้าใช้ด้วย Passkey"
+unknownWebAuthnKey: "พาสคีย์ไม่ถูกต้องค่ะ"
+passkeyVerificationFailed: "การยืนยันกุญแจดิจิทัลไม่สำเร็จค่ะ"
+passkeyVerificationSucceededButPasswordlessLoginDisabled: "การยืนยันพาสคีย์สำเร็จแล้ว แต่การลงชื่อเข้าใช้แบบไม่ต้องใส่รหัสผ่านถูกปิดใช้งานแล้ว"
+messageToFollower: "ข้อความถึงผู้ติดตาม"
+target: "เป้า"
+testCaptchaWarning: "ฟังก์ชันนี้มีไว้สำหรับทดสอบ CAPTCHA เท่านั้น\n<strong>ห้ามนำไปใช้ในระบบจริงโดยเด็ดขาด</strong>"
+prohibitedWordsForNameOfUser: "คำนี้ไม่สามารถใช้เป็นชื่อผู้ใช้ได้"
+prohibitedWordsForNameOfUserDescription: "หากมีสตริงใดๆ ในรายการนี้ปรากฏอยู่ในชื่อของผู้ใช้ ชื่อนั้นจะถูกปฏิเสธ ผู้ใช้ที่มีสิทธิ์แต่ผู้ดูแลระบบนั้นจะไม่ได้รับผลกระทบใดๆจากข้อจำกัดนี้ค่ะ"
+yourNameContainsProhibitedWords: "ชื่อของคุณนั้นมีคำที่ต้องห้าม"
+yourNameContainsProhibitedWordsDescription: "ถ้าหากคุณต้องการใช้ชื่อนี้ กรุณาติดต่อผู้ดูแลระบบของเซิร์ฟเวอร์นะค่ะ"
+_abuseUserReport:
+  forward: "ส่ง​ต่อ"
+  forwardDescription: "ส่งรายงานไปยังเซิร์ฟเวอร์ระยะไกลโดยใช้บัญชีระบบที่ไม่ระบุตัวตน"
+  resolve: "แก้ไข"
+  accept: "ยอมรับ"
+  reject: "ปฏิเสธ"
+  resolveTutorial: "ถ้าหากรายงานนี้มีเนื้อหาถูกต้อง ให้เลือก \"ยอมรับ\" เพื่อปิดเคสกรณีนี้โดยถือว่าได้รับการแก้ไขแล้ว\nถ้าหากเนื้อหาในรายงานนี้นั้นไม่ถูกต้อง ให้เลือก \"ปฏิเสธ\" เพื่อปิดเคสกรณีนี้โดยถือว่าไม่ได้รับการแก้ไข"
 _delivery:
   status: "สถานะการจัดส่ง"
   stop: "ระงับการส่ง"
@@ -1393,8 +1434,10 @@ _serverSettings:
   fanoutTimelineDescription: "เพิ่มประสิทธิภาพการดึงข้อมูลไทม์ไลน์อย่างมาก และลดภาระในฐานข้อมูลเมื่อเปิดใช้งาน ในทางกลับกัน การใช้หน่วยความจำของ Redis จะเพิ่มขึ้น ลองปิดการใช้งานนี้ในกรณีที่หน่วยความจำเซิร์ฟเวอร์เหลือน้อยหรือเซิร์ฟเวอร์ไม่เสถียร"
   fanoutTimelineDbFallback: "ฟอลแบ๊กกลับฐานข้อมูล"
   fanoutTimelineDbFallbackDescription: "เมื่อเปิดใช้งาน หากไม่ได้แคชไทม์ไลน์ ไทม์ไลน์จะฟอลแบ๊กไปยังฐานข้อมูลสำหรับการ query เพิ่มเติม การปิดใช้งานจะช่วยลดภาระของเซิร์ฟเวอร์ด้วยการกำจัดกระบวนฟอลแบ๊ก แต่มันก็จะจำกัดช่วงเวลาไทม์ไลน์ที่สามารถดึงข้อมูลได้"
+  reactionsBufferingDescription: "เมื่อเปิดใช้งานฟังก์ชันนี้ก็จะช่วยลด latency ในการสร้างปฏิกิริยา แต่อาจจะส่งผลให้ memory footprint ของ Redis เพิ่มขึ้นนะ"
   inquiryUrl: "URL สำหรับการติดต่อสอบถาม"
   inquiryUrlDescription: "ระบุ URL ของหน้าเว็บที่มีแบบฟอร์มสำหรับติดต่อผู้ดูแลเซิร์ฟเวอร์ หรือข้อมูลการติดต่อของผู้ดูแลเซิร์ฟเวอร์"
+  thisSettingWillAutomaticallyOffWhenModeratorsInactive: "ถ้าหากไม่มีการตรวจสอบจากผู้ดูแลระบบหรือไม่มีความเคลื่อนไหวมาเป็นระยะเวลาหนึ่ง ระบบจะทำการปิดใช้งานฟังก์ชันนี้โดยอัตโนมัติ เพื่อลดความเสี่ยงในการถูกโจมตีด้วยสแปมและอื่นๆ"
 _accountMigration:
   moveFrom: "ย้ายจากบัญชีอื่นมาที่บัญชีนี้"
   moveFromSub: "สร้างนามแฝงไปยังบัญชีอื่น"
@@ -1726,6 +1769,11 @@ _role:
     canSearchNotes: "การใช้การค้นหาโน้ต"
     canUseTranslator: "การใช้งานแปล"
     avatarDecorationLimit: "จำนวนการตกแต่งไอคอนสูงสุดที่สามารถติดตั้งได้"
+    canImportAntennas: "อนุญาตให้นำเข้าเสาอากาศ"
+    canImportBlocking: "อนุญาตให้นำเข้าการบล็อก"
+    canImportFollowing: "อนุญาตให้นำเข้ารายการต่อไปนี้"
+    canImportMuting: "อนุญาตให้นำเข้าการปิดกั้น"
+    canImportUserLists: "อนุญาตให้นำเข้ารายการ"
   _condition:
     roleAssignedTo: "มอบหมายให้มีบทบาทแบบทำมือ"
     isLocal: "ผู้ใช้ท้องถิ่น"
@@ -2219,6 +2267,9 @@ _profile:
   changeBanner: "เปลี่ยนแบนเนอร์"
   verifiedLinkDescription: "หากป้อน URL ที่มีลิงก์ไปยังโปรไฟล์ของคุณ ไอคอนการยืนยันความเป็นเจ้าของจะแสดงถัดจากฟิลด์นั้น ๆ"
   avatarDecorationMax: "คุณสามารถเพิ่มการตกแต่งได้สูงสุด {max}"
+  followedMessage: "ส่งข้อความเมื่อมีคนกดติดตาม"
+  followedMessageDescription: "ส่งข้อความเมื่อมีคนกดติดตามแล้ว"
+  followedMessageDescriptionForLockedAccount: "ถ้าหากคุณตั้งค่าให้คนอื่นต้องขออนุญาตก่อนที่จะติดตามคุณ ระบบจะขึ้นข้อความนี้ในตอนที่คุณอนุมัติให้เขาติดตาม"
 _exportOrImport:
   allNotes: "โน้ตทั้งหมด"
   favoritedNotes: "โน้ตที่ถูกใจไว้"
@@ -2311,6 +2362,7 @@ _pages:
   eyeCatchingImageSet: "ตั้งค่าภาพขนาดย่อ"
   eyeCatchingImageRemove: "ลบภาพขนาดย่อ"
   chooseBlock: "เพิ่มบล็อค"
+  enterSectionTitle: "ป้อนชื่อหัวข้อ"
   selectType: "เลือกชนิด"
   contentBlocks: "เนื้อหา"
   inputBlocks: "ป้อนข้อมูล"
@@ -2356,6 +2408,8 @@ _notification:
   renotedBySomeUsers: "รีโน้ตจากผู้ใช้ {n} ราย"
   followedBySomeUsers: "มีผู้ติดตาม {n} ราย"
   flushNotification: "ล้างประวัติการแจ้งเตือน"
+  exportOfXCompleted: "การดำเนินการส่งออก {x} ได้เสร็จสิ้นลงแล้ว"
+  login: "มีคนล็อกอิน"
   _types:
     all: "ทั้งหมด"
     note: "โน้ตใหม่"
@@ -2370,7 +2424,9 @@ _notification:
     followRequestAccepted: "อนุมัติให้ติดตามแล้ว"
     roleAssigned: "ให้บทบาท"
     achievementEarned: "ปลดล็อกความสำเร็จแล้ว"
+    exportCompleted: "กระบวนการส่งออกข้อมูลได้เสร็จสิ้นสมบูรณ์แล้ว"
     login: "เข้าสู่ระบบ"
+    test: "ทดสอบระบบแจ้งเตือน"
     app: "การแจ้งเตือนจากแอปที่มีลิงก์"
   _actions:
     followBack: "ติดตามกลับด้วย"
@@ -2436,7 +2492,10 @@ _webhookSettings:
     abuseReport: "เมื่อมีการรายงานจากผู้ใช้"
     abuseReportResolved: "เมื่อมีการจัดการกับการรายงานจากผู้ใช้"
     userCreated: "เมื่อผู้ใช้ถูกสร้างขึ้น"
+    inactiveModeratorsWarning: "เมื่อผู้ดูแลระบบไม่ได้ใช้งานมานานระยะหนึ่ง"
+    inactiveModeratorsInvitationOnlyChanged: "เมื่อผู้ดูแลระบบที่ไม่ได้ใช้งานมานาน และเซิร์ฟเวอร์เปลี่ยนเป็นแบบเชิญเข้าร่วมเท่านั้น"
   deleteConfirm: "ต้องการลบ Webhook ใช่ไหม?"
+  testRemarks: "คลิกปุ่มทางด้านขวาของสวิตช์เพื่อส่ง Webhook ทดสอบที่มีข้อมูลจำลอง"
 _abuseReport:
   _notificationRecipient:
     createRecipient: "เพิ่มปลายทางการแจ้งเตือนการรายงาน"
@@ -2480,6 +2539,8 @@ _moderationLogTypes:
   markSensitiveDriveFile: "ทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน"
   unmarkSensitiveDriveFile: "ยกเลิกทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน"
   resolveAbuseReport: "รายงานได้รับการแก้ไขแล้ว"
+  forwardAbuseReport: "ได้ส่งรายงานไปแล้ว"
+  updateAbuseReportNote: "โน้ตการกลั่นกรองที่รายงานไปนั้น ได้รับการอัปเดตแล้ว"
   createInvitation: "สร้างรหัสเชิญ"
   createAd: "สร้างโฆษณาแล้ว"
   deleteAd: "ลบโฆษณาออกแล้ว"
@@ -2495,6 +2556,10 @@ _moderationLogTypes:
   createAbuseReportNotificationRecipient: "สร้างปลายทางการแจ้งเตือนการรายงาน"
   updateAbuseReportNotificationRecipient: "อัปเดตปลายทางการแจ้งเตือนการรายงาน"
   deleteAbuseReportNotificationRecipient: "ลบปลายทางการแจ้งเตือนการรายงาน"
+  deleteAccount: "บัญชีถูกลบไปแล้ว"
+  deletePage: "เพจถูกลบออกไปแล้ว"
+  deleteFlash: "Play ถูกลบออกไปแล้ว"
+  deleteGalleryPost: "โพสต์แกลเลอรี่ถูกลบออกแล้ว"
 _fileViewer:
   title: "รายละเอียดไฟล์"
   type: "ประเภทไฟล์"
@@ -2631,3 +2696,17 @@ _contextMenu:
   app: "แอปพลิเคชัน"
   appWithShift: "แอปฟลิเคชันด้วยปุ่มยกแคร่ (Shift)"
   native: "UI ของเบราว์เซอร์"
+_embedCodeGen:
+  title: "ปรับแต่งโค้ดฝัง"
+  header: "แสดงส่วนหัว"
+  autoload: "โหลดเพิ่มโดยอัตโนมัติ (เลิกใช้แล้ว)"
+  maxHeight: "ความสูงสุด"
+  maxHeightDescription: "หากถ้าตั้งค่าเป็น 0 จะทำให้ไม่มีการจำกัดความสูงของวิดเจ็ต แต่ควรตั้งค่าเป็นตัวเลขอื่นๆ เพื่อไม่ให้วิดเจ็ตยืดตัวลงไปเรื่อยๆ"
+  maxHeightWarn: "การจำกัดความสูงสูงสุดถูกปิดใช้งาน (0) หากไม่ได้ตั้งใจให้เป็นเช่นนี้ โปรดตั้งค่าความสูงสูงสุดให้เป็นค่าอื่นๆแทน"
+  previewIsNotActual: "การแสดงผลนั้นต่างจากการฝังจริงเพราะเกินขอบเขตที่แสดงบนหน้าจอตัวอย่างนะ"
+  rounded: "ทำให้มันกลม"
+  border: "เพิ่มขอบให้กับกรอบด้านนอก"
+  applyToPreview: "นำไปใช้กับการแสดงตัวอย่าง"
+  generateCode: "สร้างโค้ดสำหรับการฝัง"
+  codeGenerated: "รหัสถูกสร้างขึ้นแล้ว"
+  codeGeneratedDescription: "นำโค้ดที่สร้างแล้วไปวางในเว็บไซต์ของคุณเพื่อฝังเนื้อหา"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index b81018cc1f..93804608c2 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -213,8 +213,8 @@ charts: "图表"
 perHour: "每小时"
 perDay: "每天"
 stopActivityDelivery: "停止发送活动"
-blockThisInstance: "阻止此服务器向本服务器推流"
-silenceThisInstance: "使服务器静音"
+blockThisInstance: "封锁此服务器"
+silenceThisInstance: "静音此服务器"
 mediaSilenceThisInstance: "隐藏此服务器的媒体文件"
 operations: "操作"
 software: "软件"
@@ -258,7 +258,7 @@ noCustomEmojis: "没有自定义表情符号"
 noJobs: "没有任务"
 federating: "联合中"
 blocked: "已拉黑"
-suspended: "停止推流"
+suspended: "停止投递"
 all: "全部"
 subscribing: "已订阅"
 publishing: "投递中"
@@ -706,7 +706,7 @@ useGlobalSettingDesc: "启用时,将使用账户通知设置。关闭时,则
 other: "其他"
 regenerateLoginToken: "重新生成登录令牌"
 regenerateLoginTokenDescription: "重新生成用于登录的内部令牌。通常您不需要这样做。重新生成后,您将在所有设备上登出。"
-theKeywordWhenSearchingForCustomEmoji: "这将是搜素自定义表情符号时的关键词。"
+theKeywordWhenSearchingForCustomEmoji: "这将是搜索自定义表情符号时的关键词。"
 setMultipleBySeparatingWithSpace: "您可以使用空格分隔多个项目。"
 fileIdOrUrl: "文件 ID 或者 URL"
 behavior: "行为"
@@ -947,6 +947,9 @@ oneHour: "1 小时"
 oneDay: "1 天"
 oneWeek: "1 周"
 oneMonth: "1 个月"
+threeMonths: "3 个月"
+oneYear: "1 年"
+threeDays: "3 天"
 reflectMayTakeTime: "可能需要一些时间才能体现出效果。"
 failedToFetchAccountInformation: "获取账户信息失败"
 rateLimitExceeded: "已超过速率限制"
@@ -1070,7 +1073,7 @@ nonSensitiveOnlyForLocalLikeOnlyForRemote: "仅限非敏感内容(远程仅点
 rolesAssignedToMe: "指派给自己的角色"
 resetPasswordConfirm: "确定重置密码?"
 sensitiveWords: "敏感词"
-sensitiveWordsDescription: "将包含设置词的帖子的可见范围设置为首页。可以通过用换行符分隔来设置多个。"
+sensitiveWordsDescription: "包含这些词的帖子将只在首页可见。可用换行来设定多个词。"
 sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
 prohibitedWords: "禁用词"
 prohibitedWordsDescription: "发布包含设定词汇的帖子时将出错。可用换行设定多个关键字"
@@ -1293,6 +1296,21 @@ prohibitedWordsForNameOfUser: "用户名中禁止的词"
 prohibitedWordsForNameOfUserDescription: "更改用户名时,如果用户名中包含此列表里的词汇,用户的改名请求将被拒绝。持有管理员权限的用户不受此限制。"
 yourNameContainsProhibitedWords: "目标用户名包含违禁词"
 yourNameContainsProhibitedWordsDescription: "用户名内含有违禁词。若想使用此用户名,请联系服务器管理员。"
+thisContentsAreMarkedAsSigninRequiredByAuthor: "根据发帖者的设定,需要登录才能显示"
+lockdown: "锁定"
+pleaseSelectAccount: "请选择帐户"
+_accountSettings:
+  requireSigninToViewContents: "需要登录才能显示内容"
+  requireSigninToViewContentsDescription1: "您发布的所有帖子将变成需要登入后才会显示。有望防止爬虫收集各种信息。"
+  requireSigninToViewContentsDescription2: "没有 URL 预览(OGP)、内嵌网页、引用帖子的功能的服务器也将无法显示。"
+  requireSigninToViewContentsDescription3: "这些限制可能不适用于联合到远程服务器的内容。"
+  makeNotesFollowersOnlyBefore: "可将过去的帖子设为仅关注者可见"
+  makeNotesFollowersOnlyBeforeDescription: "开启此设定时,超过设定的时间或日期后,帖子将变为仅关注者可见。关闭后帖子的公开状态将恢复成原本的设定。"
+  makeNotesHiddenBefore: "将过去的帖子设为私密"
+  makeNotesHiddenBeforeDescription: "开启此设定时,超过设定的时间或日期后,帖子将变为仅自己可见。关闭后帖子的公开状态将恢复成原本的设定。"
+  mayNotEffectForFederatedNotes: "与远程服务器联合的帖子在远端可能会没有效果。"
+  notesHavePassedSpecifiedPeriod: "超过指定时间的帖子"
+  notesOlderThanSpecifiedDateAndTime: "指定日期前的帖子"
 _abuseUserReport:
   forward: "转发"
   forwardDescription: "目标是匿名系统账户,将把举报转发给远程服务器。"
@@ -2157,8 +2175,11 @@ _auth:
   permissionAsk: "这个应用程序需要以下权限"
   pleaseGoBack: "请返回到应用程序"
   callback: "回到应用程序"
+  accepted: "已允许访问"
   denied: "拒绝访问"
+  scopeUser: "以下面的用户进行操作"
   pleaseLogin: "在对应用进行授权许可之前,请先登录"
+  byClickingYouWillBeRedirectedToThisUrl: "允许访问后将会自动重定向到以下 URL"
 _antennaSources:
   all: "所有帖子"
   homeTimeline: "已关注用户的帖子"
@@ -2710,3 +2731,9 @@ _embedCodeGen:
   generateCode: "生成嵌入代码"
   codeGenerated: "已生成代码"
   codeGeneratedDescription: "将生成的代码贴到网站上来使用。"
+_selfXssPrevention:
+  warning: "警告"
+  title: "「在此处粘贴什么东西」是欺诈行为。"
+  description1: "如果在此处粘贴了什么,恶意用户可能会接管账户或者盗取个人资料。"
+  description2: "如果不能完全理解将要粘贴的内容,%c 请立即停止操作并关闭这个窗口。"
+  description3: "详情请看这里。{link}"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index de18342bbf..16afeed0f8 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -947,6 +947,9 @@ oneHour: "一小時"
 oneDay: "一天"
 oneWeek: "一週"
 oneMonth: "一個月"
+threeMonths: "3 個月"
+oneYear: "1 年"
+threeDays: "3 日"
 reflectMayTakeTime: "可能需要一些時間才會出現效果。"
 failedToFetchAccountInformation: "取得帳戶資訊失敗"
 rateLimitExceeded: "已超過速率限制"
@@ -1293,6 +1296,21 @@ prohibitedWordsForNameOfUser: "禁止使用的字詞(使用者名稱)"
 prohibitedWordsForNameOfUserDescription: "如果使用者名稱包含此清單中的任何字串,則拒絕重新命名使用者。 具有審查員權限的使用者不受此限制的影響。"
 yourNameContainsProhibitedWords: "您嘗試更改的名稱包含禁止的字串"
 yourNameContainsProhibitedWordsDescription: "名稱中包含禁止使用的字串。 如果您想使用此名稱,請聯絡您的伺服器管理員。"
+thisContentsAreMarkedAsSigninRequiredByAuthor: "作者將其設定為需要登入才能顯示。"
+lockdown: "鎖定"
+pleaseSelectAccount: "請選擇帳戶"
+_accountSettings:
+  requireSigninToViewContents: "須登入以顯示內容"
+  requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。"
+  requireSigninToViewContentsDescription2: "來自不支援 URL 預覽 (OGP)、 網頁嵌入和引用貼文的伺服器,也將停止顯示。"
+  requireSigninToViewContentsDescription3: "這些限制可能不適用於被聯邦發送至遠端伺服器的內容。"
+  makeNotesFollowersOnlyBefore: "讓過去的貼文僅對追隨者顯示"
+  makeNotesFollowersOnlyBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對追隨者顯示。 如果您再次停用它,貼文的公開狀態也會恢復原狀。"
+  makeNotesHiddenBefore: "隱藏過去的貼文"
+  makeNotesHiddenBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對自己顯示(私密化)。 如果您再次停用它,貼文的公開狀態也會恢復原狀。"
+  mayNotEffectForFederatedNotes: "聯邦發送至遠端伺服器的貼文可能會不受影響。"
+  notesHavePassedSpecifiedPeriod: "早於指定時間的貼文"
+  notesOlderThanSpecifiedDateAndTime: "指定時間和日期之前的貼文"
 _abuseUserReport:
   forward: "轉發"
   forwardDescription: "以匿名系統帳戶將檢舉轉發至遠端伺服器。"
@@ -2157,8 +2175,11 @@ _auth:
   permissionAsk: "此應用程式需要以下權限"
   pleaseGoBack: "請返回至應用程式"
   callback: "回到應用程式"
+  accepted: "已授予存取權限"
   denied: "拒絕訪問"
+  scopeUser: "以下列使用者身分操作"
   pleaseLogin: "必須登入以提供應用程式的存取權限。"
+  byClickingYouWillBeRedirectedToThisUrl: "如果授予存取權限,就會自動導向到以下的網址"
 _antennaSources:
   all: "全部貼文"
   homeTimeline: "來自已追隨使用者的貼文"
@@ -2416,7 +2437,7 @@ _notification:
     follow: "追隨中"
     mention: "提及"
     reply: "回覆"
-    renote: "轉發貼文"
+    renote: "轉發"
     quote: "引用"
     reaction: "反應"
     pollEnded: "問卷調查結束"
@@ -2710,3 +2731,9 @@ _embedCodeGen:
   generateCode: "建立嵌入程式碼"
   codeGenerated: "已產生程式碼"
   codeGeneratedDescription: "請將產生的程式碼貼到您的網站上。"
+_selfXssPrevention:
+  warning: "警告"
+  title: "「在此畫面貼上一些內容」完全是個騙局。"
+  description1: "如果您在此處貼上任何內容,惡意使用者可能會接管您的帳戶或竊取您的個人資訊。"
+  description2: "如果您不確切知道要貼上的內容,%c 請立即停止工作並關閉此視窗。"
+  description3: "細節請看這裡。{link}"

From 04b37a13151942c16f13193b00ae18a60b0ea62e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 28 Oct 2024 12:32:17 +0900
Subject: [PATCH 021/125] =?UTF-8?q?enhance(i18n):=20=E3=82=AB=E3=82=BF?=
 =?UTF-8?q?=E3=83=AB=E3=83=BC=E3=83=8B=E3=83=A3=E8=AA=9E=E3=82=92=E8=BF=BD?=
 =?UTF-8?q?=E5=8A=A0=20(#14842)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(i18n): 対応言語の追加

* 翻訳進捗が70%に満たないものを除外

* Update Changelog

* 翻訳進捗が70%を超えたら導入の旨を明記

* typo

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 CHANGELOG.md     | 1 +
 CONTRIBUTING.md  | 3 ++-
 locales/index.js | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90ad015dab..cbd48b8b6c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@
   - どのアカウントで認証しようとしているのかがわかるように
   - 認証するアカウントを切り替えられるように
 - Enhance: Self-XSS防止用の警告を追加
+- Enhance: カタルーニャ語 (ca-ES) に対応  
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3bc0faf96d..4bcf7e1642 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -132,7 +132,8 @@ You can improve our translations with your Crowdin account.
 Your changes in Crowdin are automatically submitted as a PR (with the title "New Crowdin translations") to the repository.
 The owner [@syuilo](https://github.com/syuilo) merges the PR into the develop branch before the next release.
 
-If your language is not listed in Crowdin, please open an issue.
+If your language is not listed in Crowdin, please open an issue. We will add it to Crowdin.
+For newly added languages, once the translation progress per language exceeds 70%, it will be officially introduced into Misskey and made available to users.
 
 ![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
 
diff --git a/locales/index.js b/locales/index.js
index c2738884eb..091d216dee 100644
--- a/locales/index.js
+++ b/locales/index.js
@@ -15,6 +15,7 @@ const merge = (...args) => args.reduce((a, c) => ({
 
 const languages = [
 	'ar-SA',
+	'ca-ES',
 	'cs-CZ',
 	'da-DK',
 	'de-DE',

From b1073714ba65e60ff90b448e71415c106eba623b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 28 Oct 2024 12:46:39 +0900
Subject: [PATCH 022/125] Update about-misskey.vue

---
 packages/frontend/src/pages/about-misskey.vue | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index 68b98c2ab7..fbbfb6ea61 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -269,6 +269,9 @@ const patronsWithIcon = [{
 }, {
 	name: '如月ユカ',
 	icon: 'https://assets.misskey-hub.net/patrons/f24a042076a041b6811a2f124eb620ca.jpg',
+}, {
+	name: 'Yatoigawa',
+	icon: 'https://assets.misskey-hub.net/patrons/505e3568885a4a488431a8f22b4553d0.jpg',
 }];
 
 const patrons = [
@@ -375,6 +378,8 @@ const patrons = [
 	'はとぽぷさん',
 	'100の人 (エスパー・イーシア)',
 	'ケモナーのケシン',
+	'こまつぶり',
+	'まゆつな空高',
 ];
 
 const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));

From e927507886b9478c9f7197cf64ce375cf65a164c Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 28 Oct 2024 18:34:18 +0900
Subject: [PATCH 023/125] :art:

---
 packages/frontend/src/pages/emoji-edit-dialog.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue
index 969aa6bbf7..3b3f41d9b1 100644
--- a/packages/frontend/src/pages/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/emoji-edit-dialog.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	ref="windowEl"
 	:initialWidth="400"
 	:initialHeight="500"
-	:canResize="false"
+	:canResize="true"
 	@close="windowEl.close()"
 	@closed="$emit('closed')"
 >

From eecfac1dd933b65bee469a0a103d19f378d3fcef Mon Sep 17 00:00:00 2001
From: woxtu <woxtup@gmail.com>
Date: Mon, 28 Oct 2024 20:22:07 +0900
Subject: [PATCH 024/125] Remove undefined styles (#14858)

---
 packages/frontend/src/components/MkAbuseReport.vue     |  4 +---
 packages/frontend/src/components/MkAuthConfirm.vue     |  4 ++--
 packages/frontend/src/components/MkSignin.password.vue | 10 +++++-----
 packages/frontend/src/components/global/MkAd.vue       |  6 +-----
 4 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue
index b9413270ae..e48b6ef781 100644
--- a/packages/frontend/src/components/MkAbuseReport.vue
+++ b/packages/frontend/src/components/MkAbuseReport.vue
@@ -29,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 	</template>
 
-	<div :class="$style.root" class="_gaps_s">
+	<div class="_gaps_s">
 		<MkFolder :withSpacer="false">
 			<template #icon><MkAvatar :user="report.targetUser" style="width: 18px; height: 18px;"/></template>
 			<template #label>{{ i18n.ts.target }}: <MkAcct :user="report.targetUser"/></template>
@@ -151,6 +151,4 @@ function showMenu(ev: MouseEvent) {
 </script>
 
 <style lang="scss" module>
-.root {
-}
 </style>
diff --git a/packages/frontend/src/components/MkAuthConfirm.vue b/packages/frontend/src/components/MkAuthConfirm.vue
index f5f6d7f6cc..f78d2d38f0 100644
--- a/packages/frontend/src/components/MkAuthConfirm.vue
+++ b/packages/frontend/src/components/MkAuthConfirm.vue
@@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				</div>
 				<div :class="$style.headerText">{{ i18n.ts.pleaseSelectAccount }}</div>
 			</div>
-			<div :class="$style.accountSelectorRoot">
+			<div>
 				<div :class="$style.accountSelectorLabel">{{ i18n.ts.selectAccount }}</div>
 				<div :class="$style.accountSelectorList">
 					<template v-for="[id, user] in users">
@@ -63,7 +63,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				</div>
 			</div>
 			<slot name="consentAdditionalInfo"></slot>
-			<div :class="$style.accountSelectorRoot">
+			<div>
 				<div :class="$style.accountSelectorLabel">
 					{{ i18n.ts._auth.scopeUser }} <button class="_textButton" @click="clickBackToAccountSelect">{{ i18n.ts.switchAccount }}</button>
 				</div>
diff --git a/packages/frontend/src/components/MkSignin.password.vue b/packages/frontend/src/components/MkSignin.password.vue
index 5608122a39..cd003a39df 100644
--- a/packages/frontend/src/components/MkSignin.password.vue
+++ b/packages/frontend/src/components/MkSignin.password.vue
@@ -24,11 +24,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</MkInput>
 
 			<div v-if="needCaptcha">
-				<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :class="$style.captcha" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/>
-				<MkCaptcha v-if="instance.enableMcaptcha" ref="mcaptcha" v-model="mCaptchaResponse" :class="$style.captcha" provider="mcaptcha" :sitekey="instance.mcaptchaSiteKey" :instanceUrl="instance.mcaptchaInstanceUrl"/>
-				<MkCaptcha v-if="instance.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" :class="$style.captcha" provider="recaptcha" :sitekey="instance.recaptchaSiteKey"/>
-				<MkCaptcha v-if="instance.enableTurnstile" ref="turnstile" v-model="turnstileResponse" :class="$style.captcha" provider="turnstile" :sitekey="instance.turnstileSiteKey"/>
-				<MkCaptcha v-if="instance.enableTestcaptcha" ref="testcaptcha" v-model="testcaptchaResponse" :class="$style.captcha" provider="testcaptcha"/>
+				<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/>
+				<MkCaptcha v-if="instance.enableMcaptcha" ref="mcaptcha" v-model="mCaptchaResponse" provider="mcaptcha" :sitekey="instance.mcaptchaSiteKey" :instanceUrl="instance.mcaptchaInstanceUrl"/>
+				<MkCaptcha v-if="instance.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" provider="recaptcha" :sitekey="instance.recaptchaSiteKey"/>
+				<MkCaptcha v-if="instance.enableTurnstile" ref="turnstile" v-model="turnstileResponse" provider="turnstile" :sitekey="instance.turnstileSiteKey"/>
+				<MkCaptcha v-if="instance.enableTestcaptcha" ref="testcaptcha" v-model="testcaptchaResponse" provider="testcaptcha"/>
 			</div>
 
 			<MkButton type="submit" :disabled="needCaptcha && captchaFailed" large primary rounded style="margin: 0 auto;" data-cy-signin-page-password-continue>{{ i18n.ts.continue }} <i class="ti ti-arrow-right"></i></MkButton>
diff --git a/packages/frontend/src/components/global/MkAd.vue b/packages/frontend/src/components/global/MkAd.vue
index 0d68d02e35..08a78c8d81 100644
--- a/packages/frontend/src/components/global/MkAd.vue
+++ b/packages/frontend/src/components/global/MkAd.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<div v-if="chosen && !shouldHide" :class="$style.root">
+<div v-if="chosen && !shouldHide">
 	<div
 		v-if="!showMenu"
 		:class="[$style.main, {
@@ -120,10 +120,6 @@ function reduceFrequency(): void {
 </script>
 
 <style lang="scss" module>
-.root {
-
-}
-
 .main {
 	text-align: center;
 

From 74847bce303449124282a748fc50b1c6588288fc Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 28 Oct 2024 20:42:14 +0900
Subject: [PATCH 025/125] =?UTF-8?q?enhance:=20=E3=82=A2=E3=82=A4=E3=82=B3?=
 =?UTF-8?q?=E3=83=B3=E3=83=87=E3=82=B3=E3=83=AC=E3=83=BC=E3=82=B7=E3=83=A7?=
 =?UTF-8?q?=E3=83=B3=E7=AE=A1=E7=90=86=E7=94=BB=E9=9D=A2=E3=81=AE=E6=94=B9?=
 =?UTF-8?q?=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md                                  |   1 +
 locales/index.d.ts                            |   4 +
 locales/ja-JP.yml                             |   1 +
 .../admin/avatar-decorations/create.ts        |  57 ++++-
 .../admin/avatar-decorations/list.ts          |   3 -
 .../pages/avatar-decoration-edit-dialog.vue   | 220 ++++++++++++++++++
 .../frontend/src/pages/avatar-decorations.vue | 172 +++++---------
 .../settings/avatar-decoration.decoration.vue |   7 +-
 .../settings/avatar-decoration.dialog.vue     |   4 +-
 packages/misskey-js/etc/misskey-js.api.md     |   4 +
 packages/misskey-js/src/autogen/endpoint.ts   |   3 +-
 packages/misskey-js/src/autogen/entities.ts   |   1 +
 packages/misskey-js/src/autogen/types.ts      |  19 +-
 13 files changed, 374 insertions(+), 122 deletions(-)
 create mode 100644 packages/frontend/src/pages/avatar-decoration-edit-dialog.vue

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cbd48b8b6c..52077f813f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
 - Enhance: ドライブでソートができるように
+- Enhance: アイコンデコレーション管理画面の改善
 - Enhance: 「単なるラッキー」の取得条件を変更
 - Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )  
 - Enhance: MiAuth, OAuthの認可画面の改善
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 9058c70496..440f24ac84 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -5214,6 +5214,10 @@ export interface Locale extends ILocale {
      * アカウントを選択してください
      */
     "pleaseSelectAccount": string;
+    /**
+     * 利用可能なロール
+     */
+    "availableRoles": string;
     "_accountSettings": {
         /**
          * コンテンツの表示にログインを必須にする
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 1d426f1705..5d8e1a5e72 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1299,6 +1299,7 @@ yourNameContainsProhibitedWordsDescription: "名前に禁止されている文
 thisContentsAreMarkedAsSigninRequiredByAuthor: "投稿者により、表示にはログインが必要と設定されています"
 lockdown: "ロックダウン"
 pleaseSelectAccount: "アカウントを選択してください"
+availableRoles: "利用可能なロール"
 
 _accountSettings:
   requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
diff --git a/packages/backend/src/server/api/endpoints/admin/avatar-decorations/create.ts b/packages/backend/src/server/api/endpoints/admin/avatar-decorations/create.ts
index fd21309818..87d80cbe80 100644
--- a/packages/backend/src/server/api/endpoints/admin/avatar-decorations/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/avatar-decorations/create.ts
@@ -6,6 +6,7 @@
 import { Injectable } from '@nestjs/common';
 import { Endpoint } from '@/server/api/endpoint-base.js';
 import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
+import { IdService } from '@/core/IdService.js';
 
 export const meta = {
 	tags: ['admin'],
@@ -13,6 +14,49 @@ export const meta = {
 	requireCredential: true,
 	requireRolePolicy: 'canManageAvatarDecorations',
 	kind: 'write:admin:avatar-decorations',
+
+	res: {
+		type: 'object',
+		optional: false, nullable: false,
+		properties: {
+			id: {
+				type: 'string',
+				optional: false, nullable: false,
+				format: 'id',
+			},
+			createdAt: {
+				type: 'string',
+				optional: false, nullable: false,
+				format: 'date-time',
+			},
+			updatedAt: {
+				type: 'string',
+				optional: false, nullable: true,
+				format: 'date-time',
+			},
+			name: {
+				type: 'string',
+				optional: false, nullable: false,
+			},
+			description: {
+				type: 'string',
+				optional: false, nullable: false,
+			},
+			url: {
+				type: 'string',
+				optional: false, nullable: false,
+			},
+			roleIdsThatCanBeUsedThisDecoration: {
+				type: 'array',
+				optional: false, nullable: false,
+				items: {
+					type: 'string',
+					optional: false, nullable: false,
+					format: 'id',
+				},
+			},
+		},
+	},
 } as const;
 
 export const paramDef = {
@@ -32,14 +76,25 @@ export const paramDef = {
 export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
 	constructor(
 		private avatarDecorationService: AvatarDecorationService,
+		private idService: IdService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			await this.avatarDecorationService.create({
+			const created = await this.avatarDecorationService.create({
 				name: ps.name,
 				description: ps.description,
 				url: ps.url,
 				roleIdsThatCanBeUsedThisDecoration: ps.roleIdsThatCanBeUsedThisDecoration,
 			}, me);
+
+			return {
+				id: created.id,
+				createdAt: this.idService.parse(created.id).date.toISOString(),
+				updatedAt: null,
+				name: created.name,
+				description: created.description,
+				url: created.url,
+				roleIdsThatCanBeUsedThisDecoration: created.roleIdsThatCanBeUsedThisDecoration,
+			};
 		});
 	}
 }
diff --git a/packages/backend/src/server/api/endpoints/admin/avatar-decorations/list.ts b/packages/backend/src/server/api/endpoints/admin/avatar-decorations/list.ts
index aee90023e1..d785f085ac 100644
--- a/packages/backend/src/server/api/endpoints/admin/avatar-decorations/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/avatar-decorations/list.ts
@@ -4,10 +4,7 @@
  */
 
 import { Inject, Injectable } from '@nestjs/common';
-import type { AnnouncementsRepository, AnnouncementReadsRepository } from '@/models/_.js';
-import type { MiAnnouncement } from '@/models/Announcement.js';
 import { Endpoint } from '@/server/api/endpoint-base.js';
-import { QueryService } from '@/core/QueryService.js';
 import { DI } from '@/di-symbols.js';
 import { IdService } from '@/core/IdService.js';
 import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
diff --git a/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue b/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue
new file mode 100644
index 0000000000..a834f1c5fd
--- /dev/null
+++ b/packages/frontend/src/pages/avatar-decoration-edit-dialog.vue
@@ -0,0 +1,220 @@
+<!--
+SPDX-FileCopyrightText: syuilo and misskey-project
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<MkWindow
+	ref="windowEl"
+	:initialWidth="400"
+	:initialHeight="500"
+	:canResize="true"
+	@close="windowEl?.close()"
+	@closed="emit('closed')"
+>
+	<template v-if="avatarDecoration" #header>{{ avatarDecoration.name }}</template>
+	<template v-else #header>New decoration</template>
+
+	<div style="display: flex; flex-direction: column; min-height: 100%;">
+		<MkSpacer :marginMin="20" :marginMax="28" style="flex-grow: 1;">
+			<div class="_gaps_m">
+				<div :class="$style.preview">
+					<div :class="[$style.previewItem, $style.light]">
+						<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="url != '' ? [{ url }] : []" forceShowDecoration/>
+					</div>
+					<div :class="[$style.previewItem, $style.dark]">
+						<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="url != '' ? [{ url }] : []" forceShowDecoration/>
+					</div>
+				</div>
+				<MkInput v-model="name">
+					<template #label>{{ i18n.ts.name }}</template>
+				</MkInput>
+				<MkInput v-model="url">
+					<template #label>{{ i18n.ts.imageUrl }}</template>
+				</MkInput>
+				<MkTextarea v-model="description">
+					<template #label>{{ i18n.ts.description }}</template>
+				</MkTextarea>
+				<MkFolder>
+					<template #label>{{ i18n.ts.availableRoles }}</template>
+					<template #suffix>{{ rolesThatCanBeUsedThisDecoration.length === 0 ? i18n.ts.all : rolesThatCanBeUsedThisDecoration.length }}</template>
+
+					<div class="_gaps">
+						<MkButton rounded @click="addRole"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
+
+						<div v-for="role in rolesThatCanBeUsedThisDecoration" :key="role.id" :class="$style.roleItem">
+							<MkRolePreview :class="$style.role" :role="role" :forModeration="true" :detailed="false" style="pointer-events: none;"/>
+							<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="removeRole(role, $event)"><i class="ti ti-x"></i></button>
+							<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
+						</div>
+					</div>
+				</MkFolder>
+				<MkButton v-if="avatarDecoration" danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
+			</div>
+		</MkSpacer>
+		<div :class="$style.footer">
+			<MkButton primary rounded style="margin: 0 auto;" @click="done"><i class="ti ti-check"></i> {{ props.avatarDecoration ? i18n.ts.update : i18n.ts.create }}</MkButton>
+		</div>
+	</div>
+</MkWindow>
+</template>
+
+<script lang="ts" setup>
+import { computed, watch, ref } from 'vue';
+import * as Misskey from 'misskey-js';
+import MkWindow from '@/components/MkWindow.vue';
+import MkButton from '@/components/MkButton.vue';
+import MkInput from '@/components/MkInput.vue';
+import MkInfo from '@/components/MkInfo.vue';
+import MkFolder from '@/components/MkFolder.vue';
+import * as os from '@/os.js';
+import { misskeyApi } from '@/scripts/misskey-api.js';
+import { i18n } from '@/i18n.js';
+import MkSwitch from '@/components/MkSwitch.vue';
+import MkRolePreview from '@/components/MkRolePreview.vue';
+import MkTextarea from '@/components/MkTextarea.vue';
+import { signinRequired } from '@/account.js';
+
+const $i = signinRequired();
+
+const props = defineProps<{
+	avatarDecoration?: any,
+}>();
+
+const emit = defineEmits<{
+	(ev: 'done', v: { deleted?: boolean; updated?: any; created?: any }): void,
+	(ev: 'closed'): void
+}>();
+
+const windowEl = ref<InstanceType<typeof MkWindow> | null>(null);
+const url = ref<string>(props.avatarDecoration ? props.avatarDecoration.url : '');
+const name = ref<string>(props.avatarDecoration ? props.avatarDecoration.name : '');
+const description = ref<string>(props.avatarDecoration ? props.avatarDecoration.description : '');
+const roleIdsThatCanBeUsedThisDecoration = ref(props.avatarDecoration ? props.avatarDecoration.roleIdsThatCanBeUsedThisDecoration : []);
+const rolesThatCanBeUsedThisDecoration = ref<Misskey.entities.Role[]>([]);
+
+watch(roleIdsThatCanBeUsedThisDecoration, async () => {
+	rolesThatCanBeUsedThisDecoration.value = (await Promise.all(roleIdsThatCanBeUsedThisDecoration.value.map((id) => misskeyApi('admin/roles/show', { roleId: id }).catch(() => null)))).filter(x => x != null);
+}, { immediate: true });
+
+async function addRole() {
+	const roles = await misskeyApi('admin/roles/list');
+	const currentRoleIds = rolesThatCanBeUsedThisDecoration.value.map(x => x.id);
+
+	const { canceled, result: role } = await os.select({
+		items: roles.filter(r => r.isPublic).filter(r => !currentRoleIds.includes(r.id)).map(r => ({ text: r.name, value: r })),
+	});
+	if (canceled || role == null) return;
+
+	rolesThatCanBeUsedThisDecoration.value.push(role);
+}
+
+async function removeRole(role, ev) {
+	rolesThatCanBeUsedThisDecoration.value = rolesThatCanBeUsedThisDecoration.value.filter(x => x.id !== role.id);
+}
+
+async function done() {
+	const params = {
+		url: url.value,
+		name: name.value,
+		description: description.value,
+		roleIdsThatCanBeUsedThisDecoration: rolesThatCanBeUsedThisDecoration.value.map(x => x.id),
+	};
+
+	if (props.avatarDecoration) {
+		await os.apiWithDialog('admin/avatar-decorations/update', {
+			id: props.avatarDecoration.id,
+			...params,
+		});
+
+		emit('done', {
+			updated: {
+				id: props.avatarDecoration.id,
+				...params,
+			},
+		});
+
+		windowEl.value?.close();
+	} else {
+		const created = await os.apiWithDialog('admin/avatar-decorations/create', params);
+
+		emit('done', {
+			created: created,
+		});
+
+		windowEl.value?.close();
+	}
+}
+
+async function del() {
+	const { canceled } = await os.confirm({
+		type: 'warning',
+		text: i18n.tsx.removeAreYouSure({ x: name.value }),
+	});
+	if (canceled) return;
+
+	misskeyApi('admin/avatar-decorations/delete', {
+		id: props.avatarDecoration.id,
+	}).then(() => {
+		emit('done', {
+			deleted: true,
+		});
+		windowEl.value?.close();
+	});
+}
+</script>
+
+<style lang="scss" module>
+.preview {
+	display: grid;
+	place-items: center;
+	grid-template-columns: 1fr 1fr;
+	grid-template-rows: 1fr;
+	gap: var(--MI-margin);
+}
+
+.previewItem {
+	width: 100%;
+	height: 100%;
+	min-height: 160px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	border-radius: var(--MI-radius);
+
+	&.light {
+		background: #eee;
+	}
+
+	&.dark {
+		background: #222;
+	}
+}
+
+.roleItem {
+	display: flex;
+}
+
+.role {
+	flex: 1;
+}
+
+.roleUnassign {
+	width: 32px;
+	height: 32px;
+	margin-left: 8px;
+	align-self: center;
+}
+
+.footer {
+	position: sticky;
+	z-index: 10000;
+	bottom: 0;
+	left: 0;
+	padding: 12px;
+	border-top: solid 0.5px var(--MI_THEME-divider);
+	background: var(--MI_THEME-acrylicBg);
+	-webkit-backdrop-filter: var(--MI-blur, blur(15px));
+	backdrop-filter: var(--MI-blur, blur(15px));
+}
+</style>
diff --git a/packages/frontend/src/pages/avatar-decorations.vue b/packages/frontend/src/pages/avatar-decorations.vue
index b97e7c0eea..a5cafb1678 100644
--- a/packages/frontend/src/pages/avatar-decorations.vue
+++ b/packages/frontend/src/pages/avatar-decorations.vue
@@ -5,92 +5,38 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <MkStickyContainer>
-	<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
+	<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
 	<MkSpacer :contentMax="900">
 		<div class="_gaps">
-			<MkFolder v-for="avatarDecoration in avatarDecorations" :key="avatarDecoration.id ?? avatarDecoration._id" :defaultOpen="avatarDecoration.id == null">
-				<template #label>{{ avatarDecoration.name }}</template>
-				<template #caption>{{ avatarDecoration.description }}</template>
-
-				<div :class="$style.editorRoot">
-					<div :class="$style.editorWrapper">
-						<div :class="$style.preview">
-							<div :class="[$style.previewItem, $style.light]">
-								<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[avatarDecoration]" forceShowDecoration/>
-							</div>
-							<div :class="[$style.previewItem, $style.dark]">
-								<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[avatarDecoration]" forceShowDecoration/>
-							</div>
-						</div>
-						<div class="_gaps_m">
-							<MkInput v-model="avatarDecoration.name">
-								<template #label>{{ i18n.ts.name }}</template>
-							</MkInput>
-							<MkTextarea v-model="avatarDecoration.description">
-								<template #label>{{ i18n.ts.description }}</template>
-							</MkTextarea>
-							<MkInput v-model="avatarDecoration.url">
-								<template #label>{{ i18n.ts.imageUrl }}</template>
-							</MkInput>
-							<div class="_buttons">
-								<MkButton inline primary @click="save(avatarDecoration)"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
-								<MkButton v-if="avatarDecoration.id != null" inline danger @click="del(avatarDecoration)"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
-							</div>
-						</div>
-					</div>
+			<div :class="$style.decorations">
+				<div
+					v-for="avatarDecoration in avatarDecorations"
+					:key="avatarDecoration.id"
+					v-panel
+					:class="$style.decoration"
+					@click="edit(avatarDecoration)"
+				>
+					<div :class="$style.decorationName"><MkCondensedLine :minScale="0.5">{{ avatarDecoration.name }}</MkCondensedLine></div>
+					<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[{ url: avatarDecoration.url }]" forceShowDecoration/>
 				</div>
-			</MkFolder>
+			</div>
 		</div>
 	</MkSpacer>
 </MkStickyContainer>
 </template>
 
 <script lang="ts" setup>
-import { ref, computed } from 'vue';
+import { ref, computed, defineAsyncComponent } from 'vue';
 import * as Misskey from 'misskey-js';
-import MkButton from '@/components/MkButton.vue';
-import MkInput from '@/components/MkInput.vue';
-import MkTextarea from '@/components/MkTextarea.vue';
 import { signinRequired } from '@/account.js';
 import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import MkFolder from '@/components/MkFolder.vue';
-
-const avatarDecorations = ref<Misskey.entities.AdminAvatarDecorationsListResponse>([]);
 
 const $i = signinRequired();
 
-function add() {
-	avatarDecorations.value.unshift({
-		_id: Math.random().toString(36),
-		id: null,
-		name: '',
-		description: '',
-		url: '',
-	});
-}
-
-function del(avatarDecoration) {
-	os.confirm({
-		type: 'warning',
-		text: i18n.tsx.deleteAreYouSure({ x: avatarDecoration.name }),
-	}).then(({ canceled }) => {
-		if (canceled) return;
-		avatarDecorations.value = avatarDecorations.value.filter(x => x !== avatarDecoration);
-		misskeyApi('admin/avatar-decorations/delete', avatarDecoration);
-	});
-}
-
-async function save(avatarDecoration) {
-	if (avatarDecoration.id == null) {
-		await os.apiWithDialog('admin/avatar-decorations/create', avatarDecoration);
-		load();
-	} else {
-		os.apiWithDialog('admin/avatar-decorations/update', avatarDecoration);
-	}
-}
+const avatarDecorations = ref<Misskey.entities.AdminAvatarDecorationsListResponse>([]);
 
 function load() {
 	misskeyApi('admin/avatar-decorations/list').then(_avatarDecorations => {
@@ -100,6 +46,37 @@ function load() {
 
 load();
 
+async function add(ev: MouseEvent) {
+	const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration-edit-dialog.vue')), {
+	}, {
+		done: result => {
+			if (result.created) {
+				avatarDecorations.value.unshift(result.created);
+			}
+		},
+		closed: () => dispose(),
+	});
+}
+
+function edit(avatarDecoration) {
+	const { dispose } = os.popup(defineAsyncComponent(() => import('./avatar-decoration-edit-dialog.vue')), {
+		avatarDecoration: avatarDecoration,
+	}, {
+		done: result => {
+			if (result.updated) {
+				const index = avatarDecorations.value.findIndex(x => x.id === avatarDecoration.id);
+				avatarDecorations.value[index] = {
+					...avatarDecorations.value[index],
+					...result.updated,
+				};
+			} else if (result.deleted) {
+				avatarDecorations.value = avatarDecorations.value.filter(x => x.id !== avatarDecoration.id);
+			}
+		},
+		closed: () => dispose(),
+	});
+}
+
 const headerActions = computed(() => [{
 	asFullButton: true,
 	icon: 'ti ti-plus',
@@ -116,53 +93,26 @@ definePageMetadata(() => ({
 </script>
 
 <style lang="scss" module>
-.editorRoot {
-	container: editor / inline-size;
-}
-
-.editorWrapper {
+.decorations {
 	display: grid;
-	grid-template-columns: 1fr;
-	grid-template-rows: auto auto;
-	gap: var(--MI-margin);
+	grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
+	grid-gap: 12px;
 }
 
-.preview {
-	display: grid;
-	place-items: center;
-	grid-template-columns: 1fr 1fr;
-	grid-template-rows: 1fr;
-	gap: var(--MI-margin);
+.decoration {
+	cursor: pointer;
+	padding: 16px 16px 28px 16px;
+	border-radius: 8px;
+	text-align: center;
+	font-size: 90%;
+	overflow: clip;
+	contain: content;
 }
 
-.previewItem {
-	width: 100%;
-	height: 100%;
-	min-height: 160px;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	border-radius: var(--MI-radius);
-
-	&.light {
-		background: #eee;
-	}
-
-	&.dark {
-		background: #222;
-	}
-}
-
-@container editor (min-width: 600px) {
-	.editorWrapper {
-		grid-template-columns: 200px 1fr;
-		grid-template-rows: 1fr;
-		gap: calc(var(--MI-margin) * 2);
-	}
-
-	.preview {
-		grid-template-columns: 1fr;
-		grid-template-rows: 1fr 1fr;
-	}
+.decorationName {
+	position: relative;
+	z-index: 10;
+	font-weight: bold;
+	margin-bottom: 20px;
 }
 </style>
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue
index f72a0b9383..3c9914b4e2 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.decoration.vue
@@ -10,12 +10,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 >
 	<div :class="$style.name"><MkCondensedLine :minScale="0.5">{{ decoration.name }}</MkCondensedLine></div>
 	<MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[{ url: decoration.url, angle, flipH, offsetX, offsetY }]" forceShowDecoration/>
-	<i v-if="decoration.roleIdsThatCanBeUsedThisDecoration.length > 0 && !$i.roles.some(r => decoration.roleIdsThatCanBeUsedThisDecoration.includes(r.id))" :class="$style.lock" class="ti ti-lock"></i>
+	<i v-if="locked" :class="$style.lock" class="ti ti-lock"></i>
 </div>
 </template>
 
 <script lang="ts" setup>
-import { } from 'vue';
+import { computed } from 'vue';
 import { signinRequired } from '@/account.js';
 
 const $i = signinRequired();
@@ -37,6 +37,8 @@ const props = defineProps<{
 const emit = defineEmits<{
 	(ev: 'click'): void;
 }>();
+
+const locked = computed(() => props.decoration.roleIdsThatCanBeUsedThisDecoration.length > 0 && !$i.roles.some(r => props.decoration.roleIdsThatCanBeUsedThisDecoration.includes(r.id)));
 </script>
 
 <style lang="scss" module>
@@ -67,5 +69,6 @@ const emit = defineEmits<{
 	position: absolute;
 	bottom: 12px;
 	right: 12px;
+	color: var(--MI_THEME-warn);
 }
 </style>
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue
index 853e536ea3..aa899ac649 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue
@@ -38,7 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<div :class="$style.footer" class="_buttonsCenter">
 			<MkButton v-if="usingIndex != null" primary rounded @click="update"><i class="ti ti-check"></i> {{ i18n.ts.update }}</MkButton>
 			<MkButton v-if="usingIndex != null" rounded @click="detach"><i class="ti ti-x"></i> {{ i18n.ts.detach }}</MkButton>
-			<MkButton v-else :disabled="exceeded" primary rounded @click="attach"><i class="ti ti-check"></i> {{ i18n.ts.attach }}</MkButton>
+			<MkButton v-else :disabled="exceeded || locked" primary rounded @click="attach"><i class="ti ti-check"></i> {{ i18n.ts.attach }}</MkButton>
 		</div>
 	</div>
 </MkModalWindow>
@@ -61,6 +61,7 @@ const props = defineProps<{
 		id: string;
 		url: string;
 		name: string;
+		roleIdsThatCanBeUsedThisDecoration: string[];
 	};
 }>();
 
@@ -83,6 +84,7 @@ const emit = defineEmits<{
 
 const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
 const exceeded = computed(() => ($i.policies.avatarDecorationLimit - $i.avatarDecorations.length) <= 0);
+const locked = computed(() => props.decoration.roleIdsThatCanBeUsedThisDecoration.length > 0 && !$i.roles.some(r => props.decoration.roleIdsThatCanBeUsedThisDecoration.includes(r.id)));
 const angle = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].angle : null) ?? 0);
 const flipH = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].flipH : null) ?? false);
 const offsetX = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].offsetX : null) ?? 0);
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index 61de8b8c7e..061b533b72 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -121,6 +121,9 @@ type AdminAnnouncementsUpdateRequest = operations['admin___announcements___updat
 // @public (undocumented)
 type AdminAvatarDecorationsCreateRequest = operations['admin___avatar-decorations___create']['requestBody']['content']['application/json'];
 
+// @public (undocumented)
+type AdminAvatarDecorationsCreateResponse = operations['admin___avatar-decorations___create']['responses']['200']['content']['application/json'];
+
 // @public (undocumented)
 type AdminAvatarDecorationsDeleteRequest = operations['admin___avatar-decorations___delete']['requestBody']['content']['application/json'];
 
@@ -1253,6 +1256,7 @@ declare namespace entities {
         AdminAnnouncementsListResponse,
         AdminAnnouncementsUpdateRequest,
         AdminAvatarDecorationsCreateRequest,
+        AdminAvatarDecorationsCreateResponse,
         AdminAvatarDecorationsDeleteRequest,
         AdminAvatarDecorationsListRequest,
         AdminAvatarDecorationsListResponse,
diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts
index d0367d8496..5e6bc0a99c 100644
--- a/packages/misskey-js/src/autogen/endpoint.ts
+++ b/packages/misskey-js/src/autogen/endpoint.ts
@@ -31,6 +31,7 @@ import type {
 	AdminAnnouncementsListResponse,
 	AdminAnnouncementsUpdateRequest,
 	AdminAvatarDecorationsCreateRequest,
+	AdminAvatarDecorationsCreateResponse,
 	AdminAvatarDecorationsDeleteRequest,
 	AdminAvatarDecorationsListRequest,
 	AdminAvatarDecorationsListResponse,
@@ -597,7 +598,7 @@ export type Endpoints = {
 	'admin/announcements/delete': { req: AdminAnnouncementsDeleteRequest; res: EmptyResponse };
 	'admin/announcements/list': { req: AdminAnnouncementsListRequest; res: AdminAnnouncementsListResponse };
 	'admin/announcements/update': { req: AdminAnnouncementsUpdateRequest; res: EmptyResponse };
-	'admin/avatar-decorations/create': { req: AdminAvatarDecorationsCreateRequest; res: EmptyResponse };
+	'admin/avatar-decorations/create': { req: AdminAvatarDecorationsCreateRequest; res: AdminAvatarDecorationsCreateResponse };
 	'admin/avatar-decorations/delete': { req: AdminAvatarDecorationsDeleteRequest; res: EmptyResponse };
 	'admin/avatar-decorations/list': { req: AdminAvatarDecorationsListRequest; res: AdminAvatarDecorationsListResponse };
 	'admin/avatar-decorations/update': { req: AdminAvatarDecorationsUpdateRequest; res: EmptyResponse };
diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts
index ced87c4c7e..f3ddf64481 100644
--- a/packages/misskey-js/src/autogen/entities.ts
+++ b/packages/misskey-js/src/autogen/entities.ts
@@ -34,6 +34,7 @@ export type AdminAnnouncementsListRequest = operations['admin___announcements___
 export type AdminAnnouncementsListResponse = operations['admin___announcements___list']['responses']['200']['content']['application/json'];
 export type AdminAnnouncementsUpdateRequest = operations['admin___announcements___update']['requestBody']['content']['application/json'];
 export type AdminAvatarDecorationsCreateRequest = operations['admin___avatar-decorations___create']['requestBody']['content']['application/json'];
+export type AdminAvatarDecorationsCreateResponse = operations['admin___avatar-decorations___create']['responses']['200']['content']['application/json'];
 export type AdminAvatarDecorationsDeleteRequest = operations['admin___avatar-decorations___delete']['requestBody']['content']['application/json'];
 export type AdminAvatarDecorationsListRequest = operations['admin___avatar-decorations___list']['requestBody']['content']['application/json'];
 export type AdminAvatarDecorationsListResponse = operations['admin___avatar-decorations___list']['responses']['200']['content']['application/json'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 560960f018..a5333d4f93 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -6324,9 +6324,22 @@ export type operations = {
       };
     };
     responses: {
-      /** @description OK (without any results) */
-      204: {
-        content: never;
+      /** @description OK (with results) */
+      200: {
+        content: {
+          'application/json': {
+            /** Format: id */
+            id: string;
+            /** Format: date-time */
+            createdAt: string;
+            /** Format: date-time */
+            updatedAt: string | null;
+            name: string;
+            description: string;
+            url: string;
+            roleIdsThatCanBeUsedThisDecoration: string[];
+          };
+        };
       };
       /** @description Client error */
       400: {

From 0472d43ee97f1ac0fd13969b2111d67b322a947f Mon Sep 17 00:00:00 2001
From: Pinapelz <donaldshan1@outlook.com>
Date: Mon, 28 Oct 2024 05:04:46 -0700
Subject: [PATCH 026/125] fix: encode RSS uris with escape sequences before
 fetching (#14826)

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 CHANGELOG.md                                        | 1 +
 packages/frontend/src/ui/_common_/statusbar-rss.vue | 2 +-
 packages/frontend/src/widgets/WidgetRss.vue         | 2 +-
 packages/frontend/src/widgets/WidgetRssTicker.vue   | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 52077f813f..0b2cb43e25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
 - Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
+- Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
 - Fix: リンク切れを修正
 
 ### Server
diff --git a/packages/frontend/src/ui/_common_/statusbar-rss.vue b/packages/frontend/src/ui/_common_/statusbar-rss.vue
index 550fc39b00..da8fa8bb21 100644
--- a/packages/frontend/src/ui/_common_/statusbar-rss.vue
+++ b/packages/frontend/src/ui/_common_/statusbar-rss.vue
@@ -48,7 +48,7 @@ const fetching = ref(true);
 const key = ref(0);
 
 const tick = () => {
-	window.fetch(`/api/fetch-rss?url=${props.url}`, {}).then(res => {
+	window.fetch(`/api/fetch-rss?url=${encodeURIComponent(props.url)}`, {}).then(res => {
 		res.json().then((feed: Misskey.entities.FetchRssResponse) => {
 			if (props.shuffle) {
 				shuffle(feed.items);
diff --git a/packages/frontend/src/widgets/WidgetRss.vue b/packages/frontend/src/widgets/WidgetRss.vue
index 3e43687709..92dc6d148e 100644
--- a/packages/frontend/src/widgets/WidgetRss.vue
+++ b/packages/frontend/src/widgets/WidgetRss.vue
@@ -70,7 +70,7 @@ const items = computed(() => rawItems.value.slice(0, widgetProps.maxEntries));
 const fetching = ref(true);
 const fetchEndpoint = computed(() => {
 	const url = new URL('/api/fetch-rss', base);
-	url.searchParams.set('url', widgetProps.url);
+	url.searchParams.set('url', encodeURIComponent(widgetProps.url));
 	return url;
 });
 const intervalClear = ref<(() => void) | undefined>();
diff --git a/packages/frontend/src/widgets/WidgetRssTicker.vue b/packages/frontend/src/widgets/WidgetRssTicker.vue
index 4f594b720f..6957878572 100644
--- a/packages/frontend/src/widgets/WidgetRssTicker.vue
+++ b/packages/frontend/src/widgets/WidgetRssTicker.vue
@@ -99,7 +99,7 @@ const items = computed(() => {
 const fetching = ref(true);
 const fetchEndpoint = computed(() => {
 	const url = new URL('/api/fetch-rss', base);
-	url.searchParams.set('url', widgetProps.url);
+	url.searchParams.set('url', encodeURIComponent(widgetProps.url));
 	return url;
 });
 const intervalClear = ref<(() => void) | undefined>();

From 8eb7749e448d912bdbe2c4eadc35f5d5f1becf61 Mon Sep 17 00:00:00 2001
From: Tamme Schichler <tamme@schichler.dev>
Date: Mon, 28 Oct 2024 13:06:16 +0100
Subject: [PATCH 027/125] fix(backend): Accept arrays in ActivityPub `icon` and
 `image` properties (#14825)

This is allowed according to the Activity vocabulary: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-icon
The issue is noticeable in combination with Bridgy Fed: https://github.com/snarfed/bridgy-fed/issues/1408
---
 .../backend/src/core/activitypub/models/ApPersonService.ts  | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 0e2934301b..c9de67b3a0 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -232,6 +232,12 @@ export class ApPersonService implements OnModuleInit {
 		if (user == null) throw new Error('failed to create user: user is null');
 
 		const [avatar, banner] = await Promise.all([icon, image].map(img => {
+			// icon and image may be arrays
+			// see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-icon
+			if (Array.isArray(img)) {
+				img = img.find(item => item && item.url) ?? null;
+			}
+			
 			// if we have an explicitly missing image, return an
 			// explicitly-null set of values
 			if ((img == null) || (typeof img === 'object' && img.url == null)) {

From f30d19051fb67f800185da283672ae7f9e8c535e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Mon, 28 Oct 2024 21:06:54 +0900
Subject: [PATCH 028/125] =?UTF-8?q?enhance(backend):=20check=5Fconnect.js?=
 =?UTF-8?q?=20=E3=81=A7=E5=85=A8Redis=E3=81=A8DB=E3=81=B8=E3=81=AE?=
 =?UTF-8?q?=E6=8E=A5=E7=B6=9A=E3=82=92=E7=A2=BA=E8=AA=8D=E3=81=99=E3=82=8B?=
 =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=20(#14853)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix race conditions in check_connect.js

(cherry picked from commit 524ddb96770690455b82522104a543c5b0b1f3b3)

* fix

* Update Changelog

---------

Co-authored-by: Hazelnoot <acomputerdog@gmail.com>
---
 CHANGELOG.md                              |  3 ++
 packages/backend/scripts/check_connect.js | 51 ++++++++++++++++++++---
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b2cb43e25..23be962d9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,9 @@
 - Fix: リンク切れを修正
 
 ### Server
+- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように  
+  (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
 - Fix: Nested proxy requestsを検出した際にブロックするように
   [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
 - Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正  
diff --git a/packages/backend/scripts/check_connect.js b/packages/backend/scripts/check_connect.js
index ba25fd416c..bb149444b5 100644
--- a/packages/backend/scripts/check_connect.js
+++ b/packages/backend/scripts/check_connect.js
@@ -5,11 +5,52 @@
 
 import Redis from 'ioredis';
 import { loadConfig } from '../built/config.js';
+import { createPostgresDataSource } from '../built/postgres.js';
 
 const config = loadConfig();
-const redis = new Redis(config.redis);
 
-redis.on('connect', () => redis.disconnect());
-redis.on('error', (e) => {
-	throw e;
-});
+async function connectToPostgres() {
+	const source = createPostgresDataSource(config);
+	await source.initialize();
+	await source.destroy();
+}
+
+async function connectToRedis(redisOptions) {
+	return await new Promise(async (resolve, reject) => {
+		const redis = new Redis({
+			...redisOptions,
+			lazyConnect: true,
+			reconnectOnError: false,
+			showFriendlyErrorStack: true,
+		});
+		redis.on('error', e => reject(e));
+
+		try {
+			await redis.connect();
+			resolve();
+
+		} catch (e) {
+			reject(e);
+
+		} finally {
+			redis.disconnect(false);
+		}
+	});
+}
+
+// If not all of these are defined, the default one gets reused.
+// so we use a Set to only try connecting once to each **uniq** redis.
+const promises = Array
+	.from(new Set([
+		config.redis,
+		config.redisForPubsub,
+		config.redisForJobQueue,
+		config.redisForTimelines,
+		config.redisForReactions,
+	]))
+	.map(connectToRedis)
+	.concat([
+		connectToPostgres()
+	]);
+
+await Promise.allSettled(promises);

From a96f09cee352f8ae7cc11c3dd45e0182a5623350 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Mon, 28 Oct 2024 12:23:59 +0000
Subject: [PATCH 029/125] Bump version to 2024.10.2-alpha.2

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 6c598e11a3..55ae092967 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.10.2-alpha.1",
+	"version": "2024.10.2-alpha.2",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index ef3d84ee96..32d6c8b0cb 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.10.2-alpha.1",
+	"version": "2024.10.2-alpha.2",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 7fc8a2a7b04d8550abdf55259bde4c857bd462a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 30 Oct 2024 09:57:54 +0900
Subject: [PATCH 030/125] =?UTF-8?q?fix(frontend):=20=E4=B8=80=E9=83=A8?=
 =?UTF-8?q?=E3=81=AE=E3=83=8E=E3=83=BC=E3=83=88=E8=A1=A8=E7=A4=BA=E3=81=A7?=
 =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E3=81=AB=E3=81=8B=E3=81=8B=E3=82=8F=E3=82=89?=
 =?UTF-8?q?=E3=81=9A=E3=82=BB=E3=83=B3=E3=82=B7=E3=83=86=E3=82=A3=E3=83=96?=
 =?UTF-8?q?=E3=81=AA=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92=E5=90=AB?=
 =?UTF-8?q?=E3=82=80=E3=83=8E=E3=83=BC=E3=83=88=E3=81=8C=E6=9C=80=E5=B0=8F?=
 =?UTF-8?q?=E5=8C=96=E3=81=95=E3=82=8C=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fix https://github.com/misskey-dev/misskey/pull/14772#discussion_r1821707117
---
 packages/frontend/src/components/MkNote.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index be1339ecc4..3de69d6d09 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -227,7 +227,7 @@ const emit = defineEmits<{
 }>();
 
 const inTimeline = inject<boolean>('inTimeline', false);
-const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(false));
+const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(true));
 const inChannel = inject('inChannel', null);
 const currentClip = inject<Ref<Misskey.entities.Clip> | null>('currentClip', null);
 

From 17d9aca5a7ec6149a8dbf0c1607c81ab188e7015 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Thu, 31 Oct 2024 13:46:42 +0900
Subject: [PATCH 031/125] =?UTF-8?q?refactor(frontend):=20as=E3=81=A8any?=
 =?UTF-8?q?=E3=82=92=E3=81=99=E3=81=90=E3=81=AA=E3=81=8A=E3=81=9B=E3=82=8B?=
 =?UTF-8?q?=E7=AF=84=E5=9B=B2=E3=81=A7=E9=99=A4=E5=8E=BB=20(#14848)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* refactor(frontend): できるだけanyを除去

* refactor

* lint

* fix

* remove unused

* Update packages/frontend/src/components/MkReactionsViewer.details.vue

* Update packages/frontend/src/components/MkUsersTooltip.vue

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 .../src/components/MkAntennaEditor.vue        |  2 +-
 .../src/components/MkChannelPreview.vue       |  3 +-
 packages/frontend/src/components/MkDialog.vue |  4 +--
 packages/frontend/src/components/MkDrive.vue  |  8 ++---
 .../src/components/MkEmojiPicker.section.vue  |  2 +-
 .../frontend/src/components/MkEmojiPicker.vue |  4 +--
 .../src/components/MkExtensionInstaller.vue   |  2 +-
 packages/frontend/src/components/MkInput.vue  |  8 ++---
 .../components/MkNotificationSelectWindow.vue |  2 +-
 .../src/components/MkObjectView.value.vue     | 10 +++---
 .../frontend/src/components/MkPageWindow.vue  |  2 +-
 .../frontend/src/components/MkPopupMenu.vue   |  2 +-
 .../frontend/src/components/MkPostForm.vue    | 20 +++--------
 .../src/components/MkPostFormAttaches.vue     |  8 ++---
 .../src/components/MkPostFormDialog.vue       | 16 ++-------
 packages/frontend/src/components/MkRadio.vue  |  8 ++---
 .../components/MkReactionsViewer.details.vue  |  3 +-
 .../frontend/src/components/MkSuperMenu.vue   | 33 +++++++++++++++++--
 .../frontend/src/components/MkUrlPreview.vue  | 10 +++---
 .../MkUserAnnouncementEditDialog.vue          |  8 +++--
 .../src/components/MkUsersTooltip.vue         |  4 +--
 packages/frontend/src/components/MkWindow.vue | 11 +++++--
 .../frontend/src/components/form/suspense.vue |  6 ++--
 .../frontend/src/components/global/MkMfm.ts   |  4 +--
 packages/frontend/src/nirax.ts                | 12 ++++---
 packages/frontend/src/os.ts                   | 23 ++++++-------
 packages/frontend/src/pages/admin/users.vue   |  6 ++--
 .../src/pages/custom-emojis-manager.vue       | 26 +++++++--------
 .../frontend/src/pages/emoji-edit-dialog.vue  | 19 ++++++-----
 .../frontend/src/pages/follow-requests.vue    |  4 +--
 packages/frontend/src/pages/lookup.vue        |  2 +-
 .../frontend/src/pages/my-clips/index.vue     |  6 ++--
 packages/frontend/src/pages/my-lists/list.vue |  4 +--
 .../page-editor/els/page-editor.el.image.vue  |  5 +--
 .../page-editor/els/page-editor.el.note.vue   | 13 +++++---
 .../els/page-editor.el.section.vue            | 12 +++----
 .../page-editor/els/page-editor.el.text.vue   |  5 +--
 packages/frontend/src/pages/registry.keys.vue |  2 +-
 .../src/pages/reversi/game.setting.vue        |  6 ++--
 packages/frontend/src/pages/scratchpad.vue    |  6 +++-
 .../src/pages/settings/2fa.qrdialog.vue       |  7 ++--
 .../frontend/src/pages/settings/accounts.vue  |  2 +-
 packages/frontend/src/pages/settings/apps.vue |  3 +-
 .../settings/avatar-decoration.dialog.vue     |  8 ++---
 packages/frontend/src/pages/user/home.vue     |  2 +-
 packages/frontend/src/router/definition.ts    |  2 +-
 packages/frontend/src/router/main.ts          |  8 ++---
 .../frontend/src/scripts/check-word-mute.ts   |  3 +-
 packages/frontend/src/scripts/form.ts         | 16 ++++-----
 packages/frontend/src/scripts/misskey-api.ts  |  6 ++--
 packages/frontend/src/scripts/select-file.ts  |  6 ++--
 packages/frontend/src/scripts/shuffle.ts      |  5 +--
 packages/frontend/src/scripts/upload.ts       |  8 ++---
 packages/frontend/src/store.ts                |  9 ++---
 packages/frontend/src/types/post-form.ts      | 22 +++++++++++++
 .../frontend/src/widgets/WidgetPhotos.vue     |  4 +--
 56 files changed, 250 insertions(+), 192 deletions(-)
 create mode 100644 packages/frontend/src/types/post-form.ts

diff --git a/packages/frontend/src/components/MkAntennaEditor.vue b/packages/frontend/src/components/MkAntennaEditor.vue
index 2386ba6fa7..e622d57f1e 100644
--- a/packages/frontend/src/components/MkAntennaEditor.vue
+++ b/packages/frontend/src/components/MkAntennaEditor.vue
@@ -160,7 +160,7 @@ async function deleteAntenna() {
 function addUser() {
 	os.selectUser({ includeSelf: true }).then(user => {
 		users.value = users.value.trim();
-		users.value += '\n@' + Misskey.acct.toString(user as any);
+		users.value += '\n@' + Misskey.acct.toString(user);
 		users.value = users.value.trim();
 	});
 }
diff --git a/packages/frontend/src/components/MkChannelPreview.vue b/packages/frontend/src/components/MkChannelPreview.vue
index 99580df5e2..c470042b79 100644
--- a/packages/frontend/src/components/MkChannelPreview.vue
+++ b/packages/frontend/src/components/MkChannelPreview.vue
@@ -47,11 +47,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { computed, ref, watch } from 'vue';
+import * as Misskey from 'misskey-js';
 import { i18n } from '@/i18n.js';
 import { miLocalStorage } from '@/local-storage.js';
 
 const props = defineProps<{
-	channel: Record<string, any>;
+	channel: Misskey.entities.Channel;
 }>();
 
 const getLastReadedAt = (): number | null => {
diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue
index 22130d4fab..b095a1cd4a 100644
--- a/packages/frontend/src/components/MkDialog.vue
+++ b/packages/frontend/src/components/MkDialog.vue
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</template>
 		</MkSelect>
 		<div v-if="(showOkButton || showCancelButton) && !actions" :class="$style.buttons">
-			<MkButton v-if="showOkButton" data-cy-modal-dialog-ok inline primary rounded :autofocus="!input && !select" :disabled="okButtonDisabledReason" @click="ok">{{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }}</MkButton>
+			<MkButton v-if="showOkButton" data-cy-modal-dialog-ok inline primary rounded :autofocus="!input && !select" :disabled="okButtonDisabledReason != null" @click="ok">{{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }}</MkButton>
 			<MkButton v-if="showCancelButton || input || select" data-cy-modal-dialog-cancel inline rounded @click="cancel">{{ cancelText ?? i18n.ts.cancel }}</MkButton>
 		</div>
 		<div v-if="actions" :class="$style.buttons">
@@ -98,7 +98,7 @@ const props = withDefaults(defineProps<{
 		text: string;
 		primary?: boolean,
 		danger?: boolean,
-		callback: (...args: any[]) => void;
+		callback: (...args: unknown[]) => void;
 	}[];
 	showOkButton?: boolean;
 	showCancelButton?: boolean;
diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue
index 910b73c798..8be6d6f53d 100644
--- a/packages/frontend/src/components/MkDrive.vue
+++ b/packages/frontend/src/components/MkDrive.vue
@@ -157,7 +157,7 @@ const ilFilesObserver = new IntersectionObserver(
 	(entries) => entries.some((entry) => entry.isIntersecting) && !fetching.value && moreFiles.value && fetchMoreFiles(),
 );
 
-const sortModeSelect = ref('+createdAt');
+const sortModeSelect = ref<NonNullable<Misskey.entities.DriveFilesRequest['sort']>>('+createdAt');
 
 watch(folder, () => emit('cd', folder.value));
 watch(sortModeSelect, () => {
@@ -198,7 +198,7 @@ function onStreamDriveFolderDeleted(folderId: string) {
 	removeFolder(folderId);
 }
 
-function onDragover(ev: DragEvent): any {
+function onDragover(ev: DragEvent) {
 	if (!ev.dataTransfer) return;
 
 	// ドラッグ元が自分自身の所有するアイテムだったら
@@ -243,7 +243,7 @@ function onDragleave() {
 	draghover.value = false;
 }
 
-function onDrop(ev: DragEvent): any {
+function onDrop(ev: DragEvent) {
 	draghover.value = false;
 
 	if (!ev.dataTransfer) return;
@@ -332,7 +332,7 @@ function createFolder() {
 		title: i18n.ts.createFolder,
 		placeholder: i18n.ts.folderName,
 	}).then(({ canceled, result: name }) => {
-		if (canceled) return;
+		if (canceled || name == null) return;
 		misskeyApi('drive/folders/create', {
 			name: name,
 			parentId: folder.value ? folder.value.id : undefined,
diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue
index f4caa730bf..b418ed3ae6 100644
--- a/packages/frontend/src/components/MkEmojiPicker.section.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.section.vue
@@ -90,7 +90,7 @@ function computeButtonTitle(ev: MouseEvent): void {
 	elm.title = getEmojiName(emoji);
 }
 
-function nestedChosen(emoji: any, ev: MouseEvent) {
+function nestedChosen(emoji: string, ev: MouseEvent) {
 	emit('chosen', emoji, ev);
 }
 </script>
diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue
index 219950f135..8187d991e7 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -409,7 +409,7 @@ function computeButtonTitle(ev: MouseEvent): void {
 	elm.title = getEmojiName(emoji);
 }
 
-function chosen(emoji: any, ev?: MouseEvent) {
+function chosen(emoji: string | Misskey.entities.EmojiSimple | UnicodeEmojiDef, ev?: MouseEvent) {
 	const el = ev && (ev.currentTarget ?? ev.target) as HTMLElement | null | undefined;
 	if (el) {
 		const rect = el.getBoundingClientRect();
@@ -426,7 +426,7 @@ function chosen(emoji: any, ev?: MouseEvent) {
 	// 最近使った絵文字更新
 	if (!pinned.value?.includes(key)) {
 		let recents = defaultStore.state.recentlyUsedEmojis;
-		recents = recents.filter((emoji: any) => emoji !== key);
+		recents = recents.filter((emoji) => emoji !== key);
 		recents.unshift(key);
 		defaultStore.set('recentlyUsedEmojis', recents.splice(0, 32));
 	}
diff --git a/packages/frontend/src/components/MkExtensionInstaller.vue b/packages/frontend/src/components/MkExtensionInstaller.vue
index b41604b2c3..d59b20435e 100644
--- a/packages/frontend/src/components/MkExtensionInstaller.vue
+++ b/packages/frontend/src/components/MkExtensionInstaller.vue
@@ -73,7 +73,7 @@ export type Extension = {
 		author: string;
 		description?: string;
 		permissions?: string[];
-		config?: Record<string, any>;
+		config?: Record<string, unknown>;
 	};
 } | {
 	type: 'theme';
diff --git a/packages/frontend/src/components/MkInput.vue b/packages/frontend/src/components/MkInput.vue
index e01ff86c5a..08817fd6a8 100644
--- a/packages/frontend/src/components/MkInput.vue
+++ b/packages/frontend/src/components/MkInput.vue
@@ -44,7 +44,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-import { onMounted, onUnmounted, nextTick, ref, shallowRef, watch, computed, toRefs } from 'vue';
+import { onMounted, onUnmounted, nextTick, ref, shallowRef, watch, computed, toRefs, InputHTMLAttributes } from 'vue';
 import { debounce } from 'throttle-debounce';
 import MkButton from '@/components/MkButton.vue';
 import { useInterval } from '@@/js/use-interval.js';
@@ -53,7 +53,7 @@ import { Autocomplete, SuggestionType } from '@/scripts/autocomplete.js';
 
 const props = defineProps<{
 	modelValue: string | number | null;
-	type?: 'text' | 'number' | 'password' | 'email' | 'url' | 'date' | 'time' | 'search' | 'datetime-local';
+	type?: InputHTMLAttributes['type'];
 	required?: boolean;
 	readonly?: boolean;
 	disabled?: boolean;
@@ -64,8 +64,8 @@ const props = defineProps<{
 	mfmAutocomplete?: boolean | SuggestionType[],
 	autocapitalize?: string;
 	spellcheck?: boolean;
-	inputmode?: 'none' | 'text' | 'search' | 'email' | 'url' | 'numeric' | 'tel' | 'decimal';
-	step?: any;
+	inputmode?: InputHTMLAttributes['inputmode'];
+	step?: InputHTMLAttributes['step'];
 	datalist?: string[];
 	min?: number;
 	max?: number;
diff --git a/packages/frontend/src/components/MkNotificationSelectWindow.vue b/packages/frontend/src/components/MkNotificationSelectWindow.vue
index 47a9c79e45..d07827d11a 100644
--- a/packages/frontend/src/components/MkNotificationSelectWindow.vue
+++ b/packages/frontend/src/components/MkNotificationSelectWindow.vue
@@ -53,7 +53,7 @@ const props = withDefaults(defineProps<{
 
 const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
 
-const typesMap: TypesMap = notificationTypes.reduce((p, t) => ({ ...p, [t]: ref<boolean>(!props.excludeTypes.includes(t)) }), {} as any);
+const typesMap = notificationTypes.reduce((p, t) => ({ ...p, [t]: ref<boolean>(!props.excludeTypes.includes(t)) }), {} as TypesMap);
 
 function ok() {
 	emit('done', {
diff --git a/packages/frontend/src/components/MkObjectView.value.vue b/packages/frontend/src/components/MkObjectView.value.vue
index dabdd324fd..7fa8c23c6c 100644
--- a/packages/frontend/src/components/MkObjectView.value.vue
+++ b/packages/frontend/src/components/MkObjectView.value.vue
@@ -39,7 +39,7 @@ import number from '@/filters/number.js';
 import XValue from '@/components/MkObjectView.value.vue';
 
 const props = defineProps<{
-	value: any;
+	value: unknown;
 }>();
 
 const collapsed = reactive({});
@@ -50,19 +50,19 @@ if (isObject(props.value)) {
 	}
 }
 
-function isObject(v): boolean {
+function isObject(v: unknown): v is Record<PropertyKey, unknown> {
 	return typeof v === 'object' && !Array.isArray(v) && v !== null;
 }
 
-function isArray(v): boolean {
+function isArray(v: unknown): v is unknown[] {
 	return Array.isArray(v);
 }
 
-function isEmpty(v): boolean {
+function isEmpty(v: unknown): v is Record<PropertyKey, never> | never[] {
 	return (isArray(v) && v.length === 0) || (isObject(v) && Object.keys(v).length === 0);
 }
 
-function collapsable(v): boolean {
+function collapsable(v: unknown): boolean {
 	return (isObject(v) || isArray(v)) && !isEmpty(v);
 }
 </script>
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index 4777da2848..02c84df447 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -58,7 +58,7 @@ const windowRouter = routerFactory(props.initialPath);
 const contents = shallowRef<HTMLElement | null>(null);
 const pageMetadata = ref<null | PageMetadata>(null);
 const windowEl = shallowRef<InstanceType<typeof MkWindow>>();
-const history = ref<{ path: string; key: any; }[]>([{
+const history = ref<{ path: string; key: string; }[]>([{
 	path: windowRouter.getCurrentPath(),
 	key: windowRouter.getCurrentKey(),
 }]);
diff --git a/packages/frontend/src/components/MkPopupMenu.vue b/packages/frontend/src/components/MkPopupMenu.vue
index 26c251a8d2..df664e49f7 100644
--- a/packages/frontend/src/components/MkPopupMenu.vue
+++ b/packages/frontend/src/components/MkPopupMenu.vue
@@ -19,7 +19,7 @@ defineProps<{
 	items: MenuItem[];
 	align?: 'center' | string;
 	width?: number;
-	src?: any;
+	src?: HTMLElement | null;
 	returnFocusTo?: HTMLElement | null;
 }>();
 
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index b6b80082d3..f2fe048449 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -129,25 +129,13 @@ import { miLocalStorage } from '@/local-storage.js';
 import { claimAchievement } from '@/scripts/achievements.js';
 import { emojiPicker } from '@/scripts/emoji-picker.js';
 import { mfmFunctionPicker } from '@/scripts/mfm-function-picker.js';
+import type { PostFormProps } from '@/types/post-form.js';
 
 const $i = signinRequired();
 
 const modal = inject('modal');
 
-const props = withDefaults(defineProps<{
-	reply?: Misskey.entities.Note;
-	renote?: Misskey.entities.Note;
-	channel?: Misskey.entities.Channel; // TODO
-	mention?: Misskey.entities.User;
-	specified?: Misskey.entities.UserDetailed;
-	initialText?: string;
-	initialCw?: string;
-	initialVisibility?: (typeof Misskey.noteVisibilities)[number];
-	initialFiles?: Misskey.entities.DriveFile[];
-	initialLocalOnly?: boolean;
-	initialVisibleUsers?: Misskey.entities.UserDetailed[];
-	initialNote?: Misskey.entities.Note;
-	instant?: boolean;
+const props = withDefaults(defineProps<PostFormProps & {
 	fixed?: boolean;
 	autofocus?: boolean;
 	freezeAfterPosted?: boolean;
@@ -955,8 +943,8 @@ function showActions(ev: MouseEvent) {
 			action.handler({
 				text: text.value,
 				cw: cw.value,
-			}, (key, value: any) => {
-				if (typeof key !== 'string') return;
+			}, (key, value) => {
+				if (typeof key !== 'string' || typeof value !== 'string') return;
 				if (key === 'text') { text.value = value; }
 				if (key === 'cw') { useCw.value = value !== null; cw.value = value; }
 			});
diff --git a/packages/frontend/src/components/MkPostFormAttaches.vue b/packages/frontend/src/components/MkPostFormAttaches.vue
index ee7038df64..56e026aa3c 100644
--- a/packages/frontend/src/components/MkPostFormAttaches.vue
+++ b/packages/frontend/src/components/MkPostFormAttaches.vue
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <template>
 <div v-show="props.modelValue.length != 0" :class="$style.root">
 	<Sortable :modelValue="props.modelValue" :class="$style.files" itemKey="id" :animation="150" :delay="100" :delayOnTouchOnly="true" @update:modelValue="v => emit('update:modelValue', v)">
-		<template #item="{element}">
+		<template #item="{ element }">
 			<div
 				:class="$style.file"
 				role="button"
@@ -38,14 +38,14 @@ import type { MenuItem } from '@/types/menu.js';
 const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default));
 
 const props = defineProps<{
-	modelValue: any[];
+	modelValue: Misskey.entities.DriveFile[];
 	detachMediaFn?: (id: string) => void;
 }>();
 
 const mock = inject<boolean>('mock', false);
 
 const emit = defineEmits<{
-	(ev: 'update:modelValue', value: any[]): void;
+	(ev: 'update:modelValue', value: Misskey.entities.DriveFile[]): void;
 	(ev: 'detach', id: string): void;
 	(ev: 'changeSensitive', file: Misskey.entities.DriveFile, isSensitive: boolean): void;
 	(ev: 'changeName', file: Misskey.entities.DriveFile, newName: string): void;
@@ -113,7 +113,7 @@ async function rename(file) {
 	});
 }
 
-async function describe(file) {
+async function describe(file: Misskey.entities.DriveFile) {
 	if (mock) return;
 
 	const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
diff --git a/packages/frontend/src/components/MkPostFormDialog.vue b/packages/frontend/src/components/MkPostFormDialog.vue
index d6bca29050..32d8df1504 100644
--- a/packages/frontend/src/components/MkPostFormDialog.vue
+++ b/packages/frontend/src/components/MkPostFormDialog.vue
@@ -11,23 +11,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { shallowRef } from 'vue';
-import * as Misskey from 'misskey-js';
 import MkModal from '@/components/MkModal.vue';
 import MkPostForm from '@/components/MkPostForm.vue';
+import type { PostFormProps } from '@/types/post-form.js';
 
-const props = withDefaults(defineProps<{
-	reply?: Misskey.entities.Note;
-	renote?: Misskey.entities.Note;
-	channel?: any; // TODO
-	mention?: Misskey.entities.User;
-	specified?: Misskey.entities.UserDetailed;
-	initialText?: string;
-	initialCw?: string;
-	initialVisibility?: (typeof Misskey.noteVisibilities)[number];
-	initialFiles?: Misskey.entities.DriveFile[];
-	initialLocalOnly?: boolean;
-	initialVisibleUsers?: Misskey.entities.UserDetailed[];
-	initialNote?: Misskey.entities.Note;
+const props = withDefaults(defineProps<PostFormProps & {
 	instant?: boolean;
 	fixed?: boolean;
 	autofocus?: boolean;
diff --git a/packages/frontend/src/components/MkRadio.vue b/packages/frontend/src/components/MkRadio.vue
index e735d9fff8..f16c8f6c2a 100644
--- a/packages/frontend/src/components/MkRadio.vue
+++ b/packages/frontend/src/components/MkRadio.vue
@@ -24,17 +24,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 </div>
 </template>
 
-<script lang="ts" setup>
+<script lang="ts" setup generic="T extends unknown">
 import { computed } from 'vue';
 
 const props = defineProps<{
-	modelValue: any;
-	value: any;
+	modelValue: T;
+	value: T;
 	disabled?: boolean;
 }>();
 
 const emit = defineEmits<{
-	(ev: 'update:modelValue', value: any): void;
+	(ev: 'update:modelValue', value: T): void;
 }>();
 
 const checked = computed(() => props.modelValue === props.value);
diff --git a/packages/frontend/src/components/MkReactionsViewer.details.vue b/packages/frontend/src/components/MkReactionsViewer.details.vue
index f4c3643ba8..d24e0b15bf 100644
--- a/packages/frontend/src/components/MkReactionsViewer.details.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.details.vue
@@ -23,6 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { } from 'vue';
+import * as Misskey from 'misskey-js';
 import { getEmojiName } from '@@/js/emojilist.js';
 import MkTooltip from './MkTooltip.vue';
 import MkReactionIcon from '@/components/MkReactionIcon.vue';
@@ -30,7 +31,7 @@ import MkReactionIcon from '@/components/MkReactionIcon.vue';
 defineProps<{
 	showing: boolean;
 	reaction: string;
-	users: any[]; // TODO
+	users: Misskey.entities.UserLite[];
 	count: number;
 	targetElement: HTMLElement;
 }>();
diff --git a/packages/frontend/src/components/MkSuperMenu.vue b/packages/frontend/src/components/MkSuperMenu.vue
index 6e7a875dec..0caaed6f39 100644
--- a/packages/frontend/src/components/MkSuperMenu.vue
+++ b/packages/frontend/src/components/MkSuperMenu.vue
@@ -28,11 +28,38 @@ SPDX-License-Identifier: AGPL-3.0-only
 </div>
 </template>
 
-<script lang="ts" setup>
-import { } from 'vue';
+<script lang="ts">
+export type SuperMenuDef = {
+	title?: string;
+	items: ({
+		type: 'a';
+		href: string;
+		target?: string;
+		icon?: string;
+		text: string;
+		danger?: boolean;
+		active?: boolean;
+	} | {
+		type: 'button';
+		icon?: string;
+		text: string;
+		danger?: boolean;
+		active?: boolean;
+		action: (ev: MouseEvent) => void;
+	} | {
+		type: 'link';
+		to: string;
+		icon?: string;
+		text: string;
+		danger?: boolean;
+		active?: boolean;
+	})[];
+};
+</script>
 
+<script lang="ts" setup>
 defineProps<{
-	def: any[];
+	def: SuperMenuDef[];
 	grid?: boolean;
 }>();
 </script>
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index c287effadc..f0da8fd3f2 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -180,7 +180,7 @@ window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${versatileLa
 		sensitive.value = info.sensitive ?? false;
 	});
 
-function adjustTweetHeight(message: any) {
+function adjustTweetHeight(message: MessageEvent) {
 	if (message.origin !== 'https://platform.twitter.com') return;
 	const embed = message.data?.['twttr.embed'];
 	if (embed?.method !== 'twttr.private.resize') return;
@@ -193,14 +193,16 @@ function openPlayer(): void {
 	const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
 		url: requestUrl.href,
 	}, {
-		// TODO
+		closed: () => {
+			dispose();
+		},
 	});
 }
 
-(window as any).addEventListener('message', adjustTweetHeight);
+window.addEventListener('message', adjustTweetHeight);
 
 onUnmounted(() => {
-	(window as any).removeEventListener('message', adjustTweetHeight);
+	window.removeEventListener('message', adjustTweetHeight);
 });
 </script>
 
diff --git a/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue b/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue
index 7a2b5f5ddc..7f0266d1d3 100644
--- a/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue
+++ b/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue
@@ -62,9 +62,11 @@ import MkTextarea from '@/components/MkTextarea.vue';
 import MkSwitch from '@/components/MkSwitch.vue';
 import MkRadios from '@/components/MkRadios.vue';
 
+type AdminAnnouncementType = Misskey.entities.AdminAnnouncementsCreateRequest & { id: string; }
+
 const props = defineProps<{
 	user: Misskey.entities.User,
-	announcement?: Misskey.entities.Announcement,
+	announcement?: Required<AdminAnnouncementType>,
 }>();
 
 const dialog = ref<InstanceType<typeof MkModalWindow> | null>(null);
@@ -75,7 +77,7 @@ const display = ref(props.announcement ? props.announcement.display : 'dialog');
 const needConfirmationToRead = ref(props.announcement ? props.announcement.needConfirmationToRead : false);
 
 const emit = defineEmits<{
-	(ev: 'done', v: { deleted?: boolean; updated?: any; created?: any }): void,
+	(ev: 'done', v: { deleted?: boolean; updated?: AdminAnnouncementType; created?: AdminAnnouncementType; }): void,
 	(ev: 'closed'): void
 }>();
 
@@ -88,7 +90,7 @@ async function done() {
 		display: display.value,
 		needConfirmationToRead: needConfirmationToRead.value,
 		userId: props.user.id,
-	};
+	} satisfies Misskey.entities.AdminAnnouncementsCreateRequest;
 
 	if (props.announcement) {
 		await os.apiWithDialog('admin/announcements/update', {
diff --git a/packages/frontend/src/components/MkUsersTooltip.vue b/packages/frontend/src/components/MkUsersTooltip.vue
index 054a503257..0cb7f22e93 100644
--- a/packages/frontend/src/components/MkUsersTooltip.vue
+++ b/packages/frontend/src/components/MkUsersTooltip.vue
@@ -16,12 +16,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-import { } from 'vue';
+import * as Misskey from 'misskey-js';
 import MkTooltip from './MkTooltip.vue';
 
 defineProps<{
 	showing: boolean;
-	users: any[]; // TODO
+	users: Misskey.entities.UserLite[];
 	count: number;
 	targetElement: HTMLElement;
 }>();
diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue
index 056b6a37ed..ed7e3867ce 100644
--- a/packages/frontend/src/components/MkWindow.vue
+++ b/packages/frontend/src/components/MkWindow.vue
@@ -60,6 +60,13 @@ import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { defaultStore } from '@/store.js';
 
+type WindowButton = {
+	title: string;
+	icon: string;
+	onClick: () => void;
+	highlighted?: boolean;
+};
+
 const minHeight = 50;
 const minWidth = 250;
 
@@ -87,8 +94,8 @@ const props = withDefaults(defineProps<{
 	mini?: boolean;
 	front?: boolean;
 	contextmenu?: MenuItem[] | null;
-	buttonsLeft?: any[];
-	buttonsRight?: any[];
+	buttonsLeft?: WindowButton[];
+	buttonsRight?: WindowButton[];
 }>(), {
 	initialWidth: 400,
 	initialHeight: null,
diff --git a/packages/frontend/src/components/form/suspense.vue b/packages/frontend/src/components/form/suspense.vue
index 5226c61d68..821f07510b 100644
--- a/packages/frontend/src/components/form/suspense.vue
+++ b/packages/frontend/src/components/form/suspense.vue
@@ -18,19 +18,19 @@ SPDX-License-Identifier: AGPL-3.0-only
 </div>
 </template>
 
-<script lang="ts" setup>
+<script lang="ts" setup generic="T extends unknown">
 import { ref, watch } from 'vue';
 import MkButton from '@/components/MkButton.vue';
 import { i18n } from '@/i18n.js';
 
 const props = defineProps<{
-	p: () => Promise<any>;
+	p: () => Promise<T>;
 }>();
 
 const pending = ref(true);
 const resolved = ref(false);
 const rejected = ref(false);
-const result = ref<any>(null);
+const result = ref<T | null>(null);
 
 const process = () => {
 	if (props.p == null) {
diff --git a/packages/frontend/src/components/global/MkMfm.ts b/packages/frontend/src/components/global/MkMfm.ts
index 0d4ae8cacb..0d138d1f1c 100644
--- a/packages/frontend/src/components/global/MkMfm.ts
+++ b/packages/frontend/src/components/global/MkMfm.ts
@@ -467,8 +467,8 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
 			}
 
 			default: {
-				// eslint-disable-next-line @typescript-eslint/no-explicit-any
-				console.error('unrecognized ast type:', (token as any).type);
+				// @ts-expect-error 存在しないASTタイプ
+				console.error('unrecognized ast type:', token.type);
 
 				return [];
 			}
diff --git a/packages/frontend/src/nirax.ts b/packages/frontend/src/nirax.ts
index 25f853453a..965bd6f0bc 100644
--- a/packages/frontend/src/nirax.ts
+++ b/packages/frontend/src/nirax.ts
@@ -36,6 +36,8 @@ interface RouteDefWithRedirect extends RouteDefBase {
 
 export type RouteDef = RouteDefWithComponent | RouteDefWithRedirect;
 
+export type RouterFlag = 'forcePage';
+
 type ParsedPath = (string | {
 	name: string;
 	startsWith?: string;
@@ -107,7 +109,7 @@ export interface IRouter extends EventEmitter<RouterEvent> {
 	current: Resolved;
 	currentRef: ShallowRef<Resolved>;
 	currentRoute: ShallowRef<RouteDef>;
-	navHook: ((path: string, flag?: any) => boolean) | null;
+	navHook: ((path: string, flag?: RouterFlag) => boolean) | null;
 
 	/**
 	 * ルートの初期化(eventListenerの定義後に必ず呼び出すこと)
@@ -116,11 +118,11 @@ export interface IRouter extends EventEmitter<RouterEvent> {
 
 	resolve(path: string): Resolved | null;
 
-	getCurrentPath(): any;
+	getCurrentPath(): string;
 
 	getCurrentKey(): string;
 
-	push(path: string, flag?: any): void;
+	push(path: string, flag?: RouterFlag): void;
 
 	replace(path: string, key?: string | null): void;
 
@@ -197,7 +199,7 @@ export class Router extends EventEmitter<RouterEvent> implements IRouter {
 	private currentKey = Date.now().toString();
 	private redirectCount = 0;
 
-	public navHook: ((path: string, flag?: any) => boolean) | null = null;
+	public navHook: ((path: string, flag?: RouterFlag) => boolean) | null = null;
 
 	constructor(routes: Router['routes'], currentPath: Router['currentPath'], isLoggedIn: boolean, notFoundPageComponent: Component) {
 		super();
@@ -404,7 +406,7 @@ export class Router extends EventEmitter<RouterEvent> implements IRouter {
 		return this.currentKey;
 	}
 
-	public push(path: string, flag?: any) {
+	public push(path: string, flag?: RouterFlag) {
 		const beforePath = this.currentPath;
 		if (path === beforePath) {
 			this.emit('same');
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 07d91a0644..ea1b673de9 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -28,12 +28,13 @@ import { pleaseLogin } from '@/scripts/please-login.js';
 import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
 import { getHTMLElementOrNull } from '@/scripts/get-dom-node-or-null.js';
 import { focusParent } from '@/scripts/focus.js';
+import type { PostFormProps } from '@/types/post-form.js';
 
 export const openingWindowsCount = ref(0);
 
-export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req']>(
+export const apiWithDialog = (<E extends keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req']>(
 	endpoint: E,
-	data: P = {} as any,
+	data: P,
 	token?: string | null | undefined,
 	customErrors?: Record<string, { title?: string; text: string; }>,
 ) => {
@@ -94,7 +95,7 @@ export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey
 
 export function promiseDialog<T extends Promise<any>>(
 	promise: T,
-	onSuccess?: ((res: any) => void) | null,
+	onSuccess?: ((res: Awaited<T>) => void) | null,
 	onFailure?: ((err: Misskey.api.APIError) => void) | null,
 	text?: string,
 ): T {
@@ -136,12 +137,12 @@ export function promiseDialog<T extends Promise<any>>(
 }
 
 let popupIdCount = 0;
-export const popups = ref([]) as Ref<{
+export const popups = ref<{
 	id: number;
 	component: Component;
 	props: Record<string, any>;
 	events: Record<string, any>;
-}[]>;
+}[]>([]);
 
 const zIndexes = {
 	veryLow: 500000,
@@ -458,7 +459,7 @@ type SelectItem<C> = {
 };
 
 // default が指定されていたら result は null になり得ないことを保証する overload function
-export function select<C = any>(props: {
+export function select<C = unknown>(props: {
 	title?: string;
 	text?: string;
 	default: string;
@@ -471,7 +472,7 @@ export function select<C = any>(props: {
 } | {
 	canceled: false; result: C;
 }>;
-export function select<C = any>(props: {
+export function select<C = unknown>(props: {
 	title?: string;
 	text?: string;
 	default?: string | null;
@@ -484,7 +485,7 @@ export function select<C = any>(props: {
 } | {
 	canceled: false; result: C | null;
 }>;
-export function select<C = any>(props: {
+export function select<C = unknown>(props: {
 	title?: string;
 	text?: string;
 	default?: string | null;
@@ -687,13 +688,13 @@ export function contextMenu(items: MenuItem[], ev: MouseEvent): Promise<void> {
 	}));
 }
 
-export function post(props: Record<string, any> = {}): Promise<void> {
+export function post(props: PostFormProps = {}): Promise<void> {
 	pleaseLogin({
 		openOnRemote: (props.initialText || props.initialNote ? {
 			type: 'share',
 			params: {
-				text: props.initialText ?? props.initialNote.text,
-				visibility: props.initialVisibility ?? props.initialNote?.visibility,
+				text: props.initialText ?? props.initialNote?.text ?? '',
+				visibility: props.initialVisibility ?? props.initialNote?.visibility ?? 'public',
 				localOnly: (props.initialLocalOnly || props.initialNote?.localOnly) ? '1' : '0',
 			},
 		} : undefined),
diff --git a/packages/frontend/src/pages/admin/users.vue b/packages/frontend/src/pages/admin/users.vue
index d1bbb5b734..870c3ce88b 100644
--- a/packages/frontend/src/pages/admin/users.vue
+++ b/packages/frontend/src/pages/admin/users.vue
@@ -99,19 +99,19 @@ async function addUser() {
 	const { canceled: canceled1, result: username } = await os.inputText({
 		title: i18n.ts.username,
 	});
-	if (canceled1) return;
+	if (canceled1 || username == null) return;
 
 	const { canceled: canceled2, result: password } = await os.inputText({
 		title: i18n.ts.password,
 		type: 'password',
 	});
-	if (canceled2) return;
+	if (canceled2 || password == null) return;
 
 	os.apiWithDialog('admin/accounts/create', {
 		username: username,
 		password: password,
 	}).then(res => {
-		paginationComponent.value.reload();
+		paginationComponent.value?.reload();
 	});
 }
 
diff --git a/packages/frontend/src/pages/custom-emojis-manager.vue b/packages/frontend/src/pages/custom-emojis-manager.vue
index 1e416e22d3..cae3f3ede9 100644
--- a/packages/frontend/src/pages/custom-emojis-manager.vue
+++ b/packages/frontend/src/pages/custom-emojis-manager.vue
@@ -116,7 +116,7 @@ const selectAll = () => {
 	if (selectedEmojis.value.length > 0) {
 		selectedEmojis.value = [];
 	} else {
-		selectedEmojis.value = Array.from(emojisPaginationComponent.value.items.values(), item => item.id);
+		selectedEmojis.value = Array.from(emojisPaginationComponent.value?.items.values(), item => item.id);
 	}
 };
 
@@ -133,7 +133,7 @@ const add = async (ev: MouseEvent) => {
 	}, {
 		done: result => {
 			if (result.created) {
-				emojisPaginationComponent.value.prepend(result.created);
+				emojisPaginationComponent.value?.prepend(result.created);
 			}
 		},
 		closed: () => dispose(),
@@ -146,12 +146,12 @@ const edit = (emoji) => {
 	}, {
 		done: result => {
 			if (result.updated) {
-				emojisPaginationComponent.value.updateItem(result.updated.id, (oldEmoji: any) => ({
+				emojisPaginationComponent.value?.updateItem(result.updated.id, (oldEmoji) => ({
 					...oldEmoji,
 					...result.updated,
 				}));
 			} else if (result.deleted) {
-				emojisPaginationComponent.value.removeItem(emoji.id);
+				emojisPaginationComponent.value?.removeItem(emoji.id);
 			}
 		},
 		closed: () => dispose(),
@@ -226,7 +226,7 @@ const setCategoryBulk = async () => {
 		ids: selectedEmojis.value,
 		category: result,
 	});
-	emojisPaginationComponent.value.reload();
+	emojisPaginationComponent.value?.reload();
 };
 
 const setLicenseBulk = async () => {
@@ -238,43 +238,43 @@ const setLicenseBulk = async () => {
 		ids: selectedEmojis.value,
 		license: result,
 	});
-	emojisPaginationComponent.value.reload();
+	emojisPaginationComponent.value?.reload();
 };
 
 const addTagBulk = async () => {
 	const { canceled, result } = await os.inputText({
 		title: 'Tag',
 	});
-	if (canceled) return;
+	if (canceled || result == null) return;
 	await os.apiWithDialog('admin/emoji/add-aliases-bulk', {
 		ids: selectedEmojis.value,
 		aliases: result.split(' '),
 	});
-	emojisPaginationComponent.value.reload();
+	emojisPaginationComponent.value?.reload();
 };
 
 const removeTagBulk = async () => {
 	const { canceled, result } = await os.inputText({
 		title: 'Tag',
 	});
-	if (canceled) return;
+	if (canceled || result == null) return;
 	await os.apiWithDialog('admin/emoji/remove-aliases-bulk', {
 		ids: selectedEmojis.value,
 		aliases: result.split(' '),
 	});
-	emojisPaginationComponent.value.reload();
+	emojisPaginationComponent.value?.reload();
 };
 
 const setTagBulk = async () => {
 	const { canceled, result } = await os.inputText({
 		title: 'Tag',
 	});
-	if (canceled) return;
+	if (canceled || result == null) return;
 	await os.apiWithDialog('admin/emoji/set-aliases-bulk', {
 		ids: selectedEmojis.value,
 		aliases: result.split(' '),
 	});
-	emojisPaginationComponent.value.reload();
+	emojisPaginationComponent.value?.reload();
 };
 
 const delBulk = async () => {
@@ -286,7 +286,7 @@ const delBulk = async () => {
 	await os.apiWithDialog('admin/emoji/delete-bulk', {
 		ids: selectedEmojis.value,
 	});
-	emojisPaginationComponent.value.reload();
+	emojisPaginationComponent.value?.reload();
 };
 
 const headerActions = computed(() => [{
diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue
index 3b3f41d9b1..2caba03675 100644
--- a/packages/frontend/src/pages/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/emoji-edit-dialog.vue
@@ -95,14 +95,14 @@ import { selectFile } from '@/scripts/select-file.js';
 import MkRolePreview from '@/components/MkRolePreview.vue';
 
 const props = defineProps<{
-	emoji?: any,
+	emoji?: Misskey.entities.EmojiDetailed,
 }>();
 
 const windowEl = ref<InstanceType<typeof MkWindow> | null>(null);
 const name = ref<string>(props.emoji ? props.emoji.name : '');
-const category = ref<string>(props.emoji ? props.emoji.category : '');
+const category = ref<string>(props.emoji?.category ? props.emoji.category : '');
 const aliases = ref<string>(props.emoji ? props.emoji.aliases.join(' ') : '');
-const license = ref<string>(props.emoji ? (props.emoji.license ?? '') : '');
+const license = ref<string>(props.emoji?.license ? props.emoji.license : '');
 const isSensitive = ref(props.emoji ? props.emoji.isSensitive : false);
 const localOnly = ref(props.emoji ? props.emoji.localOnly : false);
 const roleIdsThatCanBeUsedThisEmojiAsReaction = ref(props.emoji ? props.emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : []);
@@ -116,11 +116,11 @@ watch(roleIdsThatCanBeUsedThisEmojiAsReaction, async () => {
 const imgUrl = computed(() => file.value ? file.value.url : props.emoji ? `/emoji/${props.emoji.name}.webp` : null);
 
 const emit = defineEmits<{
-	(ev: 'done', v: { deleted?: boolean; updated?: any; created?: any }): void,
+	(ev: 'done', v: { deleted?: boolean; updated?: Misskey.entities.AdminEmojiUpdateRequest; created?: Misskey.entities.AdminEmojiUpdateRequest }): void,
 	(ev: 'closed'): void
 }>();
 
-async function changeImage(ev) {
+async function changeImage(ev: Event) {
 	file.value = await selectFile(ev.currentTarget ?? ev.target, null);
 	const candidate = file.value.name.replace(/\.(.+)$/, '');
 	if (candidate.match(/^[a-z0-9_]+$/)) {
@@ -140,7 +140,7 @@ async function addRole() {
 	rolesThatCanBeUsedThisEmojiAsReaction.value.push(role);
 }
 
-async function removeRole(role, ev) {
+async function removeRole(role: Misskey.entities.RoleLite, ev: Event) {
 	rolesThatCanBeUsedThisEmojiAsReaction.value = rolesThatCanBeUsedThisEmojiAsReaction.value.filter(x => x.id !== role.id);
 }
 
@@ -172,7 +172,7 @@ async function done() {
 			},
 		});
 
-		windowEl.value.close();
+		windowEl.value?.close();
 	} else {
 		const created = await os.apiWithDialog('admin/emoji/add', params);
 
@@ -180,11 +180,12 @@ async function done() {
 			created: created,
 		});
 
-		windowEl.value.close();
+		windowEl.value?.close();
 	}
 }
 
 async function del() {
+	if (!props.emoji) return;
 	const { canceled } = await os.confirm({
 		type: 'warning',
 		text: i18n.tsx.removeAreYouSure({ x: name.value }),
@@ -197,7 +198,7 @@ async function del() {
 		emit('done', {
 			deleted: true,
 		});
-		windowEl.value.close();
+		windowEl.value?.close();
 	});
 }
 </script>
diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue
index 8991af8086..a840d0d0b3 100644
--- a/packages/frontend/src/pages/follow-requests.vue
+++ b/packages/frontend/src/pages/follow-requests.vue
@@ -55,13 +55,13 @@ const pagination = {
 
 function accept(user) {
 	misskeyApi('following/requests/accept', { userId: user.id }).then(() => {
-		paginationComponent.value.reload();
+		paginationComponent.value?.reload();
 	});
 }
 
 function reject(user) {
 	misskeyApi('following/requests/reject', { userId: user.id }).then(() => {
-		paginationComponent.value.reload();
+		paginationComponent.value?.reload();
 	});
 }
 
diff --git a/packages/frontend/src/pages/lookup.vue b/packages/frontend/src/pages/lookup.vue
index 3233953942..6f10c69640 100644
--- a/packages/frontend/src/pages/lookup.vue
+++ b/packages/frontend/src/pages/lookup.vue
@@ -40,7 +40,7 @@ function fetch() {
 		return;
 	}
 
-	let promise: Promise<any>;
+	let promise: Promise<unknown>;
 
 	if (uri.startsWith('https://')) {
 		promise = misskeyApi('ap/show', {
diff --git a/packages/frontend/src/pages/my-clips/index.vue b/packages/frontend/src/pages/my-clips/index.vue
index ece998a7a5..acf37a9a2f 100644
--- a/packages/frontend/src/pages/my-clips/index.vue
+++ b/packages/frontend/src/pages/my-clips/index.vue
@@ -77,15 +77,15 @@ async function create() {
 
 	clipsCache.delete();
 
-	pagingComponent.value.reload();
+	pagingComponent.value?.reload();
 }
 
 function onClipCreated() {
-	pagingComponent.value.reload();
+	pagingComponent.value?.reload();
 }
 
 function onClipDeleted() {
-	pagingComponent.value.reload();
+	pagingComponent.value?.reload();
 }
 
 const headerActions = computed(() => []);
diff --git a/packages/frontend/src/pages/my-lists/list.vue b/packages/frontend/src/pages/my-lists/list.vue
index 804a5ae8f8..69e404bd85 100644
--- a/packages/frontend/src/pages/my-lists/list.vue
+++ b/packages/frontend/src/pages/my-lists/list.vue
@@ -110,7 +110,7 @@ function addUser() {
 			listId: list.value.id,
 			userId: user.id,
 		}).then(() => {
-			paginationEl.value.reload();
+			paginationEl.value?.reload();
 		});
 	});
 }
@@ -126,7 +126,7 @@ async function removeUser(item, ev) {
 				listId: list.value.id,
 				userId: item.userId,
 			}).then(() => {
-				paginationEl.value.removeItem(item.id);
+				paginationEl.value?.removeItem(item.id);
 			});
 		},
 	}], ev.currentTarget ?? ev.target);
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue
index 1cfe7a6d2d..247b8f61a1 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue
@@ -30,11 +30,12 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
 
 const props = defineProps<{
-	modelValue: any
+	modelValue: Misskey.entities.PageBlock & { type: 'image' };
 }>();
 
 const emit = defineEmits<{
-	(ev: 'update:modelValue', value: any): void;
+	(ev: 'update:modelValue', value: Misskey.entities.PageBlock & { type: 'image' }): void;
+	(ev: 'remove'): void;
 }>();
 
 const file = ref<Misskey.entities.DriveFile | null>(null);
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue
index 0a28386986..52b4f2aaa3 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue
@@ -34,19 +34,24 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
 
 const props = defineProps<{
-	modelValue: any
+	modelValue: Misskey.entities.PageBlock & { type: 'note' };
 }>();
 
 const emit = defineEmits<{
-	(ev: 'update:modelValue', value: any): void;
+	(ev: 'update:modelValue', value: Misskey.entities.PageBlock & { type: 'note' }): void;
 }>();
 
-const id = ref<any>(props.modelValue.note);
+const id = ref(props.modelValue.note);
 const note = ref<Misskey.entities.Note | null>(null);
 
 watch(id, async () => {
 	if (id.value && (id.value.startsWith('http://') || id.value.startsWith('https://'))) {
-		id.value = (id.value.endsWith('/') ? id.value.slice(0, -1) : id.value).split('/').pop();
+		id.value = (id.value.endsWith('/') ? id.value.slice(0, -1) : id.value).split('/').pop() ?? null;
+	}
+
+	if (!id.value) {
+		note.value = null;
+		return;
 	}
 
 	emit('update:modelValue', {
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue
index 0f8dc33143..eea52255c7 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue
@@ -23,6 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 /* eslint-disable vue/no-mutating-props */
 import { defineAsyncComponent, inject, onMounted, watch, ref } from 'vue';
+import * as Misskey from 'misskey-js';
 import { v4 as uuid } from 'uuid';
 import XContainer from '../page-editor.container.vue';
 import * as os from '@/os.js';
@@ -33,14 +34,13 @@ import { getPageBlockList } from '@/pages/page-editor/common.js';
 
 const XBlocks = defineAsyncComponent(() => import('../page-editor.blocks.vue'));
 
-const props = withDefaults(defineProps<{
-	modelValue: any,
-}>(), {
-	modelValue: {},
-});
+const props = defineProps<{
+	modelValue: Misskey.entities.PageBlock & { type: 'section'; },
+}>();
 
 const emit = defineEmits<{
-	(ev: 'update:modelValue', value: any): void;
+	(ev: 'update:modelValue', value: Misskey.entities.PageBlock & { type: 'section' }): void;
+	(ev: 'remove'): void;
 }>();
 
 const children = ref(deepClone(props.modelValue.children ?? []));
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue
index f09f7e1acd..43a1e37f9e 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue
@@ -17,16 +17,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 /* eslint-disable vue/no-mutating-props */
 import { watch, ref, shallowRef, onMounted, onUnmounted } from 'vue';
+import * as Misskey from 'misskey-js';
 import XContainer from '../page-editor.container.vue';
 import { i18n } from '@/i18n.js';
 import { Autocomplete } from '@/scripts/autocomplete.js';
 
 const props = defineProps<{
-	modelValue: any
+	modelValue: Misskey.entities.PageBlock & { type: 'text' }
 }>();
 
 const emit = defineEmits<{
-	(ev: 'update:modelValue', value: any): void;
+	(ev: 'update:modelValue', value: Misskey.entities.PageBlock & { type: 'text' }): void;
 }>();
 
 let autocomplete: Autocomplete;
diff --git a/packages/frontend/src/pages/registry.keys.vue b/packages/frontend/src/pages/registry.keys.vue
index bac1d2bb70..4cacbd0906 100644
--- a/packages/frontend/src/pages/registry.keys.vue
+++ b/packages/frontend/src/pages/registry.keys.vue
@@ -52,7 +52,7 @@ const props = defineProps<{
 
 const scope = computed(() => props.path ? props.path.split('/') : []);
 
-const keys = ref<any>(null);
+const keys = ref<[string, string][]>([]);
 
 function fetchKeys() {
 	misskeyApi('i/registry/keys-with-type', {
diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue
index dfb6e3f53e..437a1a2294 100644
--- a/packages/frontend/src/pages/reversi/game.setting.vue
+++ b/packages/frontend/src/pages/reversi/game.setting.vue
@@ -132,7 +132,7 @@ const mapCategories = Array.from(new Set(Object.values(Reversi.maps).map(x => x.
 
 const props = defineProps<{
 	game: Misskey.entities.ReversiGameDetailed;
-	connection: Misskey.ChannelConnection;
+	connection: Misskey.ChannelConnection<Misskey.Channels['reversiGame']>;
 }>();
 
 const shareWhenStart = defineModel<boolean>('shareWhenStart', { default: false });
@@ -217,14 +217,14 @@ function onChangeReadyStates(states) {
 	game.value.user2Ready = states.user2;
 }
 
-function updateSettings(key: keyof Misskey.entities.ReversiGameDetailed) {
+function updateSettings(key: typeof Misskey.reversiUpdateKeys[number]) {
 	props.connection.send('updateSettings', {
 		key: key,
 		value: game.value[key],
 	});
 }
 
-function onUpdateSettings({ userId, key, value }: { userId: string; key: keyof Misskey.entities.ReversiGameDetailed; value: any; }) {
+function onUpdateSettings<K extends typeof Misskey.reversiUpdateKeys[number]>({ userId, key, value }: { userId: string; key: K; value: Misskey.entities.ReversiGameDetailed[K]; }) {
 	if (userId === $i.id) return;
 	if (game.value[key] === value) return;
 	game.value[key] = value;
diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue
index 2250e1ce60..88171f7d70 100644
--- a/packages/frontend/src/pages/scratchpad.vue
+++ b/packages/frontend/src/pages/scratchpad.vue
@@ -76,7 +76,11 @@ import { claimAchievement } from '@/scripts/achievements.js';
 const parser = new Parser();
 let aiscript: Interpreter;
 const code = ref('');
-const logs = ref<any[]>([]);
+const logs = ref<{
+	id: number;
+	text: string;
+	print: boolean;
+}[]>([]);
 const root = ref<AsUiRoot>();
 const components = ref<Ref<AsUiComponent>[]>([]);
 const uiKey = ref(0);
diff --git a/packages/frontend/src/pages/settings/2fa.qrdialog.vue b/packages/frontend/src/pages/settings/2fa.qrdialog.vue
index 2244047b31..18c82ffdf6 100644
--- a/packages/frontend/src/pages/settings/2fa.qrdialog.vue
+++ b/packages/frontend/src/pages/settings/2fa.qrdialog.vue
@@ -138,12 +138,13 @@ const token = ref<string | number | null>(null);
 const backupCodes = ref<string[]>();
 
 function cancel() {
-	dialog.value.close();
+	dialog.value?.close();
 }
 
 async function tokenDone() {
+	if (token.value == null) return;
 	const res = await os.apiWithDialog('i/2fa/done', {
-		token: token.value.toString(),
+		token: typeof token.value === 'string' ? token.value : token.value.toString(),
 	});
 
 	backupCodes.value = res.backupCodes;
@@ -166,7 +167,7 @@ function downloadBackupCodes() {
 }
 
 function allDone() {
-	dialog.value.close();
+	dialog.value?.close();
 }
 </script>
 
diff --git a/packages/frontend/src/pages/settings/accounts.vue b/packages/frontend/src/pages/settings/accounts.vue
index 16f0716a12..97e960675f 100644
--- a/packages/frontend/src/pages/settings/accounts.vue
+++ b/packages/frontend/src/pages/settings/accounts.vue
@@ -90,7 +90,7 @@ function createAccount() {
 	});
 }
 
-async function switchAccount(account: any) {
+async function switchAccount(account: Misskey.entities.UserDetailed) {
 	const fetchedAccounts = await getAccounts();
 	const token = fetchedAccounts.find(x => x.id === account.id)!.token;
 	switchAccountWithToken(token);
diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue
index 68e36ef1bb..6515503505 100644
--- a/packages/frontend/src/pages/settings/apps.vue
+++ b/packages/frontend/src/pages/settings/apps.vue
@@ -55,6 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { ref, computed } from 'vue';
+import * as Misskey from 'misskey-js';
 import FormPagination from '@/components/MkPagination.vue';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { i18n } from '@/i18n.js';
@@ -77,7 +78,7 @@ const pagination = {
 
 function revoke(token) {
 	misskeyApi('i/revoke-token', { tokenId: token.id }).then(() => {
-		list.value.reload();
+		list.value?.reload();
 	});
 }
 
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue
index aa899ac649..40542ad5b2 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.dialog.vue
@@ -110,7 +110,7 @@ const decorationsForPreview = computed(() => {
 });
 
 function cancel() {
-	dialog.value.close();
+	dialog.value?.close();
 }
 
 async function update() {
@@ -120,7 +120,7 @@ async function update() {
 		offsetX: offsetX.value,
 		offsetY: offsetY.value,
 	});
-	dialog.value.close();
+	dialog.value?.close();
 }
 
 async function attach() {
@@ -130,12 +130,12 @@ async function attach() {
 		offsetX: offsetX.value,
 		offsetY: offsetY.value,
 	});
-	dialog.value.close();
+	dialog.value?.close();
 }
 
 async function detach() {
 	emit('detach');
-	dialog.value.close();
+	dialog.value?.close();
 }
 </script>
 
diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue
index 00b5740639..2794db2821 100644
--- a/packages/frontend/src/pages/user/home.vue
+++ b/packages/frontend/src/pages/user/home.vue
@@ -257,7 +257,7 @@ function parallaxLoop() {
 }
 
 function parallax() {
-	const banner = bannerEl.value as any;
+	const banner = bannerEl.value;
 	if (banner == null) return;
 
 	const top = getScrollPosition(rootEl.value);
diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts
index b5fd6b6ec3..e98e0b59b1 100644
--- a/packages/frontend/src/router/definition.ts
+++ b/packages/frontend/src/router/definition.ts
@@ -10,7 +10,7 @@ import { $i, iAmModerator } from '@/account.js';
 import MkLoading from '@/pages/_loading_.vue';
 import MkError from '@/pages/_error_.vue';
 
-export const page = (loader: AsyncComponentLoader<any>) => defineAsyncComponent({
+export const page = (loader: AsyncComponentLoader) => defineAsyncComponent({
 	loader: loader,
 	loadingComponent: MkLoading,
 	errorComponent: MkError,
diff --git a/packages/frontend/src/router/main.ts b/packages/frontend/src/router/main.ts
index 6ee967e6f4..3c25e80d12 100644
--- a/packages/frontend/src/router/main.ts
+++ b/packages/frontend/src/router/main.ts
@@ -4,7 +4,7 @@
  */
 
 import { EventEmitter } from 'eventemitter3';
-import { IRouter, Resolved, RouteDef, RouterEvent } from '@/nirax.js';
+import { IRouter, Resolved, RouteDef, RouterEvent, RouterFlag } from '@/nirax.js';
 
 import type { App, ShallowRef } from 'vue';
 
@@ -79,7 +79,7 @@ class MainRouterProxy implements IRouter {
 		return this.supplier().currentRoute;
 	}
 
-	get navHook(): ((path: string, flag?: any) => boolean) | null {
+	get navHook(): ((path: string, flag?: RouterFlag) => boolean) | null {
 		return this.supplier().navHook;
 	}
 
@@ -91,11 +91,11 @@ class MainRouterProxy implements IRouter {
 		return this.supplier().getCurrentKey();
 	}
 
-	getCurrentPath(): any {
+	getCurrentPath(): string {
 		return this.supplier().getCurrentPath();
 	}
 
-	push(path: string, flag?: any): void {
+	push(path: string, flag?: RouterFlag): void {
 		this.supplier().push(path, flag);
 	}
 
diff --git a/packages/frontend/src/scripts/check-word-mute.ts b/packages/frontend/src/scripts/check-word-mute.ts
index 67e896b4b9..0a37a08bf0 100644
--- a/packages/frontend/src/scripts/check-word-mute.ts
+++ b/packages/frontend/src/scripts/check-word-mute.ts
@@ -2,8 +2,9 @@
  * SPDX-FileCopyrightText: syuilo and misskey-project
  * SPDX-License-Identifier: AGPL-3.0-only
  */
+import * as Misskey from 'misskey-js';
 
-export function checkWordMute(note: Record<string, any>, me: Record<string, any> | null | undefined, mutedWords: Array<string | string[]>): boolean {
+export function checkWordMute(note: Misskey.entities.Note, me: Misskey.entities.UserLite | null | undefined, mutedWords: Array<string | string[]>): boolean {
 	// 自分自身
 	if (me && (note.userId === me.id)) return false;
 
diff --git a/packages/frontend/src/scripts/form.ts b/packages/frontend/src/scripts/form.ts
index 242a504c3b..1032e97ac9 100644
--- a/packages/frontend/src/scripts/form.ts
+++ b/packages/frontend/src/scripts/form.ts
@@ -15,7 +15,7 @@ type Hidden = boolean | ((v: any) => boolean);
 export type FormItem = {
 	label?: string;
 	type: 'string';
-	default: string | null;
+	default?: string | null;
 	description?: string;
 	required?: boolean;
 	hidden?: Hidden;
@@ -24,7 +24,7 @@ export type FormItem = {
 } | {
 	label?: string;
 	type: 'number';
-	default: number | null;
+	default?: number | null;
 	description?: string;
 	required?: boolean;
 	hidden?: Hidden;
@@ -32,20 +32,20 @@ export type FormItem = {
 } | {
 	label?: string;
 	type: 'boolean';
-	default: boolean | null;
+	default?: boolean | null;
 	description?: string;
 	hidden?: Hidden;
 } | {
 	label?: string;
 	type: 'enum';
-	default: string | null;
+	default?: string | null;
 	required?: boolean;
 	hidden?: Hidden;
 	enum: EnumItem[];
 } | {
 	label?: string;
 	type: 'radio';
-	default: unknown | null;
+	default?: unknown | null;
 	required?: boolean;
 	hidden?: Hidden;
 	options: {
@@ -55,7 +55,7 @@ export type FormItem = {
 } | {
 	label?: string;
 	type: 'range';
-	default: number | null;
+	default?: number | null;
 	description?: string;
 	required?: boolean;
 	step?: number;
@@ -66,12 +66,12 @@ export type FormItem = {
 } | {
 	label?: string;
 	type: 'object';
-	default: Record<string, unknown> | null;
+	default?: Record<string, unknown> | null;
 	hidden: Hidden;
 } | {
 	label?: string;
 	type: 'array';
-	default: unknown[] | null;
+	default?: unknown[] | null;
 	hidden: Hidden;
 } | {
 	type: 'button';
diff --git a/packages/frontend/src/scripts/misskey-api.ts b/packages/frontend/src/scripts/misskey-api.ts
index 1b1159fd01..e7a92e2d5c 100644
--- a/packages/frontend/src/scripts/misskey-api.ts
+++ b/packages/frontend/src/scripts/misskey-api.ts
@@ -17,7 +17,7 @@ export function misskeyApi<
 	_ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType<E, P> : ResT,
 >(
 	endpoint: E,
-	data: P = {} as any,
+	data: P & { i?: string | null; } = {} as any,
 	token?: string | null | undefined,
 	signal?: AbortSignal,
 ): Promise<_ResT> {
@@ -30,8 +30,8 @@ export function misskeyApi<
 
 	const promise = new Promise<_ResT>((resolve, reject) => {
 		// Append a credential
-		if ($i) (data as any).i = $i.token;
-		if (token !== undefined) (data as any).i = token;
+		if ($i) data.i = $i.token;
+		if (token !== undefined) data.i = token;
 
 		// Send request
 		window.fetch(`${apiUrl}/${endpoint}`, {
diff --git a/packages/frontend/src/scripts/select-file.ts b/packages/frontend/src/scripts/select-file.ts
index 9aa38178b2..b037aa8acc 100644
--- a/packages/frontend/src/scripts/select-file.ts
+++ b/packages/frontend/src/scripts/select-file.ts
@@ -80,7 +80,7 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
 	});
 }
 
-function select(src: any, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
+function select(src: HTMLElement | EventTarget | null, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
 	return new Promise((res, rej) => {
 		const keepOriginal = ref(defaultStore.state.keepOriginalUploading);
 
@@ -107,10 +107,10 @@ function select(src: any, label: string | null, multiple: boolean): Promise<Miss
 	});
 }
 
-export function selectFile(src: any, label: string | null = null): Promise<Misskey.entities.DriveFile> {
+export function selectFile(src: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile> {
 	return select(src, label, false).then(files => files[0]);
 }
 
-export function selectFiles(src: any, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
+export function selectFiles(src: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
 	return select(src, label, true);
 }
diff --git a/packages/frontend/src/scripts/shuffle.ts b/packages/frontend/src/scripts/shuffle.ts
index fed16bc71c..1f6ef1928c 100644
--- a/packages/frontend/src/scripts/shuffle.ts
+++ b/packages/frontend/src/scripts/shuffle.ts
@@ -6,8 +6,9 @@
 /**
  * 配列をシャッフル (破壊的)
  */
-export function shuffle<T extends any[]>(array: T): T {
-	let currentIndex = array.length, randomIndex;
+export function shuffle<T extends unknown[]>(array: T): T {
+	let currentIndex = array.length;
+	let randomIndex: number;
 
 	// While there remain elements to shuffle.
 	while (currentIndex !== 0) {
diff --git a/packages/frontend/src/scripts/upload.ts b/packages/frontend/src/scripts/upload.ts
index 22dce609c6..713573a377 100644
--- a/packages/frontend/src/scripts/upload.ts
+++ b/packages/frontend/src/scripts/upload.ts
@@ -32,13 +32,13 @@ const mimeTypeMap = {
 
 export function uploadFile(
 	file: File,
-	folder?: any,
+	folder?: string | Misskey.entities.DriveFolder,
 	name?: string,
 	keepOriginal: boolean = defaultStore.state.keepOriginalUploading,
 ): Promise<Misskey.entities.DriveFile> {
 	if ($i == null) throw new Error('Not logged in');
 
-	if (folder && typeof folder === 'object') folder = folder.id;
+	const _folder = typeof folder === 'string' ? folder : folder?.id;
 
 	if (file.size > instance.maxFileSize) {
 		alert({
@@ -89,11 +89,11 @@ export function uploadFile(
 			}
 
 			const formData = new FormData();
-			formData.append('i', $i.token);
+			formData.append('i', $i!.token);
 			formData.append('force', 'true');
 			formData.append('file', resizedImage ?? file);
 			formData.append('name', ctx.name);
-			if (folder) formData.append('folderId', folder);
+			if (_folder) formData.append('folderId', _folder);
 
 			const xhr = new XMLHttpRequest();
 			xhr.open('POST', apiUrl + '/drive/files/create', true);
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index aab67e0b5c..911a463636 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -11,6 +11,7 @@ import darkTheme from '@@/themes/d-green-lime.json5';
 import { miLocalStorage } from './local-storage.js';
 import type { SoundType } from '@/scripts/sound.js';
 import { Storage } from '@/pizzax.js';
+import type { Ast } from '@syuilo/aiscript';
 
 interface PostFormAction {
 	title: string,
@@ -516,7 +517,7 @@ export type Plugin = {
 	token: string;
 	src: string | null;
 	version: string;
-	ast: any[];
+	ast: Ast.Node[];
 	author?: string;
 	description?: string;
 	permissions?: string[];
@@ -554,13 +555,13 @@ export class ColdDeviceStorage {
 	}
 
 	public static getAll(): Partial<typeof this.default> {
-		return (Object.keys(this.default) as (keyof typeof this.default)[]).reduce((acc, key) => {
+		return (Object.keys(this.default) as (keyof typeof this.default)[]).reduce<Partial<typeof this.default>>((acc, key) => {
 			const value = localStorage.getItem(PREFIX + key);
 			if (value != null) {
 				acc[key] = JSON.parse(value);
 			}
 			return acc;
-		}, {} as any);
+		}, {});
 	}
 
 	public static set<T extends keyof typeof ColdDeviceStorage.default>(key: T, value: typeof ColdDeviceStorage.default[T]): void {
@@ -605,7 +606,7 @@ export class ColdDeviceStorage {
 			get: () => {
 				return valueRef.value;
 			},
-			set: (value: unknown) => {
+			set: (value: typeof ColdDeviceStorage.default[K]) => {
 				const val = value;
 				ColdDeviceStorage.set(key, val);
 			},
diff --git a/packages/frontend/src/types/post-form.ts b/packages/frontend/src/types/post-form.ts
new file mode 100644
index 0000000000..5bb04a95a0
--- /dev/null
+++ b/packages/frontend/src/types/post-form.ts
@@ -0,0 +1,22 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import * as Misskey from 'misskey-js';
+
+export interface PostFormProps {
+	reply?: Misskey.entities.Note;
+	renote?: Misskey.entities.Note;
+	channel?: Misskey.entities.Channel; // TODO
+	mention?: Misskey.entities.User;
+	specified?: Misskey.entities.UserDetailed;
+	initialText?: string;
+	initialCw?: string;
+	initialVisibility?: (typeof Misskey.noteVisibilities)[number];
+	initialFiles?: Misskey.entities.DriveFile[];
+	initialLocalOnly?: boolean;
+	initialVisibleUsers?: Misskey.entities.UserDetailed[];
+	initialNote?: Misskey.entities.Note;
+	instant?: boolean;
+};
diff --git a/packages/frontend/src/widgets/WidgetPhotos.vue b/packages/frontend/src/widgets/WidgetPhotos.vue
index 34be8c5e57..40e2d8fbc7 100644
--- a/packages/frontend/src/widgets/WidgetPhotos.vue
+++ b/packages/frontend/src/widgets/WidgetPhotos.vue
@@ -68,10 +68,10 @@ const onDriveFileCreated = (file) => {
 	}
 };
 
-const thumbnail = (image: any): string => {
+const thumbnail = (image: Misskey.entities.DriveFile): string => {
 	return defaultStore.state.disableShowingAnimatedImages
 		? getStaticImageUrl(image.url)
-		: image.thumbnailUrl;
+		: image.thumbnailUrl ?? image.url;
 };
 
 misskeyApi('drive/stream', {

From ceb60d61b05e32fa340269122378ea93efb20517 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 31 Oct 2024 13:47:30 +0900
Subject: [PATCH 032/125] refactor

---
 packages/frontend/src/pages/emoji-edit-dialog.vue | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue
index 2caba03675..db3f436873 100644
--- a/packages/frontend/src/pages/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/emoji-edit-dialog.vue
@@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:initialHeight="500"
 	:canResize="true"
 	@close="windowEl.close()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template v-if="emoji" #header>:{{ emoji.name }}:</template>
 	<template v-else #header>New emoji</template>
@@ -98,6 +98,11 @@ const props = defineProps<{
 	emoji?: Misskey.entities.EmojiDetailed,
 }>();
 
+const emit = defineEmits<{
+	(ev: 'done', v: { deleted?: boolean; updated?: Misskey.entities.AdminEmojiUpdateRequest; created?: Misskey.entities.AdminEmojiUpdateRequest }): void,
+	(ev: 'closed'): void
+}>();
+
 const windowEl = ref<InstanceType<typeof MkWindow> | null>(null);
 const name = ref<string>(props.emoji ? props.emoji.name : '');
 const category = ref<string>(props.emoji?.category ? props.emoji.category : '');
@@ -115,11 +120,6 @@ watch(roleIdsThatCanBeUsedThisEmojiAsReaction, async () => {
 
 const imgUrl = computed(() => file.value ? file.value.url : props.emoji ? `/emoji/${props.emoji.name}.webp` : null);
 
-const emit = defineEmits<{
-	(ev: 'done', v: { deleted?: boolean; updated?: Misskey.entities.AdminEmojiUpdateRequest; created?: Misskey.entities.AdminEmojiUpdateRequest }): void,
-	(ev: 'closed'): void
-}>();
-
 async function changeImage(ev: Event) {
 	file.value = await selectFile(ev.currentTarget ?? ev.target, null);
 	const candidate = file.value.name.replace(/\.(.+)$/, '');

From 724dea8136164dcfcd7238888ef93ccab8270fb9 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 31 Oct 2024 13:47:47 +0900
Subject: [PATCH 033/125] lint

---
 packages/frontend/src/pages/emoji-edit-dialog.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue
index db3f436873..3765319b25 100644
--- a/packages/frontend/src/pages/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/emoji-edit-dialog.vue
@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:initialWidth="400"
 	:initialHeight="500"
 	:canResize="true"
-	@close="windowEl.close()"
+	@close="windowEl?.close()"
 	@closed="emit('closed')"
 >
 	<template v-if="emoji" #header>:{{ emoji.name }}:</template>

From 224bbd486f8745cd471b77f38570b65be3b87cfc Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 31 Oct 2024 13:50:50 +0900
Subject: [PATCH 034/125] refactor

---
 packages/frontend/src/components/MkCropperDialog.vue |  2 +-
 .../src/components/MkCustomEmojiDetailedDialog.vue   |  2 +-
 .../frontend/src/components/MkEmbedCodeGenDialog.vue |  2 +-
 packages/frontend/src/components/MkFormDialog.vue    |  2 +-
 packages/frontend/src/components/MkPageWindow.vue    |  8 ++++----
 packages/frontend/src/components/MkSignupDialog.vue  |  2 +-
 .../src/components/MkTokenGenerateWindow.vue         |  2 +-
 .../src/components/MkUserAnnouncementEditDialog.vue  | 12 ++++++------
 .../frontend/src/components/MkUserSelectDialog.vue   |  2 +-
 packages/frontend/src/components/MkWidgets.vue       |  2 +-
 packages/frontend/src/components/MkWindow.vue        |  2 +-
 .../pages/page-editor/els/page-editor.el.image.vue   |  2 +-
 .../pages/page-editor/els/page-editor.el.note.vue    |  2 +-
 .../pages/page-editor/els/page-editor.el.section.vue |  4 ++--
 .../pages/page-editor/els/page-editor.el.text.vue    |  4 ++--
 .../src/pages/page-editor/page-editor.blocks.vue     |  2 +-
 16 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/packages/frontend/src/components/MkCropperDialog.vue b/packages/frontend/src/components/MkCropperDialog.vue
index c2a1aaf29a..0186cfc2c0 100644
--- a/packages/frontend/src/components/MkCropperDialog.vue
+++ b/packages/frontend/src/components/MkCropperDialog.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:withOkButton="true"
 	@close="cancel()"
 	@ok="ok()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template #header>{{ i18n.ts.cropImage }}</template>
 	<template #default="{ width, height }">
diff --git a/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue b/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue
index 949adc6a8e..ecbee864dc 100644
--- a/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue
+++ b/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<MkModalWindow ref="dialogEl" @close="cancel()" @closed="$emit('closed')">
+<MkModalWindow ref="dialogEl" @close="cancel()" @closed="emit('closed')">
 	<template #header>:{{ emoji.name }}:</template>
 	<template #default>
 		<MkSpacer>
diff --git a/packages/frontend/src/components/MkEmbedCodeGenDialog.vue b/packages/frontend/src/components/MkEmbedCodeGenDialog.vue
index c2bb516c7c..6e9eb75920 100644
--- a/packages/frontend/src/components/MkEmbedCodeGenDialog.vue
+++ b/packages/frontend/src/components/MkEmbedCodeGenDialog.vue
@@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:scroll="false"
 	:withOkButton="false"
 	@close="cancel()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template #header><i class="ti ti-code"></i> {{ i18n.ts._embedCodeGen.title }}</template>
 
diff --git a/packages/frontend/src/components/MkFormDialog.vue b/packages/frontend/src/components/MkFormDialog.vue
index 124f114111..a639eae208 100644
--- a/packages/frontend/src/components/MkFormDialog.vue
+++ b/packages/frontend/src/components/MkFormDialog.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	@click="cancel()"
 	@ok="ok()"
 	@close="cancel()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template #header>
 		{{ title }}
diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue
index 02c84df447..9547423227 100644
--- a/packages/frontend/src/components/MkPageWindow.vue
+++ b/packages/frontend/src/components/MkPageWindow.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:buttonsLeft="buttonsLeft"
 	:buttonsRight="buttonsRight"
 	:contextmenu="contextmenu"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template #header>
 		<template v-if="pageMetadata">
@@ -30,17 +30,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import { computed, onMounted, onUnmounted, provide, ref, shallowRef } from 'vue';
+import { url } from '@@/js/config.js';
+import { getScrollContainer } from '@@/js/scroll.js';
 import RouterView from '@/components/global/RouterView.vue';
 import MkWindow from '@/components/MkWindow.vue';
 import { popout as _popout } from '@/scripts/popout.js';
 import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
-import { url } from '@@/js/config.js';
 import { useScrollPositionManager } from '@/nirax.js';
 import { i18n } from '@/i18n.js';
 import { PageMetadata, provideMetadataReceiver, provideReactiveMetadata } from '@/scripts/page-metadata.js';
 import { openingWindowsCount } from '@/os.js';
 import { claimAchievement } from '@/scripts/achievements.js';
-import { getScrollContainer } from '@@/js/scroll.js';
 import { useRouterFactory } from '@/router/supplier.js';
 import { mainRouter } from '@/router/main.js';
 
@@ -48,7 +48,7 @@ const props = defineProps<{
 	initialPath: string;
 }>();
 
-defineEmits<{
+const emit = defineEmits<{
 	(ev: 'closed'): void;
 }>();
 
diff --git a/packages/frontend/src/components/MkSignupDialog.vue b/packages/frontend/src/components/MkSignupDialog.vue
index 4f75a36fbe..6fb9d77837 100644
--- a/packages/frontend/src/components/MkSignupDialog.vue
+++ b/packages/frontend/src/components/MkSignupDialog.vue
@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:width="500"
 	:height="600"
 	@close="onClose"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template #header>{{ i18n.ts.signup }}</template>
 
diff --git a/packages/frontend/src/components/MkTokenGenerateWindow.vue b/packages/frontend/src/components/MkTokenGenerateWindow.vue
index a7bc3f37f1..73aef68964 100644
--- a/packages/frontend/src/components/MkTokenGenerateWindow.vue
+++ b/packages/frontend/src/components/MkTokenGenerateWindow.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:okButtonDisabled="false"
 	:canClose="false"
 	@close="dialog?.close()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 	@ok="ok()"
 >
 	<template #header>{{ title || i18n.ts.generateAccessToken }}</template>
diff --git a/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue b/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue
index 7f0266d1d3..fe499fabbf 100644
--- a/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue
+++ b/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue
@@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	ref="dialog"
 	:width="400"
 	@close="dialog?.close()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template v-if="announcement" #header>:{{ announcement.title }}:</template>
 	<template v-else #header>New announcement</template>
@@ -69,6 +69,11 @@ const props = defineProps<{
 	announcement?: Required<AdminAnnouncementType>,
 }>();
 
+const emit = defineEmits<{
+	(ev: 'done', v: { deleted?: boolean; updated?: AdminAnnouncementType; created?: AdminAnnouncementType; }): void,
+	(ev: 'closed'): void
+}>();
+
 const dialog = ref<InstanceType<typeof MkModalWindow> | null>(null);
 const title = ref(props.announcement ? props.announcement.title : '');
 const text = ref(props.announcement ? props.announcement.text : '');
@@ -76,11 +81,6 @@ const icon = ref(props.announcement ? props.announcement.icon : 'info');
 const display = ref(props.announcement ? props.announcement.display : 'dialog');
 const needConfirmationToRead = ref(props.announcement ? props.announcement.needConfirmationToRead : false);
 
-const emit = defineEmits<{
-	(ev: 'done', v: { deleted?: boolean; updated?: AdminAnnouncementType; created?: AdminAnnouncementType; }): void,
-	(ev: 'closed'): void
-}>();
-
 async function done() {
 	const params = {
 		title: title.value,
diff --git a/packages/frontend/src/components/MkUserSelectDialog.vue b/packages/frontend/src/components/MkUserSelectDialog.vue
index 8e58a6c5a2..764bf74f21 100644
--- a/packages/frontend/src/components/MkUserSelectDialog.vue
+++ b/packages/frontend/src/components/MkUserSelectDialog.vue
@@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	@click="cancel()"
 	@close="cancel()"
 	@ok="ok()"
-	@closed="$emit('closed')"
+	@closed="emit('closed')"
 >
 	<template #header>{{ i18n.ts.selectUser }}</template>
 	<div>
diff --git a/packages/frontend/src/components/MkWidgets.vue b/packages/frontend/src/components/MkWidgets.vue
index 492dd4cdc0..ba619f6063 100644
--- a/packages/frontend/src/components/MkWidgets.vue
+++ b/packages/frontend/src/components/MkWidgets.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ i18n.ts._widgets[widget] }}</option>
 			</MkSelect>
 			<MkButton inline primary data-cy-widget-add @click="addWidget"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
-			<MkButton inline @click="$emit('exit')">{{ i18n.ts.close }}</MkButton>
+			<MkButton inline @click="emit('exit')">{{ i18n.ts.close }}</MkButton>
 		</header>
 		<Sortable
 			:modelValue="props.widgets"
diff --git a/packages/frontend/src/components/MkWindow.vue b/packages/frontend/src/components/MkWindow.vue
index ed7e3867ce..2953f656d4 100644
--- a/packages/frontend/src/components/MkWindow.vue
+++ b/packages/frontend/src/components/MkWindow.vue
@@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 	:enterFromClass="defaultStore.state.animation ? $style.transition_window_enterFrom : ''"
 	:leaveToClass="defaultStore.state.animation ? $style.transition_window_leaveTo : ''"
 	appear
-	@afterLeave="$emit('closed')"
+	@afterLeave="emit('closed')"
 >
 	<div v-if="showing" ref="rootEl" :class="[$style.root, { [$style.maximized]: maximized }]">
 		<div :class="$style.body" class="_shadow" @mousedown="onBodyMousedown" @keydown="onKeydown">
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue
index 247b8f61a1..c3ad6657b0 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.image.vue
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <!-- eslint-disable vue/no-mutating-props -->
-<XContainer :draggable="true" @remove="() => $emit('remove')">
+<XContainer :draggable="true" @remove="() => emit('remove')">
 	<template #header><i class="ti ti-photo"></i> {{ i18n.ts._pages.blocks.image }}</template>
 	<template #func>
 		<button @click="choose()">
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue
index 52b4f2aaa3..36e03b4790 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.note.vue
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <!-- eslint-disable vue/no-mutating-props -->
-<XContainer :draggable="true" @remove="() => $emit('remove')">
+<XContainer :draggable="true" @remove="() => emit('remove')">
 	<template #header><i class="ti ti-note"></i> {{ i18n.ts._pages.blocks.note }}</template>
 
 	<section style="padding: 16px;" class="_gaps_s">
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue
index eea52255c7..3fed07f7e8 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.section.vue
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <!-- eslint-disable vue/no-mutating-props -->
-<XContainer :draggable="true" @remove="() => $emit('remove')">
+<XContainer :draggable="true" @remove="() => emit('remove')">
 	<template #header><i class="ti ti-note"></i> {{ props.modelValue.title }}</template>
 	<template #func>
 		<button class="_button" @click="rename()">
@@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-/* eslint-disable vue/no-mutating-props */
+ 
 import { defineAsyncComponent, inject, onMounted, watch, ref } from 'vue';
 import * as Misskey from 'misskey-js';
 import { v4 as uuid } from 'uuid';
diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue
index 43a1e37f9e..5795b46c00 100644
--- a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue
+++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <!-- eslint-disable vue/no-mutating-props -->
-<XContainer :draggable="true" @remove="() => $emit('remove')">
+<XContainer :draggable="true" @remove="() => emit('remove')">
 	<template #header><i class="ti ti-align-left"></i> {{ i18n.ts._pages.blocks.text }}</template>
 
 	<section>
@@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-/* eslint-disable vue/no-mutating-props */
+ 
 import { watch, ref, shallowRef, onMounted, onUnmounted } from 'vue';
 import * as Misskey from 'misskey-js';
 import XContainer from '../page-editor.container.vue';
diff --git a/packages/frontend/src/pages/page-editor/page-editor.blocks.vue b/packages/frontend/src/pages/page-editor/page-editor.blocks.vue
index 4967e73000..f191320180 100644
--- a/packages/frontend/src/pages/page-editor/page-editor.blocks.vue
+++ b/packages/frontend/src/pages/page-editor/page-editor.blocks.vue
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<Sortable :modelValue="modelValue" tag="div" itemKey="id" handle=".drag-handle" :group="{ name: 'blocks' }" :animation="150" :swapThreshold="0.5" @update:modelValue="v => $emit('update:modelValue', v)">
+<Sortable :modelValue="modelValue" tag="div" itemKey="id" handle=".drag-handle" :group="{ name: 'blocks' }" :animation="150" :swapThreshold="0.5" @update:modelValue="v => emit('update:modelValue', v)">
 	<template #item="{element}">
 		<div :class="$style.item">
 			<!-- divが無いとエラーになる https://github.com/SortableJS/vue.draggable.next/issues/189 -->

From d57b8bf2e211cd7e4d5f03f19387a27bdb9cbde9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sun, 3 Nov 2024 08:23:52 +0900
Subject: [PATCH 035/125] =?UTF-8?q?fix(frontend):=20withSensitive=E3=83=95?=
 =?UTF-8?q?=E3=82=A3=E3=83=AB=E3=82=BF=E5=91=A8=E3=82=8A=E3=81=AE=E6=8C=99?=
 =?UTF-8?q?=E5=8B=95=E4=BF=AE=E6=AD=A3=20(#14884)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): withSensitiveフィルタ周りの挙動修正

* Update MkNote.vue
---
 packages/frontend/src/components/MkNote.vue     | 15 +++++++++------
 packages/frontend/src/components/MkTimeline.vue |  1 +
 packages/frontend/src/pages/timeline.vue        |  2 +-
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 3de69d6d09..cf0d0787b1 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -292,15 +292,18 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
 function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): boolean | 'sensitiveMute';
 */
 function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): boolean | 'sensitiveMute' {
-	if (mutedWords == null) return false;
-
-	if (checkWordMute(noteToCheck, $i, mutedWords)) return true;
-	if (noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords)) return true;
-	if (noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords)) return true;
+	if (mutedWords != null) {
+		if (checkWordMute(noteToCheck, $i, mutedWords)) return true;
+		if (noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords)) return true;
+		if (noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords)) return true;
+	}
 
 	if (checkOnly) return false;
 
-	if (inTimeline && !tl_withSensitive.value && noteToCheck.files?.some((v) => v.isSensitive)) return 'sensitiveMute';
+	if (inTimeline && tl_withSensitive.value === false && noteToCheck.files?.some((v) => v.isSensitive)) {
+		return 'sensitiveMute';
+	}
+
 	return false;
 }
 
diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue
index 226faac291..fb8eb4ae37 100644
--- a/packages/frontend/src/components/MkTimeline.vue
+++ b/packages/frontend/src/components/MkTimeline.vue
@@ -43,6 +43,7 @@ const props = withDefaults(defineProps<{
 }>(), {
 	withRenotes: true,
 	withReplies: false,
+	withSensitive: true,
 	onlyFiles: false,
 });
 
diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue
index 7a3195304b..044a1908ab 100644
--- a/packages/frontend/src/pages/timeline.vue
+++ b/packages/frontend/src/pages/timeline.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				<div :class="$style.tl">
 					<MkTimeline
 						ref="tlComponent"
-						:key="src + withRenotes + withReplies + onlyFiles"
+						:key="src + withRenotes + withReplies + onlyFiles + withSensitive"
 						:src="src.split(':')[0]"
 						:list="src.split(':')[1]"
 						:withRenotes="withRenotes"

From 6718a54f6fce29edbe2755c31a119e4468fc56e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sun, 3 Nov 2024 08:26:51 +0900
Subject: [PATCH 036/125] =?UTF-8?q?fix(backend):=20=E3=83=8E=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E3=82=92=E9=80=A3=E5=90=88=E3=81=99=E3=82=8B=E9=9A=9B?=
 =?UTF-8?q?=E3=81=AB=E3=83=AA=E3=83=A2=E3=83=BC=E3=83=88=E3=83=A6=E3=83=BC?=
 =?UTF-8?q?=E3=82=B6=E3=83=BC=E3=81=AEacct=E3=81=AE=E5=A4=A7=E5=B0=8F?=
 =?UTF-8?q?=E6=96=87=E5=AD=97=E3=82=92=E5=8C=BA=E5=88=A5=E3=81=97=E3=81=A6?=
 =?UTF-8?q?=E5=87=A6=E7=90=86=E3=81=97=E3=81=A6=E3=81=84=E3=82=8B=E5=95=8F?=
 =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#14880)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: make sure outgoing remote mentions get resolved correctly if referenced with non-canonical casing (resolves #646)

* Update Changelog

* Update Changelog

* indent

---------

Co-authored-by: Laura Hausmann <laura@hausmann.dev>
---
 CHANGELOG.md                            | 2 ++
 packages/backend/src/core/MfmService.ts | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23be962d9e..f87fc3a2bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,8 @@
   [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
 - Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
+- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index d33b228c3d..edfb3aa4fc 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -406,7 +406,7 @@ export class MfmService {
 			mention: (node) => {
 				const a = doc.createElement('a');
 				const { username, host, acct } = node.props;
-				const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
+				const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username.toLowerCase() === username.toLowerCase() && remoteUser.host?.toLowerCase() === host?.toLowerCase());
 				a.setAttribute('href', remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`);
 				a.className = 'u-url mention';
 				a.textContent = acct;

From a896c39dbfd3bf35c2c264de7a77ac92818e01db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 6 Nov 2024 15:15:28 +0900
Subject: [PATCH 037/125] =?UTF-8?q?fix(frontend):=20=E3=83=8E=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E6=8A=95=E7=A8=BF=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=AB?=
 =?UTF-8?q?=E3=83=9B=E3=83=90=E3=83=BC=E6=99=82=E3=81=AE=E3=82=B9=E3=82=BF?=
 =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=81=8C=E9=81=A9=E7=94=A8=E3=81=95=E3=82=8C?=
 =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=20(#14887)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): ノート投稿ボタンにホバー時のスタイルが適用されていない (#305)

(cherry picked from commit 711ab846a967feeddbe0c908bee4b91646cec321)

* Update Changelog

---------

Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
---
 CHANGELOG.md                                    | 2 ++
 packages/frontend/src/components/MkPostForm.vue | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f87fc3a2bb..0309f338f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,8 @@
 - Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
 - Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
 - Fix: リンク切れを修正
+= Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正  
+  (Cherry-picked from https://github.com/taiyme/misskey/pull/305)
 
 ### Server
 - Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように  
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index f2fe048449..0b5794d1e3 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -1108,7 +1108,7 @@ defineExpose({
 	&:focus-visible {
 		outline: none;
 
-		.submitInner {
+		> .submitInner {
 			outline: 2px solid var(--MI_THEME-fgOnAccent);
 			outline-offset: -4px;
 		}
@@ -1123,13 +1123,13 @@ defineExpose({
 	}
 
 	&:not(:disabled):hover {
-		> .inner {
+		> .submitInner {
 			background: linear-gradient(90deg, hsl(from var(--MI_THEME-accent) h s calc(l + 5)), hsl(from var(--MI_THEME-accent) h s calc(l + 5)));
 		}
 	}
 
 	&:not(:disabled):active {
-		> .inner {
+		> .submitInner {
 			background: linear-gradient(90deg, hsl(from var(--MI_THEME-accent) h s calc(l + 5)), hsl(from var(--MI_THEME-accent) h s calc(l + 5)));
 		}
 	}

From b1c82213a320dd7c83f8b2e742406646ef18ff1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Wed, 6 Nov 2024 22:01:21 +0900
Subject: [PATCH 038/125] =?UTF-8?q?fix(backend):=20FTT=E7=84=A1=E5=8A=B9?=
 =?UTF-8?q?=E6=99=82=E3=81=AB=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC=E3=83=AA?=
 =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=BF=E3=82=A4=E3=83=A0=E3=83=A9=E3=82=A4?=
 =?UTF-8?q?=E3=83=B3=E3=81=8C=E4=BD=BF=E7=94=A8=E3=81=A7=E3=81=8D=E3=81=AA?=
 =?UTF-8?q?=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1487?=
 =?UTF-8?q?8)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: return getfromdb when FanoutTimeline is not enabled

* Update Changelog

* fix

---------

Co-authored-by: Lhc_fl <lhcfl@outlook.com>
---
 CHANGELOG.md                                                    | 2 ++
 .../src/server/api/endpoints/notes/user-list-timeline.ts        | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0309f338f1..1740d0171e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,6 +35,8 @@
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
 - Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
+- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
index 6c7185c9eb..87f9b322a6 100644
--- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -112,7 +112,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 
 				this.activeUsersChart.read(me);
 
-				await this.noteEntityService.packMany(timeline, me);
+				return await this.noteEntityService.packMany(timeline, me);
 			}
 
 			const timeline = await this.fanoutTimelineEndpointService.timeline({

From f1eb17f66c75f09e884a41be821cccef363ecee7 Mon Sep 17 00:00:00 2001
From: Linca <41134017+Lhcfl@users.noreply.github.com>
Date: Wed, 6 Nov 2024 21:01:58 +0800
Subject: [PATCH 039/125] chore: little type trick in pizzax.ts (#14891)

Make `makeGetterSetter` take the correct type associated with getter and setter
---
 packages/frontend/src/pizzax.ts | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/packages/frontend/src/pizzax.ts b/packages/frontend/src/pizzax.ts
index ac325e923f..7740fe0d39 100644
--- a/packages/frontend/src/pizzax.ts
+++ b/packages/frontend/src/pizzax.ts
@@ -241,9 +241,13 @@ export class Storage<T extends StateDef> {
 	 * 特定のキーの、簡易的なgetter/setterを作ります
 	 * 主にvue上で設定コントロールのmodelとして使う用
 	 */
-	public makeGetterSetter<K extends keyof T>(key: K, getter?: (v: T[K]) => unknown, setter?: (v: unknown) => T[K]): {
-		get: () => T[K]['default'];
-		set: (value: T[K]['default']) => void;
+	public makeGetterSetter<K extends keyof T, R = T[K]['default']>(
+		key: K,
+		getter?: (v: T[K]['default']) => R,
+		setter?: (v: R) => T[K]['default'],
+	): {
+		get: () => R;
+		set: (value: R) => void;
 	} {
 		const valueRef = ref(this.state[key]);
 
@@ -265,7 +269,7 @@ export class Storage<T extends StateDef> {
 					return valueRef.value;
 				}
 			},
-			set: (value: unknown) => {
+			set: (value) => {
 				const val = setter ? setter(value) : value;
 				this.set(key, val);
 				valueRef.value = val;

From bca690f256721815fb1c918c1f66a2172f4fcf40 Mon Sep 17 00:00:00 2001
From: 4ster1sk <146138447+4ster1sk@users.noreply.github.com>
Date: Thu, 7 Nov 2024 15:10:10 +0900
Subject: [PATCH 040/125] =?UTF-8?q?fix(backend):=20=E3=83=95=E3=82=A9?=
 =?UTF-8?q?=E3=83=AD=E3=83=AF=E3=83=BC=E3=81=B8=E3=81=AE=E3=83=A1=E3=83=83?=
 =?UTF-8?q?=E3=82=BB=E3=83=BC=E3=82=B8=E3=81=AE=E7=B5=B5=E6=96=87=E5=AD=97?=
 =?UTF-8?q?=E3=82=92emojis=E3=81=AB=E5=90=AB=E3=82=81=E3=82=8B=E3=82=88?=
 =?UTF-8?q?=E3=81=86=E3=81=AB=20(#14904)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/backend/src/server/api/endpoints/i/update.ts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 2183beac7c..d91e2fef4b 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -465,6 +465,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			const newName = updates.name === undefined ? user.name : updates.name;
 			const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description;
 			const newFields = profileUpdates.fields === undefined ? profile.fields : profileUpdates.fields;
+			const newFollowedMessage = profileUpdates.description === undefined ? profile.followedMessage : profileUpdates.followedMessage;
 
 			if (newName != null) {
 				let hasProhibitedWords = false;
@@ -494,6 +495,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				]);
 			}
 
+			if (newFollowedMessage != null) {
+				const tokens = mfm.parse(newFollowedMessage);
+				emojis = emojis.concat(extractCustomEmojisFromMfm(tokens));
+			}
+
 			updates.emojis = emojis;
 			updates.tags = tags;
 

From 0b976064cafcb5a9b2399937d614513f494cca85 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 7 Nov 2024 15:10:38 +0900
Subject: [PATCH 041/125] Update CHANGELOG.md

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1740d0171e..464bdd677f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@
 - Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように  
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
+- fix(backend): フォロワーへのメッセージの絵文字をemojisに含めるように
 - Fix: Nested proxy requestsを検出した際にブロックするように
   [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
 - Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正  

From 794cb9ffe205b1e2ca838978f80d2d6a35f17f77 Mon Sep 17 00:00:00 2001
From: 4ster1sk <146138447+4ster1sk@users.noreply.github.com>
Date: Thu, 7 Nov 2024 17:16:51 +0900
Subject: [PATCH 042/125] =?UTF-8?q?fix(backend):=20followedMessage?=
 =?UTF-8?q?=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=8Fdescription=E3=81=AB?=
 =?UTF-8?q?=E3=81=AA=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#14908)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/backend/src/server/api/endpoints/i/update.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index d91e2fef4b..d3eeb75b27 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -465,7 +465,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			const newName = updates.name === undefined ? user.name : updates.name;
 			const newDescription = profileUpdates.description === undefined ? profile.description : profileUpdates.description;
 			const newFields = profileUpdates.fields === undefined ? profile.fields : profileUpdates.fields;
-			const newFollowedMessage = profileUpdates.description === undefined ? profile.followedMessage : profileUpdates.followedMessage;
+			const newFollowedMessage = profileUpdates.followedMessage === undefined ? profile.followedMessage : profileUpdates.followedMessage;
 
 			if (newName != null) {
 				let hasProhibitedWords = false;

From 8a4ce16e903f5b318e60d3c9f50f66d2054ba39b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 8 Nov 2024 18:00:55 +0900
Subject: [PATCH 043/125] Update CONTRIBUTING.md

---
 CONTRIBUTING.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4bcf7e1642..76a5f42eac 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -83,6 +83,9 @@ One should not add property that has defined before by other implementation, or
 ## Reviewers guide
 Be willing to comment on the good points and not just the things you want fixed 💯
 
+読んでおくといいやつ
+- https://blog.lacolaco.net/posts/1e2cf439b3c2/
+
 ### Review perspective
 - Scope
 	- Are the goals of the PR clear?

From 98b4717c45a543e31fe5635a8850074afe0d8fe2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 10:51:28 +0900
Subject: [PATCH 044/125] =?UTF-8?q?fix(backend):=20SQL=E3=81=AE=E3=82=B5?=
 =?UTF-8?q?=E3=83=8B=E3=82=BF=E3=82=A4=E3=82=BA=E3=82=92=E5=BC=B7=E5=8C=96?=
 =?UTF-8?q?=20(#14920)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Fix code scanning alert no. 28: Incomplete string escaping or encoding (MisskeyIO#800)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
(cherry picked from commit 443335c662b14f609d6a81a8f3807e95709aebc1)

* :v:

---------

Co-authored-by: あわわわとーにゅ <17376330+u1-liquid@users.noreply.github.com>
---
 packages/backend/src/misc/sql-like-escape.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/backend/src/misc/sql-like-escape.ts b/packages/backend/src/misc/sql-like-escape.ts
index 0c05255674..6b4f51b00e 100644
--- a/packages/backend/src/misc/sql-like-escape.ts
+++ b/packages/backend/src/misc/sql-like-escape.ts
@@ -4,5 +4,5 @@
  */
 
 export function sqlLikeEscape(s: string) {
-	return s.replace(/([%_])/g, '\\$1');
+	return s.replace(/([\\%_])/g, '\\$1');
 }

From 5b60ae810b975d4b86a47a00b65b0736e39fe949 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 10:52:07 +0900
Subject: [PATCH 045/125] =?UTF-8?q?fix(frontend):=20=E5=A4=96=E9=83=A8URL?=
 =?UTF-8?q?=E3=81=B8=E3=81=AE=E3=83=AA=E3=83=80=E3=82=A4=E3=83=AC=E3=82=AF?=
 =?UTF-8?q?=E3=83=88=E3=81=AE=E3=83=90=E3=83=AA=E3=83=87=E3=83=BC=E3=82=B7?=
 =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=82=92=E5=BC=B7=E5=8C=96=20(#14919)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Fix code scanning alert no. 25: Incomplete URL scheme check (MisskeyIO#799)

* Fix code scanning alert no. 26: Incomplete URL scheme check

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Fix code scanning alert no. 25: Incomplete URL scheme check

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
(cherry picked from commit 7d7552e076c0152a5966e919be0e9a60b3736208)

* :v:

---------

Co-authored-by: あわわわとーにゅ <17376330+u1-liquid@users.noreply.github.com>
---
 packages/frontend/src/pages/auth.vue   | 2 +-
 packages/frontend/src/pages/miauth.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue
index d8f8d0b428..4170b4f73e 100644
--- a/packages/frontend/src/pages/auth.vue
+++ b/packages/frontend/src/pages/auth.vue
@@ -62,7 +62,7 @@ function accepted() {
 	state.value = 'accepted';
 	if (session.value && session.value.app.callbackUrl) {
 		const url = new URL(session.value.app.callbackUrl);
-		if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url');
+		if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(url.protocol)) throw new Error('invalid url');
 		location.href = `${session.value.app.callbackUrl}?token=${session.value.token}`;
 	}
 }
diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue
index e89dd5c4a5..e85d2c29c1 100644
--- a/packages/frontend/src/pages/miauth.vue
+++ b/packages/frontend/src/pages/miauth.vue
@@ -65,7 +65,7 @@ async function onAccept(token: string) {
 
 	if (props.callback && props.callback !== '') {
 		const cbUrl = new URL(props.callback);
-		if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(cbUrl.protocol)) throw new Error('invalid url');
+		if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:', 'vbscript:'].includes(cbUrl.protocol)) throw new Error('invalid url');
 		cbUrl.searchParams.set('session', props.session);
 		location.href = cbUrl.toString();
 	} else {

From e75b62f3f5f58e39baf949d0d601c8826f43dba3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 10:53:09 +0900
Subject: [PATCH 046/125] =?UTF-8?q?enhance(frontend):=20=E5=80=8B=E5=88=A5?=
 =?UTF-8?q?=E3=81=8A=E7=9F=A5=E3=82=89=E3=81=9B=E3=83=9A=E3=83=BC=E3=82=B8?=
 =?UTF-8?q?=E3=81=A7=E3=81=AFmeta=E3=82=BF=E3=82=B0=E3=82=92=E5=87=BA?=
 =?UTF-8?q?=E5=8A=9B=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#1490?=
 =?UTF-8?q?2)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(frontend): 個別お知らせページではmetaタグを出力するように

* Update Changelog
---
 CHANGELOG.md                                  |  3 +-
 .../src/server/web/ClientServerService.ts     | 37 ++++++++++++++++++-
 .../src/server/web/views/announcement.pug     | 21 +++++++++++
 .../backend/src/server/web/views/base.pug     |  3 +-
 packages/frontend/src/pages/announcement.vue  |  2 +-
 5 files changed, 62 insertions(+), 4 deletions(-)
 create mode 100644 packages/backend/src/server/web/views/announcement.pug

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 464bdd677f..cddd9f1ad7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,7 +15,8 @@
   - どのアカウントで認証しようとしているのかがわかるように
   - 認証するアカウントを切り替えられるように
 - Enhance: Self-XSS防止用の警告を追加
-- Enhance: カタルーニャ語 (ca-ES) に対応  
+- Enhance: カタルーニャ語 (ca-ES) に対応
+- Enhance: 個別お知らせページではMetaタグを出力するように
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index 4860ef3e12..5ebec4ffd0 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -42,13 +42,26 @@ import { MetaEntityService } from '@/core/entities/MetaEntityService.js';
 import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
 import { ClipEntityService } from '@/core/entities/ClipEntityService.js';
 import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
-import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
+import type {
+	AnnouncementsRepository,
+	ChannelsRepository,
+	ClipsRepository,
+	FlashsRepository,
+	GalleryPostsRepository,
+	MiMeta,
+	NotesRepository,
+	PagesRepository,
+	ReversiGamesRepository,
+	UserProfilesRepository,
+	UsersRepository,
+} from '@/models/_.js';
 import type Logger from '@/logger.js';
 import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
 import { bindThis } from '@/decorators.js';
 import { FlashEntityService } from '@/core/entities/FlashEntityService.js';
 import { RoleService } from '@/core/RoleService.js';
 import { ReversiGameEntityService } from '@/core/entities/ReversiGameEntityService.js';
+import { AnnouncementEntityService } from '@/core/entities/AnnouncementEntityService.js';
 import { FeedService } from './FeedService.js';
 import { UrlPreviewService } from './UrlPreviewService.js';
 import { ClientLoggerService } from './ClientLoggerService.js';
@@ -103,6 +116,9 @@ export class ClientServerService {
 		@Inject(DI.reversiGamesRepository)
 		private reversiGamesRepository: ReversiGamesRepository,
 
+		@Inject(DI.announcementsRepository)
+		private announcementsRepository: AnnouncementsRepository,
+
 		private flashEntityService: FlashEntityService,
 		private userEntityService: UserEntityService,
 		private noteEntityService: NoteEntityService,
@@ -112,6 +128,7 @@ export class ClientServerService {
 		private clipEntityService: ClipEntityService,
 		private channelEntityService: ChannelEntityService,
 		private reversiGameEntityService: ReversiGameEntityService,
+		private announcementEntityService: AnnouncementEntityService,
 		private urlPreviewService: UrlPreviewService,
 		private feedService: FeedService,
 		private roleService: RoleService,
@@ -776,6 +793,24 @@ export class ClientServerService {
 				return await renderBase(reply);
 			}
 		});
+
+		// 個別お知らせページ
+		fastify.get<{ Params: { announcementId: string; } }>('/announcements/:announcementId', async (request, reply) => {
+			const announcement = await this.announcementsRepository.findOneBy({
+				id: request.params.announcementId,
+			});
+
+			if (announcement) {
+				const _announcement = await this.announcementEntityService.pack(announcement);
+				reply.header('Cache-Control', 'public, max-age=3600');
+				return await reply.view('announcement', {
+					announcement: _announcement,
+					...await this.generateCommonPugData(this.meta),
+				});
+			} else {
+				return await renderBase(reply);
+			}
+		});
 		//#endregion
 
 		//#region noindex pages
diff --git a/packages/backend/src/server/web/views/announcement.pug b/packages/backend/src/server/web/views/announcement.pug
new file mode 100644
index 0000000000..7a4052e8a4
--- /dev/null
+++ b/packages/backend/src/server/web/views/announcement.pug
@@ -0,0 +1,21 @@
+extends ./base
+
+block vars
+	- const title = announcement.title;
+	- const description = announcement.text.length > 100 ? announcement.text.slice(0, 100) + '…' : announcement.text;
+	- const url = `${config.url}/announcements/${announcement.id}`;
+
+block title
+	= `${title} | ${instanceName}`
+
+block desc
+	meta(name='description' content=description)
+
+block og
+	meta(property='og:type'        content='article')
+	meta(property='og:title'       content= title)
+	meta(property='og:description' content= description)
+	meta(property='og:url'         content= url)
+	if announcement.imageUrl
+		meta(property='og:image' content=announcement.imageUrl)
+		meta(property='twitter:card' content='summary_large_image')
diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug
index 88714b2556..280a5923c2 100644
--- a/packages/backend/src/server/web/views/base.pug
+++ b/packages/backend/src/server/web/views/base.pug
@@ -2,6 +2,7 @@ block vars
 
 block loadClientEntry
 	- const entry = config.frontendEntry;
+	- const baseUrl = config.url;
 
 doctype html
 
@@ -32,7 +33,7 @@ html
 		link(rel='icon' href= icon || '/favicon.ico')
 		link(rel='apple-touch-icon' href= appleTouchIcon || '/apple-touch-icon.png')
 		link(rel='manifest' href='/manifest.json')
-		link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`)
+		link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${baseUrl}/opensearch.xml`)
 		link(rel='prefetch' href=serverErrorImageUrl)
 		link(rel='prefetch' href=infoImageUrl)
 		link(rel='prefetch' href=notFoundImageUrl)
diff --git a/packages/frontend/src/pages/announcement.vue b/packages/frontend/src/pages/announcement.vue
index 01c29cf02d..56c10fb292 100644
--- a/packages/frontend/src/pages/announcement.vue
+++ b/packages/frontend/src/pages/announcement.vue
@@ -103,7 +103,7 @@ const headerActions = computed(() => []);
 const headerTabs = computed(() => []);
 
 definePageMetadata(() => ({
-	title: announcement.value ? `${i18n.ts.announcements}: ${announcement.value.title}` : i18n.ts.announcements,
+	title: announcement.value ? announcement.value.title : i18n.ts.announcements,
 	icon: 'ti ti-speakerphone',
 }));
 </script>

From a4c5ce1413078c9b98816644bebfcc0a24e94a85 Mon Sep 17 00:00:00 2001
From: momoirodouhu <momoirodouhu@gmail.com>
Date: Sat, 9 Nov 2024 10:54:44 +0900
Subject: [PATCH 047/125] =?UTF-8?q?enhance(backend)=20:=20=E3=83=AA?=
 =?UTF-8?q?=E3=83=A2=E3=83=BC=E3=83=88=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC?=
 =?UTF-8?q?=E3=81=AE=E7=85=A7=E4=BC=9A=E3=82=92=E3=82=AA=E3=83=AA=E3=82=B8?=
 =?UTF-8?q?=E3=83=8A=E3=83=AB=E3=81=AB=E3=83=AA=E3=83=80=E3=82=A4=E3=83=AC?=
 =?UTF-8?q?=E3=82=AF=E3=83=88=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
 =?UTF-8?q?=20(#12892)=20(#14897)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(backend) : リモートユーザーの照会をオリジナルにリダイレクトするように (#12892)

* オリジンリダイレクトのテストをtodoとして追加。

e2eテストにリモートユーザー考慮のテストがなさそうなので。

次のコマンドで動くことは確認済みです。
curl "http://localhost:3000/@foo@bar" -H "accept: application/activity+json" -L

* Acctのパースを既存のパーサーでするように修正

* lint
---
 CHANGELOG.md                                  |  1 +
 .../src/server/ActivityPubServerService.ts    | 20 +++++++++++++++----
 packages/backend/test/e2e/fetch-resource.ts   |  2 ++
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cddd9f1ad7..b986273d0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,7 @@
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
 - Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
+- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts
index 3255d64621..ba2342b630 100644
--- a/packages/backend/src/server/ActivityPubServerService.ts
+++ b/packages/backend/src/server/ActivityPubServerService.ts
@@ -29,6 +29,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
 import { bindThis } from '@/decorators.js';
 import { IActivity } from '@/core/activitypub/type.js';
 import { isQuote, isRenote } from '@/misc/is-renote.js';
+import * as Acct from '@/misc/acct.js';
 import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions, FastifyBodyParser } from 'fastify';
 import type { FindOptionsWhere } from 'typeorm';
 
@@ -486,6 +487,16 @@ export class ActivityPubServerService {
 			return;
 		}
 
+		// リモートだったらリダイレクト
+		if (user.host != null) {
+			if (user.uri == null || this.utilityService.isSelfHost(user.host)) {
+				reply.code(500);
+				return;
+			}
+			reply.redirect(user.uri, 301);
+			return;
+		}
+
 		reply.header('Cache-Control', 'public, max-age=180');
 		this.setResponseType(request, reply);
 		return (this.apRendererService.addContext(await this.apRendererService.renderPerson(user as MiLocalUser)));
@@ -654,19 +665,20 @@ export class ActivityPubServerService {
 
 			const user = await this.usersRepository.findOneBy({
 				id: userId,
-				host: IsNull(),
 				isSuspended: false,
 			});
 
 			return await this.userInfo(request, reply, user);
 		});
 
-		fastify.get<{ Params: { user: string; } }>('/@:user', { constraints: { apOrHtml: 'ap' } }, async (request, reply) => {
+		fastify.get<{ Params: { acct: string; } }>('/@:acct', { constraints: { apOrHtml: 'ap' } }, async (request, reply) => {
 			vary(reply.raw, 'Accept');
 
+			const acct = Acct.parse(request.params.acct);
+
 			const user = await this.usersRepository.findOneBy({
-				usernameLower: request.params.user.toLowerCase(),
-				host: IsNull(),
+				usernameLower: acct.username,
+				host: acct.host ?? IsNull(),
 				isSuspended: false,
 			});
 
diff --git a/packages/backend/test/e2e/fetch-resource.ts b/packages/backend/test/e2e/fetch-resource.ts
index 7efd688ec2..8ea4cb9800 100644
--- a/packages/backend/test/e2e/fetch-resource.ts
+++ b/packages/backend/test/e2e/fetch-resource.ts
@@ -230,6 +230,7 @@ describe('Webリソース', () => {
 				path: path('xxxxxxxxxx'),
 				type: HTML,
 			}));
+			test.todo('HTMLとしてGETできる。(リモートユーザーでもリダイレクトせず)');
 		});
 
 		describe.each([
@@ -249,6 +250,7 @@ describe('Webリソース', () => {
 				path: path('xxxxxxxxxx'),
 				accept,
 			}));
+			test.todo('はオリジナルにリダイレクトされる。(リモートユーザー)');
 		});
 	});
 

From 3a421837bfc8ea816c3109394a916cb0cac0e8d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 10:57:04 +0900
Subject: [PATCH 048/125] =?UTF-8?q?refactor(frontend):=20=E5=8B=95?=
 =?UTF-8?q?=E7=94=BBUI=E3=81=AE=E3=83=95=E3=83=AB=E3=82=B9=E3=82=AF?=
 =?UTF-8?q?=E3=83=AA=E3=83=BC=E3=83=B3=E5=91=A8=E3=82=8A=E3=81=AE=E8=AA=BF?=
 =?UTF-8?q?=E6=95=B4=20(#14877)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* refactor(frontend): フルスクリーン周りの調整

(cherry picked from commit 783032caec5853d78d5af3391e29cf364f2282e8)

* refactor(frontend): deviceKindの循環参照を除去

(cherry picked from commit 1ca471f57e968a1a6e2259bde4a7c6da1fe0c54e)

* fix

---------

Co-authored-by: taiyme <53635909+taiyme@users.noreply.github.com>
---
 packages/frontend/src/boot/common.ts          |  6 ++-
 .../frontend/src/components/MkMediaVideo.vue  | 43 ++++++++---------
 packages/frontend/src/scripts/device-kind.ts  | 24 +++++-----
 packages/frontend/src/scripts/fullscreen.ts   | 46 +++++++++++++++++++
 packages/frontend/src/store.ts                |  9 ++--
 5 files changed, 88 insertions(+), 40 deletions(-)
 create mode 100644 packages/frontend/src/scripts/fullscreen.ts

diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts
index 90ae49ee59..bfe5c4f5f7 100644
--- a/packages/frontend/src/boot/common.ts
+++ b/packages/frontend/src/boot/common.ts
@@ -15,7 +15,7 @@ import { updateI18n, i18n } from '@/i18n.js';
 import { $i, refreshAccount, login } from '@/account.js';
 import { defaultStore, ColdDeviceStorage } from '@/store.js';
 import { fetchInstance, instance } from '@/instance.js';
-import { deviceKind } from '@/scripts/device-kind.js';
+import { deviceKind, updateDeviceKind } from '@/scripts/device-kind.js';
 import { reloadChannel } from '@/scripts/unison-reload.js';
 import { getUrlWithoutLoginId } from '@/scripts/login-id.js';
 import { getAccountFromId } from '@/scripts/get-account-from-id.js';
@@ -185,6 +185,10 @@ export async function common(createVue: () => App<Element>) {
 		}
 	});
 
+	watch(defaultStore.reactiveState.overridedDeviceKind, (kind) => {
+		updateDeviceKind(kind);
+	}, { immediate: true });
+
 	watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
 		document.documentElement.style.setProperty('--MI-modalBgFilter', v ? 'blur(4px)' : 'none');
 	}, { immediate: true });
diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index d3a12ca734..65e4a1eb12 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -118,7 +118,7 @@ import { hms } from '@/filters/hms.js';
 import { defaultStore } from '@/store.js';
 import { i18n } from '@/i18n.js';
 import * as os from '@/os.js';
-import { isFullscreenNotSupported } from '@/scripts/device-kind.js';
+import { exitFullscreen, requestFullscreen } from '@/scripts/fullscreen.js';
 import hasAudio from '@/scripts/media-has-audio.js';
 import MkMediaRange from '@/components/MkMediaRange.vue';
 import { $i, iAmModerator } from '@/account.js';
@@ -334,26 +334,21 @@ function togglePlayPause() {
 }
 
 function toggleFullscreen() {
-	if (isFullscreenNotSupported && videoEl.value) {
-		if (isFullscreen.value) {
-			// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-			//@ts-ignore
-			videoEl.value.webkitExitFullscreen();
-			isFullscreen.value = false;
-		} else {
-			// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-			//@ts-ignore
-			videoEl.value.webkitEnterFullscreen();
-			isFullscreen.value = true;
-		}
-	} else if (playerEl.value) {
-		if (isFullscreen.value) {
-			document.exitFullscreen();
-			isFullscreen.value = false;
-		} else {
-			playerEl.value.requestFullscreen({ navigationUI: 'hide' });
-			isFullscreen.value = true;
-		}
+	if (playerEl.value == null || videoEl.value == null) return;
+	if (isFullscreen.value) {
+		exitFullscreen({
+			videoEl: videoEl.value,
+		});
+		isFullscreen.value = false;
+	} else {
+		requestFullscreen({
+			videoEl: videoEl.value,
+			playerEl: playerEl.value,
+			options: {
+				navigationUI: 'hide',
+			},
+		});
+		isFullscreen.value = true;
 	}
 }
 
@@ -454,8 +449,10 @@ watch(loop, (to) => {
 });
 
 watch(hide, (to) => {
-	if (to && isFullscreen.value) {
-		document.exitFullscreen();
+	if (videoEl.value && to && isFullscreen.value) {
+		exitFullscreen({
+			videoEl: videoEl.value,
+		});
 		isFullscreen.value = false;
 	}
 });
diff --git a/packages/frontend/src/scripts/device-kind.ts b/packages/frontend/src/scripts/device-kind.ts
index 7c33f8ccee..7aadb617ca 100644
--- a/packages/frontend/src/scripts/device-kind.ts
+++ b/packages/frontend/src/scripts/device-kind.ts
@@ -3,22 +3,22 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { defaultStore } from '@/store.js';
-
-await defaultStore.ready;
+export type DeviceKind = 'smartphone' | 'tablet' | 'desktop';
 
 const ua = navigator.userAgent.toLowerCase();
 const isTablet = /ipad/.test(ua) || (/mobile|iphone|android/.test(ua) && window.innerWidth > 700);
 const isSmartphone = !isTablet && /mobile|iphone|android/.test(ua);
 
-const isIPhone = /iphone|ipod/gi.test(ua) && navigator.maxTouchPoints > 1;
-// navigator.platform may be deprecated but this check is still required
-const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
-const isIos = /ipad|iphone|ipod/gi.test(ua) && navigator.maxTouchPoints > 1;
+export const DEFAULT_DEVICE_KIND: DeviceKind = (
+	isSmartphone
+		? 'smartphone'
+		: isTablet
+			? 'tablet'
+			: 'desktop'
+);
 
-export const isFullscreenNotSupported = isIPhone || isIos;
+export let deviceKind: DeviceKind = DEFAULT_DEVICE_KIND;
 
-export const deviceKind: 'smartphone' | 'tablet' | 'desktop' = defaultStore.state.overridedDeviceKind ? defaultStore.state.overridedDeviceKind
-	: isSmartphone ? 'smartphone'
-	: isTablet ? 'tablet'
-	: 'desktop';
+export function updateDeviceKind(kind: DeviceKind | null) {
+	deviceKind = kind ?? DEFAULT_DEVICE_KIND;
+}
diff --git a/packages/frontend/src/scripts/fullscreen.ts b/packages/frontend/src/scripts/fullscreen.ts
new file mode 100644
index 0000000000..7a0a018ef3
--- /dev/null
+++ b/packages/frontend/src/scripts/fullscreen.ts
@@ -0,0 +1,46 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+type PartiallyPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
+
+type VideoEl = PartiallyPartial<HTMLVideoElement, 'requestFullscreen'> & {
+	webkitEnterFullscreen?(): void;
+	webkitExitFullscreen?(): void;
+};
+
+type PlayerEl = PartiallyPartial<HTMLElement, 'requestFullscreen'>;
+
+type RequestFullscreenProps = {
+	readonly videoEl: VideoEl;
+	readonly playerEl: PlayerEl;
+	readonly options?: FullscreenOptions | null;
+};
+
+type ExitFullscreenProps = {
+	readonly videoEl: VideoEl;
+};
+
+export const requestFullscreen = ({ videoEl, playerEl, options }: RequestFullscreenProps) => {
+	if (playerEl.requestFullscreen != null) {
+		playerEl.requestFullscreen(options ?? undefined);
+		return;
+	}
+	if (videoEl.webkitEnterFullscreen != null) {
+		videoEl.webkitEnterFullscreen();
+		return;
+	}
+};
+
+export const exitFullscreen = ({ videoEl }: ExitFullscreenProps) => {
+	// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+	if (document.exitFullscreen != null) {
+		document.exitFullscreen();
+		return;
+	}
+	if (videoEl.webkitExitFullscreen != null) {
+		videoEl.webkitExitFullscreen();
+		return;
+	}
+};
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index 911a463636..1d981e897b 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -8,8 +8,9 @@ import * as Misskey from 'misskey-js';
 import { hemisphere } from '@@/js/intl-const.js';
 import lightTheme from '@@/themes/l-light.json5';
 import darkTheme from '@@/themes/d-green-lime.json5';
-import { miLocalStorage } from './local-storage.js';
 import type { SoundType } from '@/scripts/sound.js';
+import { DEFAULT_DEVICE_KIND, type DeviceKind } from '@/scripts/device-kind.js';
+import { miLocalStorage } from '@/local-storage.js';
 import { Storage } from '@/pizzax.js';
 import type { Ast } from '@syuilo/aiscript';
 
@@ -207,7 +208,7 @@ export const defaultStore = markRaw(new Storage('base', {
 
 	overridedDeviceKind: {
 		where: 'device',
-		default: null as null | 'smartphone' | 'tablet' | 'desktop',
+		default: null as DeviceKind | null,
 	},
 	serverDisconnectedBehavior: {
 		where: 'device',
@@ -263,11 +264,11 @@ export const defaultStore = markRaw(new Storage('base', {
 	},
 	useBlurEffectForModal: {
 		where: 'device',
-		default: !/mobile|iphone|android/.test(navigator.userAgent.toLowerCase()), // 循環参照するのでdevice-kind.tsは参照できない
+		default: DEFAULT_DEVICE_KIND === 'desktop',
 	},
 	useBlurEffect: {
 		where: 'device',
-		default: !/mobile|iphone|android/.test(navigator.userAgent.toLowerCase()), // 循環参照するのでdevice-kind.tsは参照できない
+		default: DEFAULT_DEVICE_KIND === 'desktop',
 	},
 	showFixedPostForm: {
 		where: 'device',

From 4a62051ce7bd369335cf020d0bd39019f2a45212 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 10:58:09 +0900
Subject: [PATCH 049/125] =?UTF-8?q?fix(backend):=20=E3=83=AD=E3=83=BC?=
 =?UTF-8?q?=E3=82=AB=E3=83=AB=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=B8?=
 =?UTF-8?q?=E3=81=AE=E3=83=A1=E3=83=B3=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92?=
 =?UTF-8?q?=E5=90=AB=E3=82=80=E3=83=8E=E3=83=BC=E3=83=88=E3=81=8C=E9=80=A3?=
 =?UTF-8?q?=E5=90=88=E3=81=95=E3=82=8C=E3=82=8B=E9=9A=9B=E3=81=AB=E6=AD=A3?=
 =?UTF-8?q?=E3=81=97=E3=81=84URL=E3=81=AB=E5=A4=89=E6=8F=9B=E3=81=95?=
 =?UTF-8?q?=E3=82=8C=E3=81=AA=E3=81=84=E3=81=93=E3=81=A8=E3=81=8C=E3=81=82?=
 =?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1487?=
 =?UTF-8?q?9)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: make sure mentions of local users get rendered correctly during AP delivery (resolves #645)

* Update Changelog

* indent

---------

Co-authored-by: Laura Hausmann <laura@hausmann.dev>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 CHANGELOG.md                            | 2 ++
 packages/backend/src/core/MfmService.ts | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b986273d0d..76abe42e10 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,6 +37,8 @@
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
 - Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
+- Fix: ローカルユーザーへのメンションを含むノートが連合される際に正しいURLに変換されないことがある問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
 - Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
 - Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index edfb3aa4fc..8061622340 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -407,7 +407,9 @@ export class MfmService {
 				const a = doc.createElement('a');
 				const { username, host, acct } = node.props;
 				const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username.toLowerCase() === username.toLowerCase() && remoteUser.host?.toLowerCase() === host?.toLowerCase());
-				a.setAttribute('href', remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`);
+				a.setAttribute('href', remoteUserInfo
+					? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri)
+					: `${this.config.url}/${acct.endsWith(`@${this.config.url}`) ? acct.substring(0, acct.length - this.config.url.length - 1) : acct}`);
 				a.className = 'u-url mention';
 				a.textContent = acct;
 				return a;

From 9f7d41eb470db5d350e76c06c0d385d58e7445a7 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Sat, 9 Nov 2024 02:25:42 +0000
Subject: [PATCH 050/125] Bump version to 2024.10.2-alpha.3

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 55ae092967..dbdedd4635 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.10.2-alpha.2",
+	"version": "2024.10.2-alpha.3",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 32d6c8b0cb..f638bacbf9 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.10.2-alpha.2",
+	"version": "2024.10.2-alpha.3",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From cf09aa21f0eec86e7ffffee4fcbb610ff0e378a4 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Sat, 9 Nov 2024 02:28:02 +0000
Subject: [PATCH 051/125] Bump version to 2024.11.0-alpha.0

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index dbdedd4635..6a44eb04f3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.10.2-alpha.3",
+	"version": "2024.11.0-alpha.0",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index f638bacbf9..19615cfee5 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.10.2-alpha.3",
+	"version": "2024.11.0-alpha.0",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 00cbf9fe8085afe4190721b80a5bd55d0099c4cf Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 9 Nov 2024 14:09:02 +0900
Subject: [PATCH 052/125] Update CONTRIBUTING.md

---
 CONTRIBUTING.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 76a5f42eac..f8af6b3df0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -85,6 +85,7 @@ Be willing to comment on the good points and not just the things you want fixed
 
 読んでおくといいやつ
 - https://blog.lacolaco.net/posts/1e2cf439b3c2/
+- https://konifar-zatsu.hatenadiary.jp/entry/2024/11/05/192421
 
 ### Review perspective
 - Scope

From 1496700b3754be3a91d0123fc5ca17b6e8845488 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 15:51:49 +0900
Subject: [PATCH 053/125] Update CHANGELOG.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

たぶんリリースワークフローはこうしないと認識してくれない
---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76abe42e10..a302632a6c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 2024.10.2
+## 2024.11.0
 
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように

From e0a83e9c9ecbabcaa017d0b586b7ad56b3b4b6db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 9 Nov 2024 15:57:10 +0900
Subject: [PATCH 054/125] =?UTF-8?q?Update=20CHANGELOG.md=20(=E6=9B=B8?=
 =?UTF-8?q?=E3=81=8D=E6=96=B9=E3=82=92=E6=8F=83=E3=81=88=E3=82=8B)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a302632a6c..8f428c1c15 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,7 +30,8 @@
 - Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように  
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
-- fix(backend): フォロワーへのメッセージの絵文字をemojisに含めるように
+- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
+- Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
 - Fix: Nested proxy requestsを検出した際にブロックするように
   [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
 - Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正  
@@ -41,7 +42,6 @@
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
 - Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
-- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正

From 31e5f0bd09175baba8b1cc9e617c83934b423596 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sun, 10 Nov 2024 15:08:58 +0900
Subject: [PATCH 055/125] =?UTF-8?q?fix(frontend):=20=E3=83=A1=E3=83=BC?=
 =?UTF-8?q?=E3=83=AB=E3=82=A2=E3=83=89=E3=83=AC=E3=82=B9=E7=99=BB=E9=8C=B2?=
 =?UTF-8?q?=E6=9C=89=E5=8A=B9=E5=8C=96=E6=99=82=E3=81=AE=E3=80=8C=E5=AE=8C?=
 =?UTF-8?q?=E4=BA=86=E3=80=8D=E3=83=80=E3=82=A4=E3=82=A2=E3=83=AD=E3=82=B0?=
 =?UTF-8?q?=E3=83=9C=E3=83=83=E3=82=AF=E3=82=B9=E3=81=AE=E8=A1=A8=E7=A4=BA?=
 =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E3=82=92=E4=BF=AE=E6=AD=A3=20(#14928)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正

* Update MkSignupDialog.form.vue

* fix condition
---
 packages/frontend/src/components/MkSignupDialog.form.vue | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/packages/frontend/src/components/MkSignupDialog.form.vue b/packages/frontend/src/components/MkSignupDialog.form.vue
index 3d1c44fc90..e1f4e26d62 100644
--- a/packages/frontend/src/components/MkSignupDialog.form.vue
+++ b/packages/frontend/src/components/MkSignupDialog.form.vue
@@ -277,7 +277,7 @@ async function onSubmit(): Promise<void> {
 		return null;
 	});
 
-	if (res) {
+	if (res && res.ok) {
 		if (res.status === 204 || instance.emailRequiredForSignup) {
 			os.alert({
 				type: 'success',
@@ -295,6 +295,8 @@ async function onSubmit(): Promise<void> {
 				await login(resJson.token);
 			}
 		}
+	} else {
+		onSignupApiError();
 	}
 
 	submitting.value = false;

From 6bd3ed2074b9cfdfc46db0ca5a7a2a7507103519 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 10 Nov 2024 15:10:04 +0900
Subject: [PATCH 056/125] Update CHANGELOG.md

---
 CHANGELOG.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f428c1c15..e5bbda36fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように
 - Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
+- Enhance: 依存関係の更新
+- Enhance: l10nの更新
 
 ### Client
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  
@@ -25,6 +27,7 @@
 - Fix: リンク切れを修正
 = Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正  
   (Cherry-picked from https://github.com/taiyme/misskey/pull/305)
+- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
 
 ### Server
 - Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように  

From 458c72c15372a6ae94416656b155f7c727ab4597 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Mon, 11 Nov 2024 16:35:13 +0900
Subject: [PATCH 057/125] Update about-misskey.vue

---
 packages/frontend/src/pages/about-misskey.vue | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index fbbfb6ea61..f2becfd8f5 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -272,6 +272,9 @@ const patronsWithIcon = [{
 }, {
 	name: 'Yatoigawa',
 	icon: 'https://assets.misskey-hub.net/patrons/505e3568885a4a488431a8f22b4553d0.jpg',
+}, {
+	name: '秋瀬カヲル',
+	icon: 'https://assets.misskey-hub.net/patrons/0f22aeb866484f4fa51db6721e3f9847.jpg',
 }];
 
 const patrons = [
@@ -380,6 +383,7 @@ const patrons = [
 	'ケモナーのケシン',
 	'こまつぶり',
 	'まゆつな空高',
+	'asata',
 ];
 
 const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));

From a11b77a4158e07c18bcc57f77660cb08c0d950ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A5=BA=E5=AD=90w=20=28Yumechi=29?=
 <35571479+eternal-flame-AD@users.noreply.github.com>
Date: Mon, 11 Nov 2024 18:51:18 -0600
Subject: [PATCH 058/125] =?UTF-8?q?fix(backend):=20Webhook=20Test=E4=B8=80?=
 =?UTF-8?q?=E8=87=B4=E6=80=A7=20(#14863)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(backend): Webhook Test一致性

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* UserWebhookPayload<'followed'> 修正

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

---------

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
---
 CHANGELOG.md                                  |  1 +
 packages/backend/src/core/QueueService.ts     |  9 +++---
 .../backend/src/core/UserWebhookService.ts    | 14 ++++++++-
 .../backend/src/core/WebhookTestService.ts    | 31 ++++++++++++-------
 .../backend/test/unit/WebhookTestService.ts   | 16 +++++-----
 .../src/pages/settings/webhook.edit.vue       |  2 +-
 .../src/pages/settings/webhook.new.vue        |  2 +-
 7 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5bbda36fa..c92b8c06a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,7 @@
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
 - Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
+- Fix: User Webhookテスト機能のMock Payloadを修正  
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts
index 37028026cc..50f08da241 100644
--- a/packages/backend/src/core/QueueService.ts
+++ b/packages/backend/src/core/QueueService.ts
@@ -7,7 +7,7 @@ import { randomUUID } from 'node:crypto';
 import { Inject, Injectable } from '@nestjs/common';
 import type { IActivity } from '@/core/activitypub/type.js';
 import type { MiDriveFile } from '@/models/DriveFile.js';
-import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js';
+import type { MiWebhook, WebhookEventTypes, webhookEventTypes } from '@/models/Webhook.js';
 import type { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js';
 import type { Config } from '@/config.js';
 import { DI } from '@/di-symbols.js';
@@ -35,6 +35,7 @@ import type {
 } from './QueueModule.js';
 import type httpSignature from '@peertube/http-signature';
 import type * as Bull from 'bullmq';
+import { type UserWebhookPayload } from './UserWebhookService.js';
 
 @Injectable()
 export class QueueService {
@@ -468,10 +469,10 @@ export class QueueService {
 	 * @see UserWebhookDeliverProcessorService
 	 */
 	@bindThis
-	public userWebhookDeliver(
+	public userWebhookDeliver<T extends WebhookEventTypes>(
 		webhook: MiWebhook,
-		type: typeof webhookEventTypes[number],
-		content: unknown,
+		type: T,
+		content: UserWebhookPayload<T>,
 		opts?: { attempts?: number },
 	) {
 		const data: UserWebhookDeliverJobData = {
diff --git a/packages/backend/src/core/UserWebhookService.ts b/packages/backend/src/core/UserWebhookService.ts
index 8a40a53688..7117a3d7fa 100644
--- a/packages/backend/src/core/UserWebhookService.ts
+++ b/packages/backend/src/core/UserWebhookService.ts
@@ -6,11 +6,23 @@
 import { Inject, Injectable } from '@nestjs/common';
 import * as Redis from 'ioredis';
 import { type WebhooksRepository } from '@/models/_.js';
-import { MiWebhook } from '@/models/Webhook.js';
+import { MiWebhook, WebhookEventTypes } from '@/models/Webhook.js';
 import { DI } from '@/di-symbols.js';
 import { bindThis } from '@/decorators.js';
 import { GlobalEvents } from '@/core/GlobalEventService.js';
 import type { OnApplicationShutdown } from '@nestjs/common';
+import type { Packed } from '@/misc/json-schema.js';
+
+export type UserWebhookPayload<T extends WebhookEventTypes> =
+	T extends 'note' | 'reply' | 'renote' |'mention' ? {
+		note: Packed<'Note'>,
+	} :
+	T extends 'follow' | 'unfollow' ? {
+		user: Packed<'UserDetailedNotMe'>,
+	} :
+	T extends 'followed' ? {
+		user: Packed<'UserLite'>,
+	} : never;
 
 @Injectable()
 export class UserWebhookService implements OnApplicationShutdown {
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index c826a28963..b1ea7974fb 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -10,7 +10,7 @@ import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWeb
 import { SystemWebhookService } from '@/core/SystemWebhookService.js';
 import { Packed } from '@/misc/json-schema.js';
 import { type WebhookEventTypes } from '@/models/Webhook.js';
-import { UserWebhookService } from '@/core/UserWebhookService.js';
+import { type UserWebhookPayload, UserWebhookService } from '@/core/UserWebhookService.js';
 import { QueueService } from '@/core/QueueService.js';
 import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModeratorsActivityProcessorService.js';
 
@@ -306,10 +306,10 @@ export class WebhookTestService {
 	 * - 送信対象イベント(on)に関する設定
 	 */
 	@bindThis
-	public async testUserWebhook(
+	public async testUserWebhook<T extends WebhookEventTypes>(
 		params: {
 			webhookId: MiWebhook['id'],
-			type: WebhookEventTypes,
+			type: T,
 			override?: Partial<Omit<MiWebhook, 'id'>>,
 		},
 		sender: MiUser | null,
@@ -321,7 +321,7 @@ export class WebhookTestService {
 		}
 
 		const webhook = webhooks[0];
-		const send = (contents: unknown) => {
+		const send = <U extends WebhookEventTypes>(type: U, contents: UserWebhookPayload<U>) => {
 			const merged = {
 				...webhook,
 				...params.override,
@@ -329,7 +329,7 @@ export class WebhookTestService {
 
 			// テスト目的なのでUserWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図).
 			// また、Jobの試行回数も1回だけ.
-			this.queueService.userWebhookDeliver(merged, params.type, contents, { attempts: 1 });
+			this.queueService.userWebhookDeliver(merged, type, contents, { attempts: 1 });
 		};
 
 		const dummyNote1 = generateDummyNote({
@@ -361,33 +361,40 @@ export class WebhookTestService {
 
 		switch (params.type) {
 			case 'note': {
-				send(toPackedNote(dummyNote1));
+				send('note', { note: toPackedNote(dummyNote1) });
 				break;
 			}
 			case 'reply': {
-				send(toPackedNote(dummyReply1));
+				send('reply', { note: toPackedNote(dummyReply1) });
 				break;
 			}
 			case 'renote': {
-				send(toPackedNote(dummyRenote1));
+				send('renote', { note: toPackedNote(dummyRenote1) });
 				break;
 			}
 			case 'mention': {
-				send(toPackedNote(dummyMention1));
+				send('mention', { note: toPackedNote(dummyMention1) });
 				break;
 			}
 			case 'follow': {
-				send(toPackedUserDetailedNotMe(dummyUser1));
+				send('follow', { user: toPackedUserDetailedNotMe(dummyUser1) });
 				break;
 			}
 			case 'followed': {
-				send(toPackedUserLite(dummyUser2));
+				send('followed', { user: toPackedUserLite(dummyUser2) });
 				break;
 			}
 			case 'unfollow': {
-				send(toPackedUserDetailedNotMe(dummyUser3));
+				send('unfollow', { user: toPackedUserDetailedNotMe(dummyUser3) });
 				break;
 			}
+			// まだ実装されていない (#9485)
+			case 'reaction': return;
+			default: {
+				// eslint-disable-next-line @typescript-eslint/no-unused-vars
+				const _exhaustiveAssertion: never = params.type;
+				return;
+			}
 		}
 	}
 
diff --git a/packages/backend/test/unit/WebhookTestService.ts b/packages/backend/test/unit/WebhookTestService.ts
index 5e63b86f8f..be84ae9b84 100644
--- a/packages/backend/test/unit/WebhookTestService.ts
+++ b/packages/backend/test/unit/WebhookTestService.ts
@@ -7,7 +7,7 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { beforeAll, describe, jest } from '@jest/globals';
 import { WebhookTestService } from '@/core/WebhookTestService.js';
-import { UserWebhookService } from '@/core/UserWebhookService.js';
+import { UserWebhookPayload, UserWebhookService } from '@/core/UserWebhookService.js';
 import { SystemWebhookService } from '@/core/SystemWebhookService.js';
 import { GlobalModule } from '@/GlobalModule.js';
 import { MiSystemWebhook, MiUser, MiWebhook, UserProfilesRepository, UsersRepository } from '@/models/_.js';
@@ -122,7 +122,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('note');
-			expect((calls[2] as any).id).toBe('dummy-note-1');
+			expect((calls[2] as UserWebhookPayload<'note'>).note.id).toBe('dummy-note-1');
 		});
 
 		test('reply', async () => {
@@ -131,7 +131,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('reply');
-			expect((calls[2] as any).id).toBe('dummy-reply-1');
+			expect((calls[2] as UserWebhookPayload<'reply'>).note.id).toBe('dummy-reply-1');
 		});
 
 		test('renote', async () => {
@@ -140,7 +140,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('renote');
-			expect((calls[2] as any).id).toBe('dummy-renote-1');
+			expect((calls[2] as UserWebhookPayload<'renote'>).note.id).toBe('dummy-renote-1');
 		});
 
 		test('mention', async () => {
@@ -149,7 +149,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('mention');
-			expect((calls[2] as any).id).toBe('dummy-mention-1');
+			expect((calls[2] as UserWebhookPayload<'mention'>).note.id).toBe('dummy-mention-1');
 		});
 
 		test('follow', async () => {
@@ -158,7 +158,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('follow');
-			expect((calls[2] as any).id).toBe('dummy-user-1');
+			expect((calls[2] as UserWebhookPayload<'follow'>).user.id).toBe('dummy-user-1');
 		});
 
 		test('followed', async () => {
@@ -167,7 +167,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('followed');
-			expect((calls[2] as any).id).toBe('dummy-user-2');
+			expect((calls[2] as UserWebhookPayload<'followed'>).user.id).toBe('dummy-user-2');
 		});
 
 		test('unfollow', async () => {
@@ -176,7 +176,7 @@ describe('WebhookTestService', () => {
 			const calls = queueService.userWebhookDeliver.mock.calls[0];
 			expect((calls[0] as any).id).toBe('dummy-webhook');
 			expect(calls[1]).toBe('unfollow');
-			expect((calls[2] as any).id).toBe('dummy-user-3');
+			expect((calls[2] as UserWebhookPayload<'unfollow'>).user.id).toBe('dummy-user-3');
 		});
 
 		describe('NoSuchWebhookError', () => {
diff --git a/packages/frontend/src/pages/settings/webhook.edit.vue b/packages/frontend/src/pages/settings/webhook.edit.vue
index 40d23e36c5..22b008fb61 100644
--- a/packages/frontend/src/pages/settings/webhook.edit.vue
+++ b/packages/frontend/src/pages/settings/webhook.edit.vue
@@ -44,7 +44,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 					<MkButton transparent :class="$style.testButton" :disabled="!(active && event_renote)" @click="test('renote')"><i class="ti ti-send"></i></MkButton>
 				</div>
 				<div :class="$style.switchBox">
-					<MkSwitch v-model="event_reaction">{{ i18n.ts._webhookSettings._events.reaction }}</MkSwitch>
+					<MkSwitch v-model="event_reaction" :disabled="true">{{ i18n.ts._webhookSettings._events.reaction }}</MkSwitch>
 					<MkButton transparent :class="$style.testButton" :disabled="!(active && event_reaction)" @click="test('reaction')"><i class="ti ti-send"></i></MkButton>
 				</div>
 				<div :class="$style.switchBox">
diff --git a/packages/frontend/src/pages/settings/webhook.new.vue b/packages/frontend/src/pages/settings/webhook.new.vue
index d62357caaf..727c4df2d6 100644
--- a/packages/frontend/src/pages/settings/webhook.new.vue
+++ b/packages/frontend/src/pages/settings/webhook.new.vue
@@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 			<MkSwitch v-model="event_note">{{ i18n.ts._webhookSettings._events.note }}</MkSwitch>
 			<MkSwitch v-model="event_reply">{{ i18n.ts._webhookSettings._events.reply }}</MkSwitch>
 			<MkSwitch v-model="event_renote">{{ i18n.ts._webhookSettings._events.renote }}</MkSwitch>
-			<MkSwitch v-model="event_reaction">{{ i18n.ts._webhookSettings._events.reaction }}</MkSwitch>
+			<MkSwitch v-model="event_reaction" :disabled="true">{{ i18n.ts._webhookSettings._events.reaction }}</MkSwitch>
 			<MkSwitch v-model="event_mention">{{ i18n.ts._webhookSettings._events.mention }}</MkSwitch>
 		</div>
 	</FormSection>

From 2305788ed9cdc0c61dfeef9249f93f760a9d5f77 Mon Sep 17 00:00:00 2001
From: shimmar <78616491+shimmar@users.noreply.github.com>
Date: Wed, 13 Nov 2024 11:19:54 +0900
Subject: [PATCH 059/125] =?UTF-8?q?Enhance(frontend):=20=E3=83=8E=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E8=A9=B3=E7=B4=B0=E7=94=BB=E9=9D=A2=E3=81=AB=E3=83=AD?=
 =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=81=AE=E3=83=90=E3=83=83=E3=82=B8=E3=82=92?=
 =?UTF-8?q?=E8=A1=A8=E7=A4=BA=20(#14946)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(frontend): ノートの詳細画面にロールのバッジを表示(#14058)

* Update CHANGELOG.md
---
 CHANGELOG.md                                  |  1 +
 .../src/components/MkNoteDetailed.vue         | 27 ++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c92b8c06a1..7c07d86580 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@
 - Enhance: Self-XSS防止用の警告を追加
 - Enhance: カタルーニャ語 (ca-ES) に対応
 - Enhance: 個別お知らせページではMetaタグを出力するように
+- Enhance: ノート詳細画面にロールのバッジを表示
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index e0473dce5e..4a350388c2 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -62,7 +62,14 @@ SPDX-License-Identifier: AGPL-3.0-only
 						<span v-if="appearNote.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span>
 					</div>
 				</div>
-				<div :class="$style.noteHeaderUsername"><MkAcct :user="appearNote.user"/></div>
+				<div :class="$style.noteHeaderUsernameAndBadgeRoles">
+					<div :class="$style.noteHeaderUsername">
+						<MkAcct :user="appearNote.user"/>
+					</div>
+					<div v-if="appearNote.user.badgeRoles" :class="$style.noteHeaderBadgeRoles">
+						<img v-for="(role, i) in appearNote.user.badgeRoles" :key="i" v-tooltip="role.name" :class="$style.noteHeaderBadgeRole" :src="role.iconUrl!"/>
+					</div>
+				</div>
 				<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
 			</div>
 		</header>
@@ -679,12 +686,30 @@ function loadConversation() {
 	float: right;
 }
 
+.noteHeaderUsernameAndBadgeRoles {
+	display: flex;
+}
+
 .noteHeaderUsername {
 	margin-bottom: 2px;
+	margin-right: 0.5em;
 	line-height: 1.3;
 	word-wrap: anywhere;
 }
 
+.noteHeaderBadgeRoles {
+	margin: 0 .5em 0 0;
+}
+
+.noteHeaderBadgeRole {
+	height: 1.3em;
+	vertical-align: -20%;
+
+	& + .noteHeaderBadgeRole {
+		margin-left: 0.2em;
+	}
+}
+
 .noteContent {
 	container-type: inline-size;
 	overflow-wrap: break-word;

From 4d541015109b0b046595634f81e4e54754d4a288 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Wed, 13 Nov 2024 19:43:36 +0900
Subject: [PATCH 060/125] update node to 22.11.0 (#14869)

* wip

* Update CHANGELOG.md

* Update CHANGELOG.md
---
 .devcontainer/devcontainer.json          | 2 +-
 .github/workflows/get-api-diff.yml       | 2 +-
 .github/workflows/on-release-created.yml | 2 +-
 .github/workflows/test-backend.yml       | 4 ++--
 .github/workflows/test-federation.yml    | 2 +-
 .github/workflows/test-frontend.yml      | 4 ++--
 .github/workflows/test-misskey-js.yml    | 2 +-
 .github/workflows/test-production.yml    | 2 +-
 .github/workflows/validate-api-json.yml  | 2 +-
 .node-version                            | 2 +-
 CHANGELOG.md                             | 4 ++++
 Dockerfile                               | 2 +-
 12 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index fbf959d449..713c2e5fdd 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -5,7 +5,7 @@
 	"workspaceFolder": "/workspace",
 	"features": {
 		"ghcr.io/devcontainers/features/node:1": {
-			"version": "20.16.0"
+			"version": "22.11.0"
 		},
 		"ghcr.io/devcontainers-contrib/features/corepack:1": {}
 	},
diff --git a/.github/workflows/get-api-diff.yml b/.github/workflows/get-api-diff.yml
index 1bcaa0d9c4..972619ec60 100644
--- a/.github/workflows/get-api-diff.yml
+++ b/.github/workflows/get-api-diff.yml
@@ -17,7 +17,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
         api-json-name: [api-base.json, api-head.json]
         include:
           - api-json-name: api-base.json
diff --git a/.github/workflows/on-release-created.yml b/.github/workflows/on-release-created.yml
index ffaf7bc038..6258fa693a 100644
--- a/.github/workflows/on-release-created.yml
+++ b/.github/workflows/on-release-created.yml
@@ -17,7 +17,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
 
     steps:
       - uses: actions/checkout@v4.1.1
diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml
index d95d6676f9..cedcf16ecd 100644
--- a/.github/workflows/test-backend.yml
+++ b/.github/workflows/test-backend.yml
@@ -22,7 +22,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
 
     services:
       postgres:
@@ -71,7 +71,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
 
     services:
       postgres:
diff --git a/.github/workflows/test-federation.yml b/.github/workflows/test-federation.yml
index 183ddb6f34..e89cdcb091 100644
--- a/.github/workflows/test-federation.yml
+++ b/.github/workflows/test-federation.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
     steps:
       - uses: actions/checkout@v4
         with:
diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml
index c68e1a8ef1..eca596c7c7 100644
--- a/.github/workflows/test-frontend.yml
+++ b/.github/workflows/test-frontend.yml
@@ -26,7 +26,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
 
     steps:
     - uses: actions/checkout@v4.1.1
@@ -61,7 +61,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
         browser: [chrome]
 
     services:
diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml
index 63e81f8c92..054c10bf61 100644
--- a/.github/workflows/test-misskey-js.yml
+++ b/.github/workflows/test-misskey-js.yml
@@ -21,7 +21,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
         # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
 
     steps:
diff --git a/.github/workflows/test-production.yml b/.github/workflows/test-production.yml
index 0abc09c5a6..11a95ca82f 100644
--- a/.github/workflows/test-production.yml
+++ b/.github/workflows/test-production.yml
@@ -16,7 +16,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
 
     steps:
     - uses: actions/checkout@v4.1.1
diff --git a/.github/workflows/validate-api-json.yml b/.github/workflows/validate-api-json.yml
index f809af1063..835b2a9a24 100644
--- a/.github/workflows/validate-api-json.yml
+++ b/.github/workflows/validate-api-json.yml
@@ -18,7 +18,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [20.16.0]
+        node-version: [22.11.0]
 
     steps:
     - uses: actions/checkout@v4.1.1
diff --git a/.node-version b/.node-version
index 8ce7030825..7af24b7ddb 100644
--- a/.node-version
+++ b/.node-version
@@ -1 +1 @@
-20.16.0
+22.11.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c07d86580..e07cdc00d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 ## 2024.11.0
 
+### Note
+- DockerのNode.jsが22.11.0に更新されました
+
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように
 - Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
@@ -31,6 +34,7 @@
 - Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
 
 ### Server
+- Enhance: DockerのNode.jsを22.11.0に更新
 - Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように  
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
diff --git a/Dockerfile b/Dockerfile
index e21b2a31fc..ee765abe7c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
 # syntax = docker/dockerfile:1.4
 
-ARG NODE_VERSION=20.16.0-bullseye
+ARG NODE_VERSION=22.11.0-bullseye
 
 # build assets & compile TypeScript
 

From 7f8c8f62b1fab2b7f7ededeb7cb2dbc387895d17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 15 Nov 2024 09:33:09 +0900
Subject: [PATCH 061/125] =?UTF-8?q?fix(frontend):=20=E3=82=B9=E3=83=9E?=
 =?UTF-8?q?=E3=83=9B=E3=81=A7=E8=A1=A8=E7=A4=BA=E3=81=97=E3=81=9F=E6=99=82?=
 =?UTF-8?q?=E3=81=ABipv6=E3=81=A0=E3=81=A8=E3=81=AF=E3=81=BF=E5=87=BA?=
 =?UTF-8?q?=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E3=81=AE=E3=82=92=E4=BF=AE?=
 =?UTF-8?q?=E6=AD=A3=20(#14960)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): スマホで表示した時にipv6だとはみ出てしまうのを修正 (MisskeyIO#815)

(cherry picked from commit aec01dd4adda8e975da523c5bea329120e689569)

* Update Changelog

---------

Co-authored-by: sleep-moe <yukikum57@gmail.com>
---
 CHANGELOG.md                               | 2 ++
 packages/frontend/src/pages/admin-user.vue | 1 +
 2 files changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e07cdc00d7..f51fcb9d0a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,8 @@
 = Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正  
   (Cherry-picked from https://github.com/taiyme/misskey/pull/305)
 - Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
+- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正  
+	(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/815)
 
 ### Server
 - Enhance: DockerのNode.jsを22.11.0に更新
diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue
index 948e7a3cce..30d7e38638 100644
--- a/packages/frontend/src/pages/admin-user.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -627,6 +627,7 @@ definePageMetadata(() => ({
 <style lang="scss" module>
 .ip {
 	display: flex;
+	word-break: break-all;
 
 	> :global(.date) {
 		opacity: 0.7;

From e26e24b61050c5c5ad2f6f4c4d63f3abeb33bfb0 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 15 Nov 2024 17:22:00 +0900
Subject: [PATCH 062/125] update deps (#14950)

* update deps

* wip

* Revert "wip"

This reverts commit 393de249fe248ae181221266e0b7828a3ac53152.

* wip

* wip

* wip

* wip
---
 CHANGELOG.md                               |    1 +
 package.json                               |   18 +-
 packages/backend/package.json              |   66 +-
 packages/frontend-embed/package.json       |   32 +-
 packages/frontend-shared/package.json      |   10 +-
 packages/frontend/package.json             |   78 +-
 packages/misskey-bubble-game/package.json  |   14 +-
 packages/misskey-js/generator/package.json |    6 +-
 packages/misskey-js/package.json           |   16 +-
 packages/misskey-reversi/package.json      |   12 +-
 packages/sw/package.json                   |    4 +-
 pnpm-lock.yaml                             | 5410 ++++++++------------
 scripts/changelog-checker/package.json     |   10 +-
 13 files changed, 2295 insertions(+), 3382 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f51fcb9d0a..fcbfed5900 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 ## 2024.11.0
 
 ### Note
+- Node.js 20.xは非推奨になりました。Node.js 22.x (LTS)の利用を推奨します。
 - DockerのNode.jsが22.11.0に更新されました
 
 ### General
diff --git a/package.json b/package.json
index 6a44eb04f3..3b29007b68 100644
--- a/package.json
+++ b/package.json
@@ -52,26 +52,26 @@
 	},
 	"dependencies": {
 		"cssnano": "6.1.2",
-		"execa": "8.0.1",
+		"execa": "9.5.1",
 		"fast-glob": "3.3.2",
 		"ignore-walk": "6.0.5",
 		"js-yaml": "4.1.0",
-		"postcss": "8.4.47",
+		"postcss": "8.4.49",
 		"tar": "6.2.1",
-		"terser": "5.33.0",
-		"typescript": "5.6.2",
-		"esbuild": "0.23.1",
+		"terser": "5.36.0",
+		"typescript": "5.6.3",
+		"esbuild": "0.24.0",
 		"glob": "11.0.0"
 	},
 	"devDependencies": {
 		"@misskey-dev/eslint-plugin": "2.0.3",
-		"@types/node": "20.14.12",
+		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
 		"cross-env": "7.0.3",
-		"cypress": "13.14.2",
-		"eslint": "9.8.0",
-		"globals": "15.9.0",
+		"cypress": "13.15.2",
+		"eslint": "9.14.0",
+		"globals": "15.12.0",
 		"ncp": "2.0.0",
 		"start-server-and-test": "2.0.8"
 	},
diff --git a/packages/backend/package.json b/packages/backend/package.json
index 0dd738a1e6..5055f50235 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -69,32 +69,32 @@
 	"dependencies": {
 		"@aws-sdk/client-s3": "3.620.0",
 		"@aws-sdk/lib-storage": "3.620.0",
-		"@bull-board/api": "6.0.0",
-		"@bull-board/fastify": "6.0.0",
-		"@bull-board/ui": "6.0.0",
+		"@bull-board/api": "6.5.0",
+		"@bull-board/fastify": "6.5.0",
+		"@bull-board/ui": "6.5.0",
 		"@discordapp/twemoji": "15.1.0",
 		"@fastify/accepts": "5.0.1",
-		"@fastify/cookie": "10.0.1",
+		"@fastify/cookie": "11.0.1",
 		"@fastify/cors": "10.0.1",
 		"@fastify/express": "4.0.1",
-		"@fastify/http-proxy": "10.0.0",
+		"@fastify/http-proxy": "10.0.1",
 		"@fastify/multipart": "9.0.1",
-		"@fastify/static": "8.0.1",
+		"@fastify/static": "8.0.2",
 		"@fastify/view": "10.0.1",
 		"@misskey-dev/sharp-read-bmp": "1.2.0",
 		"@misskey-dev/summaly": "5.1.0",
 		"@napi-rs/canvas": "0.1.56",
-		"@nestjs/common": "10.4.4",
-		"@nestjs/core": "10.4.4",
-		"@nestjs/testing": "10.4.4",
+		"@nestjs/common": "10.4.7",
+		"@nestjs/core": "10.4.7",
+		"@nestjs/testing": "10.4.7",
 		"@peertube/http-signature": "1.7.0",
-		"@sentry/node": "8.20.0",
-		"@sentry/profiling-node": "8.20.0",
+		"@sentry/node": "8.38.0",
+		"@sentry/profiling-node": "8.38.0",
 		"@simplewebauthn/server": "10.0.1",
 		"@sinonjs/fake-timers": "11.2.2",
 		"@smithy/node-http-handler": "2.5.0",
 		"@swc/cli": "0.3.12",
-		"@swc/core": "1.6.6",
+		"@swc/core": "1.9.2",
 		"@twemoji/parser": "15.1.1",
 		"accepts": "1.3.8",
 		"ajv": "8.17.1",
@@ -103,7 +103,7 @@
 		"bcryptjs": "2.4.3",
 		"blurhash": "2.0.5",
 		"body-parser": "1.20.3",
-		"bullmq": "5.15.0",
+		"bullmq": "5.26.1",
 		"cacheable-lookup": "7.0.0",
 		"cbor": "9.0.2",
 		"chalk": "5.3.0",
@@ -117,11 +117,11 @@
 		"fastify": "5.0.0",
 		"fastify-raw-body": "5.0.0",
 		"feed": "4.2.2",
-		"file-type": "19.5.0",
+		"file-type": "19.6.0",
 		"fluent-ffmpeg": "2.1.3",
-		"form-data": "4.0.0",
-		"got": "14.4.2",
-		"happy-dom": "15.7.4",
+		"form-data": "4.0.1",
+		"got": "14.4.4",
+		"happy-dom": "15.11.4",
 		"hpagent": "1.2.0",
 		"htmlescape": "1.1.1",
 		"http-link-header": "1.1.3",
@@ -134,7 +134,7 @@
 		"json5": "2.2.3",
 		"jsonld": "8.3.2",
 		"jsrsasign": "11.1.0",
-		"meilisearch": "0.42.0",
+		"meilisearch": "0.45.0",
 		"juice": "11.0.0",
 		"mfm-js": "0.24.0",
 		"microformats-parser": "2.0.2",
@@ -142,18 +142,18 @@
 		"misskey-js": "workspace:*",
 		"misskey-reversi": "workspace:*",
 		"ms": "3.0.0-canary.1",
-		"nanoid": "5.0.7",
+		"nanoid": "5.0.8",
 		"nested-property": "4.0.0",
 		"node-fetch": "3.3.2",
-		"nodemailer": "6.9.15",
+		"nodemailer": "6.9.16",
 		"nsfwjs": "2.4.2",
 		"oauth": "0.10.0",
 		"oauth2orize": "1.12.0",
 		"oauth2orize-pkce": "0.1.2",
 		"os-utils": "0.0.14",
 		"otpauth": "9.3.4",
-		"parse5": "7.1.2",
-		"pg": "8.13.0",
+		"parse5": "7.2.1",
+		"pg": "8.13.1",
 		"pkce-challenge": "4.1.0",
 		"probe-image-size": "7.2.3",
 		"promise-limit": "2.7.0",
@@ -180,7 +180,7 @@
 		"tsc-alias": "1.8.10",
 		"tsconfig-paths": "4.2.0",
 		"typeorm": "0.3.20",
-		"typescript": "5.6.2",
+		"typescript": "5.6.3",
 		"ulid": "2.3.0",
 		"vary": "1.1.2",
 		"web-push": "3.6.7",
@@ -189,28 +189,28 @@
 	},
 	"devDependencies": {
 		"@jest/globals": "29.7.0",
-		"@nestjs/platform-express": "10.4.4",
+		"@nestjs/platform-express": "10.4.7",
 		"@simplewebauthn/types": "10.0.0",
-		"@swc/jest": "0.2.36",
+		"@swc/jest": "0.2.37",
 		"@types/accepts": "1.3.7",
-		"@types/archiver": "6.0.2",
+		"@types/archiver": "6.0.3",
 		"@types/bcryptjs": "2.4.6",
 		"@types/body-parser": "1.19.5",
 		"@types/color-convert": "2.0.4",
 		"@types/content-disposition": "0.5.8",
-		"@types/fluent-ffmpeg": "2.1.26",
+		"@types/fluent-ffmpeg": "2.1.27",
 		"@types/htmlescape": "1.1.3",
 		"@types/http-link-header": "1.0.7",
-		"@types/jest": "29.5.13",
+		"@types/jest": "29.5.14",
 		"@types/js-yaml": "4.0.9",
 		"@types/jsdom": "21.1.7",
 		"@types/jsonld": "1.5.15",
 		"@types/jsrsasign": "10.5.14",
 		"@types/mime-types": "2.1.4",
 		"@types/ms": "0.7.34",
-		"@types/node": "20.14.12",
+		"@types/node": "22.9.0",
 		"@types/nodemailer": "6.4.16",
-		"@types/oauth": "0.9.5",
+		"@types/oauth": "0.9.6",
 		"@types/oauth2orize": "1.11.5",
 		"@types/oauth2orize-pkce": "0.1.2",
 		"@types/pg": "8.11.10",
@@ -227,14 +227,14 @@
 		"@types/tinycolor2": "1.4.6",
 		"@types/tmp": "0.2.6",
 		"@types/vary": "1.1.3",
-		"@types/web-push": "3.6.3",
-		"@types/ws": "8.5.12",
+		"@types/web-push": "3.6.4",
+		"@types/ws": "8.5.13",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
 		"aws-sdk-client-mock": "4.0.1",
 		"cross-env": "7.0.3",
 		"eslint-plugin-import": "2.30.0",
-		"execa": "9.4.0",
+		"execa": "9.5.1",
 		"fkill": "9.0.0",
 		"jest": "29.7.0",
 		"jest-mock": "29.7.0",
diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json
index cb62191c3b..59b744e43a 100644
--- a/packages/frontend-embed/package.json
+++ b/packages/frontend-embed/package.json
@@ -14,11 +14,11 @@
 		"@discordapp/twemoji": "15.1.0",
 		"@rollup/plugin-json": "6.1.0",
 		"@rollup/plugin-replace": "5.0.7",
-		"@rollup/pluginutils": "5.1.2",
+		"@rollup/pluginutils": "5.1.3",
 		"@tabler/icons-webfont": "3.3.0",
 		"@twemoji/parser": "15.1.1",
-		"@vitejs/plugin-vue": "5.1.4",
-		"@vue/compiler-sfc": "3.5.11",
+		"@vitejs/plugin-vue": "5.2.0",
+		"@vue/compiler-sfc": "3.5.12",
 		"astring": "1.9.0",
 		"buraha": "0.0.1",
 		"estree-walker": "3.0.3",
@@ -26,47 +26,47 @@
 		"misskey-js": "workspace:*",
 		"frontend-shared": "workspace:*",
 		"punycode": "2.3.1",
-		"rollup": "4.22.5",
+		"rollup": "4.26.0",
 		"sass": "1.79.4",
-		"shiki": "1.21.0",
+		"shiki": "1.22.2",
 		"tinycolor2": "1.6.0",
 		"tsc-alias": "1.8.10",
 		"tsconfig-paths": "4.2.0",
-		"typescript": "5.6.2",
+		"typescript": "5.6.3",
 		"uuid": "10.0.0",
 		"json5": "2.2.3",
-		"vite": "5.4.8",
-		"vue": "3.5.11"
+		"vite": "5.4.11",
+		"vue": "3.5.12"
 	},
 	"devDependencies": {
 		"@misskey-dev/summaly": "5.1.0",
 		"@testing-library/vue": "8.1.0",
 		"@types/estree": "1.0.6",
 		"@types/micromatch": "4.0.9",
-		"@types/node": "20.14.12",
+		"@types/node": "22.9.0",
 		"@types/punycode": "2.1.4",
 		"@types/tinycolor2": "1.4.6",
 		"@types/uuid": "10.0.0",
-		"@types/ws": "8.5.12",
+		"@types/ws": "8.5.13",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
 		"@vitest/coverage-v8": "1.6.0",
-		"@vue/runtime-core": "3.5.11",
-		"acorn": "8.12.1",
+		"@vue/runtime-core": "3.5.12",
+		"acorn": "8.14.0",
 		"cross-env": "7.0.3",
 		"eslint-plugin-import": "2.31.0",
-		"eslint-plugin-vue": "9.28.0",
+		"eslint-plugin-vue": "9.31.0",
 		"fast-glob": "3.3.2",
 		"happy-dom": "10.0.3",
 		"intersection-observer": "0.12.2",
 		"micromatch": "4.0.8",
-		"msw": "2.3.4",
+		"msw": "2.6.4",
 		"nodemon": "3.1.7",
 		"prettier": "3.3.3",
 		"start-server-and-test": "2.0.8",
 		"vite-plugin-turbosnap": "1.0.3",
-		"vue-component-type-helpers": "2.1.6",
+		"vue-component-type-helpers": "2.1.10",
 		"vue-eslint-parser": "9.4.3",
-		"vue-tsc": "2.1.6"
+		"vue-tsc": "2.1.10"
 	}
 }
diff --git a/packages/frontend-shared/package.json b/packages/frontend-shared/package.json
index 9981d10dd2..f8770f33f2 100644
--- a/packages/frontend-shared/package.json
+++ b/packages/frontend-shared/package.json
@@ -21,12 +21,12 @@
 		"lint": "pnpm typecheck && pnpm eslint"
 	},
 	"devDependencies": {
-		"@types/node": "20.14.12",
+		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
-		"esbuild": "0.23.0",
-		"eslint-plugin-vue": "9.27.0",
-		"typescript": "5.5.4",
+		"esbuild": "0.24.0",
+		"eslint-plugin-vue": "9.31.0",
+		"typescript": "5.6.3",
 		"vue-eslint-parser": "9.4.3"
 	},
 	"files": [
@@ -34,6 +34,6 @@
 	],
 	"dependencies": {
 		"misskey-js": "workspace:*",
-		"vue": "3.4.37"
+		"vue": "3.5.12"
 	}
 }
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index 3226a554a9..4f132ab500 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -23,23 +23,23 @@
 		"@misskey-dev/browser-image-resizer": "2024.1.0",
 		"@rollup/plugin-json": "6.1.0",
 		"@rollup/plugin-replace": "5.0.7",
-		"@rollup/pluginutils": "5.1.2",
+		"@rollup/pluginutils": "5.1.3",
 		"@syuilo/aiscript": "0.19.0",
 		"@tabler/icons-webfont": "3.3.0",
 		"@twemoji/parser": "15.1.1",
-		"@vitejs/plugin-vue": "5.1.4",
-		"@vue/compiler-sfc": "3.5.11",
+		"@vitejs/plugin-vue": "5.2.0",
+		"@vue/compiler-sfc": "3.5.12",
 		"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.11",
 		"astring": "1.9.0",
 		"broadcast-channel": "7.0.0",
 		"buraha": "0.0.1",
 		"canvas-confetti": "1.9.3",
-		"chart.js": "4.4.4",
+		"chart.js": "4.4.6",
 		"chartjs-adapter-date-fns": "3.0.0",
 		"chartjs-chart-matrix": "2.0.1",
 		"chartjs-plugin-gradient": "0.6.1",
 		"chartjs-plugin-zoom": "2.0.1",
-		"chromatic": "11.11.0",
+		"chromatic": "11.18.1",
 		"compare-versions": "6.1.1",
 		"cropperjs": "2.0.0-rc.2",
 		"date-fns": "2.30.0",
@@ -57,10 +57,10 @@
 		"misskey-reversi": "workspace:*",
 		"photoswipe": "5.4.4",
 		"punycode": "2.3.1",
-		"rollup": "4.22.5",
+		"rollup": "4.26.0",
 		"sanitize-html": "2.13.1",
 		"sass": "1.79.3",
-		"shiki": "1.21.0",
+		"shiki": "1.22.2",
 		"strict-event-emitter-types": "2.0.0",
 		"textarea-caret": "3.1.0",
 		"three": "0.169.0",
@@ -68,74 +68,74 @@
 		"tinycolor2": "1.6.0",
 		"tsc-alias": "1.8.10",
 		"tsconfig-paths": "4.2.0",
-		"typescript": "5.6.2",
+		"typescript": "5.6.3",
 		"uuid": "10.0.0",
 		"v-code-diff": "1.13.1",
-		"vite": "5.4.8",
-		"vue": "3.5.11",
+		"vite": "5.4.11",
+		"vue": "3.5.12",
 		"vuedraggable": "next"
 	},
 	"devDependencies": {
 		"@misskey-dev/summaly": "5.1.0",
-		"@storybook/addon-actions": "8.3.4",
-		"@storybook/addon-essentials": "8.3.4",
-		"@storybook/addon-interactions": "8.3.4",
-		"@storybook/addon-links": "8.3.4",
-		"@storybook/addon-mdx-gfm": "8.3.4",
-		"@storybook/addon-storysource": "8.3.4",
-		"@storybook/blocks": "8.3.4",
-		"@storybook/components": "8.3.4",
-		"@storybook/core-events": "8.3.4",
-		"@storybook/manager-api": "8.3.4",
-		"@storybook/preview-api": "8.3.4",
-		"@storybook/react": "8.3.4",
-		"@storybook/react-vite": "8.3.4",
-		"@storybook/test": "8.3.4",
-		"@storybook/theming": "8.3.4",
-		"@storybook/types": "8.3.4",
-		"@storybook/vue3": "8.3.4",
-		"@storybook/vue3-vite": "8.3.4",
+		"@storybook/addon-actions": "8.4.4",
+		"@storybook/addon-essentials": "8.4.4",
+		"@storybook/addon-interactions": "8.4.4",
+		"@storybook/addon-links": "8.4.4",
+		"@storybook/addon-mdx-gfm": "8.4.4",
+		"@storybook/addon-storysource": "8.4.4",
+		"@storybook/blocks": "8.4.4",
+		"@storybook/components": "8.4.4",
+		"@storybook/core-events": "8.4.4",
+		"@storybook/manager-api": "8.4.4",
+		"@storybook/preview-api": "8.4.4",
+		"@storybook/react": "8.4.4",
+		"@storybook/react-vite": "8.4.4",
+		"@storybook/test": "8.4.4",
+		"@storybook/theming": "8.4.4",
+		"@storybook/types": "8.4.4",
+		"@storybook/vue3": "8.4.4",
+		"@storybook/vue3-vite": "8.4.4",
 		"@testing-library/vue": "8.1.0",
 		"@types/canvas-confetti": "^1.6.4",
 		"@types/estree": "1.0.6",
 		"@types/matter-js": "0.19.7",
 		"@types/micromatch": "4.0.9",
-		"@types/node": "20.14.12",
+		"@types/node": "22.9.0",
 		"@types/punycode": "2.1.4",
 		"@types/sanitize-html": "2.13.0",
 		"@types/seedrandom": "3.0.8",
 		"@types/throttle-debounce": "5.0.2",
 		"@types/tinycolor2": "1.4.6",
 		"@types/uuid": "10.0.0",
-		"@types/ws": "8.5.12",
+		"@types/ws": "8.5.13",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
 		"@vitest/coverage-v8": "1.6.0",
-		"@vue/runtime-core": "3.5.11",
-		"acorn": "8.12.1",
+		"@vue/runtime-core": "3.5.12",
+		"acorn": "8.14.0",
 		"cross-env": "7.0.3",
-		"cypress": "13.15.0",
+		"cypress": "13.15.2",
 		"eslint-plugin-import": "2.31.0",
-		"eslint-plugin-vue": "9.28.0",
+		"eslint-plugin-vue": "9.31.0",
 		"fast-glob": "3.3.2",
 		"happy-dom": "10.0.3",
 		"intersection-observer": "0.12.2",
 		"micromatch": "4.0.8",
-		"msw": "2.4.9",
-		"msw-storybook-addon": "2.0.3",
+		"msw": "2.6.4",
+		"msw-storybook-addon": "2.0.4",
 		"nodemon": "3.1.7",
 		"prettier": "3.3.3",
 		"react": "18.3.1",
 		"react-dom": "18.3.1",
 		"seedrandom": "3.0.5",
 		"start-server-and-test": "2.0.8",
-		"storybook": "8.3.4",
+		"storybook": "8.4.4",
 		"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
 		"vite-plugin-turbosnap": "1.0.3",
 		"vitest": "1.6.0",
 		"vitest-fetch-mock": "0.2.2",
-		"vue-component-type-helpers": "2.1.6",
+		"vue-component-type-helpers": "2.1.10",
 		"vue-eslint-parser": "9.4.3",
-		"vue-tsc": "2.1.6"
+		"vue-tsc": "2.1.10"
 	}
 }
diff --git a/packages/misskey-bubble-game/package.json b/packages/misskey-bubble-game/package.json
index 528eb00b74..08d5062641 100644
--- a/packages/misskey-bubble-game/package.json
+++ b/packages/misskey-bubble-game/package.json
@@ -22,16 +22,16 @@
 		"lint": "pnpm typecheck && pnpm eslint"
 	},
 	"devDependencies": {
-		"@types/matter-js": "0.19.6",
+		"@types/matter-js": "0.19.7",
 		"@types/seedrandom": "3.0.8",
-		"@types/node": "20.11.5",
+		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
-		"nodemon": "3.0.2",
-		"execa": "8.0.1",
-		"typescript": "5.3.3",
-		"esbuild": "0.19.11",
-		"glob": "10.3.10"
+		"nodemon": "3.1.7",
+		"execa": "9.5.1",
+		"typescript": "5.6.3",
+		"esbuild": "0.24.0",
+		"glob": "11.0.0"
 	},
 	"files": [
 		"built"
diff --git a/packages/misskey-js/generator/package.json b/packages/misskey-js/generator/package.json
index 212c92fba5..b796bf8775 100644
--- a/packages/misskey-js/generator/package.json
+++ b/packages/misskey-js/generator/package.json
@@ -8,14 +8,14 @@
 	},
 	"devDependencies": {
 		"@readme/openapi-parser": "2.6.0",
-		"@types/node": "20.9.1",
+		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
 		"openapi-types": "12.1.3",
 		"openapi-typescript": "6.7.3",
-		"ts-case-convert": "2.0.7",
+		"ts-case-convert": "2.1.0",
 		"tsx": "4.4.0",
-		"typescript": "5.6.2"
+		"typescript": "5.6.3"
 	},
 	"files": [
 		"built"
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 19615cfee5..6fff5ce38f 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -35,10 +35,10 @@
 		"directory": "packages/misskey-js"
 	},
 	"devDependencies": {
-		"@microsoft/api-extractor": "7.47.9",
-		"@swc/jest": "0.2.36",
-		"@types/jest": "29.5.13",
-		"@types/node": "20.14.12",
+		"@microsoft/api-extractor": "7.47.11",
+		"@swc/jest": "0.2.37",
+		"@types/jest": "29.5.14",
+		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.17.0",
 		"@typescript-eslint/parser": "7.17.0",
 		"jest": "29.7.0",
@@ -47,17 +47,17 @@
 		"mock-socket": "9.3.1",
 		"ncp": "2.0.0",
 		"nodemon": "3.1.7",
-		"execa": "9.4.0",
+		"execa": "9.5.1",
 		"tsd": "0.31.2",
-		"typescript": "5.6.2",
-		"esbuild": "0.23.1",
+		"typescript": "5.6.3",
+		"esbuild": "0.24.0",
 		"glob": "11.0.0"
 	},
 	"files": [
 		"built"
 	],
 	"dependencies": {
-		"@simplewebauthn/types": "10.0.0",
+		"@simplewebauthn/types": "11.0.0",
 		"eventemitter3": "5.0.1",
 		"reconnecting-websocket": "4.4.0"
 	}
diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json
index c6db6e6221..1cd6b0de2e 100644
--- a/packages/misskey-reversi/package.json
+++ b/packages/misskey-reversi/package.json
@@ -22,14 +22,14 @@
 		"lint": "pnpm typecheck && pnpm eslint"
 	},
 	"devDependencies": {
-		"@types/node": "20.11.5",
+		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
-		"execa": "8.0.1",
-		"nodemon": "3.0.2",
-		"typescript": "5.3.3",
-		"esbuild": "0.19.11",
-		"glob": "10.3.10"
+		"execa": "9.5.1",
+		"nodemon": "3.1.7",
+		"typescript": "5.6.3",
+		"esbuild": "0.24.0",
+		"glob": "11.0.0"
 	},
 	"files": [
 		"built"
diff --git a/packages/sw/package.json b/packages/sw/package.json
index 09e604ff4c..dddd6e8bd7 100644
--- a/packages/sw/package.json
+++ b/packages/sw/package.json
@@ -9,7 +9,7 @@
 		"lint": "pnpm typecheck && pnpm eslint"
 	},
 	"dependencies": {
-		"esbuild": "0.23.1",
+		"esbuild": "0.24.0",
 		"idb-keyval": "6.2.1",
 		"misskey-js": "workspace:*"
 	},
@@ -18,7 +18,7 @@
 		"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
 		"eslint-plugin-import": "2.30.0",
 		"nodemon": "3.1.7",
-		"typescript": "5.6.2"
+		"typescript": "5.6.3"
 	},
 	"type": "module"
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1312e8c886..d5fe19ed64 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,13 +14,13 @@ importers:
     dependencies:
       cssnano:
         specifier: 6.1.2
-        version: 6.1.2(postcss@8.4.47)
+        version: 6.1.2(postcss@8.4.49)
       esbuild:
-        specifier: 0.23.1
-        version: 0.23.1
+        specifier: 0.24.0
+        version: 0.24.0
       execa:
-        specifier: 8.0.1
-        version: 8.0.1
+        specifier: 9.5.1
+        version: 9.5.1
       fast-glob:
         specifier: 3.3.2
         version: 3.3.2
@@ -34,17 +34,17 @@ importers:
         specifier: 4.1.0
         version: 4.1.0
       postcss:
-        specifier: 8.4.47
-        version: 8.4.47
+        specifier: 8.4.49
+        version: 8.4.49
       tar:
         specifier: 6.2.1
         version: 6.2.1
       terser:
-        specifier: 5.33.0
-        version: 5.33.0
+        specifier: 5.36.0
+        version: 5.36.0
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
     optionalDependencies:
       '@tensorflow/tfjs-core':
         specifier: 4.4.0
@@ -52,28 +52,28 @@ importers:
     devDependencies:
       '@misskey-dev/eslint-plugin':
         specifier: 2.0.3
-        version: 2.0.3(@eslint/compat@1.1.1)(@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0)(typescript@5.6.2))(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0))(eslint@9.8.0)(globals@15.9.0)
+        version: 2.0.3(@eslint/compat@1.1.1)(@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3))(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0))(eslint@9.14.0)(globals@15.12.0)
       '@types/node':
-        specifier: 20.14.12
-        version: 20.14.12
+        specifier: 22.9.0
+        version: 22.9.0
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0)(typescript@5.6.2)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.8.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       cross-env:
         specifier: 7.0.3
         version: 7.0.3
       cypress:
-        specifier: 13.14.2
-        version: 13.14.2
+        specifier: 13.15.2
+        version: 13.15.2
       eslint:
-        specifier: 9.8.0
-        version: 9.8.0
+        specifier: 9.14.0
+        version: 9.14.0
       globals:
-        specifier: 15.9.0
-        version: 15.9.0
+        specifier: 15.12.0
+        version: 15.12.0
       ncp:
         specifier: 2.0.0
         version: 2.0.0
@@ -90,14 +90,14 @@ importers:
         specifier: 3.620.0
         version: 3.620.0(@aws-sdk/client-s3@3.620.0)
       '@bull-board/api':
-        specifier: 6.0.0
-        version: 6.0.0(@bull-board/ui@6.0.0)
+        specifier: 6.5.0
+        version: 6.5.0(@bull-board/ui@6.5.0)
       '@bull-board/fastify':
-        specifier: 6.0.0
-        version: 6.0.0
+        specifier: 6.5.0
+        version: 6.5.0
       '@bull-board/ui':
-        specifier: 6.0.0
-        version: 6.0.0
+        specifier: 6.5.0
+        version: 6.5.0
       '@discordapp/twemoji':
         specifier: 15.1.0
         version: 15.1.0
@@ -105,8 +105,8 @@ importers:
         specifier: 5.0.1
         version: 5.0.1
       '@fastify/cookie':
-        specifier: 10.0.1
-        version: 10.0.1
+        specifier: 11.0.1
+        version: 11.0.1
       '@fastify/cors':
         specifier: 10.0.1
         version: 10.0.1
@@ -114,14 +114,14 @@ importers:
         specifier: 4.0.1
         version: 4.0.1
       '@fastify/http-proxy':
-        specifier: 10.0.0
-        version: 10.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3)
+        specifier: 10.0.1
+        version: 10.0.1(bufferutil@4.0.7)(utf-8-validate@6.0.3)
       '@fastify/multipart':
         specifier: 9.0.1
         version: 9.0.1
       '@fastify/static':
-        specifier: 8.0.1
-        version: 8.0.1
+        specifier: 8.0.2
+        version: 8.0.2
       '@fastify/view':
         specifier: 10.0.1
         version: 10.0.1
@@ -135,23 +135,23 @@ importers:
         specifier: 0.1.56
         version: 0.1.56
       '@nestjs/common':
-        specifier: 10.4.4
-        version: 10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1)
+        specifier: 10.4.7
+        version: 10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1)
       '@nestjs/core':
-        specifier: 10.4.4
-        version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+        specifier: 10.4.7
+        version: 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)
       '@nestjs/testing':
-        specifier: 10.4.4
-        version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4))
+        specifier: 10.4.7
+        version: 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7))
       '@peertube/http-signature':
         specifier: 1.7.0
         version: 1.7.0
       '@sentry/node':
-        specifier: 8.20.0
-        version: 8.20.0
+        specifier: 8.38.0
+        version: 8.38.0
       '@sentry/profiling-node':
-        specifier: 8.20.0
-        version: 8.20.0
+        specifier: 8.38.0
+        version: 8.38.0
       '@simplewebauthn/server':
         specifier: 10.0.1
         version: 10.0.1(encoding@0.1.13)
@@ -163,10 +163,10 @@ importers:
         version: 2.5.0
       '@swc/cli':
         specifier: 0.3.12
-        version: 0.3.12(@swc/core@1.6.6)(chokidar@3.5.3)
+        version: 0.3.12(@swc/core@1.9.2)(chokidar@3.5.3)
       '@swc/core':
-        specifier: 1.6.6
-        version: 1.6.6
+        specifier: 1.9.2
+        version: 1.9.2
       '@twemoji/parser':
         specifier: 15.1.1
         version: 15.1.1
@@ -192,8 +192,8 @@ importers:
         specifier: 1.20.3
         version: 1.20.3
       bullmq:
-        specifier: 5.15.0
-        version: 5.15.0
+        specifier: 5.26.1
+        version: 5.26.1
       cacheable-lookup:
         specifier: 7.0.0
         version: 7.0.0
@@ -234,20 +234,20 @@ importers:
         specifier: 4.2.2
         version: 4.2.2
       file-type:
-        specifier: 19.5.0
-        version: 19.5.0
+        specifier: 19.6.0
+        version: 19.6.0
       fluent-ffmpeg:
         specifier: 2.1.3
         version: 2.1.3
       form-data:
-        specifier: 4.0.0
-        version: 4.0.0
+        specifier: 4.0.1
+        version: 4.0.1
       got:
-        specifier: 14.4.2
-        version: 14.4.2
+        specifier: 14.4.4
+        version: 14.4.4
       happy-dom:
-        specifier: 15.7.4
-        version: 15.7.4
+        specifier: 15.11.4
+        version: 15.11.4
       hpagent:
         specifier: 1.2.0
         version: 1.2.0
@@ -288,8 +288,8 @@ importers:
         specifier: 11.0.0
         version: 11.0.0
       meilisearch:
-        specifier: 0.42.0
-        version: 0.42.0(encoding@0.1.13)
+        specifier: 0.45.0
+        version: 0.45.0
       mfm-js:
         specifier: 0.24.0
         version: 0.24.0
@@ -309,8 +309,8 @@ importers:
         specifier: 3.0.0-canary.1
         version: 3.0.0-canary.1
       nanoid:
-        specifier: 5.0.7
-        version: 5.0.7
+        specifier: 5.0.8
+        version: 5.0.8
       nested-property:
         specifier: 4.0.0
         version: 4.0.0
@@ -318,8 +318,8 @@ importers:
         specifier: 3.3.2
         version: 3.3.2
       nodemailer:
-        specifier: 6.9.15
-        version: 6.9.15
+        specifier: 6.9.16
+        version: 6.9.16
       nsfwjs:
         specifier: 2.4.2
         version: 2.4.2(@tensorflow/tfjs@4.4.0(encoding@0.1.13)(seedrandom@3.0.5))
@@ -339,11 +339,11 @@ importers:
         specifier: 9.3.4
         version: 9.3.4
       parse5:
-        specifier: 7.1.2
-        version: 7.1.2
+        specifier: 7.2.1
+        version: 7.2.1
       pg:
-        specifier: 8.13.0
-        version: 8.13.0
+        specifier: 8.13.1
+        version: 8.13.1
       pkce-challenge:
         specifier: 4.1.0
         version: 4.1.0
@@ -421,10 +421,10 @@ importers:
         version: 4.2.0
       typeorm:
         specifier: 0.3.20
-        version: 0.3.20(ioredis@5.4.1)(pg@8.13.0)
+        version: 0.3.20(ioredis@5.4.1)(pg@8.13.1)
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
       ulid:
         specifier: 2.3.0
         version: 2.3.0
@@ -533,20 +533,20 @@ importers:
         specifier: 29.7.0
         version: 29.7.0
       '@nestjs/platform-express':
-        specifier: 10.4.4
-        version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4)
+        specifier: 10.4.7
+        version: 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7)
       '@simplewebauthn/types':
         specifier: 10.0.0
         version: 10.0.0
       '@swc/jest':
-        specifier: 0.2.36
-        version: 0.2.36(@swc/core@1.6.6)
+        specifier: 0.2.37
+        version: 0.2.37(@swc/core@1.9.2)
       '@types/accepts':
         specifier: 1.3.7
         version: 1.3.7
       '@types/archiver':
-        specifier: 6.0.2
-        version: 6.0.2
+        specifier: 6.0.3
+        version: 6.0.3
       '@types/bcryptjs':
         specifier: 2.4.6
         version: 2.4.6
@@ -560,8 +560,8 @@ importers:
         specifier: 0.5.8
         version: 0.5.8
       '@types/fluent-ffmpeg':
-        specifier: 2.1.26
-        version: 2.1.26
+        specifier: 2.1.27
+        version: 2.1.27
       '@types/htmlescape':
         specifier: 1.1.3
         version: 1.1.3
@@ -569,8 +569,8 @@ importers:
         specifier: 1.0.7
         version: 1.0.7
       '@types/jest':
-        specifier: 29.5.13
-        version: 29.5.13
+        specifier: 29.5.14
+        version: 29.5.14
       '@types/js-yaml':
         specifier: 4.0.9
         version: 4.0.9
@@ -590,14 +590,14 @@ importers:
         specifier: 0.7.34
         version: 0.7.34
       '@types/node':
-        specifier: 20.14.12
-        version: 20.14.12
+        specifier: 22.9.0
+        version: 22.9.0
       '@types/nodemailer':
         specifier: 6.4.16
         version: 6.4.16
       '@types/oauth':
-        specifier: 0.9.5
-        version: 0.9.5
+        specifier: 0.9.6
+        version: 0.9.6
       '@types/oauth2orize':
         specifier: 1.11.5
         version: 1.11.5
@@ -647,17 +647,17 @@ importers:
         specifier: 1.1.3
         version: 1.1.3
       '@types/web-push':
-        specifier: 3.6.3
-        version: 3.6.3
+        specifier: 3.6.4
+        version: 3.6.4
       '@types/ws':
-        specifier: 8.5.12
-        version: 8.5.12
+        specifier: 8.5.13
+        version: 8.5.13
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       aws-sdk-client-mock:
         specifier: 4.0.1
         version: 4.0.1
@@ -666,16 +666,16 @@ importers:
         version: 7.0.3
       eslint-plugin-import:
         specifier: 2.30.0
-        version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)
+        version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       execa:
-        specifier: 9.4.0
-        version: 9.4.0
+        specifier: 9.5.1
+        version: 9.5.1
       fkill:
         specifier: 9.0.0
         version: 9.0.0
       jest:
         specifier: 29.7.0
-        version: 29.7.0(@types/node@20.14.12)
+        version: 29.7.0(@types/node@22.9.0)
       jest-mock:
         specifier: 29.7.0
         version: 29.7.0
@@ -705,13 +705,13 @@ importers:
         version: 2024.1.0
       '@rollup/plugin-json':
         specifier: 6.1.0
-        version: 6.1.0(rollup@4.22.5)
+        version: 6.1.0(rollup@4.26.0)
       '@rollup/plugin-replace':
         specifier: 5.0.7
-        version: 5.0.7(rollup@4.22.5)
+        version: 5.0.7(rollup@4.26.0)
       '@rollup/pluginutils':
-        specifier: 5.1.2
-        version: 5.1.2(rollup@4.22.5)
+        specifier: 5.1.3
+        version: 5.1.3(rollup@4.26.0)
       '@syuilo/aiscript':
         specifier: 0.19.0
         version: 0.19.0
@@ -722,11 +722,11 @@ importers:
         specifier: 15.1.1
         version: 15.1.1
       '@vitejs/plugin-vue':
-        specifier: 5.1.4
-        version: 5.1.4(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))(vue@3.5.11(typescript@5.6.2))
+        specifier: 5.2.0
+        version: 5.2.0(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))
       '@vue/compiler-sfc':
-        specifier: 3.5.11
-        version: 3.5.11
+        specifier: 3.5.12
+        version: 3.5.12
       aiscript-vscode:
         specifier: github:aiscript-dev/aiscript-vscode#v0.1.11
         version: https://codeload.github.com/aiscript-dev/aiscript-vscode/tar.gz/e1e1b27f2f72cd28a473e004b6da0d8fc0bd40d9
@@ -743,23 +743,23 @@ importers:
         specifier: 1.9.3
         version: 1.9.3
       chart.js:
-        specifier: 4.4.4
-        version: 4.4.4
+        specifier: 4.4.6
+        version: 4.4.6
       chartjs-adapter-date-fns:
         specifier: 3.0.0
-        version: 3.0.0(chart.js@4.4.4)(date-fns@2.30.0)
+        version: 3.0.0(chart.js@4.4.6)(date-fns@2.30.0)
       chartjs-chart-matrix:
         specifier: 2.0.1
-        version: 2.0.1(chart.js@4.4.4)
+        version: 2.0.1(chart.js@4.4.6)
       chartjs-plugin-gradient:
         specifier: 0.6.1
-        version: 0.6.1(chart.js@4.4.4)
+        version: 0.6.1(chart.js@4.4.6)
       chartjs-plugin-zoom:
         specifier: 2.0.1
-        version: 2.0.1(chart.js@4.4.4)
+        version: 2.0.1(chart.js@4.4.6)
       chromatic:
-        specifier: 11.11.0
-        version: 11.11.0
+        specifier: 11.18.1
+        version: 11.18.1
       compare-versions:
         specifier: 6.1.1
         version: 6.1.1
@@ -812,8 +812,8 @@ importers:
         specifier: 2.3.1
         version: 2.3.1
       rollup:
-        specifier: 4.22.5
-        version: 4.22.5
+        specifier: 4.26.0
+        version: 4.26.0
       sanitize-html:
         specifier: 2.13.1
         version: 2.13.1
@@ -821,8 +821,8 @@ importers:
         specifier: 1.79.3
         version: 1.79.3
       shiki:
-        specifier: 1.21.0
-        version: 1.21.0
+        specifier: 1.22.2
+        version: 1.22.2
       strict-event-emitter-types:
         specifier: 2.0.0
         version: 2.0.0
@@ -845,84 +845,84 @@ importers:
         specifier: 4.2.0
         version: 4.2.0
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
       uuid:
         specifier: 10.0.0
         version: 10.0.0
       v-code-diff:
         specifier: 1.13.1
-        version: 1.13.1(vue@3.5.11(typescript@5.6.2))
+        version: 1.13.1(vue@3.5.12(typescript@5.6.3))
       vite:
-        specifier: 5.4.8
-        version: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
+        specifier: 5.4.11
+        version: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
       vue:
-        specifier: 3.5.11
-        version: 3.5.11(typescript@5.6.2)
+        specifier: 3.5.12
+        version: 3.5.12(typescript@5.6.3)
       vuedraggable:
         specifier: next
-        version: 4.1.0(vue@3.5.11(typescript@5.6.2))
+        version: 4.1.0(vue@3.5.12(typescript@5.6.3))
     devDependencies:
       '@misskey-dev/summaly':
         specifier: 5.1.0
         version: 5.1.0
       '@storybook/addon-actions':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/addon-essentials':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(@types/react@18.0.28)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/addon-interactions':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/addon-links':
-        specifier: 8.3.4
-        version: 8.3.4(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/addon-mdx-gfm':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/addon-storysource':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/blocks':
-        specifier: 8.3.4
-        version: 8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/components':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/core-events':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/manager-api':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/preview-api':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/react':
-        specifier: 8.3.4
-        version: 8.3.4(@storybook/test@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)
+        specifier: 8.4.4
+        version: 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(typescript@5.6.3)
       '@storybook/react-vite':
-        specifier: 8.3.4
-        version: 8.3.4(@storybook/test@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.22.5)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))
+        specifier: 8.4.4
+        version: 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.26.0)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))
       '@storybook/test':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/theming':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/types':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/vue3':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.5.11(typescript@5.6.2))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vue@3.5.12(typescript@5.6.3))
       '@storybook/vue3-vite':
-        specifier: 8.3.4
-        version: 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))(vue@3.5.11(typescript@5.6.2))
+        specifier: 8.4.4
+        version: 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))
       '@testing-library/vue':
         specifier: 8.1.0
-        version: 8.1.0(@vue/compiler-sfc@3.5.11)(@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2)))(vue@3.5.11(typescript@5.6.2))
+        version: 8.1.0(@vue/compiler-sfc@3.5.12)(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))
       '@types/canvas-confetti':
         specifier: ^1.6.4
         version: 1.6.4
@@ -936,8 +936,8 @@ importers:
         specifier: 4.0.9
         version: 4.0.9
       '@types/node':
-        specifier: 20.14.12
-        version: 20.14.12
+        specifier: 22.9.0
+        version: 22.9.0
       '@types/punycode':
         specifier: 2.1.4
         version: 2.1.4
@@ -957,35 +957,35 @@ importers:
         specifier: 10.0.0
         version: 10.0.0
       '@types/ws':
-        specifier: 8.5.12
-        version: 8.5.12
+        specifier: 8.5.13
+        version: 8.5.13
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       '@vitest/coverage-v8':
         specifier: 1.6.0
-        version: 1.6.0(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0))
+        version: 1.6.0(vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0))
       '@vue/runtime-core':
-        specifier: 3.5.11
-        version: 3.5.11
+        specifier: 3.5.12
+        version: 3.5.12
       acorn:
-        specifier: 8.12.1
-        version: 8.12.1
+        specifier: 8.14.0
+        version: 8.14.0
       cross-env:
         specifier: 7.0.3
         version: 7.0.3
       cypress:
-        specifier: 13.15.0
-        version: 13.15.0
+        specifier: 13.15.2
+        version: 13.15.2
       eslint-plugin-import:
         specifier: 2.31.0
-        version: 2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)
+        version: 2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       eslint-plugin-vue:
-        specifier: 9.28.0
-        version: 9.28.0(eslint@9.11.0)
+        specifier: 9.31.0
+        version: 9.31.0(eslint@9.14.0)
       fast-glob:
         specifier: 3.3.2
         version: 3.3.2
@@ -999,11 +999,11 @@ importers:
         specifier: 4.0.8
         version: 4.0.8
       msw:
-        specifier: 2.4.9
-        version: 2.4.9(typescript@5.6.2)
+        specifier: 2.6.4
+        version: 2.6.4(@types/node@22.9.0)(typescript@5.6.3)
       msw-storybook-addon:
-        specifier: 2.0.3
-        version: 2.0.3(msw@2.4.9(typescript@5.6.2))
+        specifier: 2.0.4
+        version: 2.0.4(msw@2.6.4(@types/node@22.9.0)(typescript@5.6.3))
       nodemon:
         specifier: 3.1.7
         version: 3.1.7
@@ -1023,29 +1023,29 @@ importers:
         specifier: 2.0.8
         version: 2.0.8
       storybook:
-        specifier: 8.3.4
-        version: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+        specifier: 8.4.4
+        version: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       storybook-addon-misskey-theme:
         specifier: github:misskey-dev/storybook-addon-misskey-theme
-        version: https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/components@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/core-events@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/manager-api@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/preview-api@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/theming@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/types@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/components@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/core-events@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/manager-api@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/preview-api@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/theming@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/types@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       vite-plugin-turbosnap:
         specifier: 1.0.3
         version: 1.0.3
       vitest:
         specifier: 1.6.0
-        version: 1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0)
+        version: 1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0)
       vitest-fetch-mock:
         specifier: 0.2.2
-        version: 0.2.2(encoding@0.1.13)(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0))
+        version: 0.2.2(encoding@0.1.13)(vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0))
       vue-component-type-helpers:
-        specifier: 2.1.6
-        version: 2.1.6
+        specifier: 2.1.10
+        version: 2.1.10
       vue-eslint-parser:
         specifier: 9.4.3
-        version: 9.4.3(eslint@9.11.0)
+        version: 9.4.3(eslint@9.14.0)
       vue-tsc:
-        specifier: 2.1.6
-        version: 2.1.6(typescript@5.6.2)
+        specifier: 2.1.10
+        version: 2.1.10(typescript@5.6.3)
 
   packages/frontend-embed:
     dependencies:
@@ -1054,13 +1054,13 @@ importers:
         version: 15.1.0
       '@rollup/plugin-json':
         specifier: 6.1.0
-        version: 6.1.0(rollup@4.22.5)
+        version: 6.1.0(rollup@4.26.0)
       '@rollup/plugin-replace':
         specifier: 5.0.7
-        version: 5.0.7(rollup@4.22.5)
+        version: 5.0.7(rollup@4.26.0)
       '@rollup/pluginutils':
-        specifier: 5.1.2
-        version: 5.1.2(rollup@4.22.5)
+        specifier: 5.1.3
+        version: 5.1.3(rollup@4.26.0)
       '@tabler/icons-webfont':
         specifier: 3.3.0
         version: 3.3.0
@@ -1068,11 +1068,11 @@ importers:
         specifier: 15.1.1
         version: 15.1.1
       '@vitejs/plugin-vue':
-        specifier: 5.1.4
-        version: 5.1.4(vite@5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0))(vue@3.5.11(typescript@5.6.2))
+        specifier: 5.2.0
+        version: 5.2.0(vite@5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))
       '@vue/compiler-sfc':
-        specifier: 3.5.11
-        version: 3.5.11
+        specifier: 3.5.12
+        version: 3.5.12
       astring:
         specifier: 1.9.0
         version: 1.9.0
@@ -1098,14 +1098,14 @@ importers:
         specifier: 2.3.1
         version: 2.3.1
       rollup:
-        specifier: 4.22.5
-        version: 4.22.5
+        specifier: 4.26.0
+        version: 4.26.0
       sass:
         specifier: 1.79.4
         version: 1.79.4
       shiki:
-        specifier: 1.21.0
-        version: 1.21.0
+        specifier: 1.22.2
+        version: 1.22.2
       tinycolor2:
         specifier: 1.6.0
         version: 1.6.0
@@ -1116,24 +1116,24 @@ importers:
         specifier: 4.2.0
         version: 4.2.0
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
       uuid:
         specifier: 10.0.0
         version: 10.0.0
       vite:
-        specifier: 5.4.8
-        version: 5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0)
+        specifier: 5.4.11
+        version: 5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0)
       vue:
-        specifier: 3.5.11
-        version: 3.5.11(typescript@5.6.2)
+        specifier: 3.5.12
+        version: 3.5.12(typescript@5.6.3)
     devDependencies:
       '@misskey-dev/summaly':
         specifier: 5.1.0
         version: 5.1.0
       '@testing-library/vue':
         specifier: 8.1.0
-        version: 8.1.0(@vue/compiler-sfc@3.5.11)(@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2)))(vue@3.5.11(typescript@5.6.2))
+        version: 8.1.0(@vue/compiler-sfc@3.5.12)(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))
       '@types/estree':
         specifier: 1.0.6
         version: 1.0.6
@@ -1141,8 +1141,8 @@ importers:
         specifier: 4.0.9
         version: 4.0.9
       '@types/node':
-        specifier: 20.14.12
-        version: 20.14.12
+        specifier: 22.9.0
+        version: 22.9.0
       '@types/punycode':
         specifier: 2.1.4
         version: 2.1.4
@@ -1153,32 +1153,32 @@ importers:
         specifier: 10.0.0
         version: 10.0.0
       '@types/ws':
-        specifier: 8.5.12
-        version: 8.5.12
+        specifier: 8.5.13
+        version: 8.5.13
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       '@vitest/coverage-v8':
         specifier: 1.6.0
-        version: 1.6.0(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.4)(terser@5.33.0))
+        version: 1.6.0(vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1)(sass@1.79.4)(terser@5.36.0))
       '@vue/runtime-core':
-        specifier: 3.5.11
-        version: 3.5.11
+        specifier: 3.5.12
+        version: 3.5.12
       acorn:
-        specifier: 8.12.1
-        version: 8.12.1
+        specifier: 8.14.0
+        version: 8.14.0
       cross-env:
         specifier: 7.0.3
         version: 7.0.3
       eslint-plugin-import:
         specifier: 2.31.0
-        version: 2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)
+        version: 2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       eslint-plugin-vue:
-        specifier: 9.28.0
-        version: 9.28.0(eslint@9.11.0)
+        specifier: 9.31.0
+        version: 9.31.0(eslint@9.14.0)
       fast-glob:
         specifier: 3.3.2
         version: 3.3.2
@@ -1192,8 +1192,8 @@ importers:
         specifier: 4.0.8
         version: 4.0.8
       msw:
-        specifier: 2.3.4
-        version: 2.3.4(typescript@5.6.2)
+        specifier: 2.6.4
+        version: 2.6.4(@types/node@22.9.0)(typescript@5.6.3)
       nodemon:
         specifier: 3.1.7
         version: 3.1.7
@@ -1207,14 +1207,14 @@ importers:
         specifier: 1.0.3
         version: 1.0.3
       vue-component-type-helpers:
-        specifier: 2.1.6
-        version: 2.1.6
+        specifier: 2.1.10
+        version: 2.1.10
       vue-eslint-parser:
         specifier: 9.4.3
-        version: 9.4.3(eslint@9.11.0)
+        version: 9.4.3(eslint@9.14.0)
       vue-tsc:
-        specifier: 2.1.6
-        version: 2.1.6(typescript@5.6.2)
+        specifier: 2.1.10
+        version: 2.1.10(typescript@5.6.3)
 
   packages/frontend-shared:
     dependencies:
@@ -1222,30 +1222,30 @@ importers:
         specifier: workspace:*
         version: link:../misskey-js
       vue:
-        specifier: 3.4.37
-        version: 3.4.37(typescript@5.5.4)
+        specifier: 3.5.12
+        version: 3.5.12(typescript@5.6.3)
     devDependencies:
       '@types/node':
-        specifier: 20.14.12
-        version: 20.14.12
+        specifier: 22.9.0
+        version: 22.9.0
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.5.4))(eslint@9.11.0)(typescript@5.5.4)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.5.4)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       esbuild:
-        specifier: 0.23.0
-        version: 0.23.0
+        specifier: 0.24.0
+        version: 0.24.0
       eslint-plugin-vue:
-        specifier: 9.27.0
-        version: 9.27.0(eslint@9.11.0)
+        specifier: 9.31.0
+        version: 9.31.0(eslint@9.14.0)
       typescript:
-        specifier: 5.5.4
-        version: 5.5.4
+        specifier: 5.6.3
+        version: 5.6.3
       vue-eslint-parser:
         specifier: 9.4.3
-        version: 9.4.3(eslint@9.11.0)
+        version: 9.4.3(eslint@9.14.0)
 
   packages/misskey-bubble-game:
     dependencies:
@@ -1260,41 +1260,41 @@ importers:
         version: 3.0.5
     devDependencies:
       '@types/matter-js':
-        specifier: 0.19.6
-        version: 0.19.6
+        specifier: 0.19.7
+        version: 0.19.7
       '@types/node':
-        specifier: 20.11.5
-        version: 20.11.5
+        specifier: 22.9.0
+        version: 22.9.0
       '@types/seedrandom':
         specifier: 3.0.8
         version: 3.0.8
       '@typescript-eslint/eslint-plugin':
         specifier: 7.1.0
-        version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.11.0)(typescript@5.3.3))(eslint@9.11.0)(typescript@5.3.3)
+        version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.1.0
-        version: 7.1.0(eslint@9.11.0)(typescript@5.3.3)
+        version: 7.1.0(eslint@9.14.0)(typescript@5.6.3)
       esbuild:
-        specifier: 0.19.11
-        version: 0.19.11
+        specifier: 0.24.0
+        version: 0.24.0
       execa:
-        specifier: 8.0.1
-        version: 8.0.1
+        specifier: 9.5.1
+        version: 9.5.1
       glob:
-        specifier: 10.3.10
-        version: 10.3.10
+        specifier: 11.0.0
+        version: 11.0.0
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       typescript:
-        specifier: 5.3.3
-        version: 5.3.3
+        specifier: 5.6.3
+        version: 5.6.3
 
   packages/misskey-js:
     dependencies:
       '@simplewebauthn/types':
-        specifier: 10.0.0
-        version: 10.0.0
+        specifier: 11.0.0
+        version: 11.0.0
       eventemitter3:
         specifier: 5.0.1
         version: 5.0.1
@@ -1303,35 +1303,35 @@ importers:
         version: 4.4.0
     devDependencies:
       '@microsoft/api-extractor':
-        specifier: 7.47.9
-        version: 7.47.9(@types/node@20.14.12)
+        specifier: 7.47.11
+        version: 7.47.11(@types/node@22.9.0)
       '@swc/jest':
-        specifier: 0.2.36
-        version: 0.2.36(@swc/core@1.6.13)
+        specifier: 0.2.37
+        version: 0.2.37(@swc/core@1.9.2)
       '@types/jest':
-        specifier: 29.5.13
-        version: 29.5.13
+        specifier: 29.5.14
+        version: 29.5.14
       '@types/node':
-        specifier: 20.14.12
-        version: 20.14.12
+        specifier: 22.9.0
+        version: 22.9.0
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       esbuild:
-        specifier: 0.23.1
-        version: 0.23.1
+        specifier: 0.24.0
+        version: 0.24.0
       execa:
-        specifier: 9.4.0
-        version: 9.4.0
+        specifier: 9.5.1
+        version: 9.5.1
       glob:
         specifier: 11.0.0
         version: 11.0.0
       jest:
         specifier: 29.7.0
-        version: 29.7.0(@types/node@20.14.12)
+        version: 29.7.0(@types/node@22.9.0)
       jest-fetch-mock:
         specifier: 3.0.3
         version: 3.0.3(encoding@0.1.13)
@@ -1351,8 +1351,8 @@ importers:
         specifier: 0.31.2
         version: 0.31.2
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
 
   packages/misskey-js/generator:
     devDependencies:
@@ -1360,14 +1360,14 @@ importers:
         specifier: 2.6.0
         version: 2.6.0(openapi-types@12.1.3)
       '@types/node':
-        specifier: 20.9.1
-        version: 20.9.1
+        specifier: 22.9.0
+        version: 22.9.0
       '@typescript-eslint/eslint-plugin':
         specifier: 7.17.0
-        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       openapi-types:
         specifier: 12.1.3
         version: 12.1.3
@@ -1375,14 +1375,14 @@ importers:
         specifier: 6.7.3
         version: 6.7.3
       ts-case-convert:
-        specifier: 2.0.7
-        version: 2.0.7
+        specifier: 2.1.0
+        version: 2.1.0
       tsx:
         specifier: 4.4.0
         version: 4.4.0
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
 
   packages/misskey-reversi:
     dependencies:
@@ -1391,35 +1391,35 @@ importers:
         version: 1.2.2
     devDependencies:
       '@types/node':
-        specifier: 20.11.5
-        version: 20.11.5
+        specifier: 22.9.0
+        version: 22.9.0
       '@typescript-eslint/eslint-plugin':
         specifier: 7.1.0
-        version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.11.0)(typescript@5.3.3))(eslint@9.11.0)(typescript@5.3.3)
+        version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/parser':
         specifier: 7.1.0
-        version: 7.1.0(eslint@9.11.0)(typescript@5.3.3)
+        version: 7.1.0(eslint@9.14.0)(typescript@5.6.3)
       esbuild:
-        specifier: 0.19.11
-        version: 0.19.11
+        specifier: 0.24.0
+        version: 0.24.0
       execa:
-        specifier: 8.0.1
-        version: 8.0.1
+        specifier: 9.5.1
+        version: 9.5.1
       glob:
-        specifier: 10.3.10
-        version: 10.3.10
+        specifier: 11.0.0
+        version: 11.0.0
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       typescript:
-        specifier: 5.3.3
-        version: 5.3.3
+        specifier: 5.6.3
+        version: 5.6.3
 
   packages/sw:
     dependencies:
       esbuild:
-        specifier: 0.23.1
-        version: 0.23.1
+        specifier: 0.24.0
+        version: 0.24.0
       idb-keyval:
         specifier: 6.2.1
         version: 6.2.1
@@ -1429,19 +1429,19 @@ importers:
     devDependencies:
       '@typescript-eslint/parser':
         specifier: 7.17.0
-        version: 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+        version: 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       '@typescript/lib-webworker':
         specifier: npm:@types/serviceworker@0.0.67
         version: '@types/serviceworker@0.0.67'
       eslint-plugin-import:
         specifier: 2.30.0
-        version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)
+        version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       nodemon:
         specifier: 3.1.7
         version: 3.1.7
       typescript:
-        specifier: 5.6.2
-        version: 5.6.2
+        specifier: 5.6.3
+        version: 5.6.3
 
 packages:
 
@@ -1888,25 +1888,22 @@ packages:
     resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==}
     engines: {node: '>=6.9.0'}
 
-  '@base2/pretty-print-object@1.0.1':
-    resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==}
-
   '@bcoe/v8-coverage@0.2.3':
     resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
 
-  '@bull-board/api@6.0.0':
-    resolution: {integrity: sha512-O0IsIwAOU47bPTJnqRO7RtKFQToMvwRebbuPi6M+SG1gXyiqixLg9pycnfXgSeroaT9E7QQ2PsCPW1HO8VORvw==}
+  '@bull-board/api@6.5.0':
+    resolution: {integrity: sha512-sFHxmqtbBBkQaJxHdRq2sAR0+l9TBInItXaIdBMjeBXrFW881g4aLAbO7Lno6cDPKBMauYg4TdBtRPTkjhr43w==}
     peerDependencies:
-      '@bull-board/ui': 6.0.0
+      '@bull-board/ui': 6.5.0
 
-  '@bull-board/fastify@6.0.0':
-    resolution: {integrity: sha512-VrKa5BdxYmXh5fJvlSPSm71b+QA9VVXHyGk6xmI/qAefUQbwd2cWJo+ppqaWSaweXa9ymJc+V4l/un0K4oomVA==}
+  '@bull-board/fastify@6.5.0':
+    resolution: {integrity: sha512-oPLqIJPkis13WMPeuephkGeP/++AB5Qw3aw0qESU1K+e1pdwzf1kYIFpOZuTe9L/MrEulKe2ZgENw6RIgC1RBw==}
 
-  '@bull-board/ui@6.0.0':
-    resolution: {integrity: sha512-wAFTlBTJbq5DSWxCzTV+FOyZDVwrXP+G1CQ2BpLG9o9+dpwYxUESx/VxNEDHnyPcy13gm29kB4fSRY+nkelkcQ==}
+  '@bull-board/ui@6.5.0':
+    resolution: {integrity: sha512-gIoOgKNVAnPdKBBUaBUSNS2cBJz8UYGfEuYzD/H9HIpkCHiPTUVoMO48w/D+urJoko2nW8OSkU1kf2OkZsqP0Q==}
 
-  '@bundled-es-modules/cookie@2.0.0':
-    resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==}
+  '@bundled-es-modules/cookie@2.0.1':
+    resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==}
 
   '@bundled-es-modules/statuses@1.0.1':
     resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==}
@@ -1954,8 +1951,8 @@ packages:
   '@cropper/utils@2.0.0-rc.2':
     resolution: {integrity: sha512-EEivNsyV6BtL496m4Q/IeAC6FGlyKjKIT1qMtwaxtkR+2ZlKnf9O7AdcGpClemIBA+TbwWAzp0UyIvYFtKUZ1Q==}
 
-  '@cypress/request@3.0.5':
-    resolution: {integrity: sha512-v+XHd9XmWbufxF1/bTaVm2yhbxY+TB4YtWRqF2zaXBlDNMkls34KiATz0AVDLavL3iB6bQk9/7n3oY1EoLSWGA==}
+  '@cypress/request@3.0.6':
+    resolution: {integrity: sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==}
     engines: {node: '>= 6'}
 
   '@cypress/xvfb@1.2.4':
@@ -1971,26 +1968,14 @@ packages:
   '@emnapi/runtime@1.2.0':
     resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==}
 
-  '@esbuild/aix-ppc64@0.19.11':
-    resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==}
-    engines: {node: '>=12'}
-    cpu: [ppc64]
-    os: [aix]
-
   '@esbuild/aix-ppc64@0.21.5':
     resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
     engines: {node: '>=12'}
     cpu: [ppc64]
     os: [aix]
 
-  '@esbuild/aix-ppc64@0.23.0':
-    resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==}
-    engines: {node: '>=18'}
-    cpu: [ppc64]
-    os: [aix]
-
-  '@esbuild/aix-ppc64@0.23.1':
-    resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
+  '@esbuild/aix-ppc64@0.24.0':
+    resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
     engines: {node: '>=18'}
     cpu: [ppc64]
     os: [aix]
@@ -2001,26 +1986,14 @@ packages:
     cpu: [arm64]
     os: [android]
 
-  '@esbuild/android-arm64@0.19.11':
-    resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [android]
-
   '@esbuild/android-arm64@0.21.5':
     resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [android]
 
-  '@esbuild/android-arm64@0.23.0':
-    resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [android]
-
-  '@esbuild/android-arm64@0.23.1':
-    resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
+  '@esbuild/android-arm64@0.24.0':
+    resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
     engines: {node: '>=18'}
     cpu: [arm64]
     os: [android]
@@ -2031,26 +2004,14 @@ packages:
     cpu: [arm]
     os: [android]
 
-  '@esbuild/android-arm@0.19.11':
-    resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==}
-    engines: {node: '>=12'}
-    cpu: [arm]
-    os: [android]
-
   '@esbuild/android-arm@0.21.5':
     resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [android]
 
-  '@esbuild/android-arm@0.23.0':
-    resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==}
-    engines: {node: '>=18'}
-    cpu: [arm]
-    os: [android]
-
-  '@esbuild/android-arm@0.23.1':
-    resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
+  '@esbuild/android-arm@0.24.0':
+    resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
     engines: {node: '>=18'}
     cpu: [arm]
     os: [android]
@@ -2061,26 +2022,14 @@ packages:
     cpu: [x64]
     os: [android]
 
-  '@esbuild/android-x64@0.19.11':
-    resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [android]
-
   '@esbuild/android-x64@0.21.5':
     resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [android]
 
-  '@esbuild/android-x64@0.23.0':
-    resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [android]
-
-  '@esbuild/android-x64@0.23.1':
-    resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
+  '@esbuild/android-x64@0.24.0':
+    resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [android]
@@ -2091,26 +2040,14 @@ packages:
     cpu: [arm64]
     os: [darwin]
 
-  '@esbuild/darwin-arm64@0.19.11':
-    resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [darwin]
-
   '@esbuild/darwin-arm64@0.21.5':
     resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [darwin]
 
-  '@esbuild/darwin-arm64@0.23.0':
-    resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [darwin]
-
-  '@esbuild/darwin-arm64@0.23.1':
-    resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
+  '@esbuild/darwin-arm64@0.24.0':
+    resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
     engines: {node: '>=18'}
     cpu: [arm64]
     os: [darwin]
@@ -2121,26 +2058,14 @@ packages:
     cpu: [x64]
     os: [darwin]
 
-  '@esbuild/darwin-x64@0.19.11':
-    resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [darwin]
-
   '@esbuild/darwin-x64@0.21.5':
     resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [darwin]
 
-  '@esbuild/darwin-x64@0.23.0':
-    resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [darwin]
-
-  '@esbuild/darwin-x64@0.23.1':
-    resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
+  '@esbuild/darwin-x64@0.24.0':
+    resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [darwin]
@@ -2151,26 +2076,14 @@ packages:
     cpu: [arm64]
     os: [freebsd]
 
-  '@esbuild/freebsd-arm64@0.19.11':
-    resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [freebsd]
-
   '@esbuild/freebsd-arm64@0.21.5':
     resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [freebsd]
 
-  '@esbuild/freebsd-arm64@0.23.0':
-    resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [freebsd]
-
-  '@esbuild/freebsd-arm64@0.23.1':
-    resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
+  '@esbuild/freebsd-arm64@0.24.0':
+    resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
     engines: {node: '>=18'}
     cpu: [arm64]
     os: [freebsd]
@@ -2181,26 +2094,14 @@ packages:
     cpu: [x64]
     os: [freebsd]
 
-  '@esbuild/freebsd-x64@0.19.11':
-    resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [freebsd]
-
   '@esbuild/freebsd-x64@0.21.5':
     resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [freebsd]
 
-  '@esbuild/freebsd-x64@0.23.0':
-    resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [freebsd]
-
-  '@esbuild/freebsd-x64@0.23.1':
-    resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
+  '@esbuild/freebsd-x64@0.24.0':
+    resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [freebsd]
@@ -2211,26 +2112,14 @@ packages:
     cpu: [arm64]
     os: [linux]
 
-  '@esbuild/linux-arm64@0.19.11':
-    resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [linux]
-
   '@esbuild/linux-arm64@0.21.5':
     resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [linux]
 
-  '@esbuild/linux-arm64@0.23.0':
-    resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [linux]
-
-  '@esbuild/linux-arm64@0.23.1':
-    resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
+  '@esbuild/linux-arm64@0.24.0':
+    resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
     engines: {node: '>=18'}
     cpu: [arm64]
     os: [linux]
@@ -2241,26 +2130,14 @@ packages:
     cpu: [arm]
     os: [linux]
 
-  '@esbuild/linux-arm@0.19.11':
-    resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==}
-    engines: {node: '>=12'}
-    cpu: [arm]
-    os: [linux]
-
   '@esbuild/linux-arm@0.21.5':
     resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [linux]
 
-  '@esbuild/linux-arm@0.23.0':
-    resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==}
-    engines: {node: '>=18'}
-    cpu: [arm]
-    os: [linux]
-
-  '@esbuild/linux-arm@0.23.1':
-    resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
+  '@esbuild/linux-arm@0.24.0':
+    resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
     engines: {node: '>=18'}
     cpu: [arm]
     os: [linux]
@@ -2271,26 +2148,14 @@ packages:
     cpu: [ia32]
     os: [linux]
 
-  '@esbuild/linux-ia32@0.19.11':
-    resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==}
-    engines: {node: '>=12'}
-    cpu: [ia32]
-    os: [linux]
-
   '@esbuild/linux-ia32@0.21.5':
     resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [linux]
 
-  '@esbuild/linux-ia32@0.23.0':
-    resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==}
-    engines: {node: '>=18'}
-    cpu: [ia32]
-    os: [linux]
-
-  '@esbuild/linux-ia32@0.23.1':
-    resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
+  '@esbuild/linux-ia32@0.24.0':
+    resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
     engines: {node: '>=18'}
     cpu: [ia32]
     os: [linux]
@@ -2301,26 +2166,14 @@ packages:
     cpu: [loong64]
     os: [linux]
 
-  '@esbuild/linux-loong64@0.19.11':
-    resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==}
-    engines: {node: '>=12'}
-    cpu: [loong64]
-    os: [linux]
-
   '@esbuild/linux-loong64@0.21.5':
     resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
     engines: {node: '>=12'}
     cpu: [loong64]
     os: [linux]
 
-  '@esbuild/linux-loong64@0.23.0':
-    resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==}
-    engines: {node: '>=18'}
-    cpu: [loong64]
-    os: [linux]
-
-  '@esbuild/linux-loong64@0.23.1':
-    resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
+  '@esbuild/linux-loong64@0.24.0':
+    resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
     engines: {node: '>=18'}
     cpu: [loong64]
     os: [linux]
@@ -2331,26 +2184,14 @@ packages:
     cpu: [mips64el]
     os: [linux]
 
-  '@esbuild/linux-mips64el@0.19.11':
-    resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==}
-    engines: {node: '>=12'}
-    cpu: [mips64el]
-    os: [linux]
-
   '@esbuild/linux-mips64el@0.21.5':
     resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
     engines: {node: '>=12'}
     cpu: [mips64el]
     os: [linux]
 
-  '@esbuild/linux-mips64el@0.23.0':
-    resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==}
-    engines: {node: '>=18'}
-    cpu: [mips64el]
-    os: [linux]
-
-  '@esbuild/linux-mips64el@0.23.1':
-    resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
+  '@esbuild/linux-mips64el@0.24.0':
+    resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
     engines: {node: '>=18'}
     cpu: [mips64el]
     os: [linux]
@@ -2361,26 +2202,14 @@ packages:
     cpu: [ppc64]
     os: [linux]
 
-  '@esbuild/linux-ppc64@0.19.11':
-    resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==}
-    engines: {node: '>=12'}
-    cpu: [ppc64]
-    os: [linux]
-
   '@esbuild/linux-ppc64@0.21.5':
     resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
     engines: {node: '>=12'}
     cpu: [ppc64]
     os: [linux]
 
-  '@esbuild/linux-ppc64@0.23.0':
-    resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==}
-    engines: {node: '>=18'}
-    cpu: [ppc64]
-    os: [linux]
-
-  '@esbuild/linux-ppc64@0.23.1':
-    resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
+  '@esbuild/linux-ppc64@0.24.0':
+    resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
     engines: {node: '>=18'}
     cpu: [ppc64]
     os: [linux]
@@ -2391,26 +2220,14 @@ packages:
     cpu: [riscv64]
     os: [linux]
 
-  '@esbuild/linux-riscv64@0.19.11':
-    resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==}
-    engines: {node: '>=12'}
-    cpu: [riscv64]
-    os: [linux]
-
   '@esbuild/linux-riscv64@0.21.5':
     resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
     engines: {node: '>=12'}
     cpu: [riscv64]
     os: [linux]
 
-  '@esbuild/linux-riscv64@0.23.0':
-    resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==}
-    engines: {node: '>=18'}
-    cpu: [riscv64]
-    os: [linux]
-
-  '@esbuild/linux-riscv64@0.23.1':
-    resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
+  '@esbuild/linux-riscv64@0.24.0':
+    resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
     engines: {node: '>=18'}
     cpu: [riscv64]
     os: [linux]
@@ -2421,26 +2238,14 @@ packages:
     cpu: [s390x]
     os: [linux]
 
-  '@esbuild/linux-s390x@0.19.11':
-    resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==}
-    engines: {node: '>=12'}
-    cpu: [s390x]
-    os: [linux]
-
   '@esbuild/linux-s390x@0.21.5':
     resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
     engines: {node: '>=12'}
     cpu: [s390x]
     os: [linux]
 
-  '@esbuild/linux-s390x@0.23.0':
-    resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==}
-    engines: {node: '>=18'}
-    cpu: [s390x]
-    os: [linux]
-
-  '@esbuild/linux-s390x@0.23.1':
-    resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
+  '@esbuild/linux-s390x@0.24.0':
+    resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
     engines: {node: '>=18'}
     cpu: [s390x]
     os: [linux]
@@ -2451,26 +2256,14 @@ packages:
     cpu: [x64]
     os: [linux]
 
-  '@esbuild/linux-x64@0.19.11':
-    resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [linux]
-
   '@esbuild/linux-x64@0.21.5':
     resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [linux]
 
-  '@esbuild/linux-x64@0.23.0':
-    resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [linux]
-
-  '@esbuild/linux-x64@0.23.1':
-    resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
+  '@esbuild/linux-x64@0.24.0':
+    resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [linux]
@@ -2481,38 +2274,20 @@ packages:
     cpu: [x64]
     os: [netbsd]
 
-  '@esbuild/netbsd-x64@0.19.11':
-    resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [netbsd]
-
   '@esbuild/netbsd-x64@0.21.5':
     resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [netbsd]
 
-  '@esbuild/netbsd-x64@0.23.0':
-    resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==}
+  '@esbuild/netbsd-x64@0.24.0':
+    resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [netbsd]
 
-  '@esbuild/netbsd-x64@0.23.1':
-    resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [netbsd]
-
-  '@esbuild/openbsd-arm64@0.23.0':
-    resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [openbsd]
-
-  '@esbuild/openbsd-arm64@0.23.1':
-    resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
+  '@esbuild/openbsd-arm64@0.24.0':
+    resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
     engines: {node: '>=18'}
     cpu: [arm64]
     os: [openbsd]
@@ -2523,26 +2298,14 @@ packages:
     cpu: [x64]
     os: [openbsd]
 
-  '@esbuild/openbsd-x64@0.19.11':
-    resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [openbsd]
-
   '@esbuild/openbsd-x64@0.21.5':
     resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [openbsd]
 
-  '@esbuild/openbsd-x64@0.23.0':
-    resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [openbsd]
-
-  '@esbuild/openbsd-x64@0.23.1':
-    resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
+  '@esbuild/openbsd-x64@0.24.0':
+    resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [openbsd]
@@ -2553,26 +2316,14 @@ packages:
     cpu: [x64]
     os: [sunos]
 
-  '@esbuild/sunos-x64@0.19.11':
-    resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [sunos]
-
   '@esbuild/sunos-x64@0.21.5':
     resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [sunos]
 
-  '@esbuild/sunos-x64@0.23.0':
-    resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [sunos]
-
-  '@esbuild/sunos-x64@0.23.1':
-    resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
+  '@esbuild/sunos-x64@0.24.0':
+    resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [sunos]
@@ -2583,26 +2334,14 @@ packages:
     cpu: [arm64]
     os: [win32]
 
-  '@esbuild/win32-arm64@0.19.11':
-    resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==}
-    engines: {node: '>=12'}
-    cpu: [arm64]
-    os: [win32]
-
   '@esbuild/win32-arm64@0.21.5':
     resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [win32]
 
-  '@esbuild/win32-arm64@0.23.0':
-    resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [win32]
-
-  '@esbuild/win32-arm64@0.23.1':
-    resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
+  '@esbuild/win32-arm64@0.24.0':
+    resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
     engines: {node: '>=18'}
     cpu: [arm64]
     os: [win32]
@@ -2613,26 +2352,14 @@ packages:
     cpu: [ia32]
     os: [win32]
 
-  '@esbuild/win32-ia32@0.19.11':
-    resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==}
-    engines: {node: '>=12'}
-    cpu: [ia32]
-    os: [win32]
-
   '@esbuild/win32-ia32@0.21.5':
     resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [win32]
 
-  '@esbuild/win32-ia32@0.23.0':
-    resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==}
-    engines: {node: '>=18'}
-    cpu: [ia32]
-    os: [win32]
-
-  '@esbuild/win32-ia32@0.23.1':
-    resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
+  '@esbuild/win32-ia32@0.24.0':
+    resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
     engines: {node: '>=18'}
     cpu: [ia32]
     os: [win32]
@@ -2643,26 +2370,14 @@ packages:
     cpu: [x64]
     os: [win32]
 
-  '@esbuild/win32-x64@0.19.11':
-    resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==}
-    engines: {node: '>=12'}
-    cpu: [x64]
-    os: [win32]
-
   '@esbuild/win32-x64@0.21.5':
     resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [win32]
 
-  '@esbuild/win32-x64@0.23.0':
-    resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [win32]
-
-  '@esbuild/win32-x64@0.23.1':
-    resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
+  '@esbuild/win32-x64@0.24.0':
+    resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
     engines: {node: '>=18'}
     cpu: [x64]
     os: [win32]
@@ -2677,6 +2392,10 @@ packages:
     resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==}
     engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
 
+  '@eslint-community/regexpp@4.12.1':
+    resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
+    engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
   '@eslint-community/regexpp@4.6.2':
     resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==}
     engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
@@ -2685,24 +2404,20 @@ packages:
     resolution: {integrity: sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  '@eslint/config-array@0.17.1':
-    resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   '@eslint/config-array@0.18.0':
     resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
+  '@eslint/core@0.7.0':
+    resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
   '@eslint/eslintrc@3.1.0':
     resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  '@eslint/js@9.11.0':
-    resolution: {integrity: sha512-LPkkenkDqyzTFauZLLAPhIb48fj6drrfMvRGSL9tS3AcZBSVTllemLSNyCvHNNL2t797S/6DJNSIwRwXgMO/eQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
-  '@eslint/js@9.8.0':
-    resolution: {integrity: sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==}
+  '@eslint/js@9.14.0':
+    resolution: {integrity: sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
   '@eslint/object-schema@2.1.4':
@@ -2729,8 +2444,8 @@ packages:
   '@fastify/busboy@3.0.0':
     resolution: {integrity: sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==}
 
-  '@fastify/cookie@10.0.1':
-    resolution: {integrity: sha512-NV/wbCUv4ETJ5KM1KMu0fLx0nSCm9idIxwg66NZnNbfPQH3rdbx6k0qRs5uy0y+MhBgvDudYRA30KlK659chyw==}
+  '@fastify/cookie@11.0.1':
+    resolution: {integrity: sha512-n1Ooz4bgQ5LcOlJQboWPfsMNxIrGV0SgU85UkctdpTlCQE0mtA3rlspOPUdqk9ubiiZn053ucnia4DjTquI4/g==}
 
   '@fastify/cors@10.0.1':
     resolution: {integrity: sha512-O8JIf6448uQbOgzSkCqhClw6gFTAqrdfeA6R3fc/3gwTJGUp7gl8/3tbNB+6INuu4RmgVOq99BmvdGbtu5pgOA==}
@@ -2747,8 +2462,8 @@ packages:
   '@fastify/fast-json-stringify-compiler@5.0.0':
     resolution: {integrity: sha512-tywfuZfXsyxLC5kEqrMubbFa9vpAxNtuPE7j9w5si1r+6p5b981pDfZ5Y8HBqmjDQl+PABT7cV5jZgXI2j+I5g==}
 
-  '@fastify/http-proxy@10.0.0':
-    resolution: {integrity: sha512-n5/EPspNKtzpCUavuDflYtvtB+aEkablb2sZM83gDKbxM9GF+93maJYQrGozJ2HNRqpt7wfzsDeUuGVFFkYzMQ==}
+  '@fastify/http-proxy@10.0.1':
+    resolution: {integrity: sha512-wCMwI9RXK5ISe9G1FGPDCCD2KlSAuLtDDU8XBEfiBxYV0nt+aYm4vPhU/0+IhUM6t+r7UWiV+9OYaJxcTem9+g==}
 
   '@fastify/merge-json-schemas@0.1.1':
     resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==}
@@ -2762,8 +2477,8 @@ packages:
   '@fastify/send@3.1.1':
     resolution: {integrity: sha512-LdiV2mle/2tH8vh6GwGl0ubfUAgvY+9yF9oGI1iiwVyNUVOQamvw5n+OFu6iCNNoyuCY80FFURBn4TZCbTe8LA==}
 
-  '@fastify/static@8.0.1':
-    resolution: {integrity: sha512-7idyhbcgf14v4bjWzUeHEFvnVxvNJ1n5cyGPgFtwTZjnjUQ1wgC7a2FQai7OGKqCKywDEjzbPhAZRW+uEK1LMg==}
+  '@fastify/static@8.0.2':
+    resolution: {integrity: sha512-xJ+XaZVl4Y+lKztx8jGi+BE73aByhOmjMgaTx98E4XtVZxUpiaYQIMBlwACsJz+xohm0kvzV34BZoiZ+bsJtBQ==}
 
   '@fastify/view@10.0.1':
     resolution: {integrity: sha512-rXtBN0oVDmoRZAS7lelrCIahf+qFtlMOOas8VPdA7JvrJ9ChcF7e36pIUPU0Vbs3KmHxESUb7XatavUZEe/k5Q==}
@@ -2793,6 +2508,14 @@ packages:
   '@hexagon/base64@1.1.27':
     resolution: {integrity: sha512-PdUmzpvcUM3Rh39kvz9RdbPVYhMjBjdV7Suw7ZduP7urRLsZR8l5tzgSWKm7TExwBYDFwTnYrZbnE0rQ3N5NLQ==}
 
+  '@humanfs/core@0.19.1':
+    resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanfs/node@0.16.6':
+    resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==}
+    engines: {node: '>=18.18.0'}
+
   '@humanwhocodes/module-importer@1.0.1':
     resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
     engines: {node: '>=12.22'}
@@ -2805,6 +2528,10 @@ packages:
     resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
     engines: {node: '>=18.18'}
 
+  '@humanwhocodes/retry@0.4.1':
+    resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==}
+    engines: {node: '>=18.18'}
+
   '@img/sharp-darwin-arm64@0.33.5':
     resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -2910,21 +2637,25 @@ packages:
     cpu: [x64]
     os: [win32]
 
-  '@inquirer/confirm@3.1.6':
-    resolution: {integrity: sha512-Mj4TU29g6Uy+37UtpA8UpEOI2icBfpCwSW1QDtfx60wRhUy90s/kHPif2OXSSvuwDQT1lhAYRWUfkNf9Tecxvg==}
+  '@inquirer/confirm@5.0.2':
+    resolution: {integrity: sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==}
+    engines: {node: '>=18'}
+    peerDependencies:
+      '@types/node': '>=18'
+
+  '@inquirer/core@10.1.0':
+    resolution: {integrity: sha512-I+ETk2AL+yAVbvuKx5AJpQmoaWhpiTFOg/UJb7ZkMAK4blmtG8ATh5ct+T/8xNld0CZG/2UhtkdMwpgvld92XQ==}
     engines: {node: '>=18'}
 
-  '@inquirer/core@8.1.0':
-    resolution: {integrity: sha512-kfx0SU9nWgGe1f03ao/uXc85SFH1v2w3vQVH7QDGjKxdtJz+7vPitFtG++BTyJMYyYgH8MpXigutcXJeiQwVRw==}
+  '@inquirer/figures@1.0.8':
+    resolution: {integrity: sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==}
     engines: {node: '>=18'}
 
-  '@inquirer/figures@1.0.1':
-    resolution: {integrity: sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==}
-    engines: {node: '>=18'}
-
-  '@inquirer/type@1.3.1':
-    resolution: {integrity: sha512-Pe3PFccjPVJV1vtlfVvm9OnlbxqdnP5QcscFEFEnK5quChf1ufZtM0r8mR5ToWHMxZOh0s8o/qp9ANGRTo/DAw==}
+  '@inquirer/type@3.0.1':
+    resolution: {integrity: sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==}
     engines: {node: '>=18'}
+    peerDependencies:
+      '@types/node': '>=18'
 
   '@ioredis/commands@1.2.0':
     resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
@@ -3094,8 +2825,8 @@ packages:
   '@microsoft/api-extractor-model@7.29.8':
     resolution: {integrity: sha512-t3Z/xcO6TRbMcnKGVMs4uMzv/gd5j0NhMiJIGjD4cJMeFJ1Hf8wnLSx37vxlRlL0GWlGJhnFgxvnaL6JlS+73g==}
 
-  '@microsoft/api-extractor@7.47.9':
-    resolution: {integrity: sha512-TTq30M1rikVsO5wZVToQT/dGyJY7UXJmjiRtkHPLb74Prx3Etw8+bX7Bv7iLuby6ysb7fuu1NFWqma+csym8Jw==}
+  '@microsoft/api-extractor@7.47.11':
+    resolution: {integrity: sha512-lrudfbPub5wzBhymfFtgZKuBvXxoSIAdrvS2UbHjoMT2TjIEddq6Z13pcve7A03BAouw0x8sW8G4txdgfiSwpQ==}
     hasBin: true
 
   '@microsoft/tsdoc-config@0.17.0':
@@ -3157,12 +2888,8 @@ packages:
     cpu: [x64]
     os: [win32]
 
-  '@mswjs/interceptors@0.29.1':
-    resolution: {integrity: sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==}
-    engines: {node: '>=18'}
-
-  '@mswjs/interceptors@0.35.8':
-    resolution: {integrity: sha512-PFfqpHplKa7KMdoQdj5td03uG05VK2Ng1dG0sP4pT9h0dGSX2v9txYt/AnrzPb/vAmfyBBC0NQV7VaBEX+efgQ==}
+  '@mswjs/interceptors@0.36.10':
+    resolution: {integrity: sha512-GXrJgakgJW3DWKueebkvtYgGKkxA7s0u5B0P5syJM5rvQUnrpLPigvci8Hukl7yEM+sU06l+er2Fgvx/gmiRgg==}
     engines: {node: '>=18'}
 
   '@napi-rs/canvas-android-arm64@0.1.56':
@@ -3223,8 +2950,8 @@ packages:
     resolution: {integrity: sha512-SujSchzG6lLc/wT+Mwxam/w30Kk2sFTiU6bLFcidecKSmlhenAhGMQhZh2iGFfKoh2+8iit0jrt99n6TqReICQ==}
     engines: {node: '>= 10'}
 
-  '@nestjs/common@10.4.4':
-    resolution: {integrity: sha512-0j2/zqRw9nvHV1GKTktER8B/hIC/Z8CYFjN/ZqUuvwayCH+jZZBhCR2oRyuvLTXdnlSmtCAg2xvQ0ULqQvzqhA==}
+  '@nestjs/common@10.4.7':
+    resolution: {integrity: sha512-gIOpjD3Mx8gfYGxYm/RHPcJzqdknNNFCyY+AxzBT3gc5Xvvik1Dn5OxaMGw5EbVfhZgJKVP0n83giUOAlZQe7w==}
     peerDependencies:
       class-transformer: '*'
       class-validator: '*'
@@ -3236,8 +2963,8 @@ packages:
       class-validator:
         optional: true
 
-  '@nestjs/core@10.4.4':
-    resolution: {integrity: sha512-y9tjmAzU6LTh1cC/lWrRsCcOd80khSR0qAHAqwY2svbW+AhsR/XCzgpZrAAKJrm/dDfjLCZKyxJSayeirGcW5Q==}
+  '@nestjs/core@10.4.7':
+    resolution: {integrity: sha512-AIpQzW/vGGqSLkKvll1R7uaSNv99AxZI2EFyVJPNGDgFsfXaohfV1Ukl6f+s75Km+6Fj/7aNl80EqzNWQCS8Ig==}
     peerDependencies:
       '@nestjs/common': ^10.0.0
       '@nestjs/microservices': ^10.0.0
@@ -3253,14 +2980,14 @@ packages:
       '@nestjs/websockets':
         optional: true
 
-  '@nestjs/platform-express@10.4.4':
-    resolution: {integrity: sha512-y52q1MxhbHaT3vAgWd08RgiYon0lJgtTa8U6g6gV0KI0IygwZhDQFJVxnrRDUdxQGIP5CKHmfQu3sk9gTNFoEA==}
+  '@nestjs/platform-express@10.4.7':
+    resolution: {integrity: sha512-q6XDOxZPTZ9cxALcVuKUlRBk+cVEv6dW2S8p2yVre22kpEQxq53/OI8EseDvzObGb6hepZ8+yBY04qoYqSlXNQ==}
     peerDependencies:
       '@nestjs/common': ^10.0.0
       '@nestjs/core': ^10.0.0
 
-  '@nestjs/testing@10.4.4':
-    resolution: {integrity: sha512-qRGFj51A5RM7JqA8pcyEwSLA3Y0dle/PAZ8oxP0suimoCusRY3Tk7wYqutZdCNj1ATb678SDaUZDHk2pwSv9/g==}
+  '@nestjs/testing@10.4.7':
+    resolution: {integrity: sha512-aS3sQ0v4g8cyHDzW3xJv1+8MiFAkxUNXmnau588IFFI/nBIo/kevLNHNPr85keYekkJ/lwNDW72h8UGg8BYd9w==}
     peerDependencies:
       '@nestjs/common': ^10.0.0
       '@nestjs/core': ^10.0.0
@@ -3323,6 +3050,14 @@ packages:
     resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==}
     engines: {node: '>=14'}
 
+  '@opentelemetry/api-logs@0.53.0':
+    resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==}
+    engines: {node: '>=14'}
+
+  '@opentelemetry/api-logs@0.54.2':
+    resolution: {integrity: sha512-4MTVwwmLgUh5QrJnZpYo6YRO5IBLAggf2h8gWDblwRagDStY13aEvt7gGk3jewrMaPlHiF83fENhIx0HO97/cQ==}
+    engines: {node: '>=14'}
+
   '@opentelemetry/api@1.9.0':
     resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
     engines: {node: '>=8.0.0'}
@@ -3333,156 +3068,210 @@ packages:
     peerDependencies:
       '@opentelemetry/api': '>=1.0.0 <1.10.0'
 
-  '@opentelemetry/core@1.24.1':
-    resolution: {integrity: sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==}
-    engines: {node: '>=14'}
-    peerDependencies:
-      '@opentelemetry/api': '>=1.0.0 <1.9.0'
-
   '@opentelemetry/core@1.25.1':
     resolution: {integrity: sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': '>=1.0.0 <1.10.0'
 
-  '@opentelemetry/instrumentation-connect@0.38.0':
-    resolution: {integrity: sha512-2/nRnx3pjYEmdPIaBwtgtSviTKHWnDZN3R+TkRUnhIVrvBKVcq+I5B2rtd6mr6Fe9cHlZ9Ojcuh7pkNh/xdWWg==}
+  '@opentelemetry/core@1.26.0':
+    resolution: {integrity: sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': '>=1.0.0 <1.10.0'
+
+  '@opentelemetry/core@1.27.0':
+    resolution: {integrity: sha512-yQPKnK5e+76XuiqUH/gKyS8wv/7qITd5ln56QkBTf3uggr0VkXOXfcaAuG330UfdYu83wsyoBwqwxigpIG+Jkg==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': '>=1.0.0 <1.10.0'
+
+  '@opentelemetry/instrumentation-amqplib@0.43.0':
+    resolution: {integrity: sha512-ALjfQC+0dnIEcvNYsbZl/VLh7D2P1HhFF4vicRKHhHFIUV3Shpg4kXgiek5PLhmeKSIPiUB25IYH5RIneclL4A==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-express@0.41.0':
-    resolution: {integrity: sha512-/B7fbMdaf3SYe5f1P973tkqd6s7XZirjpfkoJ63E7nltU30qmlgm9tY5XwZOzAFI0rHS9tbrFI2HFPAvQUFe/A==}
+  '@opentelemetry/instrumentation-connect@0.40.0':
+    resolution: {integrity: sha512-3aR/3YBQ160siitwwRLjwqrv2KBT16897+bo6yz8wIfel6nWOxTZBJudcbsK3p42pTC7qrbotJ9t/1wRLpv79Q==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-fastify@0.38.0':
-    resolution: {integrity: sha512-HBVLpTSYpkQZ87/Df3N0gAw7VzYZV3n28THIBrJWfuqw3Or7UqdhnjeuMIPQ04BKk3aZc0cWn2naSQObbh5vXw==}
+  '@opentelemetry/instrumentation-dataloader@0.12.0':
+    resolution: {integrity: sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-graphql@0.42.0':
-    resolution: {integrity: sha512-N8SOwoKL9KQSX7z3gOaw5UaTeVQcfDO1c21csVHnmnmGUoqsXbArK2B8VuwPWcv6/BC/i3io+xTo7QGRZ/z28Q==}
+  '@opentelemetry/instrumentation-express@0.44.0':
+    resolution: {integrity: sha512-GWgibp6Q0wxyFaaU8ERIgMMYgzcHmGrw3ILUtGchLtLncHNOKk0SNoWGqiylXWWT4HTn5XdV8MGawUgpZh80cA==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-hapi@0.40.0':
-    resolution: {integrity: sha512-8U/w7Ifumtd2bSN1OLaSwAAFhb9FyqWUki3lMMB0ds+1+HdSxYBe9aspEJEgvxAqOkrQnVniAPTEGf1pGM7SOw==}
+  '@opentelemetry/instrumentation-fastify@0.41.0':
+    resolution: {integrity: sha512-pNRjFvf0mvqfJueaeL/qEkuGJwgtE5pgjIHGYwjc2rMViNCrtY9/Sf+Nu8ww6dDd/Oyk2fwZZP7i0XZfCnETrA==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-http@0.52.1':
-    resolution: {integrity: sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==}
+  '@opentelemetry/instrumentation-fs@0.16.0':
+    resolution: {integrity: sha512-hMDRUxV38ln1R3lNz6osj3YjlO32ykbHqVrzG7gEhGXFQfu7LJUx8t9tEwE4r2h3CD4D0Rw4YGDU4yF4mP3ilg==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-ioredis@0.42.0':
-    resolution: {integrity: sha512-P11H168EKvBB9TUSasNDOGJCSkpT44XgoM6d3gRIWAa9ghLpYhl0uRkS8//MqPzcJVHr3h3RmfXIpiYLjyIZTw==}
+  '@opentelemetry/instrumentation-generic-pool@0.39.0':
+    resolution: {integrity: sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-koa@0.42.0':
-    resolution: {integrity: sha512-H1BEmnMhho8o8HuNRq5zEI4+SIHDIglNB7BPKohZyWG4fWNuR7yM4GTlR01Syq21vODAS7z5omblScJD/eZdKw==}
+  '@opentelemetry/instrumentation-graphql@0.44.0':
+    resolution: {integrity: sha512-FYXTe3Bv96aNpYktqm86BFUTpjglKD0kWI5T5bxYkLUPEPvFn38vWGMJTGrDMVou/i55E4jlWvcm6hFIqLsMbg==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-mongodb@0.46.0':
-    resolution: {integrity: sha512-VF/MicZ5UOBiXrqBslzwxhN7TVqzu1/LN/QDpkskqM0Zm0aZ4CVRbUygL8d7lrjLn15x5kGIe8VsSphMfPJzlA==}
+  '@opentelemetry/instrumentation-hapi@0.41.0':
+    resolution: {integrity: sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-mongoose@0.40.0':
-    resolution: {integrity: sha512-niRi5ZUnkgzRhIGMOozTyoZIvJKNJyhijQI4nF4iFSb+FUx2v5fngfR+8XLmdQAO7xmsD8E5vEGdDVYVtKbZew==}
+  '@opentelemetry/instrumentation-http@0.53.0':
+    resolution: {integrity: sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-mysql2@0.40.0':
-    resolution: {integrity: sha512-0xfS1xcqUmY7WE1uWjlmI67Xg3QsSUlNT+AcXHeA4BDUPwZtWqF4ezIwLgpVZfHOnkAEheqGfNSWd1PIu3Wnfg==}
+  '@opentelemetry/instrumentation-ioredis@0.43.0':
+    resolution: {integrity: sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-mysql@0.40.0':
-    resolution: {integrity: sha512-d7ja8yizsOCNMYIJt5PH/fKZXjb/mS48zLROO4BzZTtDfhNCl2UM/9VIomP2qkGIFVouSJrGr/T00EzY7bPtKA==}
+  '@opentelemetry/instrumentation-kafkajs@0.4.0':
+    resolution: {integrity: sha512-I9VwDG314g7SDL4t8kD/7+1ytaDBRbZQjhVaQaVIDR8K+mlsoBhLsWH79yHxhHQKvwCSZwqXF+TiTOhoQVUt7A==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-nestjs-core@0.39.0':
-    resolution: {integrity: sha512-mewVhEXdikyvIZoMIUry8eb8l3HUjuQjSjVbmLVTt4NQi35tkpnHQrG9bTRBrl3403LoWZ2njMPJyg4l6HfKvA==}
+  '@opentelemetry/instrumentation-knex@0.41.0':
+    resolution: {integrity: sha512-OhI1SlLv5qnsnm2dOVrian/x3431P75GngSpnR7c4fcVFv7prXGYu29Z6ILRWJf/NJt6fkbySmwdfUUnFnHCTg==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-pg@0.43.0':
-    resolution: {integrity: sha512-og23KLyoxdnAeFs1UWqzSonuCkePUzCX30keSYigIzJe/6WSYA8rnEI5lobcxPEzg+GcU06J7jzokuEHbjVJNw==}
+  '@opentelemetry/instrumentation-koa@0.43.0':
+    resolution: {integrity: sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation-redis-4@0.41.0':
-    resolution: {integrity: sha512-H7IfGTqW2reLXqput4yzAe8YpDC0fmVNal95GHMLOrS89W+qWUKIqxolSh63hJyfmwPSFwXASzj7wpSk8Az+Dg==}
+  '@opentelemetry/instrumentation-lru-memoizer@0.40.0':
+    resolution: {integrity: sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
-  '@opentelemetry/instrumentation@0.46.0':
-    resolution: {integrity: sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw==}
+  '@opentelemetry/instrumentation-mongodb@0.48.0':
+    resolution: {integrity: sha512-9YWvaGvrrcrydMsYGLu0w+RgmosLMKe3kv/UNlsPy8RLnCkN2z+bhhbjjjuxtUmvEuKZMCoXFluABVuBr1yhjw==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
+  '@opentelemetry/instrumentation-mongoose@0.42.0':
+    resolution: {integrity: sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-mysql2@0.41.0':
+    resolution: {integrity: sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-mysql@0.41.0':
+    resolution: {integrity: sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-nestjs-core@0.40.0':
+    resolution: {integrity: sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-pg@0.44.0':
+    resolution: {integrity: sha512-oTWVyzKqXud1BYEGX1loo2o4k4vaU1elr3vPO8NZolrBtFvQ34nx4HgUaexUDuEog00qQt+MLR5gws/p+JXMLQ==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-redis-4@0.42.0':
+    resolution: {integrity: sha512-NaD+t2JNcOzX/Qa7kMy68JbmoVIV37fT/fJYzLKu2Wwd+0NCxt+K2OOsOakA8GVg8lSpFdbx4V/suzZZ2Pvdjg==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-tedious@0.15.0':
+    resolution: {integrity: sha512-Kb7yo8Zsq2TUwBbmwYgTAMPK0VbhoS8ikJ6Bup9KrDtCx2JC01nCb+M0VJWXt7tl0+5jARUbKWh5jRSoImxdCw==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation-undici@0.6.0':
+    resolution: {integrity: sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.7.0
+
   '@opentelemetry/instrumentation@0.52.1':
     resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': ^1.3.0
 
+  '@opentelemetry/instrumentation@0.53.0':
+    resolution: {integrity: sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
+  '@opentelemetry/instrumentation@0.54.2':
+    resolution: {integrity: sha512-go6zpOVoZVztT9r1aPd79Fr3OWiD4N24bCPJsIKkBses8oyFo12F/Ew3UBTdIu6hsW4HC4MVEJygG6TEyJI/lg==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@opentelemetry/api': ^1.3.0
+
   '@opentelemetry/redis-common@0.36.2':
     resolution: {integrity: sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==}
     engines: {node: '>=14'}
 
-  '@opentelemetry/resources@1.24.1':
-    resolution: {integrity: sha512-cyv0MwAaPF7O86x5hk3NNgenMObeejZFLJJDVuSeSMIsknlsj3oOZzRv3qSzlwYomXsICfBeFFlxwHQte5mGXQ==}
-    engines: {node: '>=14'}
-    peerDependencies:
-      '@opentelemetry/api': '>=1.0.0 <1.9.0'
-
-  '@opentelemetry/resources@1.25.1':
-    resolution: {integrity: sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==}
+  '@opentelemetry/resources@1.27.0':
+    resolution: {integrity: sha512-jOwt2VJ/lUD5BLc+PMNymDrUCpm5PKi1E9oSVYAvz01U/VdndGmrtV3DU1pG4AwlYhJRHbHfOUIlpBeXCPw6QQ==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': '>=1.0.0 <1.10.0'
 
-  '@opentelemetry/sdk-metrics@1.24.1':
-    resolution: {integrity: sha512-FrAqCbbGao9iKI+Mgh+OsC9+U2YMoXnlDHe06yH7dvavCKzE3S892dGtX54+WhSFVxHR/TMRVJiK/CV93GR0TQ==}
-    engines: {node: '>=14'}
-    peerDependencies:
-      '@opentelemetry/api': '>=1.3.0 <1.9.0'
-
-  '@opentelemetry/sdk-trace-base@1.25.1':
-    resolution: {integrity: sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==}
+  '@opentelemetry/sdk-trace-base@1.27.0':
+    resolution: {integrity: sha512-btz6XTQzwsyJjombpeqCX6LhiMQYpzt2pIYNPnw0IPO/3AhT6yjnf8Mnv3ZC2A4eRYOjqrg+bfaXg9XHDRJDWQ==}
     engines: {node: '>=14'}
     peerDependencies:
       '@opentelemetry/api': '>=1.0.0 <1.10.0'
 
-  '@opentelemetry/semantic-conventions@1.24.1':
-    resolution: {integrity: sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==}
-    engines: {node: '>=14'}
-
   '@opentelemetry/semantic-conventions@1.25.1':
     resolution: {integrity: sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==}
     engines: {node: '>=14'}
 
+  '@opentelemetry/semantic-conventions@1.27.0':
+    resolution: {integrity: sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==}
+    engines: {node: '>=14'}
+
   '@opentelemetry/sql-common@0.40.1':
     resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==}
     engines: {node: '>=14'}
@@ -3512,8 +3301,8 @@ packages:
     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
     engines: {node: '>=14'}
 
-  '@prisma/instrumentation@5.17.0':
-    resolution: {integrity: sha512-c1Sle4ji8aasMcYfBBHFM56We4ljfenVtRmS8aY06BllS7SoU6SmJBwG7vil+GHiR0Yrh+t9iBwt4AY0Jr4KNQ==}
+  '@prisma/instrumentation@5.19.1':
+    resolution: {integrity: sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w==}
 
   '@readme/better-ajv-errors@1.6.0':
     resolution: {integrity: sha512-9gO9rld84Jgu13kcbKRU+WHseNhaVt76wYMeRDGsUGYxwJtI3RmEJ9LY9dZCYQGI8eUZLuxb5qDja0nqklpFjQ==}
@@ -3552,8 +3341,8 @@ packages:
       rollup:
         optional: true
 
-  '@rollup/pluginutils@5.1.2':
-    resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==}
+  '@rollup/pluginutils@5.1.3':
+    resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
       rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
@@ -3561,83 +3350,93 @@ packages:
       rollup:
         optional: true
 
-  '@rollup/rollup-android-arm-eabi@4.22.5':
-    resolution: {integrity: sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==}
+  '@rollup/rollup-android-arm-eabi@4.26.0':
+    resolution: {integrity: sha512-gJNwtPDGEaOEgejbaseY6xMFu+CPltsc8/T+diUTTbOQLqD+bnrJq9ulH6WD69TqwqWmrfRAtUv30cCFZlbGTQ==}
     cpu: [arm]
     os: [android]
 
-  '@rollup/rollup-android-arm64@4.22.5':
-    resolution: {integrity: sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==}
+  '@rollup/rollup-android-arm64@4.26.0':
+    resolution: {integrity: sha512-YJa5Gy8mEZgz5JquFruhJODMq3lTHWLm1fOy+HIANquLzfIOzE9RA5ie3JjCdVb9r46qfAQY/l947V0zfGJ0OQ==}
     cpu: [arm64]
     os: [android]
 
-  '@rollup/rollup-darwin-arm64@4.22.5':
-    resolution: {integrity: sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==}
+  '@rollup/rollup-darwin-arm64@4.26.0':
+    resolution: {integrity: sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==}
     cpu: [arm64]
     os: [darwin]
 
-  '@rollup/rollup-darwin-x64@4.22.5':
-    resolution: {integrity: sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==}
+  '@rollup/rollup-darwin-x64@4.26.0':
+    resolution: {integrity: sha512-wbgkYDHcdWW+NqP2mnf2NOuEbOLzDblalrOWcPyY6+BRbVhliavon15UploG7PpBRQ2bZJnbmh8o3yLoBvDIHA==}
     cpu: [x64]
     os: [darwin]
 
-  '@rollup/rollup-linux-arm-gnueabihf@4.22.5':
-    resolution: {integrity: sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==}
+  '@rollup/rollup-freebsd-arm64@4.26.0':
+    resolution: {integrity: sha512-Y9vpjfp9CDkAG4q/uwuhZk96LP11fBz/bYdyg9oaHYhtGZp7NrbkQrj/66DYMMP2Yo/QPAsVHkV891KyO52fhg==}
+    cpu: [arm64]
+    os: [freebsd]
+
+  '@rollup/rollup-freebsd-x64@4.26.0':
+    resolution: {integrity: sha512-A/jvfCZ55EYPsqeaAt/yDAG4q5tt1ZboWMHEvKAH9Zl92DWvMIbnZe/f/eOXze65aJaaKbL+YeM0Hz4kLQvdwg==}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@rollup/rollup-linux-arm-gnueabihf@4.26.0':
+    resolution: {integrity: sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==}
     cpu: [arm]
     os: [linux]
 
-  '@rollup/rollup-linux-arm-musleabihf@4.22.5':
-    resolution: {integrity: sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==}
+  '@rollup/rollup-linux-arm-musleabihf@4.26.0':
+    resolution: {integrity: sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==}
     cpu: [arm]
     os: [linux]
 
-  '@rollup/rollup-linux-arm64-gnu@4.22.5':
-    resolution: {integrity: sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==}
+  '@rollup/rollup-linux-arm64-gnu@4.26.0':
+    resolution: {integrity: sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==}
     cpu: [arm64]
     os: [linux]
 
-  '@rollup/rollup-linux-arm64-musl@4.22.5':
-    resolution: {integrity: sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==}
+  '@rollup/rollup-linux-arm64-musl@4.26.0':
+    resolution: {integrity: sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==}
     cpu: [arm64]
     os: [linux]
 
-  '@rollup/rollup-linux-powerpc64le-gnu@4.22.5':
-    resolution: {integrity: sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==}
+  '@rollup/rollup-linux-powerpc64le-gnu@4.26.0':
+    resolution: {integrity: sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==}
     cpu: [ppc64]
     os: [linux]
 
-  '@rollup/rollup-linux-riscv64-gnu@4.22.5':
-    resolution: {integrity: sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==}
+  '@rollup/rollup-linux-riscv64-gnu@4.26.0':
+    resolution: {integrity: sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==}
     cpu: [riscv64]
     os: [linux]
 
-  '@rollup/rollup-linux-s390x-gnu@4.22.5':
-    resolution: {integrity: sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==}
+  '@rollup/rollup-linux-s390x-gnu@4.26.0':
+    resolution: {integrity: sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==}
     cpu: [s390x]
     os: [linux]
 
-  '@rollup/rollup-linux-x64-gnu@4.22.5':
-    resolution: {integrity: sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==}
+  '@rollup/rollup-linux-x64-gnu@4.26.0':
+    resolution: {integrity: sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==}
     cpu: [x64]
     os: [linux]
 
-  '@rollup/rollup-linux-x64-musl@4.22.5':
-    resolution: {integrity: sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==}
+  '@rollup/rollup-linux-x64-musl@4.26.0':
+    resolution: {integrity: sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==}
     cpu: [x64]
     os: [linux]
 
-  '@rollup/rollup-win32-arm64-msvc@4.22.5':
-    resolution: {integrity: sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==}
+  '@rollup/rollup-win32-arm64-msvc@4.26.0':
+    resolution: {integrity: sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==}
     cpu: [arm64]
     os: [win32]
 
-  '@rollup/rollup-win32-ia32-msvc@4.22.5':
-    resolution: {integrity: sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==}
+  '@rollup/rollup-win32-ia32-msvc@4.26.0':
+    resolution: {integrity: sha512-D4CxkazFKBfN1akAIY6ieyOqzoOoBV1OICxgUblWxff/pSjCA2khXlASUx7mK6W1oP4McqhgcCsu6QaLj3WMWg==}
     cpu: [ia32]
     os: [win32]
 
-  '@rollup/rollup-win32-x64-msvc@4.22.5':
-    resolution: {integrity: sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==}
+  '@rollup/rollup-win32-x64-msvc@4.26.0':
+    resolution: {integrity: sha512-2x8MO1rm4PGEP0xWbubJW5RtbNLk3puzAMaLQd3B3JHVw4KcHlmXcO+Wewx9zCoo7EUFiMlu/aZbCJ7VjMzAag==}
     cpu: [x64]
     os: [win32]
 
@@ -3663,57 +3462,57 @@ packages:
       '@types/node':
         optional: true
 
-  '@rushstack/ts-command-line@4.22.8':
-    resolution: {integrity: sha512-XbFjOoV7qZHJnSuFUHv0pKaFA4ixyCuki+xMjsMfDwfvQjs5MYG0IK5COal3tRnG7KCDe2l/G+9LrzYE/RJhgg==}
+  '@rushstack/ts-command-line@4.23.0':
+    resolution: {integrity: sha512-jYREBtsxduPV6ptNq8jOKp9+yx0ld1Tb/Tkdnlj8gTjazl1sF3DwX2VbluyYrNd0meWIL0bNeer7WDf5tKFjaQ==}
 
   '@sec-ant/readable-stream@0.4.1':
     resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
 
-  '@sentry/core@8.20.0':
-    resolution: {integrity: sha512-R81snuw+67VT4aCxr6ShST/s0Y6FlwN2YczhDwaGyzumn5rlvA6A4JtQDeExduNoDDyv4T3LrmW8wlYZn3CJJw==}
+  '@sentry/core@8.38.0':
+    resolution: {integrity: sha512-sGD+5TEHU9G7X7zpyaoJxpOtwjTjvOd1f/MKBrWW2vf9UbYK+GUJrOzLhMoSWp/pHSYgvObkJkDb/HwieQjvhQ==}
     engines: {node: '>=14.18'}
 
-  '@sentry/node@8.20.0':
-    resolution: {integrity: sha512-i4ywT2m0Gw65U3uwI4NwiNcyqp9YF6/RsusfH1pg4YkiL/RYp7FS0MPVgMggfvoue9S3KjCgRVlzTLwFATyPXQ==}
+  '@sentry/node@8.38.0':
+    resolution: {integrity: sha512-nwW0XqZFQseXYn0i6i6nKPkbjgHMBEFSF9TnK6mHHqJHHObHIZ6qu5CfvGKgxATia8JPIg9NN8XcyYOnQMi07w==}
     engines: {node: '>=14.18'}
 
-  '@sentry/opentelemetry@8.20.0':
-    resolution: {integrity: sha512-NFcLK6+t9wUc4HlGKeuDn6W4KjZxZfZmWlrK2/tgC5KzG1cnVeOnWUrJzGHTa+YDDdIijpjiFUcpXGPkX3rmIg==}
+  '@sentry/opentelemetry@8.38.0':
+    resolution: {integrity: sha512-AfjmIf/v7+x2WplhkX66LyGKvrzzPeSgff9uJ0cFCC2s0yd1qA2VPuIwEyr5i/FOJOP5bvFr8tu/hz3LA4+F5Q==}
     engines: {node: '>=14.18'}
     peerDependencies:
       '@opentelemetry/api': ^1.9.0
       '@opentelemetry/core': ^1.25.1
-      '@opentelemetry/instrumentation': ^0.52.1
-      '@opentelemetry/sdk-trace-base': ^1.25.1
-      '@opentelemetry/semantic-conventions': ^1.25.1
+      '@opentelemetry/instrumentation': ^0.54.0
+      '@opentelemetry/sdk-trace-base': ^1.26.0
+      '@opentelemetry/semantic-conventions': ^1.27.0
 
-  '@sentry/profiling-node@8.20.0':
-    resolution: {integrity: sha512-vQaMYjPM7o0qvmj4atxXZywIDhnxMwTlc6x24eKqT8zN0OFBuIc1nYIacT7pEmd7R6e/mXdiG04GH1Vg0bHfOQ==}
+  '@sentry/profiling-node@8.38.0':
+    resolution: {integrity: sha512-7I+hANLQRUAciRLzz4nUehEUHYeMNKkMfu6KkBuLcD1F3x7Y/tcxyHlHl+bNKf6tyUdW7IKGb+7Pk/WKMBnZrg==}
     engines: {node: '>=14.18'}
     hasBin: true
 
-  '@sentry/types@8.20.0':
-    resolution: {integrity: sha512-6IP278KojOpiAA7vrd1hjhUyn26cl0n0nGsShzic5ztCVs92sTeVRnh7MTB9irDVtAbOEyt/YH6go3h+Jia1pA==}
+  '@sentry/types@8.38.0':
+    resolution: {integrity: sha512-fP5H9ZX01W4Z/EYctk3mkSHi7d06cLcX2/UWqwdWbyPWI+pL2QpUPICeO/C+8SnmYx//wFj3qWDhyPCh1PdFAA==}
     engines: {node: '>=14.18'}
 
-  '@sentry/utils@8.20.0':
-    resolution: {integrity: sha512-+1I5H8dojURiEUGPliDwheQk8dhjp8uV1sMccR/W/zjFrt4wZyPs+Ttp/V7gzm9LDJoNek9tmELert/jQqWTgg==}
+  '@sentry/utils@8.38.0':
+    resolution: {integrity: sha512-3X7MgIKIx+2q5Al7QkhaRB4wV6DvzYsaeIwdqKUzGLuRjXmNgJrLoU87TAwQRmZ6Wr3IoEpThZZMNrzYPXxArw==}
     engines: {node: '>=14.18'}
 
-  '@shikijs/core@1.21.0':
-    resolution: {integrity: sha512-zAPMJdiGuqXpZQ+pWNezQAk5xhzRXBNiECFPcJLtUdsFM3f//G95Z15EHTnHchYycU8kIIysqGgxp8OVSj1SPQ==}
+  '@shikijs/core@1.22.2':
+    resolution: {integrity: sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==}
 
-  '@shikijs/engine-javascript@1.21.0':
-    resolution: {integrity: sha512-jxQHNtVP17edFW4/0vICqAVLDAxmyV31MQJL4U/Kg+heQALeKYVOWo0sMmEZ18FqBt+9UCdyqGKYE7bLRtk9mg==}
+  '@shikijs/engine-javascript@1.22.2':
+    resolution: {integrity: sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==}
 
-  '@shikijs/engine-oniguruma@1.21.0':
-    resolution: {integrity: sha512-AIZ76XocENCrtYzVU7S4GY/HL+tgHGbVU+qhiDyNw1qgCA5OSi4B4+HY4BtAoJSMGuD/L5hfTzoRVbzEm2WTvg==}
+  '@shikijs/engine-oniguruma@1.22.2':
+    resolution: {integrity: sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==}
 
-  '@shikijs/types@1.21.0':
-    resolution: {integrity: sha512-tzndANDhi5DUndBtpojEq/42+dpUF2wS7wdCDQaFtIXm3Rd1QkrcVgSSRLOvEwexekihOXfbYJINW37g96tJRw==}
+  '@shikijs/types@1.22.2':
+    resolution: {integrity: sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==}
 
-  '@shikijs/vscode-textmate@9.2.2':
-    resolution: {integrity: sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==}
+  '@shikijs/vscode-textmate@9.3.0':
+    resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==}
 
   '@sideway/address@4.1.4':
     resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
@@ -3734,6 +3533,9 @@ packages:
   '@simplewebauthn/types@10.0.0':
     resolution: {integrity: sha512-SFXke7xkgPRowY2E+8djKbdEznTVnD5R6GO7GPTthpHrokLvNKw8C3lFZypTxLI7KkCfGPfhtqB3d7OVGGa9jQ==}
 
+  '@simplewebauthn/types@11.0.0':
+    resolution: {integrity: sha512-b2o0wC5u2rWts31dTgBkAtSNKGX0cvL6h8QedNsKmj8O4QoLFQFR3DBVBUlpyVEhYKA+mXGUaXbcOc4JdQ3HzA==}
+
   '@sinclair/typebox@0.27.8':
     resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
 
@@ -3745,8 +3547,8 @@ packages:
     resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==}
     engines: {node: '>=14.16'}
 
-  '@sindresorhus/is@7.0.0':
-    resolution: {integrity: sha512-WDTlVTyvFivSOuyvMeedzg2hdoBLZ3f1uNVuEida2Rl9BrfjrIRjWA/VZIrMRLvSwJYCAlCRA3usDt1THytxWQ==}
+  '@sindresorhus/is@7.0.1':
+    resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==}
     engines: {node: '>=18'}
 
   '@sindresorhus/merge-streams@4.0.0':
@@ -4001,125 +3803,120 @@ packages:
   '@sqltools/formatter@1.2.5':
     resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==}
 
-  '@storybook/addon-actions@8.3.4':
-    resolution: {integrity: sha512-1y0yD3upKcyzNwwA6loAGW2cRDqExwl4oAT7GJQA4tmabI+fNwmANSgU/ezLvvSUf4Qo0eJHg2Zcn8y+Apq2eA==}
+  '@storybook/addon-actions@8.4.4':
+    resolution: {integrity: sha512-+Dd6alcieS6UN7IKhXLuhyQYQMu9HG/Tdr790a4EOQKpJM1NxIMuPuUH3fAoKfa9VhtI1BxTBr7zNtzg9Akqhg==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-backgrounds@8.3.4':
-    resolution: {integrity: sha512-o3nl7cN3x8erJNxLEv8YptanEQAnbqnaseOAsvSC6/nnSAcRYBSs3BvekKvo4CcpS2mxn7F5NJTBFYnCXzy8EA==}
+  '@storybook/addon-backgrounds@8.4.4':
+    resolution: {integrity: sha512-asaGD4ruIPFthyhpByQSJagvtNN7EGKdHj5yMnsMvkSXnN0r1uVkI2/Z37hmLt02Qbzf6OQiBPW5TDL+X+EEBg==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-controls@8.3.4':
-    resolution: {integrity: sha512-qQcaK6dczsb6wXkzGZKOjUYNA7FfKBewRv6NvoVKYY6LfhllGOkmUAtYpdtQG8adsZWTSoZaAOJS2vP2uM67lw==}
+  '@storybook/addon-controls@8.4.4':
+    resolution: {integrity: sha512-FbZRbwJQggLz6M3zB6scCp1SDGwQ5zdiD6sjBilZzgGO5rBFqG0A8PoOyr4iPrLU2y/NZBdRrJBD+6MkaJ+yzw==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-docs@8.3.4':
-    resolution: {integrity: sha512-TWauhqF/gJgfwPuWeM6KM3LwC+ErCOM+K2z16w3vgao9s67sij8lnrdAoQ0hjA+kw2/KAdCakFS6FyciG81qog==}
+  '@storybook/addon-docs@8.4.4':
+    resolution: {integrity: sha512-wuHaStfpd2rkAN5Lf0qmvE3JKTHTEDbnAMTvfs9inzGBL0iAwBLjW48/ll7lLkJ2E3k/FQtaevNpuc7C52u1Bw==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-essentials@8.3.4':
-    resolution: {integrity: sha512-C3+3hpmSn/8zdx5sXEP0eE6zMzxgRosHVZYfe9nBcMiEDp6UKVUyHVetWxEULOEgN46ysjcpllZ0bUkRYxi2IQ==}
+  '@storybook/addon-essentials@8.4.4':
+    resolution: {integrity: sha512-0ObUQ98zZkeWqP2k3Un5jny3WxT3THgUKZUGD+mR8eq6CuTmJ3bUXWzDHreuDxQwgr8s5f04XD8IcRvjZ9IRgA==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-highlight@8.3.4':
-    resolution: {integrity: sha512-rxZTeuZyZ7RnU+xmRhS01COFLbGnVEmlUNxBw8ArsrTEZKW5PbKpIxNLTj9F0zdH8H0MfryJGP+Aadcm0oHWlw==}
+  '@storybook/addon-highlight@8.4.4':
+    resolution: {integrity: sha512-k7EUxiMe8RCasmgfa6ZKx7UG6kU9RooTYGwqY5TG5xAQOzDwKn4qom+OYkT/9/6lORhJrUe2GgQLCrq/WGpS1A==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-interactions@8.3.4':
-    resolution: {integrity: sha512-ORxqe35wUmF7EDHo45mdDHiju3Ryk2pZ1vO9PyvW6ZItNlHt/IxAr7T/TysGejZ/eTBg6tMZR3ExGky3lTg/CQ==}
+  '@storybook/addon-interactions@8.4.4':
+    resolution: {integrity: sha512-izqcc6tY0BiKW7DYrEnoXUEH9FYDPWNfQnqqE0nVBv3BS2DoNmm8M9SB8fZx7pPfw53cMJBGt3vrlY0Wtxy1+Q==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-links@8.3.4':
-    resolution: {integrity: sha512-R1DjARmxRIKJDGIG6uxmQ1yFNyoQbb+QIPUFjgWCak8+AdLJbC7W+Esvo9F5hQfh6czyy0piiM3qj5hpQJVh3A==}
+  '@storybook/addon-links@8.4.4':
+    resolution: {integrity: sha512-hqTv06fPq9k5GUZD8JR49ANw5sBg8EYAsuCNoSd9OwVSBO/3y53HrMA0NCILUK8hnupPvtBuKXXoHmHes9R+1g==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
-      storybook: ^8.3.4
+      storybook: ^8.4.4
     peerDependenciesMeta:
       react:
         optional: true
 
-  '@storybook/addon-mdx-gfm@8.3.4':
-    resolution: {integrity: sha512-O0sMP7VFo1fKsdViY+W6OMNYEXvB5FzEEsqgsydMcsJ0qOKR1li2l3cLCMLXdUKVZ+2uRbEhnm2RnB9RWF5O7g==}
+  '@storybook/addon-mdx-gfm@8.4.4':
+    resolution: {integrity: sha512-dj98NGWowhSwWYn2LUaLMxHNvBY+73n9CFsELrttg24nOxmeRfku0uh2hp5epMmRMX3Fej7nCkKNJaU1fihZ+Q==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-measure@8.3.4':
-    resolution: {integrity: sha512-IJ6WKEbqmG+r7sukFjo+bVmPB2Zry04sylGx/OGyOh7zIhhqAqpwOwMHP0uQrc3tLNnUM6qB/o83UyYX79ql+A==}
+  '@storybook/addon-measure@8.4.4':
+    resolution: {integrity: sha512-KsjrwrXwrI+z7hKKfjyY1w1b0gLSLZmp15vIRJMELybWV0+4bZFLJGwMBOQFx+aWBED8yZrRV9OjTmoczawsZg==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-outline@8.3.4':
-    resolution: {integrity: sha512-kRRJTTLKM8gMfeh/e83djN5XLlc0hFtr9zKWxuZxaXt9Hmr+9tH/PRFtVK/S4SgqnBDoXk49Wgv6raiwj5/e3A==}
+  '@storybook/addon-outline@8.4.4':
+    resolution: {integrity: sha512-CVS1dm6BNUWKGrJj9E1ThBp5Khe6Yw+Hhz6OFxrPZfoTr6RstwoTmvSpKjDUCn8zj6ujoORdiQUh1FsHOxAPBg==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-storysource@8.3.4':
-    resolution: {integrity: sha512-uHTUiK7dzWRZAKpPafBH3U5PWAP7+J97lg66HDKAHpmmQdy7v3HfXaYNX1FoI+PeC5piUxFETXM0z+BNvJCknA==}
+  '@storybook/addon-storysource@8.4.4':
+    resolution: {integrity: sha512-BuMQMQvYqiaosbGkUxDPU2nfZtI2E/zxpNaubpUAH2j+bx4zdXRXyW1P71wj5GZC84bszoyXhdd++9A0knmaYA==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-toolbars@8.3.4':
-    resolution: {integrity: sha512-Km1YciVIxqluDbd1xmHjANNFyMonEOtnA6e4MrnBnC9XkPXSigeFlj0JvxyI/zjBsLBoFRmQiwq55W6l3hQ9sA==}
+  '@storybook/addon-toolbars@8.4.4':
+    resolution: {integrity: sha512-ENPshJMDpfzOJ4Tgm1hSzQoaEmgDxCtP6C8LKk4MOd3X92MJ7p6kfb3y3R1BLg4E/g90qp6lKPFdcohS2tKCgQ==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/addon-viewport@8.3.4':
-    resolution: {integrity: sha512-fU4LdXSSqIOLbCEh2leq/tZUYlFliXZBWr/+igQHdUoU7HY8RIImXqVUaR9wlCaTb48WezAWT60vJtwNijyIiQ==}
+  '@storybook/addon-viewport@8.4.4':
+    resolution: {integrity: sha512-SRHJlLhf3tu7+sYNfVIYTeMegn6aiv4HGX97ZLvL76NWWBU8BntQ1LKMki7475mWiZNUFMoYYPsHlG+HU9FAtg==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/blocks@8.3.4':
-    resolution: {integrity: sha512-1g4aCrd5CcN+pVhF2ATu9ZRVvAIgBMb2yF9KkCuTpdvqKDuDNK3sGb0CxjS7jp3LOvyjJr9laTOQsz8v8MQc5A==}
+  '@storybook/blocks@8.4.4':
+    resolution: {integrity: sha512-LwM3guL7uWpYR1a/SY0KZjCUskTKEaS22eF7GK8iXAV5BY4KpKr6ArW4O9orK29KtFwKhDZQLcMcECsOJBVk/A==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
       react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
-      storybook: ^8.3.4
+      storybook: ^8.4.4
     peerDependenciesMeta:
       react:
         optional: true
       react-dom:
         optional: true
 
-  '@storybook/builder-vite@8.3.4':
-    resolution: {integrity: sha512-Sa6SZ7LeHpkrnuvua8P8MR8e8a+MPKbyMmr9TqCCy8Ud/t4AM4kHY3JpJGtrgeK9l43fBnBwfdZYoRl5J6oWeA==}
+  '@storybook/builder-vite@8.4.4':
+    resolution: {integrity: sha512-UfPzE0p2xvBK7sA853N3VN+Plfw6/DIVppwbgsaRdzie52QXZQrl60u0igD47DHi6+xbqCBWDz7up4h3k00Z5A==}
     peerDependencies:
-      '@preact/preset-vite': '*'
-      storybook: ^8.3.4
-      typescript: '>= 4.3.x'
+      storybook: ^8.4.4
       vite: ^4.0.0 || ^5.0.0
-      vite-plugin-glimmerx: '*'
+
+  '@storybook/components@8.4.4':
+    resolution: {integrity: sha512-0BSZVmsk23C0BSRKx3liZSVQFXtoF86XQFdNQxjrXIwdHIEN7TcL3DwcxeVUU5ilGp7HeDgAydGNIPGgTeEe6g==}
+    peerDependencies:
+      storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
+
+  '@storybook/core-events@8.4.4':
+    resolution: {integrity: sha512-pkwr0UU95WSJtn9Q7q5ip0x8WxerLf5z4CWonvymGu9Z0bZyMXeA+GOEt/YQIJgqI4fbTK8Jqi+suC6ibUu9oQ==}
+    peerDependencies:
+      storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
+
+  '@storybook/core@8.4.4':
+    resolution: {integrity: sha512-WjTmJpsHsFCd7tQ/8jFpDWjhntauXcWYYTcEZk56Pq4miyNrrXhV0S80Gxv3Uvzk0jocgtT2AKf8rQuH2UkQEg==}
+    peerDependencies:
+      prettier: ^2 || ^3
     peerDependenciesMeta:
-      '@preact/preset-vite':
-        optional: true
-      typescript:
-        optional: true
-      vite-plugin-glimmerx:
+      prettier:
         optional: true
 
-  '@storybook/components@8.3.4':
-    resolution: {integrity: sha512-iQzLJd87uGbFBbYNqlrN/ABrnx3dUrL0tjPCarzglzshZoPCNOsllJeJx5TJwB9kCxSZ8zB9TTOgr7NXl+oyVA==}
+  '@storybook/csf-plugin@8.4.4':
+    resolution: {integrity: sha512-4+6SUhp5sEJN9BY5RuxcFKvJbOqCzIUp9oHSSz36hkP07a4QH+SwxfEd0U7JRfmPpB63L+izywTzWhdADiAMOQ==}
     peerDependencies:
-      storybook: ^8.3.4
-
-  '@storybook/core-events@8.3.4':
-    resolution: {integrity: sha512-3/5oJN2UnlmUILXCh7SXMTa2MYZOvrjeZCm3wFomoQASU2FFzS5AxBYYnwNdtrZmn4w32uw4T7qvA0+96Utwsg==}
-    peerDependencies:
-      storybook: ^8.3.4
-
-  '@storybook/core@8.3.4':
-    resolution: {integrity: sha512-4PZB91JJpuKfcjeOR2LXj3ABaPLLSd2P/SfYOKNCygrDstsQa/yay3/yN5Z9yi1cIG84KRr6/sUW+0x8HsGLPg==}
-
-  '@storybook/csf-plugin@8.3.4':
-    resolution: {integrity: sha512-ZMFWYxeTN4GxCn8dyIH4roECyLDy29yv/QKM+pHM3AC5Ny2HWI35SohWao4fGBAFxPQFbR5hPN8xa6ofHPSSTg==}
-    peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
   '@storybook/csf@0.1.11':
     resolution: {integrity: sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==}
@@ -4134,45 +3931,45 @@ packages:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0
       react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
 
-  '@storybook/instrumenter@8.3.4':
-    resolution: {integrity: sha512-jVhfNOPekOyJmta0BTkQl9Z6rgRbFHlc0eV4z1oSrzaawSlc9TFzAeDCtCP57vg3FuBX8ydDYAvyZ7s4xPpLyg==}
+  '@storybook/instrumenter@8.4.4':
+    resolution: {integrity: sha512-mq/YVEZrB8jyyio2Of01rQixsQ72z8ssAhJS9ldIlK+cvERQi0VBCpH3pejPmjOB40yiKBJHNqH4HIANVhibgw==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/manager-api@8.3.4':
-    resolution: {integrity: sha512-tBx7MBfPUrKSlD666zmVjtIvoNArwCciZiW/UJ8IWmomrTJRfFBnVvPVM2gp1lkDIzRHYmz5x9BHbYaEDNcZWQ==}
+  '@storybook/manager-api@8.4.4':
+    resolution: {integrity: sha512-rmNPcbEyzakEHoaecUbhkW7WWOkyZ0z7ywH4d5/s0ZuQS57Px2N+ZLVgRJwYK+YNHiJYqDf1BTln9YJ/Mt1L6Q==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
 
-  '@storybook/preview-api@8.3.4':
-    resolution: {integrity: sha512-/YKQ3QDVSHmtFXXCShf5w0XMlg8wkfTpdYxdGv1CKFV8DU24f3N7KWulAgeWWCWQwBzZClDa9kzxmroKlQqx3A==}
+  '@storybook/preview-api@8.4.4':
+    resolution: {integrity: sha512-iZrWQcjRBqBHFdDXVxGpw6mHBZMCMYqhWXdyJ0d1S2y3PwcfOjkcXlQ1UiAenFHlA6dKrcYw8luKUQTL9bKReA==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
 
-  '@storybook/react-dom-shim@8.3.4':
-    resolution: {integrity: sha512-L4llDvjaAzqPx6h4ddZMh36wPr75PrI2S8bXy+flLqAeVRYnRt4WNKGuxqH0t0U6MwId9+vlCZ13JBfFuY7eQQ==}
+  '@storybook/react-dom-shim@8.4.4':
+    resolution: {integrity: sha512-kufv2FDK3kjADBo+/aKHsUn9T5E4p9IBAmCoIvXBGRDumPRds7Pt3MB4ODKlg+IumR7LMEq0jTJkn27ZRTuUmw==}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
       react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/react-vite@8.3.4':
-    resolution: {integrity: sha512-0Xm8eTH+jQ7SV4moLkPN4G6U2IDrqXPXUqsZdXaccepIMcD4G75foQFm2LOrFJuY+IMySPspKeTqf8OLskPppw==}
+  '@storybook/react-vite@8.4.4':
+    resolution: {integrity: sha512-NbTAY4R526hJ+gz7BFLS1HpGx3BikQDbq1BuEcaWsf/rJnygwlzeQmdPyfrfNC8R0ufIKRWUiPrPmMvrf8ZI6A==}
     engines: {node: '>=18.0.0'}
     peerDependencies:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
       react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
-      storybook: ^8.3.4
+      storybook: ^8.4.4
       vite: ^4.0.0 || ^5.0.0
 
-  '@storybook/react@8.3.4':
-    resolution: {integrity: sha512-PA7iQL4/9X2/iLrv+AUPNtlhTHJWhDao9gQIT1Hef39FtFk+TU9lZGbv+g29R1H9V3cHP5162nG2aTu395kmbA==}
+  '@storybook/react@8.4.4':
+    resolution: {integrity: sha512-92lGnRcAI2qW6zH8GMBScyXmOS1ANI8ZuSP4ExQj+lGsCrAr7PBr0wuHy3wIn1YyAvQGPUn/mpYrmMz08c2HfA==}
     engines: {node: '>=18.0.0'}
     peerDependencies:
-      '@storybook/test': 8.3.4
+      '@storybook/test': 8.4.4
       react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
       react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
-      storybook: ^8.3.4
+      storybook: ^8.4.4
       typescript: '>= 4.2.x'
     peerDependenciesMeta:
       '@storybook/test':
@@ -4180,38 +3977,38 @@ packages:
       typescript:
         optional: true
 
-  '@storybook/source-loader@8.3.4':
-    resolution: {integrity: sha512-wH//LuWfa2iOmjykSqsub8M8e0EdhEUZoHUFhwBeizfYQQHaMaSEBhhAQCaWWKmdGB9lnCe1cioQ32c2IWtBIw==}
+  '@storybook/source-loader@8.4.4':
+    resolution: {integrity: sha512-xaC23ljSEpHSMdp/VdqKd1o4Dr7x5lA2897RR6SKFRFDgkKD5Mp1UXsrcwqSZNSeXETTmVWXf8rHrz14VKkK6w==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/test@8.3.4':
-    resolution: {integrity: sha512-HRiUenitln8QPHu6DEWUg9s9cEoiGN79lMykzXzw9shaUvdEIhWCsh82YKtmB3GJPj6qcc6dZL/Aio8srxyGAg==}
+  '@storybook/test@8.4.4':
+    resolution: {integrity: sha512-tmJd+lxl3MC0Xdu1KW/69V8tibv98OvdopxGqfVR0x5dkRHM3sFK/tv1ZJAUeronlvRyhGySOu1tHUrMjcNqyA==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
 
-  '@storybook/theming@8.3.4':
-    resolution: {integrity: sha512-D4XVsQgTtpHEHLhwkx59aGy1GBwOedVr/mNns7hFrH8FjEpxrrWCuZQASq1ZpCl8LXlh7uvmT5sM2rOdQbGuGg==}
+  '@storybook/theming@8.4.4':
+    resolution: {integrity: sha512-iq4yt3Fx35ZV5owNC//E6G+QPV19xHHVN2Ugi3p7KOSFK3chuXX9mxZ1rfir+t+U30a5EPOEnlsY3/1LXn7aTw==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
 
-  '@storybook/types@8.3.4':
-    resolution: {integrity: sha512-kIyb0g8C6EizI0Mv+l6L6yjCJe9/vW3UvgsZL5BXqs8THTAfs3/+A9Q9jDEMovSIVI3EgesO79+OCEazDUHmOA==}
+  '@storybook/types@8.4.4':
+    resolution: {integrity: sha512-NUeIhecJ+i2ul/u/ftV+f9gBT2cUOuLjgy1a+l0UbJd7n3wwN17vX2zrrDkrGG3dp3edr8bWMGjAN3WERJje1A==}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
 
-  '@storybook/vue3-vite@8.3.4':
-    resolution: {integrity: sha512-0H1tLbRd8i6L3EW8QC9bDlgPIUM5i6b7onvyyQhyIxODWRfigHi6UP9sjHfrljdvnlOtYlZT2A5QbpkugzwLjg==}
+  '@storybook/vue3-vite@8.4.4':
+    resolution: {integrity: sha512-cyhPX16KzOWuHZCcMXqJ+k11xOvelWXmML6pSvhV0OtizDHxgesCdbSa1X1P76ZszjOlt8MJfPiSaE+XNwB0UQ==}
     engines: {node: '>=18.0.0'}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
       vite: ^4.0.0 || ^5.0.0
 
-  '@storybook/vue3@8.3.4':
-    resolution: {integrity: sha512-NNQXwidr+QjLndORWtPjXv/obsNNfJhP5Xj6vUZslrDpdIyTL3NEM+ktLK2EMw/a3zUbJMnMkyMgoWvioCNHxQ==}
+  '@storybook/vue3@8.4.4':
+    resolution: {integrity: sha512-HVUtE8x4nIJeCO592VNyrACMgGA6ViarRS6Faw+MWdUQXnZlwkadGusx2T++hnaalAt9VJLF5NRIcV8O7dA6Ig==}
     engines: {node: '>=18.0.0'}
     peerDependencies:
-      storybook: ^8.3.4
+      storybook: ^8.4.4
       vue: ^3.0.0
 
   '@swc/cli@0.3.12':
@@ -4237,14 +4034,8 @@ packages:
     cpu: [arm64]
     os: [darwin]
 
-  '@swc/core-darwin-arm64@1.6.13':
-    resolution: {integrity: sha512-SOF4buAis72K22BGJ3N8y88mLNfxLNprTuJUpzikyMGrvkuBFNcxYtMhmomO0XHsgLDzOJ+hWzcgjRNzjMsUcQ==}
-    engines: {node: '>=10'}
-    cpu: [arm64]
-    os: [darwin]
-
-  '@swc/core-darwin-arm64@1.6.6':
-    resolution: {integrity: sha512-5DA8NUGECcbcK1YLKJwNDKqdtTYDVnkfDU1WvQSXq/rU+bjYCLtn5gCe8/yzL7ISXA6rwqPU1RDejhbNt4ARLQ==}
+  '@swc/core-darwin-arm64@1.9.2':
+    resolution: {integrity: sha512-nETmsCoY29krTF2PtspEgicb3tqw7Ci5sInTI03EU5zpqYbPjoPH99BVTjj0OsF53jP5MxwnLI5Hm21lUn1d6A==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [darwin]
@@ -4255,14 +4046,8 @@ packages:
     cpu: [x64]
     os: [darwin]
 
-  '@swc/core-darwin-x64@1.6.13':
-    resolution: {integrity: sha512-AW8akFSC+tmPE6YQQvK9S2A1B8pjnXEINg+gGgw0KRUUXunvu1/OEOeC5L2Co1wAwhD7bhnaefi06Qi9AiwOag==}
-    engines: {node: '>=10'}
-    cpu: [x64]
-    os: [darwin]
-
-  '@swc/core-darwin-x64@1.6.6':
-    resolution: {integrity: sha512-2nbh/RHpweNRsJiYDFk1KcX7UtaKgzzTNUjwtvK5cp0wWrpbXmPvdlWOx3yzwoiSASDFx78242JHHXCIOlEdsw==}
+  '@swc/core-darwin-x64@1.9.2':
+    resolution: {integrity: sha512-9gD+bwBz8ZByjP6nZTXe/hzd0tySIAjpDHgkFiUrc+5zGF+rdTwhcNrzxNHJmy6mw+PW38jqII4uspFHUqqxuQ==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [darwin]
@@ -4279,14 +4064,8 @@ packages:
     cpu: [arm]
     os: [linux]
 
-  '@swc/core-linux-arm-gnueabihf@1.6.13':
-    resolution: {integrity: sha512-f4gxxvDXVUm2HLYXRd311mSrmbpQF2MZ4Ja6XCQz1hWAxXdhRl1gpnZ+LH/xIfGSwQChrtLLVrkxdYUCVuIjFg==}
-    engines: {node: '>=10'}
-    cpu: [arm]
-    os: [linux]
-
-  '@swc/core-linux-arm-gnueabihf@1.6.6':
-    resolution: {integrity: sha512-YgytuyUfR7b0z0SRHKV+ylr83HmgnROgeT7xryEkth6JGpAEHooCspQ4RrWTU8+WKJ7aXiZlGXPgybQ4TiS+TA==}
+  '@swc/core-linux-arm-gnueabihf@1.9.2':
+    resolution: {integrity: sha512-kYq8ief1Qrn+WmsTWAYo4r+Coul4dXN6cLFjiPZ29Cv5pyU+GFvSPAB4bEdMzwy99rCR0u2P10UExaeCjurjvg==}
     engines: {node: '>=10'}
     cpu: [arm]
     os: [linux]
@@ -4297,14 +4076,8 @@ packages:
     cpu: [arm64]
     os: [linux]
 
-  '@swc/core-linux-arm64-gnu@1.6.13':
-    resolution: {integrity: sha512-Nf/eoW2CbG8s+9JoLtjl9FByBXyQ5cjdBsA4efO7Zw4p+YSuXDgc8HRPC+E2+ns0praDpKNZtLvDtmF2lL+2Gg==}
-    engines: {node: '>=10'}
-    cpu: [arm64]
-    os: [linux]
-
-  '@swc/core-linux-arm64-gnu@1.6.6':
-    resolution: {integrity: sha512-yGwx9fddzEE0iURqRVwKBQ4IwRHE6hNhl15WliHpi/PcYhzmYkUIpcbRXjr0dssubXAVPVnx6+jZVDSbutvnfg==}
+  '@swc/core-linux-arm64-gnu@1.9.2':
+    resolution: {integrity: sha512-n0W4XiXlmEIVqxt+rD3ZpkogsEWUk1jJ+i5bQNgB+1JuWh0fBE8c/blDgTQXa0GB5lTPVDZQussgdNOCnAZwiA==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [linux]
@@ -4315,14 +4088,8 @@ packages:
     cpu: [arm64]
     os: [linux]
 
-  '@swc/core-linux-arm64-musl@1.6.13':
-    resolution: {integrity: sha512-2OysYSYtdw79prJYuKIiux/Gj0iaGEbpS2QZWCIY4X9sGoETJ5iMg+lY+YCrIxdkkNYd7OhIbXdYFyGs/w5LDg==}
-    engines: {node: '>=10'}
-    cpu: [arm64]
-    os: [linux]
-
-  '@swc/core-linux-arm64-musl@1.6.6':
-    resolution: {integrity: sha512-a6fMbqzSAsS5KCxFJyg1mD5kwN3ZFO8qQLyJ75R/htZP/eCt05jrhmOI7h2n+1HjiG332jLnZ9S8lkVE5O8Nqw==}
+  '@swc/core-linux-arm64-musl@1.9.2':
+    resolution: {integrity: sha512-8xzrOmsyCC1zrx2Wzx/h8dVsdewO1oMCwBTLc1gSJ/YllZYTb04pNm6NsVbzUX2tKddJVRgSJXV10j/NECLwpA==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [linux]
@@ -4333,14 +4100,8 @@ packages:
     cpu: [x64]
     os: [linux]
 
-  '@swc/core-linux-x64-gnu@1.6.13':
-    resolution: {integrity: sha512-PkR4CZYJNk5hcd2+tMWBpnisnmYsUzazI1O5X7VkIGFcGePTqJ/bWlfUIVVExWxvAI33PQFzLbzmN5scyIUyGQ==}
-    engines: {node: '>=10'}
-    cpu: [x64]
-    os: [linux]
-
-  '@swc/core-linux-x64-gnu@1.6.6':
-    resolution: {integrity: sha512-hRGsUKNzzZle28YF0dYIpN0bt9PceR9LaVBq7x8+l9TAaDLFbgksSxcnU/ubTtsy+WsYSYGn+A83w3xWC0O8CQ==}
+  '@swc/core-linux-x64-gnu@1.9.2':
+    resolution: {integrity: sha512-kZrNz/PjRQKcchWF6W292jk3K44EoVu1ad5w+zbS4jekIAxsM8WwQ1kd+yjUlN9jFcF8XBat5NKIs9WphJCVXg==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [linux]
@@ -4351,14 +4112,8 @@ packages:
     cpu: [x64]
     os: [linux]
 
-  '@swc/core-linux-x64-musl@1.6.13':
-    resolution: {integrity: sha512-OdsY7wryTxCKwGQcwW9jwWg3cxaHBkTTHi91+5nm7hFPpmZMz1HivJrWAMwVE7iXFw+M4l6ugB/wCvpYrUAAjA==}
-    engines: {node: '>=10'}
-    cpu: [x64]
-    os: [linux]
-
-  '@swc/core-linux-x64-musl@1.6.6':
-    resolution: {integrity: sha512-NokIUtFxJDVv3LzGeEtYMTV3j2dnGKLac59luTeq36DQLZdJQawQIdTbzzWl2jE7lxxTZme+dhsVOH9LxE3ceg==}
+  '@swc/core-linux-x64-musl@1.9.2':
+    resolution: {integrity: sha512-TTIpR4rjMkhX1lnFR+PSXpaL83TrQzp9znRdp2TzYrODlUd/R20zOwSo9vFLCyH6ZoD47bccY7QeGZDYT3nlRg==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [linux]
@@ -4369,14 +4124,8 @@ packages:
     cpu: [arm64]
     os: [win32]
 
-  '@swc/core-win32-arm64-msvc@1.6.13':
-    resolution: {integrity: sha512-ap6uNmYjwk9M/+bFEuWRNl3hq4VqgQ/Lk+ID/F5WGqczNr0L7vEf+pOsRAn0F6EV+o/nyb3ePt8rLhE/wjHpPg==}
-    engines: {node: '>=10'}
-    cpu: [arm64]
-    os: [win32]
-
-  '@swc/core-win32-arm64-msvc@1.6.6':
-    resolution: {integrity: sha512-lzYdI4qb4k1dFG26yv+9Jaq/bUMAhgs/2JsrLncGjLof86+uj74wKYCQnbzKAsq2hDtS5DqnHnl+//J+miZfGA==}
+  '@swc/core-win32-arm64-msvc@1.9.2':
+    resolution: {integrity: sha512-+Eg2d4icItKC0PMjZxH7cSYFLWk0aIp94LNmOw6tPq0e69ax6oh10upeq0D1fjWsKLmOJAWEvnXlayZcijEXDw==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [win32]
@@ -4387,14 +4136,8 @@ packages:
     cpu: [ia32]
     os: [win32]
 
-  '@swc/core-win32-ia32-msvc@1.6.13':
-    resolution: {integrity: sha512-IJ8KH4yIUHTnS/U1jwQmtbfQals7zWPG0a9hbEfIr4zI0yKzjd83lmtS09lm2Q24QBWOCFGEEbuZxR4tIlvfzA==}
-    engines: {node: '>=10'}
-    cpu: [ia32]
-    os: [win32]
-
-  '@swc/core-win32-ia32-msvc@1.6.6':
-    resolution: {integrity: sha512-bvl7FMaXIJQ76WZU0ER4+RyfKIMGb6S2MgRkBhJOOp0i7VFx4WLOnrmMzaeoPJaJSkityVKAftfNh7NBzTIydQ==}
+  '@swc/core-win32-ia32-msvc@1.9.2':
+    resolution: {integrity: sha512-nLWBi4vZDdM/LkiQmPCakof8Dh1/t5EM7eudue04V1lIcqx9YHVRS3KMwEaCoHLGg0c312Wm4YgrWQd9vwZ5zQ==}
     engines: {node: '>=10'}
     cpu: [ia32]
     os: [win32]
@@ -4405,29 +4148,14 @@ packages:
     cpu: [x64]
     os: [win32]
 
-  '@swc/core-win32-x64-msvc@1.6.13':
-    resolution: {integrity: sha512-f6/sx6LMuEnbuxtiSL/EkR0Y6qUHFw1XVrh6rwzKXptTipUdOY+nXpKoh+1UsBm/r7H0/5DtOdrn3q5ZHbFZjQ==}
+  '@swc/core-win32-x64-msvc@1.9.2':
+    resolution: {integrity: sha512-ik/k+JjRJBFkXARukdU82tSVx0CbExFQoQ78qTO682esbYXzjdB5eLVkoUbwen299pnfr88Kn4kyIqFPTje8Xw==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [win32]
 
-  '@swc/core-win32-x64-msvc@1.6.6':
-    resolution: {integrity: sha512-WAP0JoCTfgeYKgOeYJoJV4ZS0sQUmU3OwvXa2dYYtMLF7zsNqOiW4niU7QlThBHgUv/qNZm2p6ITEgh3w1cltw==}
-    engines: {node: '>=10'}
-    cpu: [x64]
-    os: [win32]
-
-  '@swc/core@1.6.13':
-    resolution: {integrity: sha512-eailUYex6fkfaQTev4Oa3mwn0/e3mQU4H8y1WPuImYQESOQDtVrowwUGDSc19evpBbHpKtwM+hw8nLlhIsF+Tw==}
-    engines: {node: '>=10'}
-    peerDependencies:
-      '@swc/helpers': '*'
-    peerDependenciesMeta:
-      '@swc/helpers':
-        optional: true
-
-  '@swc/core@1.6.6':
-    resolution: {integrity: sha512-sHfmIUPUXNrQTwFMVCY5V5Ena2GTOeaWjS2GFUpjLhAgVfP90OP67DWow7+cYrfFtqBdILHuWnjkTcd0+uPKlg==}
+  '@swc/core@1.9.2':
+    resolution: {integrity: sha512-dYyEkO6mRYtZFpnOsnYzv9rY69fHAHoawYOjGOEcxk9WYtaJhowMdP/w6NcOKnz2G7GlZaenjkzkMa6ZeQeMsg==}
     engines: {node: '>=10'}
     peerDependencies:
       '@swc/helpers': '*'
@@ -4438,14 +4166,14 @@ packages:
   '@swc/counter@0.1.3':
     resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
 
-  '@swc/jest@0.2.36':
-    resolution: {integrity: sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw==}
+  '@swc/jest@0.2.37':
+    resolution: {integrity: sha512-CR2BHhmXKGxTiFr21DYPRHQunLkX3mNIFGFkxBGji6r9uyIR5zftTOVYj1e0sFNMV2H7mf/+vpaglqaryBtqfQ==}
     engines: {npm: '>= 7.0.0'}
     peerDependencies:
       '@swc/core': '*'
 
-  '@swc/types@0.1.9':
-    resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==}
+  '@swc/types@0.1.15':
+    resolution: {integrity: sha512-XKaZ+dzDIQ9Ot9o89oJQ/aluI17+VvUnIpYJTcZtvv1iYX6MzHh3Ik2CSR7MdPKpPwfZXHBeCingb2b4PoDVdw==}
 
   '@swc/wasm@1.2.130':
     resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==}
@@ -4558,8 +4286,8 @@ packages:
   '@types/accepts@1.3.7':
     resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==}
 
-  '@types/archiver@6.0.2':
-    resolution: {integrity: sha512-KmROQqbQzKGuaAbmK+ZcytkJ51+YqDa7NmbXjmtC5YBLSyQYo21YaUnQ3HbaPFKL1ooo6RQ6OPYPIDyxfpDDXw==}
+  '@types/archiver@6.0.3':
+    resolution: {integrity: sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ==}
 
   '@types/argparse@1.0.38':
     resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==}
@@ -4621,15 +4349,9 @@ packages:
   '@types/doctrine@0.0.9':
     resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==}
 
-  '@types/escodegen@0.0.6':
-    resolution: {integrity: sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==}
-
   '@types/eslint@7.29.0':
     resolution: {integrity: sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==}
 
-  '@types/estree@0.0.51':
-    resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==}
-
   '@types/estree@1.0.6':
     resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
 
@@ -4639,14 +4361,8 @@ packages:
   '@types/express@4.17.17':
     resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==}
 
-  '@types/express@4.17.21':
-    resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
-
-  '@types/find-cache-dir@3.2.1':
-    resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==}
-
-  '@types/fluent-ffmpeg@2.1.26':
-    resolution: {integrity: sha512-0JVF3wdQG+pN0ImwWD0bNgJiKF2OHg/7CDBHw5UIbRTvlnkgGHK6V5doE54ltvhud4o31/dEiHm23CAlxFiUQg==}
+  '@types/fluent-ffmpeg@2.1.27':
+    resolution: {integrity: sha512-QiDWjihpUhriISNoBi2hJBRUUmoj/BMTYcfz+F+ZM9hHWBYABFAE6hjP/TbCZC0GWwlpa3FzvHH9RzFeRusZ7A==}
 
   '@types/glob@7.2.0':
     resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
@@ -4675,8 +4391,8 @@ packages:
   '@types/istanbul-reports@3.0.1':
     resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==}
 
-  '@types/jest@29.5.13':
-    resolution: {integrity: sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==}
+  '@types/jest@29.5.14':
+    resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==}
 
   '@types/js-yaml@4.0.9':
     resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==}
@@ -4702,15 +4418,9 @@ packages:
   '@types/keyv@3.1.4':
     resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
 
-  '@types/lodash@4.14.191':
-    resolution: {integrity: sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==}
-
   '@types/long@4.0.2':
     resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
 
-  '@types/matter-js@0.19.6':
-    resolution: {integrity: sha512-ffk6tqJM5scla+ThXmnox+mdfCo3qYk6yMjQsNcrbo6eQ5DqorVdtnaL+1agCoYzxUjmHeiNB7poBMAmhuLY7w==}
-
   '@types/matter-js@0.19.7':
     resolution: {integrity: sha512-dlh50YEh1lQS4fiCDGBnK75ocHQIq/1E371Qk6hASJImICIivdZQC2GkOqnfBm0Hac2xLk5+yrqRFDAEfj/yLA==}
 
@@ -4738,26 +4448,14 @@ packages:
   '@types/ms@0.7.34':
     resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
 
-  '@types/mute-stream@0.0.4':
-    resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==}
-
-  '@types/mysql@2.15.22':
-    resolution: {integrity: sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==}
+  '@types/mysql@2.15.26':
+    resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==}
 
   '@types/node-fetch@2.6.11':
     resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
 
-  '@types/node@20.11.5':
-    resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==}
-
-  '@types/node@20.14.12':
-    resolution: {integrity: sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==}
-
-  '@types/node@20.9.1':
-    resolution: {integrity: sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==}
-
-  '@types/node@22.5.5':
-    resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==}
+  '@types/node@22.9.0':
+    resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==}
 
   '@types/nodemailer@6.4.16':
     resolution: {integrity: sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==}
@@ -4771,8 +4469,8 @@ packages:
   '@types/oauth2orize@1.11.5':
     resolution: {integrity: sha512-C6hrRoh9hCnqis39OpeUZSwgw+TIzcV0CsxwJMGfQjTx4I1r+CLmuEPzoDJr5NRTfc7OMwHNLkQwrGFLKrJjMQ==}
 
-  '@types/oauth@0.9.5':
-    resolution: {integrity: sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==}
+  '@types/oauth@0.9.6':
+    resolution: {integrity: sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==}
 
   '@types/offscreencanvas@2019.3.0':
     resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==}
@@ -4780,8 +4478,8 @@ packages:
   '@types/offscreencanvas@2019.7.0':
     resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==}
 
-  '@types/pg-pool@2.0.4':
-    resolution: {integrity: sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==}
+  '@types/pg-pool@2.0.6':
+    resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==}
 
   '@types/pg@8.11.10':
     resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==}
@@ -4852,6 +4550,9 @@ packages:
   '@types/shimmer@1.0.5':
     resolution: {integrity: sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==}
 
+  '@types/shimmer@1.2.0':
+    resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==}
+
   '@types/simple-oauth2@5.0.7':
     resolution: {integrity: sha512-8JbWVJbiTSBQP/7eiyGKyXWAqp3dKQZpaA+pdW16FCi32ujkzRMG8JfjoAzdWt6W8U591ZNdHcPtP2D7ILTKuA==}
 
@@ -4873,6 +4574,9 @@ packages:
   '@types/statuses@2.0.4':
     resolution: {integrity: sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==}
 
+  '@types/tedious@4.0.14':
+    resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==}
+
   '@types/throttle-debounce@5.0.2':
     resolution: {integrity: sha512-pDzSNulqooSKvSNcksnV72nk8p7gRqN8As71Sp28nov1IgmPKWbOEIwAWvBME5pPTtaXJAvG3O4oc76HlQ4kqQ==}
 
@@ -4900,17 +4604,14 @@ packages:
   '@types/vary@1.1.3':
     resolution: {integrity: sha512-XJT8/ZQCL7NUut9QDLf6l24JfAEl7bnNdgxfj50cHIpEPRJLHHDDFOAq6i+GsEmeFfH7NamhBE4c4Thtb2egWg==}
 
-  '@types/web-push@3.6.3':
-    resolution: {integrity: sha512-v3oT4mMJsHeJ/rraliZ+7TbZtr5bQQuxcgD7C3/1q/zkAj29c8RE0F9lVZVu3hiQe5Z9fYcBreV7TLnfKR+4mg==}
+  '@types/web-push@3.6.4':
+    resolution: {integrity: sha512-GnJmSr40H3RAnj0s34FNTcJi1hmWFV5KXugE0mYWnYhgTAHLJ/dJKAwDmvPJYMke0RplY2XE9LnM4hqSqKIjhQ==}
 
   '@types/webgl-ext@0.0.30':
     resolution: {integrity: sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==}
 
-  '@types/wrap-ansi@3.0.0':
-    resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==}
-
-  '@types/ws@8.5.12':
-    resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==}
+  '@types/ws@8.5.13':
+    resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==}
 
   '@types/yargs-parser@21.0.0':
     resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==}
@@ -5040,8 +4741,8 @@ packages:
   '@ungap/structured-clone@1.2.0':
     resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
 
-  '@vitejs/plugin-vue@5.1.4':
-    resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==}
+  '@vitejs/plugin-vue@5.2.0':
+    resolution: {integrity: sha512-7n7KdUEtx/7Yl7I/WVAMZ1bEb0eVvXF3ummWTeLcs/9gvo9pJhuLdouSXGjdZ/MKD1acf1I272+X0RMua4/R3g==}
     engines: {node: ^18.0.0 || >=20.0.0}
     peerDependencies:
       vite: ^5.0.0
@@ -5088,50 +4789,38 @@ packages:
   '@volar/language-core@2.2.0':
     resolution: {integrity: sha512-a8WG9+4OdeNDW4ywABZIM6S6UN7em8uIlM/BZ2pWQUYrVmX+m8sj/X+QadvO+Li/t/LjAqbWJQtVgxdpEWLALQ==}
 
-  '@volar/language-core@2.4.5':
-    resolution: {integrity: sha512-F4tA0DCO5Q1F5mScHmca0umsi2ufKULAnMOVBfMsZdT4myhVl4WdKRwCaKcfOkIEuyrAVvtq1ESBdZ+rSyLVww==}
+  '@volar/language-core@2.4.10':
+    resolution: {integrity: sha512-hG3Z13+nJmGaT+fnQzAkS0hjJRa2FCeqZt6Bd+oGNhUkQ+mTFsDETg5rqUTxyzIh5pSOGY7FHCWUS8G82AzLCA==}
 
   '@volar/source-map@2.2.0':
     resolution: {integrity: sha512-HQlPRlHOVqCCHK8wI76ZldHkEwKsjp7E6idUc36Ekni+KJDNrqgSqPvyHQixybXPHNU7CI9Uxd9/IkxO7LuNBw==}
 
-  '@volar/source-map@2.4.5':
-    resolution: {integrity: sha512-varwD7RaKE2J/Z+Zu6j3mNNJbNT394qIxXwdvz/4ao/vxOfyClZpSDtLKkwWmecinkOVos5+PWkWraelfMLfpw==}
+  '@volar/source-map@2.4.10':
+    resolution: {integrity: sha512-OCV+b5ihV0RF3A7vEvNyHPi4G4kFa6ukPmyVocmqm5QzOd8r5yAtiNvaPEjl8dNvgC/lj4JPryeeHLdXd62rWA==}
 
   '@volar/typescript@2.2.0':
     resolution: {integrity: sha512-wC6l4zLiiCLxF+FGaHCbWlQYf4vMsnRxYhcI6WgvaNppOD6r1g+Ef1RKRJUApALWU46Yy/JDU/TbdV6w/X6Liw==}
 
-  '@volar/typescript@2.4.5':
-    resolution: {integrity: sha512-mcT1mHvLljAEtHviVcBuOyAwwMKz1ibXTi5uYtP/pf4XxoAzpdkQ+Br2IC0NPCvLCbjPZmbf3I0udndkfB1CDg==}
-
-  '@vue/compiler-core@3.4.37':
-    resolution: {integrity: sha512-ZDDT/KiLKuCRXyzWecNzC5vTcubGz4LECAtfGPENpo0nrmqJHwuWtRLxk/Sb9RAKtR9iFflFycbkjkY+W/PZUQ==}
-
-  '@vue/compiler-core@3.5.10':
-    resolution: {integrity: sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==}
+  '@volar/typescript@2.4.10':
+    resolution: {integrity: sha512-F8ZtBMhSXyYKuBfGpYwqA5rsONnOwAVvjyE7KPYJ7wgZqo2roASqNWUnianOomJX5u1cxeRooHV59N0PhvEOgw==}
 
   '@vue/compiler-core@3.5.11':
     resolution: {integrity: sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==}
 
-  '@vue/compiler-dom@3.4.37':
-    resolution: {integrity: sha512-rIiSmL3YrntvgYV84rekAtU/xfogMUJIclUMeIKEtVBFngOL3IeZHhsH3UaFEgB5iFGpj6IW+8YuM/2Up+vVag==}
-
-  '@vue/compiler-dom@3.5.10':
-    resolution: {integrity: sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==}
+  '@vue/compiler-core@3.5.12':
+    resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==}
 
   '@vue/compiler-dom@3.5.11':
     resolution: {integrity: sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==}
 
-  '@vue/compiler-sfc@3.4.37':
-    resolution: {integrity: sha512-vCfetdas40Wk9aK/WWf8XcVESffsbNkBQwS5t13Y/PcfqKfIwJX2gF+82th6dOpnpbptNMlMjAny80li7TaCIg==}
+  '@vue/compiler-dom@3.5.12':
+    resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==}
 
-  '@vue/compiler-sfc@3.5.11':
-    resolution: {integrity: sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==}
+  '@vue/compiler-sfc@3.5.12':
+    resolution: {integrity: sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==}
 
-  '@vue/compiler-ssr@3.4.37':
-    resolution: {integrity: sha512-TyAgYBWrHlFrt4qpdACh8e9Ms6C/AZQ6A6xLJaWrCL8GCX5DxMzxyeFAEMfU/VFr4tylHm+a2NpfJpcd7+20XA==}
-
-  '@vue/compiler-ssr@3.5.11':
-    resolution: {integrity: sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==}
+  '@vue/compiler-ssr@3.5.12':
+    resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==}
 
   '@vue/compiler-vue2@2.7.16':
     resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
@@ -5144,51 +4833,34 @@ packages:
       typescript:
         optional: true
 
-  '@vue/language-core@2.1.6':
-    resolution: {integrity: sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==}
+  '@vue/language-core@2.1.10':
+    resolution: {integrity: sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ==}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
 
-  '@vue/reactivity@3.4.37':
-    resolution: {integrity: sha512-UmdKXGx0BZ5kkxPqQr3PK3tElz6adTey4307NzZ3whZu19i5VavYal7u2FfOmAzlcDVgE8+X0HZ2LxLb/jgbYw==}
+  '@vue/reactivity@3.5.12':
+    resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==}
 
-  '@vue/reactivity@3.5.11':
-    resolution: {integrity: sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==}
+  '@vue/runtime-core@3.5.12':
+    resolution: {integrity: sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==}
 
-  '@vue/runtime-core@3.4.37':
-    resolution: {integrity: sha512-MNjrVoLV/sirHZoD7QAilU1Ifs7m/KJv4/84QVbE6nyAZGQNVOa1HGxaOzp9YqCG+GpLt1hNDC4RbH+KtanV7w==}
+  '@vue/runtime-dom@3.5.12':
+    resolution: {integrity: sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==}
 
-  '@vue/runtime-core@3.5.11':
-    resolution: {integrity: sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==}
-
-  '@vue/runtime-dom@3.4.37':
-    resolution: {integrity: sha512-Mg2EwgGZqtwKrqdL/FKMF2NEaOHuH+Ks9TQn3DHKyX//hQTYOun+7Tqp1eo0P4Ds+SjltZshOSRq6VsU0baaNg==}
-
-  '@vue/runtime-dom@3.5.11':
-    resolution: {integrity: sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==}
-
-  '@vue/server-renderer@3.4.37':
-    resolution: {integrity: sha512-jZ5FAHDR2KBq2FsRUJW6GKDOAG9lUTX8aBEGq4Vf6B/35I9fPce66BornuwmqmKgfiSlecwuOb6oeoamYMohkg==}
+  '@vue/server-renderer@3.5.12':
+    resolution: {integrity: sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==}
     peerDependencies:
-      vue: 3.4.37
-
-  '@vue/server-renderer@3.5.11':
-    resolution: {integrity: sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==}
-    peerDependencies:
-      vue: 3.5.11
-
-  '@vue/shared@3.4.37':
-    resolution: {integrity: sha512-nIh8P2fc3DflG8+5Uw8PT/1i17ccFn0xxN/5oE9RfV5SVnd7G0XEFRwakrnNFE/jlS95fpGXDVG5zDETS26nmg==}
-
-  '@vue/shared@3.5.10':
-    resolution: {integrity: sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==}
+      vue: 3.5.12
 
   '@vue/shared@3.5.11':
     resolution: {integrity: sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==}
 
+  '@vue/shared@3.5.12':
+    resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==}
+
   '@vue/test-utils@2.4.1':
     resolution: {integrity: sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==}
     peerDependencies:
@@ -5219,11 +4891,6 @@ packages:
     resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
     engines: {node: '>= 0.6'}
 
-  acorn-import-assertions@1.9.0:
-    resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
-    peerDependencies:
-      acorn: ^8
-
   acorn-import-attributes@1.9.5:
     resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
     peerDependencies:
@@ -5234,10 +4901,6 @@ packages:
     peerDependencies:
       acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
 
-  acorn-walk@7.2.0:
-    resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==}
-    engines: {node: '>=0.4.0'}
-
   acorn-walk@8.3.2:
     resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==}
     engines: {node: '>=0.4.0'}
@@ -5247,8 +4910,8 @@ packages:
     engines: {node: '>=0.4.0'}
     hasBin: true
 
-  acorn@8.12.1:
-    resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
+  acorn@8.14.0:
+    resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
     engines: {node: '>=0.4.0'}
     hasBin: true
 
@@ -5309,6 +4972,9 @@ packages:
   ajv@8.17.1:
     resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
 
+  alien-signals@0.2.1:
+    resolution: {integrity: sha512-FlEQrDJe9r2RI4cDlnK2zYqJezvx1uJaWEuwxsnlFqnPwvJbgitNBRumWrLDv8lA+7cCikpMxfJD2TTHiaTklA==}
+
   ansi-colors@4.1.3:
     resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
     engines: {node: '>=6'}
@@ -5668,8 +5334,8 @@ packages:
     resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==}
     engines: {node: '>=6.14.2'}
 
-  bullmq@5.15.0:
-    resolution: {integrity: sha512-h53shVjx8s6wxYGtUfzAfENpSP7N5T0D4PMTvbZncozLjb8yUKhopfpa7PmcpQfq7SSO9dm/OZ9XQuGOCSGNug==}
+  bullmq@5.26.1:
+    resolution: {integrity: sha512-XuxCGFlC1PQ2i1JHQiB9dqkqKQILMwQpU7ipi+cT/dzJaoXVcS0/IByUz6SsZ3xyOQY3twPt6G7J2d5GrsJuEA==}
 
   buraha@0.0.1:
     resolution: {integrity: sha512-G563A0mTbzknm2jDaNxfZuNKIdeArs8T+XQN6t+KbmgnOoevXSXhKDkyf8Md/36Jrx99ikwbCag37VGe3myExQ==}
@@ -5809,8 +5475,8 @@ packages:
   character-parser@2.2.0:
     resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==}
 
-  chart.js@4.4.4:
-    resolution: {integrity: sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA==}
+  chart.js@4.4.6:
+    resolution: {integrity: sha512-8Y406zevUPbbIBA/HRk33khEmQPk5+cxeflWE/2rx1NJsjVWMPw/9mSP9rxHP5eqi6LNoPBVMfZHxbwLSgldYA==}
     engines: {pnpm: '>=8'}
 
   chartjs-adapter-date-fns@3.0.0:
@@ -5867,8 +5533,8 @@ packages:
     resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
     engines: {node: '>=10'}
 
-  chromatic@11.11.0:
-    resolution: {integrity: sha512-mwmYsNMsZlRLtlfFUEtac5zhoVRhc+O/lsuMdOpwkiDQiKX6WdSNIhic+dkLenfuzao2r18s50nphcOgFoatBg==}
+  chromatic@11.18.1:
+    resolution: {integrity: sha512-hkNT9vA6K9+PnE/khhZYBnRCOm8NonaQDs7RZ8YHFo7/lh1b/x/uFMkTjWjaj/mkM6QOR/evu5VcZMtcaauSlw==}
     hasBin: true
     peerDependencies:
       '@chromatic-com/cypress': ^0.*.* || ^1.0.0
@@ -5883,6 +5549,10 @@ packages:
     resolution: {integrity: sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==}
     engines: {node: '>=8'}
 
+  ci-info@4.1.0:
+    resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==}
+    engines: {node: '>=8'}
+
   cjs-module-lexer@1.2.2:
     resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==}
 
@@ -5903,10 +5573,6 @@ packages:
     engines: {node: '>=8.0.0', npm: '>=5.0.0'}
     hasBin: true
 
-  cli-spinners@2.9.2:
-    resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
-    engines: {node: '>=6'}
-
   cli-table3@0.6.3:
     resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==}
     engines: {node: 10.* || >= 12.*}
@@ -6015,9 +5681,6 @@ packages:
     resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
     engines: {node: '>=4.0.0'}
 
-  commondir@1.0.1:
-    resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
-
   compare-versions@6.1.1:
     resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
 
@@ -6061,18 +5724,22 @@ packages:
   cookie-signature@1.0.6:
     resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
 
-  cookie-signature@1.2.1:
-    resolution: {integrity: sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==}
-    engines: {node: '>=6.6.0'}
-
-  cookie@0.5.0:
-    resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
-    engines: {node: '>= 0.6'}
-
   cookie@0.6.0:
     resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
     engines: {node: '>= 0.6'}
 
+  cookie@0.7.1:
+    resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
+    engines: {node: '>= 0.6'}
+
+  cookie@0.7.2:
+    resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+    engines: {node: '>= 0.6'}
+
+  cookie@1.0.1:
+    resolution: {integrity: sha512-Xd8lFX4LM9QEEwxQpF9J9NTUh8pmdJO0cyRJhFiDoLTk2eH8FXlRv2IFGYVadZpqI3j8fhNrSdKCeYPxiAhLXw==}
+    engines: {node: '>=18'}
+
   core-js@3.29.1:
     resolution: {integrity: sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==}
 
@@ -6186,13 +5853,8 @@ packages:
   cwise-compiler@1.1.3:
     resolution: {integrity: sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ==}
 
-  cypress@13.14.2:
-    resolution: {integrity: sha512-lsiQrN17vHMB2fnvxIrKLAjOr9bPwsNbPZNrWf99s4u+DVmCY6U+w7O3GGG9FvP4EUVYaDu+guWeNLiUzBrqvA==}
-    engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
-    hasBin: true
-
-  cypress@13.15.0:
-    resolution: {integrity: sha512-53aO7PwOfi604qzOkCSzNlWquCynLlKE/rmmpSPcziRH6LNfaDUAklQT6WJIsD8ywxlIy+uVZsnTMCCQVd2kTw==}
+  cypress@13.15.2:
+    resolution: {integrity: sha512-ARbnUorjcCM3XiPwgHKuqsyr5W9Qn+pIIBPaoilnoBkLdSC2oLQjV1BUpnmc7KR+b7Avah3Ly2RMFnfxr96E/A==}
     engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
     hasBin: true
 
@@ -6530,10 +6192,6 @@ packages:
     resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
     engines: {node: '>=0.12'}
 
-  entities@5.0.0:
-    resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==}
-    engines: {node: '>=0.12'}
-
   env-paths@2.2.1:
     resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
     engines: {node: '>=6'}
@@ -6563,9 +6221,6 @@ packages:
   es-get-iterator@1.1.3:
     resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
 
-  es-module-lexer@1.5.4:
-    resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
-
   es-object-atoms@1.0.0:
     resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
     engines: {node: '>= 0.4'}
@@ -6588,6 +6243,9 @@ packages:
     resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
     engines: {node: '>= 0.4'}
 
+  es-toolkit@1.27.0:
+    resolution: {integrity: sha512-ETSFA+ZJArcuSCpzD2TjAy6UHpx4E4uqFsoDg9F/nTLogrLmVVZQ+zNxco5h7cWnA1nNak07IXsLcaSMih+ZPQ==}
+
   es6-promise@4.2.8:
     resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
 
@@ -6604,23 +6262,13 @@ packages:
     engines: {node: '>=12'}
     hasBin: true
 
-  esbuild@0.19.11:
-    resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==}
-    engines: {node: '>=12'}
-    hasBin: true
-
   esbuild@0.21.5:
     resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
     engines: {node: '>=12'}
     hasBin: true
 
-  esbuild@0.23.0:
-    resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==}
-    engines: {node: '>=18'}
-    hasBin: true
-
-  esbuild@0.23.1:
-    resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
+  esbuild@0.24.0:
+    resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
     engines: {node: '>=18'}
     hasBin: true
 
@@ -6654,11 +6302,6 @@ packages:
     resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
     engines: {node: '>=12'}
 
-  escodegen@2.1.0:
-    resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
-    engines: {node: '>=6.0'}
-    hasBin: true
-
   eslint-formatter-pretty@4.1.0:
     resolution: {integrity: sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==}
     engines: {node: '>=10'}
@@ -6728,14 +6371,8 @@ packages:
       '@typescript-eslint/parser':
         optional: true
 
-  eslint-plugin-vue@9.27.0:
-    resolution: {integrity: sha512-5Dw3yxEyuBSXTzT5/Ge1X5kIkRTQ3nvBn/VwPwInNiZBSJOO/timWMUaflONnFBzU6NhB68lxnCda7ULV5N7LA==}
-    engines: {node: ^14.17.0 || >=16.0.0}
-    peerDependencies:
-      eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
-
-  eslint-plugin-vue@9.28.0:
-    resolution: {integrity: sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g==}
+  eslint-plugin-vue@9.31.0:
+    resolution: {integrity: sha512-aYMUCgivhz1o4tLkRHj5oq9YgYPM4/EJc0M7TAKRLCUA5OYxRLAhYEVD2nLtTwLyixEFI+/QXSvKU9ESZFgqjQ==}
     engines: {node: ^14.17.0 || >=16.0.0}
     peerDependencies:
       eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
@@ -6747,20 +6384,20 @@ packages:
     resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
 
-  eslint-scope@8.0.2:
-    resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==}
+  eslint-scope@8.2.0:
+    resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
   eslint-visitor-keys@3.4.3:
     resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
 
-  eslint-visitor-keys@4.0.0:
-    resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
+  eslint-visitor-keys@4.2.0:
+    resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  eslint@9.11.0:
-    resolution: {integrity: sha512-yVS6XODx+tMFMDFcG4+Hlh+qG7RM6cCJXtQhCKLSsr3XkLvWggHjCqjfh0XsPPnt1c56oaT6PMgW9XWQQjdHXA==}
+  eslint@9.14.0:
+    resolution: {integrity: sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     hasBin: true
     peerDependencies:
@@ -6769,13 +6406,8 @@ packages:
       jiti:
         optional: true
 
-  eslint@9.8.0:
-    resolution: {integrity: sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    hasBin: true
-
-  espree@10.1.0:
-    resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==}
+  espree@10.3.0:
+    resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
   espree@9.6.1:
@@ -6853,8 +6485,8 @@ packages:
     resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
     engines: {node: '>=16.17'}
 
-  execa@9.4.0:
-    resolution: {integrity: sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==}
+  execa@9.5.1:
+    resolution: {integrity: sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==}
     engines: {node: ^18.19.0 || >=20.5.0}
 
   executable@4.1.1:
@@ -6876,6 +6508,10 @@ packages:
     resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==}
     engines: {node: '>= 0.10.0'}
 
+  express@4.21.1:
+    resolution: {integrity: sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==}
+    engines: {node: '>= 0.10.0'}
+
   ext-list@2.2.2:
     resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==}
     engines: {node: '>=0.10.0'}
@@ -6991,8 +6627,8 @@ packages:
     resolution: {integrity: sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
 
-  file-type@19.5.0:
-    resolution: {integrity: sha512-dMuq6WWnP6BpQY0zYJNpTtQWgeCImSMG0BTIzUBXvxbwc1HWP/E7AE4UWU9XSCOPGJuOHda0HpDnwM2FW+d90A==}
+  file-type@19.6.0:
+    resolution: {integrity: sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==}
     engines: {node: '>=18'}
 
   filelist@1.0.4:
@@ -7018,10 +6654,6 @@ packages:
     resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
     engines: {node: '>= 0.8'}
 
-  find-cache-dir@3.3.2:
-    resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
-    engines: {node: '>=8'}
-
   find-my-way@9.0.1:
     resolution: {integrity: sha512-/5NN/R0pFWuff16TMajeKt2JyiW+/OE8nOO8vo1DwZTxLaIURb7lcBYPIgRPh61yCNh9l8voeKwcrkUzmB00vw==}
     engines: {node: '>=14'}
@@ -7096,8 +6728,8 @@ packages:
     resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
     engines: {node: '>= 0.12'}
 
-  form-data@4.0.0:
-    resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+  form-data@4.0.1:
+    resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
     engines: {node: '>= 6'}
 
   formdata-polyfill@4.0.10:
@@ -7115,10 +6747,6 @@ packages:
   from@0.1.7:
     resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
 
-  fs-extra@11.1.1:
-    resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==}
-    engines: {node: '>=14.14'}
-
   fs-extra@7.0.1:
     resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
     engines: {node: '>=6 <7 || >=8'}
@@ -7235,9 +6863,6 @@ packages:
     resolution: {integrity: sha512-++rNGpDBgWQ9eXj9JfTBLHMUEd7lDOdzIvFyHQM9yL8ffxkcg4G6jWmsgu/r59Uq6nHc3wcVwtgy3geLnIWunQ==}
     engines: {node: '>= 0.8.0'}
 
-  github-slugger@2.0.0:
-    resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
-
   glob-parent@5.1.2:
     resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
     engines: {node: '>= 6'}
@@ -7287,8 +6912,8 @@ packages:
     resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
     engines: {node: '>=18'}
 
-  globals@15.9.0:
-    resolution: {integrity: sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==}
+  globals@15.12.0:
+    resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==}
     engines: {node: '>=18'}
 
   globalthis@1.0.3:
@@ -7313,8 +6938,8 @@ packages:
     resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
     engines: {node: '>=14.16'}
 
-  got@14.4.2:
-    resolution: {integrity: sha512-+Te/qEZ6hr7i+f0FNgXx/6WQteSM/QqueGvxeYQQFm0GDfoxLVJ/oiwUKYMTeioColWUTdewZ06hmrBjw6F7tw==}
+  got@14.4.4:
+    resolution: {integrity: sha512-tqiF7eSgTBwQkxb1LxsEpva8TaMYVisbhplrFVmw9GQE3855Z+MH/mnsXLLOkDxR6hZJRFMj5VTAZ8lmTF8ZOA==}
     engines: {node: '>=20'}
 
   graceful-fs@4.2.11:
@@ -7337,8 +6962,8 @@ packages:
   happy-dom@10.0.3:
     resolution: {integrity: sha512-WkCP+Z5fX6U5PY+yHP3ElV5D9PoxRAHRWPFq3pG9rg/6Hjf5ak7dozAgSCywsTRUq2qfa8vV8OQvUy5pRXy8EQ==}
 
-  happy-dom@15.7.4:
-    resolution: {integrity: sha512-r1vadDYGMtsHAAsqhDuk4IpPvr6N8MGKy5ntBo7tSdim+pWDxus2PNqOcOt8LuDZ4t3KJHE+gCuzupcx/GKnyQ==}
+  happy-dom@15.11.4:
+    resolution: {integrity: sha512-AU6tzh3ADd28vSmXahgLsGyGGihXPGeKH0owDn9lhHolB6vIwEhag//T+TBzDoAcHhmVEwlxwSgtW1KZep+1MA==}
     engines: {node: '>=18.0.0'}
 
   har-schema@2.0.0:
@@ -7409,18 +7034,9 @@ packages:
     resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
     engines: {node: '>= 0.4'}
 
-  hast-util-heading-rank@3.0.0:
-    resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==}
-
-  hast-util-is-element@3.0.0:
-    resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
-
   hast-util-to-html@9.0.3:
     resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==}
 
-  hast-util-to-string@3.0.0:
-    resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==}
-
   hast-util-whitespace@3.0.0:
     resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
 
@@ -7459,10 +7075,6 @@ packages:
   html-escaper@2.0.2:
     resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
 
-  html-tags@3.2.0:
-    resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==}
-    engines: {node: '>=8'}
-
   html-void-elements@3.0.0:
     resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
 
@@ -7586,11 +7198,8 @@ packages:
     resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
     engines: {node: '>=6'}
 
-  import-in-the-middle@1.10.0:
-    resolution: {integrity: sha512-Z1jumVdF2GwnnYfM0a/y2ts7mZbwFMgt5rRuVmLgobgahC6iKgN5MBuXjzfTIOUpq5LSU10vJIPpVKe0X89fIw==}
-
-  import-in-the-middle@1.7.1:
-    resolution: {integrity: sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==}
+  import-in-the-middle@1.11.2:
+    resolution: {integrity: sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA==}
 
   import-lazy@4.0.0:
     resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
@@ -7679,10 +7288,6 @@ packages:
     resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==}
     engines: {node: '>=8'}
 
-  is-absolute-url@4.0.1:
-    resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==}
-    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
   is-arguments@1.1.1:
     resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
     engines: {node: '>= 0.4'}
@@ -7718,10 +7323,6 @@ packages:
     resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
     engines: {node: '>= 0.4'}
 
-  is-ci@3.0.1:
-    resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
-    hasBin: true
-
   is-core-module@2.13.1:
     resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
 
@@ -8453,12 +8054,6 @@ packages:
   markdown-table@3.0.3:
     resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
 
-  markdown-to-jsx@7.4.7:
-    resolution: {integrity: sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==}
-    engines: {node: '>= 10'}
-    peerDependencies:
-      react: '>= 0.14.0'
-
   matter-js@0.19.0:
     resolution: {integrity: sha512-v2huwvQGOHTGOkMqtHd2hercCG3f6QAObTisPPHg8TZqq2lz7eIY/5i/5YUV8Ibf3mEioFEmwibcPUF2/fnKKQ==}
 
@@ -8508,8 +8103,8 @@ packages:
     resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
     engines: {node: '>= 0.6'}
 
-  meilisearch@0.42.0:
-    resolution: {integrity: sha512-pXaOPx/uhVGYVpejNuOcXifQVJlRVSxtvpgrGKb7ygmYo4qSNXkQXPxq1p0Tv+4/RsPJug3W04pcNnYXiqungA==}
+  meilisearch@0.45.0:
+    resolution: {integrity: sha512-+zCzEqE+CumY4icB0Vox180adZqaNtnr60hJWGiEdmol5eWmksfY8rYsTcz87styXC2ZOg+2yF56gdH6oyIBTA==}
 
   memoizerific@1.11.3:
     resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==}
@@ -8803,26 +8398,16 @@ packages:
     resolution: {integrity: sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==}
     hasBin: true
 
-  msgpackr@1.10.1:
-    resolution: {integrity: sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==}
+  msgpackr@1.11.2:
+    resolution: {integrity: sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==}
 
-  msw-storybook-addon@2.0.3:
-    resolution: {integrity: sha512-CzHmGO32JeOPnyUnRWnB0PFTXCY1HKfHiEB/6fYoUYiFm2NYosLjzs9aBd3XJUryYEN0avJqMNh7nCRDxE5JjQ==}
+  msw-storybook-addon@2.0.4:
+    resolution: {integrity: sha512-rstO8+r01sRMg6PPP7OxM8LG5/6r4+wmp2uapHeHvm9TQQRHvpPXOU/Y9/Somysz8Oi4Ea1aummXH3JlnP2LIA==}
     peerDependencies:
       msw: ^2.0.0
 
-  msw@2.3.4:
-    resolution: {integrity: sha512-sHMlwrajgmZSA2l1o7qRSe+azm/I+x9lvVVcOxAzi4vCtH8uVPJk1K5BQYDkzGl+tt0RvM9huEXXdeGrgcc79g==}
-    engines: {node: '>=18'}
-    hasBin: true
-    peerDependencies:
-      typescript: '>= 4.7.x'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
-
-  msw@2.4.9:
-    resolution: {integrity: sha512-1m8xccT6ipN4PTqLinPwmzhxQREuxaEJYdx4nIbggxP8aM7r1e71vE7RtOUSQoAm1LydjGfZKy7370XD/tsuYg==}
+  msw@2.6.4:
+    resolution: {integrity: sha512-Pm4LmWQeytDsNCR+A7gt39XAdtH6zQb6jnIKRig0FlvYOn8eksn3s1nXxUfz5KYUjbckof7Z4p2ewzgffPoCbg==}
     engines: {node: '>=18'}
     hasBin: true
     peerDependencies:
@@ -8841,9 +8426,9 @@ packages:
   multi-integer-range@3.0.0:
     resolution: {integrity: sha512-uQzynjVJ8F7x5wjaK0g4Ybhy2TvO/pk96+YHyS5g1W4GuUEV6HMebZ8HcRwWgKIRCUT2MLbM5uCKwYcAqkS+8Q==}
 
-  mute-stream@1.0.0:
-    resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
-    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+  mute-stream@2.0.0:
+    resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
+    engines: {node: ^18.17.0 || >=20.5.0}
 
   mylas@2.1.13:
     resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==}
@@ -8860,8 +8445,8 @@ packages:
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
     hasBin: true
 
-  nanoid@5.0.7:
-    resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==}
+  nanoid@5.0.8:
+    resolution: {integrity: sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==}
     engines: {node: ^18 || >=20}
     hasBin: true
 
@@ -8966,15 +8551,10 @@ packages:
   node-releases@2.0.14:
     resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
 
-  nodemailer@6.9.15:
-    resolution: {integrity: sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==}
+  nodemailer@6.9.16:
+    resolution: {integrity: sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==}
     engines: {node: '>=6.0.0'}
 
-  nodemon@3.0.2:
-    resolution: {integrity: sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==}
-    engines: {node: '>=10'}
-    hasBin: true
-
   nodemon@3.1.7:
     resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==}
     engines: {node: '>=10'}
@@ -9154,12 +8734,6 @@ packages:
     resolution: {integrity: sha512-es3mGcDXV6TKPo6n3aohzHm0qxhLyR39MhF6mkD1FwFGjhxnqMqfSIgM0eCpInZvqatve4CxmXcMZw3jnnsaXw==}
     hasBin: true
 
-  opentelemetry-instrumentation-fetch-node@1.2.3:
-    resolution: {integrity: sha512-Qb11T7KvoCevMaSeuamcLsAD+pZnavkhDnlVL0kRozfhl42dKG5Q3anUklAFKJZjY3twLR+BnRa6DlwwkIE/+A==}
-    engines: {node: '>18.0.0'}
-    peerDependencies:
-      '@opentelemetry/api': ^1.6.0
-
   optionator@0.9.4:
     resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
     engines: {node: '>= 0.8.0'}
@@ -9177,9 +8751,6 @@ packages:
   otpauth@9.3.4:
     resolution: {integrity: sha512-qXv+lpsCUO9ewitLYfeDKbLYt7UUCivnU/fwGK2OqhgrCBsRkTUNKWsgKAhkXG3aistOY+jEeuL90JEBu6W3mQ==}
 
-  outvariant@1.4.2:
-    resolution: {integrity: sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==}
-
   outvariant@1.4.3:
     resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==}
 
@@ -9271,8 +8842,8 @@ packages:
   parse5@6.0.1:
     resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
 
-  parse5@7.1.2:
-    resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
+  parse5@7.2.1:
+    resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==}
 
   parseurl@1.3.3:
     resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
@@ -9321,9 +8892,6 @@ packages:
   path-to-regexp@3.3.0:
     resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
 
-  path-to-regexp@6.2.1:
-    resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
-
   path-to-regexp@6.3.0:
     resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
 
@@ -9344,14 +8912,14 @@ packages:
   pause-stream@0.0.11:
     resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==}
 
-  peek-readable@5.1.3:
-    resolution: {integrity: sha512-kCsc9HwH5RgVA3H3VqkWFyGQwsxUxLdiSX1d5nqAm7hnMFjNFX1VhBLmJoUY0hZNc8gmDNgBkLjfhiWPsziXWA==}
-    engines: {node: '>=14.16'}
-
   peek-readable@5.2.0:
     resolution: {integrity: sha512-U94a+eXHzct7vAd19GH3UQ2dH4Satbng0MyYTMaQatL0pvYYL5CTPR25HBhKtecl+4bfu1/i3vC6k0hydO5Vcw==}
     engines: {node: '>=14.16'}
 
+  peek-readable@5.3.1:
+    resolution: {integrity: sha512-GVlENSDW6KHaXcd9zkZltB7tCLosKB/4Hg0fqBJkAoBgYG2Tn1xtMgXtSUuMU9AK/gCm/tTdT8mgAeF4YNeeqw==}
+    engines: {node: '>=14.16'}
+
   pend@1.2.0:
     resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
 
@@ -9391,8 +8959,8 @@ packages:
     resolution: {integrity: sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==}
     engines: {node: '>=10'}
 
-  pg@8.13.0:
-    resolution: {integrity: sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==}
+  pg@8.13.1:
+    resolution: {integrity: sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==}
     engines: {node: '>= 8.0.0'}
     peerDependencies:
       pg-native: '>=3.0.1'
@@ -9416,10 +8984,17 @@ packages:
   picocolors@1.1.0:
     resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
 
+  picocolors@1.1.1:
+    resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
   picomatch@2.3.1:
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
     engines: {node: '>=8.6'}
 
+  picomatch@4.0.2:
+    resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
+    engines: {node: '>=12'}
+
   pid-port@1.0.0:
     resolution: {integrity: sha512-LSNBeKChRPA4Xlrs6+zV588G1hSrFvANtPV5rt/5MPfSPK3V9XPWxx1d29svsrOjngT9ifLisXWCLS7DvO9ZhQ==}
     engines: {node: '>=18'}
@@ -9656,6 +9231,10 @@ packages:
     resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
     engines: {node: ^10 || ^12 || >=14}
 
+  postcss@8.4.49:
+    resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+    engines: {node: ^10 || ^12 || >=14}
+
   postgres-array@2.0.0:
     resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
     engines: {node: '>=4'}
@@ -9764,9 +9343,6 @@ packages:
     resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
     engines: {node: '>= 6'}
 
-  prop-types@15.8.1:
-    resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
-
   property-information@6.5.0:
     resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
 
@@ -9919,12 +9495,6 @@ packages:
   re2@1.21.4:
     resolution: {integrity: sha512-MVIfXWJmsP28mRsSt8HeL750ifb8H5+oF2UDIxGaiJCr8fkMqhLZ7kcX9ADRk2dC8qeGKedB7UVYRfBVpEiLfA==}
 
-  react-colorful@5.6.1:
-    resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==}
-    peerDependencies:
-      react: '>=16.8.0'
-      react-dom: '>=16.8.0'
-
   react-docgen-typescript@2.2.2:
     resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==}
     peerDependencies:
@@ -9939,21 +9509,9 @@ packages:
     peerDependencies:
       react: ^18.3.1
 
-  react-element-to-jsx-string@15.0.0:
-    resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==}
-    peerDependencies:
-      react: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0
-      react-dom: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0
-
-  react-is@16.13.1:
-    resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
-
   react-is@17.0.2:
     resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
 
-  react-is@18.1.0:
-    resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==}
-
   react-is@18.2.0:
     resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
 
@@ -10044,12 +9602,6 @@ packages:
     resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==}
     engines: {node: '>= 0.4'}
 
-  rehype-external-links@3.0.0:
-    resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==}
-
-  rehype-slug@6.0.0:
-    resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==}
-
   remark-gfm@4.0.0:
     resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==}
 
@@ -10137,9 +9689,6 @@ packages:
     resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
     engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
 
-  rfdc@1.3.0:
-    resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
-
   rfdc@1.4.1:
     resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
 
@@ -10153,8 +9702,8 @@ packages:
     deprecated: Rimraf versions prior to v4 are no longer supported
     hasBin: true
 
-  rollup@4.22.5:
-    resolution: {integrity: sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==}
+  rollup@4.26.0:
+    resolution: {integrity: sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
     hasBin: true
 
@@ -10319,8 +9868,8 @@ packages:
     resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
     engines: {node: '>=8'}
 
-  shiki@1.21.0:
-    resolution: {integrity: sha512-apCH5BoWTrmHDPGgg3RF8+HAAbEL/CdbYr8rMw7eIrdhCkZHdVGat5mMNlRtd1erNG01VPMIKHNQ0Pj2HMAiog==}
+  shiki@1.22.2:
+    resolution: {integrity: sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==}
 
   shimmer@1.2.1:
     resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==}
@@ -10589,9 +10138,14 @@ packages:
       react-dom:
         optional: true
 
-  storybook@8.3.4:
-    resolution: {integrity: sha512-nzvuK5TsEgJwcWGLGgafabBOxKn37lfJVv7ZoUVPgJIjk2mNRyJDFwYRJzUZaD37eiR/c/lQ6MoaeqlGwiXoxw==}
+  storybook@8.4.4:
+    resolution: {integrity: sha512-xBOq3q/MuUUg3zM0imMMaK5ziKq3TO388jsnaiemJ4Uf0ZGwcHjM8HDBCDt0s5/CfsOQ49zo1ouZ3aNlu0qsUg==}
     hasBin: true
+    peerDependencies:
+      prettier: ^2 || ^3
+    peerDependenciesMeta:
+      prettier:
+        optional: true
 
   stream-browserify@3.0.0:
     resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==}
@@ -10725,8 +10279,8 @@ packages:
     resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==}
     engines: {node: '>=14.16'}
 
-  strtok3@8.1.0:
-    resolution: {integrity: sha512-ExzDvHYPj6F6QkSNe/JxSlBxTh3OrI6wrAIz53ulxo1c4hBJ1bT9C/JrAthEKHWG9riVH3Xzg7B03Oxty6S2Lw==}
+  strtok3@9.0.1:
+    resolution: {integrity: sha512-ERPW+XkvX9W2A+ov07iy+ZFJpVdik04GhDA4eVogiG9hpC97Kem2iucyzhFxbFRvQ5o2UckFtKZdp1hkGvnrEw==}
     engines: {node: '>=16'}
 
   stylehacks@6.1.1:
@@ -10788,11 +10342,8 @@ packages:
     resolution: {integrity: sha512-+HRtZ40Vc+6YfCDWCeAsixwxJgMbPY4HHuTgzPYH3JXvqHWUlsCfy+ylXlAKhFNcuLp4xVeWeFBUhDk+7KYUvQ==}
     engines: {node: '>=14.16'}
 
-  telejson@7.2.0:
-    resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==}
-
-  terser@5.33.0:
-    resolution: {integrity: sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==}
+  terser@5.36.0:
+    resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==}
     engines: {node: '>=10'}
     hasBin: true
 
@@ -10857,6 +10408,13 @@ packages:
     resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
     engines: {node: '>=14.0.0'}
 
+  tldts-core@6.1.61:
+    resolution: {integrity: sha512-In7VffkDWUPgwa+c9picLUxvb0RltVwTkSgMNFgvlGSWveCzGBemBqTsgJCL4EDFWZ6WH0fKTsot6yNhzy3ZzQ==}
+
+  tldts@6.1.61:
+    resolution: {integrity: sha512-rv8LUyez4Ygkopqn+M6OLItAOT9FF3REpPQDkdMx5ix8w4qkuE7Vo2o/vw1nxKQYmJDV8JpAMJQr1b+lTKf0FA==}
+    hasBin: true
+
   tmp@0.2.3:
     resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
     engines: {node: '>=14.14'}
@@ -10906,6 +10464,10 @@ packages:
     resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
     engines: {node: '>=6'}
 
+  tough-cookie@5.0.0:
+    resolution: {integrity: sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==}
+    engines: {node: '>=16'}
+
   tr46@0.0.3:
     resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
 
@@ -10916,6 +10478,10 @@ packages:
   trace-redirect@1.0.6:
     resolution: {integrity: sha512-UUfa1DjjU5flcjMdaFIiIEGDTyu2y/IiMjOX4uGXa7meKBS4vD4f2Uy/tken9Qkd4Jsm4sRsfZcIIPqrRVF3Mg==}
 
+  tree-kill@1.2.2:
+    resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+    hasBin: true
+
   trim-lines@3.0.1:
     resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
 
@@ -10942,8 +10508,8 @@ packages:
     peerDependencies:
       typescript: '>=4.2.0'
 
-  ts-case-convert@2.0.7:
-    resolution: {integrity: sha512-Kqj8wrkuduWsKUOUNRczrkdHCDt4ZNNd6HKjVw42EnMIGHQUABS4pqfy0acETVLwUTppc1fzo/yi11+uMTaqzw==}
+  ts-case-convert@2.1.0:
+    resolution: {integrity: sha512-Ye79el/pHYXfoew6kqhMwCoxp4NWjKNcm2kBzpmEMIU9dd9aBmHNNFtZ+WTm0rz1ngyDmfqDXDlyUnBXayiD0w==}
 
   ts-dedent@2.2.0:
     resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
@@ -11020,8 +10586,8 @@ packages:
     resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
     engines: {node: '>=12.20'}
 
-  type-fest@4.20.1:
-    resolution: {integrity: sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==}
+  type-fest@4.26.1:
+    resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==}
     engines: {node: '>=16'}
 
   type-is@1.6.18:
@@ -11120,23 +10686,13 @@ packages:
       typeorm-aurora-data-api-driver:
         optional: true
 
-  typescript@5.3.3:
-    resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
-    engines: {node: '>=14.17'}
-    hasBin: true
-
   typescript@5.4.2:
     resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==}
     engines: {node: '>=14.17'}
     hasBin: true
 
-  typescript@5.5.4:
-    resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
-    engines: {node: '>=14.17'}
-    hasBin: true
-
-  typescript@5.6.2:
-    resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==}
+  typescript@5.6.3:
+    resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
     engines: {node: '>=14.17'}
     hasBin: true
 
@@ -11164,9 +10720,6 @@ packages:
   undefsafe@2.0.5:
     resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
 
-  undici-types@5.26.5:
-    resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
-
   undici-types@6.19.8:
     resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
 
@@ -11326,8 +10879,8 @@ packages:
   vite-plugin-turbosnap@1.0.3:
     resolution: {integrity: sha512-p4D8CFVhZS412SyQX125qxyzOgIFouwOcvjZWk6bQbNPR1wtaEzFT6jZxAjf1dejlGqa6fqHcuCvQea6EWUkUA==}
 
-  vite@5.4.8:
-    resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==}
+  vite@5.4.11:
+    resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
     engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
     peerDependencies:
@@ -11430,8 +10983,8 @@ packages:
   vue-component-type-helpers@2.0.16:
     resolution: {integrity: sha512-qisL/iAfdO++7w+SsfYQJVPj6QKvxp4i1MMxvsNO41z/8zu3KuAw9LkhKUfP/kcOWGDxESp+pQObWppXusejCA==}
 
-  vue-component-type-helpers@2.1.6:
-    resolution: {integrity: sha512-ng11B8B/ZADUMMOsRbqv0arc442q7lifSubD0v8oDXIFoMg/mXwAPUunrroIDkY+mcD0dHKccdaznSVp8EoX3w==}
+  vue-component-type-helpers@2.1.10:
+    resolution: {integrity: sha512-lfgdSLQKrUmADiSV6PbBvYgQ33KF3Ztv6gP85MfGaGaSGMTXORVaHT1EHfsqCgzRNBstPKYDmvAV9Do5CmJ07A==}
 
   vue-demi@0.14.7:
     resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
@@ -11463,22 +11016,14 @@ packages:
   vue-template-compiler@2.7.14:
     resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==}
 
-  vue-tsc@2.1.6:
-    resolution: {integrity: sha512-f98dyZp5FOukcYmbFpuSCJ4Z0vHSOSmxGttZJCsFeX0M4w/Rsq0s4uKXjcSRsZqsRgQa6z7SfuO+y0HVICE57Q==}
+  vue-tsc@2.1.10:
+    resolution: {integrity: sha512-RBNSfaaRHcN5uqVqJSZh++Gy/YUzryuv9u1aFWhsammDJXNtUiJMNoJ747lZcQ68wUQFx6E73y4FY3D8E7FGMA==}
     hasBin: true
     peerDependencies:
       typescript: '>=5.0.0'
 
-  vue@3.4.37:
-    resolution: {integrity: sha512-3vXvNfkKTBsSJ7JP+LyR7GBuwQuckbWvuwAid3xbqK9ppsKt/DUvfqgZ48fgOLEfpy1IacL5f8QhUVl77RaI7A==}
-    peerDependencies:
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
-
-  vue@3.5.11:
-    resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==}
+  vue@3.5.12:
+    resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
@@ -11715,6 +11260,10 @@ packages:
     resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
     engines: {node: '>=12.20'}
 
+  yoctocolors-cjs@2.1.2:
+    resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
+    engines: {node: '>=18'}
+
   yoctocolors@2.0.2:
     resolution: {integrity: sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==}
     engines: {node: '>=18'}
@@ -12315,7 +11864,7 @@ snapshots:
 
   '@babel/generator@7.24.7':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
       '@jridgewell/gen-mapping': 0.3.5
       '@jridgewell/trace-mapping': 0.3.25
       jsesc: 2.5.2
@@ -12340,25 +11889,25 @@ snapshots:
 
   '@babel/helper-environment-visitor@7.24.7':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/helper-function-name@7.23.0':
     dependencies:
       '@babel/template': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/helper-function-name@7.24.7':
     dependencies:
       '@babel/template': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/helper-hoist-variables@7.22.5':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/helper-hoist-variables@7.24.7':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/helper-module-imports@7.22.15':
     dependencies:
@@ -12367,7 +11916,7 @@ snapshots:
   '@babel/helper-module-imports@7.24.7':
     dependencies:
       '@babel/traverse': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
     transitivePeerDependencies:
       - supports-color
 
@@ -12400,7 +11949,7 @@ snapshots:
   '@babel/helper-simple-access@7.24.7':
     dependencies:
       '@babel/traverse': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
     transitivePeerDependencies:
       - supports-color
 
@@ -12410,7 +11959,7 @@ snapshots:
 
   '@babel/helper-split-export-declaration@7.24.7':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/helper-string-parser@7.24.7': {}
 
@@ -12433,7 +11982,7 @@ snapshots:
   '@babel/helpers@7.24.7':
     dependencies:
       '@babel/template': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/highlight@7.23.4':
     dependencies:
@@ -12539,14 +12088,14 @@ snapshots:
   '@babel/template@7.24.0':
     dependencies:
       '@babel/code-frame': 7.24.7
-      '@babel/parser': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/parser': 7.25.6
+      '@babel/types': 7.25.6
 
   '@babel/template@7.24.7':
     dependencies:
       '@babel/code-frame': 7.24.7
       '@babel/parser': 7.25.6
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@babel/traverse@7.23.5':
     dependencies:
@@ -12572,7 +12121,7 @@ snapshots:
       '@babel/helper-hoist-variables': 7.24.7
       '@babel/helper-split-export-declaration': 7.24.7
       '@babel/parser': 7.25.6
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
       debug: 4.3.7(supports-color@8.1.1)
       globals: 11.12.0
     transitivePeerDependencies:
@@ -12590,30 +12139,28 @@ snapshots:
       '@babel/helper-validator-identifier': 7.24.7
       to-fast-properties: 2.0.0
 
-  '@base2/pretty-print-object@1.0.1': {}
-
   '@bcoe/v8-coverage@0.2.3': {}
 
-  '@bull-board/api@6.0.0(@bull-board/ui@6.0.0)':
+  '@bull-board/api@6.5.0(@bull-board/ui@6.5.0)':
     dependencies:
-      '@bull-board/ui': 6.0.0
+      '@bull-board/ui': 6.5.0
       redis-info: 3.1.0
 
-  '@bull-board/fastify@6.0.0':
+  '@bull-board/fastify@6.5.0':
     dependencies:
-      '@bull-board/api': 6.0.0(@bull-board/ui@6.0.0)
-      '@bull-board/ui': 6.0.0
-      '@fastify/static': 8.0.1
+      '@bull-board/api': 6.5.0(@bull-board/ui@6.5.0)
+      '@bull-board/ui': 6.5.0
+      '@fastify/static': 8.0.2
       '@fastify/view': 10.0.1
       ejs: 3.1.10
 
-  '@bull-board/ui@6.0.0':
+  '@bull-board/ui@6.5.0':
     dependencies:
-      '@bull-board/api': 6.0.0(@bull-board/ui@6.0.0)
+      '@bull-board/api': 6.5.0(@bull-board/ui@6.5.0)
 
-  '@bundled-es-modules/cookie@2.0.0':
+  '@bundled-es-modules/cookie@2.0.1':
     dependencies:
-      cookie: 0.5.0
+      cookie: 0.7.2
 
   '@bundled-es-modules/statuses@1.0.1':
     dependencies:
@@ -12695,7 +12242,7 @@ snapshots:
 
   '@cropper/utils@2.0.0-rc.2': {}
 
-  '@cypress/request@3.0.5':
+  '@cypress/request@3.0.6':
     dependencies:
       aws-sign2: 0.7.0
       aws4: 1.12.0
@@ -12703,7 +12250,7 @@ snapshots:
       combined-stream: 1.0.8
       extend: 3.0.2
       forever-agent: 0.6.1
-      form-data: 4.0.0
+      form-data: 4.0.1
       http-signature: 1.4.0
       is-typedarray: 1.0.0
       isstream: 0.1.2
@@ -12712,7 +12259,7 @@ snapshots:
       performance-now: 2.1.0
       qs: 6.13.0
       safe-buffer: 5.2.1
-      tough-cookie: 4.1.4
+      tough-cookie: 5.0.0
       tunnel-agent: 0.6.0
       uuid: 8.3.2
 
@@ -12743,378 +12290,226 @@ snapshots:
       tslib: 2.7.0
     optional: true
 
-  '@esbuild/aix-ppc64@0.19.11':
-    optional: true
-
   '@esbuild/aix-ppc64@0.21.5':
     optional: true
 
-  '@esbuild/aix-ppc64@0.23.0':
-    optional: true
-
-  '@esbuild/aix-ppc64@0.23.1':
+  '@esbuild/aix-ppc64@0.24.0':
     optional: true
 
   '@esbuild/android-arm64@0.18.20':
     optional: true
 
-  '@esbuild/android-arm64@0.19.11':
-    optional: true
-
   '@esbuild/android-arm64@0.21.5':
     optional: true
 
-  '@esbuild/android-arm64@0.23.0':
-    optional: true
-
-  '@esbuild/android-arm64@0.23.1':
+  '@esbuild/android-arm64@0.24.0':
     optional: true
 
   '@esbuild/android-arm@0.18.20':
     optional: true
 
-  '@esbuild/android-arm@0.19.11':
-    optional: true
-
   '@esbuild/android-arm@0.21.5':
     optional: true
 
-  '@esbuild/android-arm@0.23.0':
-    optional: true
-
-  '@esbuild/android-arm@0.23.1':
+  '@esbuild/android-arm@0.24.0':
     optional: true
 
   '@esbuild/android-x64@0.18.20':
     optional: true
 
-  '@esbuild/android-x64@0.19.11':
-    optional: true
-
   '@esbuild/android-x64@0.21.5':
     optional: true
 
-  '@esbuild/android-x64@0.23.0':
-    optional: true
-
-  '@esbuild/android-x64@0.23.1':
+  '@esbuild/android-x64@0.24.0':
     optional: true
 
   '@esbuild/darwin-arm64@0.18.20':
     optional: true
 
-  '@esbuild/darwin-arm64@0.19.11':
-    optional: true
-
   '@esbuild/darwin-arm64@0.21.5':
     optional: true
 
-  '@esbuild/darwin-arm64@0.23.0':
-    optional: true
-
-  '@esbuild/darwin-arm64@0.23.1':
+  '@esbuild/darwin-arm64@0.24.0':
     optional: true
 
   '@esbuild/darwin-x64@0.18.20':
     optional: true
 
-  '@esbuild/darwin-x64@0.19.11':
-    optional: true
-
   '@esbuild/darwin-x64@0.21.5':
     optional: true
 
-  '@esbuild/darwin-x64@0.23.0':
-    optional: true
-
-  '@esbuild/darwin-x64@0.23.1':
+  '@esbuild/darwin-x64@0.24.0':
     optional: true
 
   '@esbuild/freebsd-arm64@0.18.20':
     optional: true
 
-  '@esbuild/freebsd-arm64@0.19.11':
-    optional: true
-
   '@esbuild/freebsd-arm64@0.21.5':
     optional: true
 
-  '@esbuild/freebsd-arm64@0.23.0':
-    optional: true
-
-  '@esbuild/freebsd-arm64@0.23.1':
+  '@esbuild/freebsd-arm64@0.24.0':
     optional: true
 
   '@esbuild/freebsd-x64@0.18.20':
     optional: true
 
-  '@esbuild/freebsd-x64@0.19.11':
-    optional: true
-
   '@esbuild/freebsd-x64@0.21.5':
     optional: true
 
-  '@esbuild/freebsd-x64@0.23.0':
-    optional: true
-
-  '@esbuild/freebsd-x64@0.23.1':
+  '@esbuild/freebsd-x64@0.24.0':
     optional: true
 
   '@esbuild/linux-arm64@0.18.20':
     optional: true
 
-  '@esbuild/linux-arm64@0.19.11':
-    optional: true
-
   '@esbuild/linux-arm64@0.21.5':
     optional: true
 
-  '@esbuild/linux-arm64@0.23.0':
-    optional: true
-
-  '@esbuild/linux-arm64@0.23.1':
+  '@esbuild/linux-arm64@0.24.0':
     optional: true
 
   '@esbuild/linux-arm@0.18.20':
     optional: true
 
-  '@esbuild/linux-arm@0.19.11':
-    optional: true
-
   '@esbuild/linux-arm@0.21.5':
     optional: true
 
-  '@esbuild/linux-arm@0.23.0':
-    optional: true
-
-  '@esbuild/linux-arm@0.23.1':
+  '@esbuild/linux-arm@0.24.0':
     optional: true
 
   '@esbuild/linux-ia32@0.18.20':
     optional: true
 
-  '@esbuild/linux-ia32@0.19.11':
-    optional: true
-
   '@esbuild/linux-ia32@0.21.5':
     optional: true
 
-  '@esbuild/linux-ia32@0.23.0':
-    optional: true
-
-  '@esbuild/linux-ia32@0.23.1':
+  '@esbuild/linux-ia32@0.24.0':
     optional: true
 
   '@esbuild/linux-loong64@0.18.20':
     optional: true
 
-  '@esbuild/linux-loong64@0.19.11':
-    optional: true
-
   '@esbuild/linux-loong64@0.21.5':
     optional: true
 
-  '@esbuild/linux-loong64@0.23.0':
-    optional: true
-
-  '@esbuild/linux-loong64@0.23.1':
+  '@esbuild/linux-loong64@0.24.0':
     optional: true
 
   '@esbuild/linux-mips64el@0.18.20':
     optional: true
 
-  '@esbuild/linux-mips64el@0.19.11':
-    optional: true
-
   '@esbuild/linux-mips64el@0.21.5':
     optional: true
 
-  '@esbuild/linux-mips64el@0.23.0':
-    optional: true
-
-  '@esbuild/linux-mips64el@0.23.1':
+  '@esbuild/linux-mips64el@0.24.0':
     optional: true
 
   '@esbuild/linux-ppc64@0.18.20':
     optional: true
 
-  '@esbuild/linux-ppc64@0.19.11':
-    optional: true
-
   '@esbuild/linux-ppc64@0.21.5':
     optional: true
 
-  '@esbuild/linux-ppc64@0.23.0':
-    optional: true
-
-  '@esbuild/linux-ppc64@0.23.1':
+  '@esbuild/linux-ppc64@0.24.0':
     optional: true
 
   '@esbuild/linux-riscv64@0.18.20':
     optional: true
 
-  '@esbuild/linux-riscv64@0.19.11':
-    optional: true
-
   '@esbuild/linux-riscv64@0.21.5':
     optional: true
 
-  '@esbuild/linux-riscv64@0.23.0':
-    optional: true
-
-  '@esbuild/linux-riscv64@0.23.1':
+  '@esbuild/linux-riscv64@0.24.0':
     optional: true
 
   '@esbuild/linux-s390x@0.18.20':
     optional: true
 
-  '@esbuild/linux-s390x@0.19.11':
-    optional: true
-
   '@esbuild/linux-s390x@0.21.5':
     optional: true
 
-  '@esbuild/linux-s390x@0.23.0':
-    optional: true
-
-  '@esbuild/linux-s390x@0.23.1':
+  '@esbuild/linux-s390x@0.24.0':
     optional: true
 
   '@esbuild/linux-x64@0.18.20':
     optional: true
 
-  '@esbuild/linux-x64@0.19.11':
-    optional: true
-
   '@esbuild/linux-x64@0.21.5':
     optional: true
 
-  '@esbuild/linux-x64@0.23.0':
-    optional: true
-
-  '@esbuild/linux-x64@0.23.1':
+  '@esbuild/linux-x64@0.24.0':
     optional: true
 
   '@esbuild/netbsd-x64@0.18.20':
     optional: true
 
-  '@esbuild/netbsd-x64@0.19.11':
-    optional: true
-
   '@esbuild/netbsd-x64@0.21.5':
     optional: true
 
-  '@esbuild/netbsd-x64@0.23.0':
+  '@esbuild/netbsd-x64@0.24.0':
     optional: true
 
-  '@esbuild/netbsd-x64@0.23.1':
-    optional: true
-
-  '@esbuild/openbsd-arm64@0.23.0':
-    optional: true
-
-  '@esbuild/openbsd-arm64@0.23.1':
+  '@esbuild/openbsd-arm64@0.24.0':
     optional: true
 
   '@esbuild/openbsd-x64@0.18.20':
     optional: true
 
-  '@esbuild/openbsd-x64@0.19.11':
-    optional: true
-
   '@esbuild/openbsd-x64@0.21.5':
     optional: true
 
-  '@esbuild/openbsd-x64@0.23.0':
-    optional: true
-
-  '@esbuild/openbsd-x64@0.23.1':
+  '@esbuild/openbsd-x64@0.24.0':
     optional: true
 
   '@esbuild/sunos-x64@0.18.20':
     optional: true
 
-  '@esbuild/sunos-x64@0.19.11':
-    optional: true
-
   '@esbuild/sunos-x64@0.21.5':
     optional: true
 
-  '@esbuild/sunos-x64@0.23.0':
-    optional: true
-
-  '@esbuild/sunos-x64@0.23.1':
+  '@esbuild/sunos-x64@0.24.0':
     optional: true
 
   '@esbuild/win32-arm64@0.18.20':
     optional: true
 
-  '@esbuild/win32-arm64@0.19.11':
-    optional: true
-
   '@esbuild/win32-arm64@0.21.5':
     optional: true
 
-  '@esbuild/win32-arm64@0.23.0':
-    optional: true
-
-  '@esbuild/win32-arm64@0.23.1':
+  '@esbuild/win32-arm64@0.24.0':
     optional: true
 
   '@esbuild/win32-ia32@0.18.20':
     optional: true
 
-  '@esbuild/win32-ia32@0.19.11':
-    optional: true
-
   '@esbuild/win32-ia32@0.21.5':
     optional: true
 
-  '@esbuild/win32-ia32@0.23.0':
-    optional: true
-
-  '@esbuild/win32-ia32@0.23.1':
+  '@esbuild/win32-ia32@0.24.0':
     optional: true
 
   '@esbuild/win32-x64@0.18.20':
     optional: true
 
-  '@esbuild/win32-x64@0.19.11':
-    optional: true
-
   '@esbuild/win32-x64@0.21.5':
     optional: true
 
-  '@esbuild/win32-x64@0.23.0':
+  '@esbuild/win32-x64@0.24.0':
     optional: true
 
-  '@esbuild/win32-x64@0.23.1':
-    optional: true
-
-  '@eslint-community/eslint-utils@4.4.0(eslint@9.11.0)':
+  '@eslint-community/eslint-utils@4.4.0(eslint@9.14.0)':
     dependencies:
-      eslint: 9.11.0
-      eslint-visitor-keys: 3.4.3
-
-  '@eslint-community/eslint-utils@4.4.0(eslint@9.8.0)':
-    dependencies:
-      eslint: 9.8.0
+      eslint: 9.14.0
       eslint-visitor-keys: 3.4.3
 
   '@eslint-community/regexpp@4.11.0': {}
 
+  '@eslint-community/regexpp@4.12.1': {}
+
   '@eslint-community/regexpp@4.6.2': {}
 
   '@eslint/compat@1.1.1': {}
 
-  '@eslint/config-array@0.17.1':
-    dependencies:
-      '@eslint/object-schema': 2.1.4
-      debug: 4.3.7(supports-color@8.1.1)
-      minimatch: 3.1.2
-    transitivePeerDependencies:
-      - supports-color
-
   '@eslint/config-array@0.18.0':
     dependencies:
       '@eslint/object-schema': 2.1.4
@@ -13123,11 +12518,13 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
+  '@eslint/core@0.7.0': {}
+
   '@eslint/eslintrc@3.1.0':
     dependencies:
       ajv: 6.12.6
       debug: 4.3.7(supports-color@8.1.1)
-      espree: 10.1.0
+      espree: 10.3.0
       globals: 14.0.0
       ignore: 5.3.1
       import-fresh: 3.3.0
@@ -13137,9 +12534,7 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@eslint/js@9.11.0': {}
-
-  '@eslint/js@9.8.0': {}
+  '@eslint/js@9.14.0': {}
 
   '@eslint/object-schema@2.1.4': {}
 
@@ -13164,9 +12559,9 @@ snapshots:
 
   '@fastify/busboy@3.0.0': {}
 
-  '@fastify/cookie@10.0.1':
+  '@fastify/cookie@11.0.1':
     dependencies:
-      cookie-signature: 1.2.1
+      cookie: 1.0.1
       fastify-plugin: 5.0.0
 
   '@fastify/cors@10.0.1':
@@ -13189,7 +12584,7 @@ snapshots:
     dependencies:
       fast-json-stringify: 6.0.0
 
-  '@fastify/http-proxy@10.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3)':
+  '@fastify/http-proxy@10.0.1(bufferutil@4.0.7)(utf-8-validate@6.0.3)':
     dependencies:
       '@fastify/reply-from': 11.0.0
       fast-querystring: 1.1.2
@@ -13229,7 +12624,7 @@ snapshots:
       http-errors: 2.0.0
       mime: 3.0.0
 
-  '@fastify/static@8.0.1':
+  '@fastify/static@8.0.2':
     dependencies:
       '@fastify/accept-negotiator': 2.0.0
       '@fastify/send': 3.1.1
@@ -13267,12 +12662,21 @@ snapshots:
 
   '@hexagon/base64@1.1.27': {}
 
+  '@humanfs/core@0.19.1': {}
+
+  '@humanfs/node@0.16.6':
+    dependencies:
+      '@humanfs/core': 0.19.1
+      '@humanwhocodes/retry': 0.3.0
+
   '@humanwhocodes/module-importer@1.0.1': {}
 
   '@humanwhocodes/momoa@2.0.4': {}
 
   '@humanwhocodes/retry@0.3.0': {}
 
+  '@humanwhocodes/retry@0.4.1': {}
+
   '@img/sharp-darwin-arm64@0.33.5':
     optionalDependencies:
       '@img/sharp-libvips-darwin-arm64': 1.0.4
@@ -13348,30 +12752,31 @@ snapshots:
   '@img/sharp-win32-x64@0.33.5':
     optional: true
 
-  '@inquirer/confirm@3.1.6':
+  '@inquirer/confirm@5.0.2(@types/node@22.9.0)':
     dependencies:
-      '@inquirer/core': 8.1.0
-      '@inquirer/type': 1.3.1
+      '@inquirer/core': 10.1.0(@types/node@22.9.0)
+      '@inquirer/type': 3.0.1(@types/node@22.9.0)
+      '@types/node': 22.9.0
 
-  '@inquirer/core@8.1.0':
+  '@inquirer/core@10.1.0(@types/node@22.9.0)':
     dependencies:
-      '@inquirer/figures': 1.0.1
-      '@inquirer/type': 1.3.1
-      '@types/mute-stream': 0.0.4
-      '@types/node': 20.14.12
-      '@types/wrap-ansi': 3.0.0
+      '@inquirer/figures': 1.0.8
+      '@inquirer/type': 3.0.1(@types/node@22.9.0)
       ansi-escapes: 4.3.2
-      chalk: 4.1.2
-      cli-spinners: 2.9.2
       cli-width: 4.1.0
-      mute-stream: 1.0.0
+      mute-stream: 2.0.0
       signal-exit: 4.1.0
       strip-ansi: 6.0.1
       wrap-ansi: 6.2.0
+      yoctocolors-cjs: 2.1.2
+    transitivePeerDependencies:
+      - '@types/node'
 
-  '@inquirer/figures@1.0.1': {}
+  '@inquirer/figures@1.0.8': {}
 
-  '@inquirer/type@1.3.1': {}
+  '@inquirer/type@3.0.1(@types/node@22.9.0)':
+    dependencies:
+      '@types/node': 22.9.0
 
   '@ioredis/commands@1.2.0': {}
 
@@ -13397,7 +12802,7 @@ snapshots:
   '@jest/console@29.7.0':
     dependencies:
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       chalk: 4.1.2
       jest-message-util: 29.7.0
       jest-util: 29.7.0
@@ -13410,14 +12815,14 @@ snapshots:
       '@jest/test-result': 29.7.0
       '@jest/transform': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       ansi-escapes: 4.3.2
       chalk: 4.1.2
       ci-info: 3.7.1
       exit: 0.1.2
       graceful-fs: 4.2.11
       jest-changed-files: 29.7.0
-      jest-config: 29.7.0(@types/node@20.14.12)
+      jest-config: 29.7.0(@types/node@22.9.0)
       jest-haste-map: 29.7.0
       jest-message-util: 29.7.0
       jest-regex-util: 29.6.3
@@ -13446,7 +12851,7 @@ snapshots:
     dependencies:
       '@jest/fake-timers': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       jest-mock: 29.7.0
 
   '@jest/expect-utils@29.7.0':
@@ -13464,7 +12869,7 @@ snapshots:
     dependencies:
       '@jest/types': 29.6.3
       '@sinonjs/fake-timers': 10.3.0
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       jest-message-util: 29.7.0
       jest-mock: 29.7.0
       jest-util: 29.7.0
@@ -13486,7 +12891,7 @@ snapshots:
       '@jest/transform': 29.7.0
       '@jest/types': 29.6.3
       '@jridgewell/trace-mapping': 0.3.25
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       chalk: 4.1.2
       collect-v8-coverage: 1.0.1
       exit: 0.1.2
@@ -13556,19 +12961,19 @@ snapshots:
       '@jest/schemas': 29.6.3
       '@types/istanbul-lib-coverage': 2.0.4
       '@types/istanbul-reports': 3.0.1
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       '@types/yargs': 17.0.19
       chalk: 4.1.2
 
-  '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))':
+  '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))':
     dependencies:
       glob: 7.2.3
       glob-promise: 4.2.2(glob@7.2.3)
       magic-string: 0.27.0
-      react-docgen-typescript: 2.2.2(typescript@5.6.2)
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
+      react-docgen-typescript: 2.2.2(typescript@5.6.3)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
     optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
 
   '@jridgewell/gen-mapping@0.3.2':
     dependencies:
@@ -13647,23 +13052,23 @@ snapshots:
       '@types/react': 18.0.28
       react: 18.3.1
 
-  '@microsoft/api-extractor-model@7.29.8(@types/node@20.14.12)':
+  '@microsoft/api-extractor-model@7.29.8(@types/node@22.9.0)':
     dependencies:
       '@microsoft/tsdoc': 0.15.0
       '@microsoft/tsdoc-config': 0.17.0
-      '@rushstack/node-core-library': 5.9.0(@types/node@20.14.12)
+      '@rushstack/node-core-library': 5.9.0(@types/node@22.9.0)
     transitivePeerDependencies:
       - '@types/node'
 
-  '@microsoft/api-extractor@7.47.9(@types/node@20.14.12)':
+  '@microsoft/api-extractor@7.47.11(@types/node@22.9.0)':
     dependencies:
-      '@microsoft/api-extractor-model': 7.29.8(@types/node@20.14.12)
+      '@microsoft/api-extractor-model': 7.29.8(@types/node@22.9.0)
       '@microsoft/tsdoc': 0.15.0
       '@microsoft/tsdoc-config': 0.17.0
-      '@rushstack/node-core-library': 5.9.0(@types/node@20.14.12)
+      '@rushstack/node-core-library': 5.9.0(@types/node@22.9.0)
       '@rushstack/rig-package': 0.5.3
-      '@rushstack/terminal': 0.14.2(@types/node@20.14.12)
-      '@rushstack/ts-command-line': 4.22.8(@types/node@20.14.12)
+      '@rushstack/terminal': 0.14.2(@types/node@22.9.0)
+      '@rushstack/ts-command-line': 4.23.0(@types/node@22.9.0)
       lodash: 4.17.21
       minimatch: 3.0.8
       resolve: 1.22.8
@@ -13684,14 +13089,14 @@ snapshots:
 
   '@misskey-dev/browser-image-resizer@2024.1.0': {}
 
-  '@misskey-dev/eslint-plugin@2.0.3(@eslint/compat@1.1.1)(@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0)(typescript@5.6.2))(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0))(eslint@9.8.0)(globals@15.9.0)':
+  '@misskey-dev/eslint-plugin@2.0.3(@eslint/compat@1.1.1)(@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3))(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0))(eslint@9.14.0)(globals@15.12.0)':
     dependencies:
       '@eslint/compat': 1.1.1
-      '@typescript-eslint/eslint-plugin': 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0)(typescript@5.6.2)
-      '@typescript-eslint/parser': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-      eslint: 9.8.0
-      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0)
-      globals: 15.9.0
+      '@typescript-eslint/eslint-plugin': 7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)
+      '@typescript-eslint/parser': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
+      eslint: 9.14.0
+      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
+      globals: 15.12.0
 
   '@misskey-dev/sharp-read-bmp@1.2.0':
     dependencies:
@@ -13739,16 +13144,7 @@ snapshots:
   '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.2':
     optional: true
 
-  '@mswjs/interceptors@0.29.1':
-    dependencies:
-      '@open-draft/deferred-promise': 2.2.0
-      '@open-draft/logger': 0.3.0
-      '@open-draft/until': 2.1.0
-      is-node-process: 1.2.0
-      outvariant: 1.4.2
-      strict-event-emitter: 0.5.1
-
-  '@mswjs/interceptors@0.35.8':
+  '@mswjs/interceptors@0.36.10':
     dependencies:
       '@open-draft/deferred-promise': 2.2.0
       '@open-draft/logger': 0.3.0
@@ -13796,7 +13192,7 @@ snapshots:
       '@napi-rs/canvas-linux-x64-musl': 0.1.56
       '@napi-rs/canvas-win32-x64-msvc': 0.1.56
 
-  '@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1)':
+  '@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1)':
     dependencies:
       iterare: 1.2.1
       reflect-metadata: 0.2.2
@@ -13804,9 +13200,9 @@ snapshots:
       tslib: 2.7.0
       uid: 2.0.2
 
-  '@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)':
+  '@nestjs/core@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)':
     dependencies:
-      '@nestjs/common': 10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/common': 10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1)
       '@nuxtjs/opencollective': 0.3.2(encoding@0.1.13)
       fast-safe-stringify: 2.1.1
       iterare: 1.2.1
@@ -13816,29 +13212,29 @@ snapshots:
       tslib: 2.7.0
       uid: 2.0.2
     optionalDependencies:
-      '@nestjs/platform-express': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4)
+      '@nestjs/platform-express': 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7)
     transitivePeerDependencies:
       - encoding
 
-  '@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4)':
+  '@nestjs/platform-express@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7)':
     dependencies:
-      '@nestjs/common': 10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1)
-      '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/common': 10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core': 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)
       body-parser: 1.20.3
       cors: 2.8.5
-      express: 4.21.0
+      express: 4.21.1
       multer: 1.4.4-lts.1
       tslib: 2.7.0
     transitivePeerDependencies:
       - supports-color
 
-  '@nestjs/testing@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4))':
+  '@nestjs/testing@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7))':
     dependencies:
-      '@nestjs/common': 10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1)
-      '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/common': 10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1)
+      '@nestjs/core': 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.7)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)
       tslib: 2.7.0
     optionalDependencies:
-      '@nestjs/platform-express': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.4)
+      '@nestjs/platform-express': 10.4.7(@nestjs/common@10.4.7(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.7)
 
   '@noble/hashes@1.5.0': {}
 
@@ -13897,7 +13293,7 @@ snapshots:
   '@open-draft/logger@0.3.0':
     dependencies:
       is-node-process: 1.2.0
-      outvariant: 1.4.2
+      outvariant: 1.4.3
 
   '@open-draft/until@2.1.0': {}
 
@@ -13905,176 +13301,271 @@ snapshots:
     dependencies:
       '@opentelemetry/api': 1.9.0
 
+  '@opentelemetry/api-logs@0.53.0':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+
+  '@opentelemetry/api-logs@0.54.2':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+
   '@opentelemetry/api@1.9.0': {}
 
   '@opentelemetry/context-async-hooks@1.25.1(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
 
-  '@opentelemetry/core@1.24.1(@opentelemetry/api@1.9.0)':
-    dependencies:
-      '@opentelemetry/api': 1.9.0
-      '@opentelemetry/semantic-conventions': 1.24.1
-
   '@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/semantic-conventions': 1.25.1
 
-  '@opentelemetry/instrumentation-connect@0.38.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/semantic-conventions': 1.27.0
+
+  '@opentelemetry/core@1.27.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/semantic-conventions': 1.27.0
+
+  '@opentelemetry/instrumentation-amqplib@0.43.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-connect@0.40.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
       '@types/connect': 3.4.36
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-express@0.41.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-dataloader@0.12.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-fastify@0.38.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-express@0.44.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-graphql@0.42.0(@opentelemetry/api@1.9.0)':
-    dependencies:
-      '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-    transitivePeerDependencies:
-      - supports-color
-
-  '@opentelemetry/instrumentation-hapi@0.40.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-fastify@0.41.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-http@0.52.1(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-fs@0.16.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-generic-pool@0.39.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-graphql@0.44.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-hapi@0.41.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-http@0.53.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
       semver: 7.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-ioredis@0.42.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-ioredis@0.43.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
       '@opentelemetry/redis-common': 0.36.2
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-koa@0.42.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-kafkajs@0.4.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-knex@0.41.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-koa@0.43.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-mongodb@0.46.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-lru-memoizer@0.40.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/sdk-metrics': 1.24.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-mongoose@0.40.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-mongodb@0.48.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-mongoose@0.42.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-mysql2@0.40.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-mysql2@0.41.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
       '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-mysql@0.40.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-mysql@0.41.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
-      '@types/mysql': 2.15.22
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+      '@types/mysql': 2.15.26
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-nestjs-core@0.39.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-nestjs-core@0.40.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-pg@0.43.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-pg@0.44.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
       '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0)
       '@types/pg': 8.6.1
-      '@types/pg-pool': 2.0.4
+      '@types/pg-pool': 2.0.6
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation-redis-4@0.41.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-redis-4@0.42.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
       '@opentelemetry/redis-common': 0.36.2
-      '@opentelemetry/semantic-conventions': 1.25.1
+      '@opentelemetry/semantic-conventions': 1.27.0
     transitivePeerDependencies:
       - supports-color
 
-  '@opentelemetry/instrumentation@0.46.0(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/instrumentation-tedious@0.15.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@types/shimmer': 1.0.5
-      import-in-the-middle: 1.7.1
-      require-in-the-middle: 7.3.0
-      semver: 7.6.3
-      shimmer: 1.2.1
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+      '@types/tedious': 4.0.14
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation-undici@0.6.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0)
     transitivePeerDependencies:
       - supports-color
-    optional: true
 
   '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/api-logs': 0.52.1
       '@types/shimmer': 1.0.5
-      import-in-the-middle: 1.10.0
+      import-in-the-middle: 1.11.2
+      require-in-the-middle: 7.3.0
+      semver: 7.6.3
+      shimmer: 1.2.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/api-logs': 0.53.0
+      '@types/shimmer': 1.2.0
+      import-in-the-middle: 1.11.2
+      require-in-the-middle: 7.3.0
+      semver: 7.6.3
+      shimmer: 1.2.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0)':
+    dependencies:
+      '@opentelemetry/api': 1.9.0
+      '@opentelemetry/api-logs': 0.54.2
+      '@types/shimmer': 1.2.0
+      import-in-the-middle: 1.11.2
       require-in-the-middle: 7.3.0
       semver: 7.6.3
       shimmer: 1.2.1
@@ -14083,36 +13574,23 @@ snapshots:
 
   '@opentelemetry/redis-common@0.36.2': {}
 
-  '@opentelemetry/resources@1.24.1(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/resources@1.27.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.24.1
+      '@opentelemetry/core': 1.27.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
 
-  '@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0)':
+  '@opentelemetry/sdk-trace-base@1.27.0(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
-      '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
-
-  '@opentelemetry/sdk-metrics@1.24.1(@opentelemetry/api@1.9.0)':
-    dependencies:
-      '@opentelemetry/api': 1.9.0
-      '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.9.0)
-      lodash.merge: 4.6.2
-
-  '@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)':
-    dependencies:
-      '@opentelemetry/api': 1.9.0
-      '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
-
-  '@opentelemetry/semantic-conventions@1.24.1': {}
+      '@opentelemetry/core': 1.27.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/resources': 1.27.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
 
   '@opentelemetry/semantic-conventions@1.25.1': {}
 
+  '@opentelemetry/semantic-conventions@1.27.0': {}
+
   '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
@@ -14161,11 +13639,11 @@ snapshots:
   '@pkgjs/parseargs@0.11.0':
     optional: true
 
-  '@prisma/instrumentation@5.17.0':
+  '@prisma/instrumentation@5.19.1':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0)
+      '@opentelemetry/sdk-trace-base': 1.27.0(@opentelemetry/api@1.9.0)
     transitivePeerDependencies:
       - supports-color
 
@@ -14201,78 +13679,84 @@ snapshots:
 
   '@readme/openapi-schemas@3.1.0': {}
 
-  '@rollup/plugin-json@6.1.0(rollup@4.22.5)':
+  '@rollup/plugin-json@6.1.0(rollup@4.26.0)':
     dependencies:
-      '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+      '@rollup/pluginutils': 5.1.3(rollup@4.26.0)
     optionalDependencies:
-      rollup: 4.22.5
+      rollup: 4.26.0
 
-  '@rollup/plugin-replace@5.0.7(rollup@4.22.5)':
+  '@rollup/plugin-replace@5.0.7(rollup@4.26.0)':
     dependencies:
-      '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
+      '@rollup/pluginutils': 5.1.3(rollup@4.26.0)
       magic-string: 0.30.10
     optionalDependencies:
-      rollup: 4.22.5
+      rollup: 4.26.0
 
-  '@rollup/pluginutils@5.1.2(rollup@4.22.5)':
+  '@rollup/pluginutils@5.1.3(rollup@4.26.0)':
     dependencies:
       '@types/estree': 1.0.6
       estree-walker: 2.0.2
-      picomatch: 2.3.1
+      picomatch: 4.0.2
     optionalDependencies:
-      rollup: 4.22.5
+      rollup: 4.26.0
 
-  '@rollup/rollup-android-arm-eabi@4.22.5':
+  '@rollup/rollup-android-arm-eabi@4.26.0':
     optional: true
 
-  '@rollup/rollup-android-arm64@4.22.5':
+  '@rollup/rollup-android-arm64@4.26.0':
     optional: true
 
-  '@rollup/rollup-darwin-arm64@4.22.5':
+  '@rollup/rollup-darwin-arm64@4.26.0':
     optional: true
 
-  '@rollup/rollup-darwin-x64@4.22.5':
+  '@rollup/rollup-darwin-x64@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-arm-gnueabihf@4.22.5':
+  '@rollup/rollup-freebsd-arm64@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-arm-musleabihf@4.22.5':
+  '@rollup/rollup-freebsd-x64@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-arm64-gnu@4.22.5':
+  '@rollup/rollup-linux-arm-gnueabihf@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-arm64-musl@4.22.5':
+  '@rollup/rollup-linux-arm-musleabihf@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-powerpc64le-gnu@4.22.5':
+  '@rollup/rollup-linux-arm64-gnu@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-riscv64-gnu@4.22.5':
+  '@rollup/rollup-linux-arm64-musl@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-s390x-gnu@4.22.5':
+  '@rollup/rollup-linux-powerpc64le-gnu@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-x64-gnu@4.22.5':
+  '@rollup/rollup-linux-riscv64-gnu@4.26.0':
     optional: true
 
-  '@rollup/rollup-linux-x64-musl@4.22.5':
+  '@rollup/rollup-linux-s390x-gnu@4.26.0':
     optional: true
 
-  '@rollup/rollup-win32-arm64-msvc@4.22.5':
+  '@rollup/rollup-linux-x64-gnu@4.26.0':
     optional: true
 
-  '@rollup/rollup-win32-ia32-msvc@4.22.5':
+  '@rollup/rollup-linux-x64-musl@4.26.0':
     optional: true
 
-  '@rollup/rollup-win32-x64-msvc@4.22.5':
+  '@rollup/rollup-win32-arm64-msvc@4.26.0':
+    optional: true
+
+  '@rollup/rollup-win32-ia32-msvc@4.26.0':
+    optional: true
+
+  '@rollup/rollup-win32-x64-msvc@4.26.0':
     optional: true
 
   '@rtsao/scc@1.1.0': {}
 
-  '@rushstack/node-core-library@5.9.0(@types/node@20.14.12)':
+  '@rushstack/node-core-library@5.9.0(@types/node@22.9.0)':
     dependencies:
       ajv: 8.13.0
       ajv-draft-04: 1.0.0(ajv@8.13.0)
@@ -14283,23 +13767,23 @@ snapshots:
       resolve: 1.22.8
       semver: 7.5.4
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@rushstack/rig-package@0.5.3':
     dependencies:
       resolve: 1.22.8
       strip-json-comments: 3.1.1
 
-  '@rushstack/terminal@0.14.2(@types/node@20.14.12)':
+  '@rushstack/terminal@0.14.2(@types/node@22.9.0)':
     dependencies:
-      '@rushstack/node-core-library': 5.9.0(@types/node@20.14.12)
+      '@rushstack/node-core-library': 5.9.0(@types/node@22.9.0)
       supports-color: 8.1.1
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
-  '@rushstack/ts-command-line@4.22.8(@types/node@20.14.12)':
+  '@rushstack/ts-command-line@4.23.0(@types/node@22.9.0)':
     dependencies:
-      '@rushstack/terminal': 0.14.2(@types/node@20.14.12)
+      '@rushstack/terminal': 0.14.2(@types/node@22.9.0)
       '@types/argparse': 1.0.38
       argparse: 1.0.10
       string-argv: 0.3.1
@@ -14308,100 +13792,107 @@ snapshots:
 
   '@sec-ant/readable-stream@0.4.1': {}
 
-  '@sentry/core@8.20.0':
+  '@sentry/core@8.38.0':
     dependencies:
-      '@sentry/types': 8.20.0
-      '@sentry/utils': 8.20.0
+      '@sentry/types': 8.38.0
+      '@sentry/utils': 8.38.0
 
-  '@sentry/node@8.20.0':
+  '@sentry/node@8.38.0':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0)
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-connect': 0.38.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-express': 0.41.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-fastify': 0.38.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-graphql': 0.42.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-hapi': 0.40.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-http': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-ioredis': 0.42.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-koa': 0.42.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-mongodb': 0.46.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-mongoose': 0.40.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-mysql': 0.40.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-mysql2': 0.40.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-nestjs-core': 0.39.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-pg': 0.43.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation-redis-4': 0.41.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
-      '@prisma/instrumentation': 5.17.0
-      '@sentry/core': 8.20.0
-      '@sentry/opentelemetry': 8.20.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)
-      '@sentry/types': 8.20.0
-      '@sentry/utils': 8.20.0
-      import-in-the-middle: 1.10.0
-    optionalDependencies:
-      opentelemetry-instrumentation-fetch-node: 1.2.3(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-amqplib': 0.43.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-connect': 0.40.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-dataloader': 0.12.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-express': 0.44.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-fastify': 0.41.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-fs': 0.16.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-generic-pool': 0.39.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-graphql': 0.44.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-hapi': 0.41.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-http': 0.53.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-ioredis': 0.43.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-kafkajs': 0.4.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-knex': 0.41.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-koa': 0.43.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-lru-memoizer': 0.40.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-mongodb': 0.48.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-mongoose': 0.42.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-mysql': 0.41.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-mysql2': 0.41.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-nestjs-core': 0.40.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-pg': 0.44.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-redis-4': 0.42.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-tedious': 0.15.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/instrumentation-undici': 0.6.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/resources': 1.27.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/sdk-trace-base': 1.27.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+      '@prisma/instrumentation': 5.19.1
+      '@sentry/core': 8.38.0
+      '@sentry/opentelemetry': 8.38.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.27.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0)
+      '@sentry/types': 8.38.0
+      '@sentry/utils': 8.38.0
+      import-in-the-middle: 1.11.2
     transitivePeerDependencies:
       - supports-color
 
-  '@sentry/opentelemetry@8.20.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)':
+  '@sentry/opentelemetry@8.38.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.54.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.27.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0)':
     dependencies:
       '@opentelemetry/api': 1.9.0
       '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
-      '@sentry/core': 8.20.0
-      '@sentry/types': 8.20.0
-      '@sentry/utils': 8.20.0
+      '@opentelemetry/instrumentation': 0.54.2(@opentelemetry/api@1.9.0)
+      '@opentelemetry/sdk-trace-base': 1.27.0(@opentelemetry/api@1.9.0)
+      '@opentelemetry/semantic-conventions': 1.27.0
+      '@sentry/core': 8.38.0
+      '@sentry/types': 8.38.0
+      '@sentry/utils': 8.38.0
 
-  '@sentry/profiling-node@8.20.0':
+  '@sentry/profiling-node@8.38.0':
     dependencies:
-      '@sentry/core': 8.20.0
-      '@sentry/node': 8.20.0
-      '@sentry/types': 8.20.0
-      '@sentry/utils': 8.20.0
+      '@sentry/core': 8.38.0
+      '@sentry/node': 8.38.0
+      '@sentry/types': 8.38.0
+      '@sentry/utils': 8.38.0
       detect-libc: 2.0.3
       node-abi: 3.62.0
     transitivePeerDependencies:
       - supports-color
 
-  '@sentry/types@8.20.0': {}
+  '@sentry/types@8.38.0': {}
 
-  '@sentry/utils@8.20.0':
+  '@sentry/utils@8.38.0':
     dependencies:
-      '@sentry/types': 8.20.0
+      '@sentry/types': 8.38.0
 
-  '@shikijs/core@1.21.0':
+  '@shikijs/core@1.22.2':
     dependencies:
-      '@shikijs/engine-javascript': 1.21.0
-      '@shikijs/engine-oniguruma': 1.21.0
-      '@shikijs/types': 1.21.0
-      '@shikijs/vscode-textmate': 9.2.2
+      '@shikijs/engine-javascript': 1.22.2
+      '@shikijs/engine-oniguruma': 1.22.2
+      '@shikijs/types': 1.22.2
+      '@shikijs/vscode-textmate': 9.3.0
       '@types/hast': 3.0.4
       hast-util-to-html: 9.0.3
 
-  '@shikijs/engine-javascript@1.21.0':
+  '@shikijs/engine-javascript@1.22.2':
     dependencies:
-      '@shikijs/types': 1.21.0
-      '@shikijs/vscode-textmate': 9.2.2
+      '@shikijs/types': 1.22.2
+      '@shikijs/vscode-textmate': 9.3.0
       oniguruma-to-js: 0.4.3
 
-  '@shikijs/engine-oniguruma@1.21.0':
+  '@shikijs/engine-oniguruma@1.22.2':
     dependencies:
-      '@shikijs/types': 1.21.0
-      '@shikijs/vscode-textmate': 9.2.2
+      '@shikijs/types': 1.22.2
+      '@shikijs/vscode-textmate': 9.3.0
 
-  '@shikijs/types@1.21.0':
+  '@shikijs/types@1.22.2':
     dependencies:
-      '@shikijs/vscode-textmate': 9.2.2
+      '@shikijs/vscode-textmate': 9.3.0
       '@types/hast': 3.0.4
 
-  '@shikijs/vscode-textmate@9.2.2': {}
+  '@shikijs/vscode-textmate@9.3.0': {}
 
   '@sideway/address@4.1.4':
     dependencies:
@@ -14431,13 +13922,15 @@ snapshots:
 
   '@simplewebauthn/types@10.0.0': {}
 
+  '@simplewebauthn/types@11.0.0': {}
+
   '@sinclair/typebox@0.27.8': {}
 
   '@sindresorhus/is@4.6.0': {}
 
   '@sindresorhus/is@5.3.0': {}
 
-  '@sindresorhus/is@7.0.0': {}
+  '@sindresorhus/is@7.0.1': {}
 
   '@sindresorhus/merge-streams@4.0.0': {}
 
@@ -14828,189 +14321,166 @@ snapshots:
 
   '@sqltools/formatter@1.2.5': {}
 
-  '@storybook/addon-actions@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-actions@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
       '@types/uuid': 9.0.8
       dequal: 2.0.3
       polished: 4.2.2
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       uuid: 9.0.1
 
-  '@storybook/addon-backgrounds@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-backgrounds@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
       memoizerific: 1.11.3
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
 
-  '@storybook/addon-controls@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-controls@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
       dequal: 2.0.3
-      lodash: 4.17.21
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
 
-  '@storybook/addon-docs@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-docs@8.4.4(@types/react@18.0.28)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@mdx-js/react': 3.0.1(@types/react@18.0.28)(react@18.3.1)
-      '@storybook/blocks': 8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/csf-plugin': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/global': 5.0.0
-      '@storybook/react-dom-shim': 8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@types/react': 18.0.28
-      fs-extra: 11.1.1
+      '@storybook/blocks': 8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/csf-plugin': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/react-dom-shim': 8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
-      rehype-external-links: 3.0.0
-      rehype-slug: 6.0.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
+    transitivePeerDependencies:
+      - '@types/react'
 
-  '@storybook/addon-essentials@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-essentials@8.4.4(@types/react@18.0.28)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      '@storybook/addon-actions': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-backgrounds': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-controls': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-docs': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-highlight': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-measure': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-outline': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-toolbars': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/addon-viewport': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      '@storybook/addon-actions': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-backgrounds': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-controls': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-docs': 8.4.4(@types/react@18.0.28)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-highlight': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-measure': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-outline': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-toolbars': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/addon-viewport': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
+    transitivePeerDependencies:
+      - '@types/react'
 
-  '@storybook/addon-highlight@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-highlight@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/addon-interactions@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-interactions@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
-      '@storybook/instrumenter': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/test': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+      '@storybook/instrumenter': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/test': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       polished: 4.2.2
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
 
-  '@storybook/addon-links@8.3.4(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-links@8.4.4(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/csf': 0.1.11
       '@storybook/global': 5.0.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
     optionalDependencies:
       react: 18.3.1
 
-  '@storybook/addon-mdx-gfm@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-mdx-gfm@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       remark-gfm: 4.0.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
     transitivePeerDependencies:
       - supports-color
 
-  '@storybook/addon-measure@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-measure@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       tiny-invariant: 1.3.3
 
-  '@storybook/addon-outline@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-outline@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
 
-  '@storybook/addon-storysource@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-storysource@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      '@storybook/source-loader': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+      '@storybook/source-loader': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       estraverse: 5.3.0
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       tiny-invariant: 1.3.3
 
-  '@storybook/addon-toolbars@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-toolbars@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/addon-viewport@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/addon-viewport@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       memoizerific: 1.11.3
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/blocks@8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/blocks@8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/csf': 0.1.11
-      '@storybook/global': 5.0.0
       '@storybook/icons': 1.2.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@types/lodash': 4.14.191
-      color-convert: 2.0.1
-      dequal: 2.0.3
-      lodash: 4.17.21
-      markdown-to-jsx: 7.4.7(react@18.3.1)
-      memoizerific: 1.11.3
-      polished: 4.2.2
-      react-colorful: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
-      telejson: 7.2.0
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
-      util-deprecate: 1.0.2
     optionalDependencies:
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
 
-  '@storybook/builder-vite@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))':
+  '@storybook/builder-vite@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))':
     dependencies:
-      '@storybook/csf-plugin': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@types/find-cache-dir': 3.2.1
+      '@storybook/csf-plugin': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       browser-assert: 1.2.1
-      es-module-lexer: 1.5.4
-      express: 4.21.0
-      find-cache-dir: 3.3.2
-      fs-extra: 11.1.1
-      magic-string: 0.30.11
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
-    optionalDependencies:
-      typescript: 5.6.2
-    transitivePeerDependencies:
-      - supports-color
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
 
-  '@storybook/components@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/components@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/core-events@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/core-events@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/core@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)':
+  '@storybook/core@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)':
     dependencies:
       '@storybook/csf': 0.1.11
-      '@types/express': 4.17.21
       better-opn: 3.0.2
       browser-assert: 1.2.1
-      esbuild: 0.23.1
-      esbuild-register: 3.5.0(esbuild@0.23.1)
-      express: 4.21.0
+      esbuild: 0.24.0
+      esbuild-register: 3.5.0(esbuild@0.24.0)
       jsdoc-type-pratt-parser: 4.1.0
       process: 0.11.10
       recast: 0.23.6
       semver: 7.6.3
       util: 0.12.5
       ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+    optionalDependencies:
+      prettier: 3.3.3
     transitivePeerDependencies:
       - bufferutil
       - supports-color
       - utf-8-validate
 
-  '@storybook/csf-plugin@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/csf-plugin@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       unplugin: 1.4.0
 
   '@storybook/csf@0.1.11':
@@ -15024,143 +14494,122 @@ snapshots:
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
 
-  '@storybook/instrumenter@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/instrumenter@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/global': 5.0.0
       '@vitest/utils': 2.1.1
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
-      util: 0.12.5
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/manager-api@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/manager-api@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/preview-api@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/preview-api@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/react-dom-shim@8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/react-dom-shim@8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/react-vite@8.3.4(@storybook/test@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.22.5)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))':
+  '@storybook/react-vite@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.26.0)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))':
     dependencies:
-      '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))
-      '@rollup/pluginutils': 5.1.2(rollup@4.22.5)
-      '@storybook/builder-vite': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))
-      '@storybook/react': 8.3.4(@storybook/test@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)
+      '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))
+      '@rollup/pluginutils': 5.1.3(rollup@4.26.0)
+      '@storybook/builder-vite': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))
+      '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(typescript@5.6.3)
       find-up: 5.0.0
       magic-string: 0.30.11
       react: 18.3.1
       react-docgen: 7.0.1
       react-dom: 18.3.1(react@18.3.1)
       resolve: 1.22.8
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       tsconfig-paths: 4.2.0
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
     transitivePeerDependencies:
-      - '@preact/preset-vite'
       - '@storybook/test'
       - rollup
       - supports-color
       - typescript
-      - vite-plugin-glimmerx
 
-  '@storybook/react@8.3.4(@storybook/test@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)':
+  '@storybook/react@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(typescript@5.6.3)':
     dependencies:
-      '@storybook/components': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+      '@storybook/components': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/global': 5.0.0
-      '@storybook/manager-api': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/preview-api': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/react-dom-shim': 8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/theming': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@types/escodegen': 0.0.6
-      '@types/estree': 0.0.51
-      '@types/node': 22.5.5
-      acorn: 7.4.1
-      acorn-jsx: 5.3.2(acorn@7.4.1)
-      acorn-walk: 7.2.0
-      escodegen: 2.1.0
-      html-tags: 3.2.0
-      prop-types: 15.8.1
+      '@storybook/manager-api': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/preview-api': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/react-dom-shim': 8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/theming': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
-      react-element-to-jsx-string: 15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      semver: 7.6.3
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
-      ts-dedent: 2.2.0
-      type-fest: 2.19.0
-      util-deprecate: 1.0.2
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
     optionalDependencies:
-      '@storybook/test': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      typescript: 5.6.2
+      '@storybook/test': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      typescript: 5.6.3
 
-  '@storybook/source-loader@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/source-loader@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/csf': 0.1.11
+      es-toolkit: 1.27.0
       estraverse: 5.3.0
-      lodash: 4.17.21
       prettier: 3.3.3
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/test@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/test@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
       '@storybook/csf': 0.1.11
       '@storybook/global': 5.0.0
-      '@storybook/instrumenter': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+      '@storybook/instrumenter': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@testing-library/dom': 10.4.0
       '@testing-library/jest-dom': 6.5.0
       '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0)
       '@vitest/expect': 2.0.5
       '@vitest/spy': 2.0.5
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
-      util: 0.12.5
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/theming@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/theming@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/types@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))':
+  '@storybook/types@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))':
     dependencies:
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
 
-  '@storybook/vue3-vite@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))(vue@3.5.11(typescript@5.6.2))':
+  '@storybook/vue3-vite@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))':
     dependencies:
-      '@storybook/builder-vite': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(typescript@5.6.2)(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))
-      '@storybook/vue3': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.5.11(typescript@5.6.2))
+      '@storybook/builder-vite': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))
+      '@storybook/vue3': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vue@3.5.12(typescript@5.6.3))
       find-package-json: 1.2.0
       magic-string: 0.30.11
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
-      typescript: 5.6.2
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
-      vue-component-meta: 2.0.16(typescript@5.6.2)
-      vue-docgen-api: 4.75.1(vue@3.5.11(typescript@5.6.2))
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
+      typescript: 5.6.3
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
+      vue-component-meta: 2.0.16(typescript@5.6.3)
+      vue-docgen-api: 4.75.1(vue@3.5.12(typescript@5.6.3))
     transitivePeerDependencies:
-      - '@preact/preset-vite'
-      - supports-color
-      - vite-plugin-glimmerx
       - vue
 
-  '@storybook/vue3@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))(vue@3.5.11(typescript@5.6.2))':
+  '@storybook/vue3@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))(vue@3.5.12(typescript@5.6.3))':
     dependencies:
-      '@storybook/components': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+      '@storybook/components': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
       '@storybook/global': 5.0.0
-      '@storybook/manager-api': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/preview-api': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/theming': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@vue/compiler-core': 3.5.10
-      storybook: 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      '@storybook/manager-api': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/preview-api': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/theming': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@vue/compiler-core': 3.5.12
+      storybook: 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
       ts-dedent: 2.2.0
       type-fest: 2.19.0
-      vue: 3.5.11(typescript@5.6.2)
-      vue-component-type-helpers: 2.1.6
+      vue: 3.5.12(typescript@5.6.3)
+      vue-component-type-helpers: 2.1.10
 
-  '@swc/cli@0.3.12(@swc/core@1.6.6)(chokidar@3.5.3)':
+  '@swc/cli@0.3.12(@swc/core@1.9.2)(chokidar@3.5.3)':
     dependencies:
       '@mole-inc/bin-wrapper': 8.0.1
-      '@swc/core': 1.6.6
+      '@swc/core': 1.9.2
       '@swc/counter': 0.1.3
       commander: 8.3.0
       fast-glob: 3.3.2
@@ -15180,19 +14629,13 @@ snapshots:
   '@swc/core-darwin-arm64@1.3.56':
     optional: true
 
-  '@swc/core-darwin-arm64@1.6.13':
-    optional: true
-
-  '@swc/core-darwin-arm64@1.6.6':
+  '@swc/core-darwin-arm64@1.9.2':
     optional: true
 
   '@swc/core-darwin-x64@1.3.56':
     optional: true
 
-  '@swc/core-darwin-x64@1.6.13':
-    optional: true
-
-  '@swc/core-darwin-x64@1.6.6':
+  '@swc/core-darwin-x64@1.9.2':
     optional: true
 
   '@swc/core-freebsd-x64@1.3.11':
@@ -15203,124 +14646,77 @@ snapshots:
   '@swc/core-linux-arm-gnueabihf@1.3.56':
     optional: true
 
-  '@swc/core-linux-arm-gnueabihf@1.6.13':
-    optional: true
-
-  '@swc/core-linux-arm-gnueabihf@1.6.6':
+  '@swc/core-linux-arm-gnueabihf@1.9.2':
     optional: true
 
   '@swc/core-linux-arm64-gnu@1.3.56':
     optional: true
 
-  '@swc/core-linux-arm64-gnu@1.6.13':
-    optional: true
-
-  '@swc/core-linux-arm64-gnu@1.6.6':
+  '@swc/core-linux-arm64-gnu@1.9.2':
     optional: true
 
   '@swc/core-linux-arm64-musl@1.3.56':
     optional: true
 
-  '@swc/core-linux-arm64-musl@1.6.13':
-    optional: true
-
-  '@swc/core-linux-arm64-musl@1.6.6':
+  '@swc/core-linux-arm64-musl@1.9.2':
     optional: true
 
   '@swc/core-linux-x64-gnu@1.3.56':
     optional: true
 
-  '@swc/core-linux-x64-gnu@1.6.13':
-    optional: true
-
-  '@swc/core-linux-x64-gnu@1.6.6':
+  '@swc/core-linux-x64-gnu@1.9.2':
     optional: true
 
   '@swc/core-linux-x64-musl@1.3.56':
     optional: true
 
-  '@swc/core-linux-x64-musl@1.6.13':
-    optional: true
-
-  '@swc/core-linux-x64-musl@1.6.6':
+  '@swc/core-linux-x64-musl@1.9.2':
     optional: true
 
   '@swc/core-win32-arm64-msvc@1.3.56':
     optional: true
 
-  '@swc/core-win32-arm64-msvc@1.6.13':
-    optional: true
-
-  '@swc/core-win32-arm64-msvc@1.6.6':
+  '@swc/core-win32-arm64-msvc@1.9.2':
     optional: true
 
   '@swc/core-win32-ia32-msvc@1.3.56':
     optional: true
 
-  '@swc/core-win32-ia32-msvc@1.6.13':
-    optional: true
-
-  '@swc/core-win32-ia32-msvc@1.6.6':
+  '@swc/core-win32-ia32-msvc@1.9.2':
     optional: true
 
   '@swc/core-win32-x64-msvc@1.3.56':
     optional: true
 
-  '@swc/core-win32-x64-msvc@1.6.13':
+  '@swc/core-win32-x64-msvc@1.9.2':
     optional: true
 
-  '@swc/core-win32-x64-msvc@1.6.6':
-    optional: true
-
-  '@swc/core@1.6.13':
+  '@swc/core@1.9.2':
     dependencies:
       '@swc/counter': 0.1.3
-      '@swc/types': 0.1.9
+      '@swc/types': 0.1.15
     optionalDependencies:
-      '@swc/core-darwin-arm64': 1.6.13
-      '@swc/core-darwin-x64': 1.6.13
-      '@swc/core-linux-arm-gnueabihf': 1.6.13
-      '@swc/core-linux-arm64-gnu': 1.6.13
-      '@swc/core-linux-arm64-musl': 1.6.13
-      '@swc/core-linux-x64-gnu': 1.6.13
-      '@swc/core-linux-x64-musl': 1.6.13
-      '@swc/core-win32-arm64-msvc': 1.6.13
-      '@swc/core-win32-ia32-msvc': 1.6.13
-      '@swc/core-win32-x64-msvc': 1.6.13
-
-  '@swc/core@1.6.6':
-    dependencies:
-      '@swc/counter': 0.1.3
-      '@swc/types': 0.1.9
-    optionalDependencies:
-      '@swc/core-darwin-arm64': 1.6.6
-      '@swc/core-darwin-x64': 1.6.6
-      '@swc/core-linux-arm-gnueabihf': 1.6.6
-      '@swc/core-linux-arm64-gnu': 1.6.6
-      '@swc/core-linux-arm64-musl': 1.6.6
-      '@swc/core-linux-x64-gnu': 1.6.6
-      '@swc/core-linux-x64-musl': 1.6.6
-      '@swc/core-win32-arm64-msvc': 1.6.6
-      '@swc/core-win32-ia32-msvc': 1.6.6
-      '@swc/core-win32-x64-msvc': 1.6.6
+      '@swc/core-darwin-arm64': 1.9.2
+      '@swc/core-darwin-x64': 1.9.2
+      '@swc/core-linux-arm-gnueabihf': 1.9.2
+      '@swc/core-linux-arm64-gnu': 1.9.2
+      '@swc/core-linux-arm64-musl': 1.9.2
+      '@swc/core-linux-x64-gnu': 1.9.2
+      '@swc/core-linux-x64-musl': 1.9.2
+      '@swc/core-win32-arm64-msvc': 1.9.2
+      '@swc/core-win32-ia32-msvc': 1.9.2
+      '@swc/core-win32-x64-msvc': 1.9.2
 
   '@swc/counter@0.1.3': {}
 
-  '@swc/jest@0.2.36(@swc/core@1.6.13)':
+  '@swc/jest@0.2.37(@swc/core@1.9.2)':
     dependencies:
       '@jest/create-cache-key-function': 29.7.0
-      '@swc/core': 1.6.13
+      '@swc/core': 1.9.2
       '@swc/counter': 0.1.3
       jsonc-parser: 3.2.0
 
-  '@swc/jest@0.2.36(@swc/core@1.6.6)':
-    dependencies:
-      '@jest/create-cache-key-function': 29.7.0
-      '@swc/core': 1.6.6
-      '@swc/counter': 0.1.3
-      jsonc-parser: 3.2.0
-
-  '@swc/types@0.1.9':
+  '@swc/types@0.1.15':
     dependencies:
       '@swc/counter': 0.1.3
 
@@ -15462,14 +14858,14 @@ snapshots:
     dependencies:
       '@testing-library/dom': 10.4.0
 
-  '@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.11)(@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2)))(vue@3.5.11(typescript@5.6.2))':
+  '@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.12)(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))':
     dependencies:
       '@babel/runtime': 7.23.4
       '@testing-library/dom': 9.3.4
-      '@vue/test-utils': 2.4.1(@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2)))(vue@3.5.11(typescript@5.6.2))
-      vue: 3.5.11(typescript@5.6.2)
+      '@vue/test-utils': 2.4.1(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))
+      vue: 3.5.12(typescript@5.6.3)
     optionalDependencies:
-      '@vue/compiler-sfc': 3.5.11
+      '@vue/compiler-sfc': 3.5.12
     transitivePeerDependencies:
       - '@vue/server-renderer'
 
@@ -15487,9 +14883,9 @@ snapshots:
 
   '@types/accepts@1.3.7':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
-  '@types/archiver@6.0.2':
+  '@types/archiver@6.0.3':
     dependencies:
       '@types/readdir-glob': 1.1.1
 
@@ -15499,31 +14895,31 @@ snapshots:
 
   '@types/babel__core@7.20.0':
     dependencies:
-      '@babel/parser': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/parser': 7.25.6
+      '@babel/types': 7.25.6
       '@types/babel__generator': 7.6.4
       '@types/babel__template': 7.4.1
       '@types/babel__traverse': 7.20.0
 
   '@types/babel__generator@7.6.4':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@types/babel__template@7.4.1':
     dependencies:
-      '@babel/parser': 7.24.7
-      '@babel/types': 7.24.7
+      '@babel/parser': 7.25.6
+      '@babel/types': 7.25.6
 
   '@types/babel__traverse@7.20.0':
     dependencies:
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
 
   '@types/bcryptjs@2.4.6': {}
 
   '@types/body-parser@1.19.5':
     dependencies:
       '@types/connect': 3.4.35
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/braces@3.0.1': {}
 
@@ -15531,7 +14927,7 @@ snapshots:
     dependencies:
       '@types/http-cache-semantics': 4.0.4
       '@types/keyv': 3.1.4
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       '@types/responselike': 1.0.0
 
   '@types/canvas-confetti@1.6.4': {}
@@ -15544,11 +14940,11 @@ snapshots:
 
   '@types/connect@3.4.35':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/connect@3.4.36':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/content-disposition@0.5.8': {}
 
@@ -15562,20 +14958,16 @@ snapshots:
 
   '@types/doctrine@0.0.9': {}
 
-  '@types/escodegen@0.0.6': {}
-
   '@types/eslint@7.29.0':
     dependencies:
       '@types/estree': 1.0.6
       '@types/json-schema': 7.0.15
 
-  '@types/estree@0.0.51': {}
-
   '@types/estree@1.0.6': {}
 
   '@types/express-serve-static-core@4.17.33':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       '@types/qs': 6.9.7
       '@types/range-parser': 1.2.4
 
@@ -15586,27 +14978,18 @@ snapshots:
       '@types/qs': 6.9.7
       '@types/serve-static': 1.15.1
 
-  '@types/express@4.17.21':
+  '@types/fluent-ffmpeg@2.1.27':
     dependencies:
-      '@types/body-parser': 1.19.5
-      '@types/express-serve-static-core': 4.17.33
-      '@types/qs': 6.9.7
-      '@types/serve-static': 1.15.1
-
-  '@types/find-cache-dir@3.2.1': {}
-
-  '@types/fluent-ffmpeg@2.1.26':
-    dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/glob@7.2.0':
     dependencies:
       '@types/minimatch': 5.1.2
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/graceful-fs@4.1.6':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/hast@3.0.4':
     dependencies:
@@ -15618,7 +15001,7 @@ snapshots:
 
   '@types/http-link-header@1.0.7':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/istanbul-lib-coverage@2.0.4': {}
 
@@ -15630,7 +15013,7 @@ snapshots:
     dependencies:
       '@types/istanbul-lib-report': 3.0.0
 
-  '@types/jest@29.5.13':
+  '@types/jest@29.5.14':
     dependencies:
       expect: 29.7.0
       pretty-format: 29.7.0
@@ -15639,9 +15022,9 @@ snapshots:
 
   '@types/jsdom@21.1.7':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       '@types/tough-cookie': 4.0.2
-      parse5: 7.1.2
+      parse5: 7.2.1
 
   '@types/json-schema@7.0.12': {}
 
@@ -15655,14 +15038,10 @@ snapshots:
 
   '@types/keyv@3.1.4':
     dependencies:
-      '@types/node': 20.14.12
-
-  '@types/lodash@4.14.191': {}
+      '@types/node': 22.9.0
 
   '@types/long@4.0.2': {}
 
-  '@types/matter-js@0.19.6': {}
-
   '@types/matter-js@0.19.7': {}
 
   '@types/mdast@4.0.3':
@@ -15685,38 +15064,22 @@ snapshots:
 
   '@types/ms@0.7.34': {}
 
-  '@types/mute-stream@0.0.4':
+  '@types/mysql@2.15.26':
     dependencies:
-      '@types/node': 20.14.12
-
-  '@types/mysql@2.15.22':
-    dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/node-fetch@2.6.11':
     dependencies:
-      '@types/node': 20.14.12
-      form-data: 4.0.0
+      '@types/node': 22.9.0
+      form-data: 4.0.1
 
-  '@types/node@20.11.5':
-    dependencies:
-      undici-types: 5.26.5
-
-  '@types/node@20.14.12':
-    dependencies:
-      undici-types: 5.26.5
-
-  '@types/node@20.9.1':
-    dependencies:
-      undici-types: 5.26.5
-
-  '@types/node@22.5.5':
+  '@types/node@22.9.0':
     dependencies:
       undici-types: 6.19.8
 
   '@types/nodemailer@6.4.16':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/normalize-package-data@2.4.1': {}
 
@@ -15727,30 +15090,30 @@ snapshots:
   '@types/oauth2orize@1.11.5':
     dependencies:
       '@types/express': 4.17.17
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
-  '@types/oauth@0.9.5':
+  '@types/oauth@0.9.6':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/offscreencanvas@2019.3.0': {}
 
   '@types/offscreencanvas@2019.7.0': {}
 
-  '@types/pg-pool@2.0.4':
+  '@types/pg-pool@2.0.6':
     dependencies:
       '@types/pg': 8.11.10
 
   '@types/pg@8.11.10':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       pg-protocol: 1.6.1
       pg-types: 4.0.1
 
   '@types/pg@8.6.1':
     dependencies:
-      '@types/node': 20.14.12
-      pg-protocol: 1.6.1
+      '@types/node': 22.9.0
+      pg-protocol: 1.7.0
       pg-types: 2.2.0
 
   '@types/prop-types@15.7.5': {}
@@ -15761,7 +15124,7 @@ snapshots:
 
   '@types/qrcode@1.5.5':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/qs@6.9.7': {}
 
@@ -15779,7 +15142,7 @@ snapshots:
 
   '@types/readdir-glob@1.1.1':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/rename@1.0.7': {}
 
@@ -15787,7 +15150,7 @@ snapshots:
 
   '@types/responselike@1.0.0':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/sanitize-html@2.13.0':
     dependencies:
@@ -15804,12 +15167,14 @@ snapshots:
   '@types/serve-static@1.15.1':
     dependencies:
       '@types/mime': 3.0.1
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/serviceworker@0.0.67': {}
 
   '@types/shimmer@1.0.5': {}
 
+  '@types/shimmer@1.2.0': {}
+
   '@types/simple-oauth2@5.0.7': {}
 
   '@types/sinon@10.0.13':
@@ -15826,6 +15191,10 @@ snapshots:
 
   '@types/statuses@2.0.4': {}
 
+  '@types/tedious@4.0.14':
+    dependencies:
+      '@types/node': 22.9.0
+
   '@types/throttle-debounce@5.0.2': {}
 
   '@types/tinycolor2@1.4.6': {}
@@ -15844,19 +15213,17 @@ snapshots:
 
   '@types/vary@1.1.3':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
-  '@types/web-push@3.6.3':
+  '@types/web-push@3.6.4':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/webgl-ext@0.0.30': {}
 
-  '@types/wrap-ansi@3.0.0': {}
-
-  '@types/ws@8.5.12':
+  '@types/ws@8.5.13':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
 
   '@types/yargs-parser@21.0.0': {}
 
@@ -15866,132 +15233,70 @@ snapshots:
 
   '@types/yauzl@2.10.0':
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
     optional: true
 
-  '@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.11.0)(typescript@5.3.3))(eslint@9.11.0)(typescript@5.3.3)':
+  '@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
       '@eslint-community/regexpp': 4.6.2
-      '@typescript-eslint/parser': 7.1.0(eslint@9.11.0)(typescript@5.3.3)
+      '@typescript-eslint/parser': 7.1.0(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/scope-manager': 7.1.0
-      '@typescript-eslint/type-utils': 7.1.0(eslint@9.11.0)(typescript@5.3.3)
-      '@typescript-eslint/utils': 7.1.0(eslint@9.11.0)(typescript@5.3.3)
+      '@typescript-eslint/type-utils': 7.1.0(eslint@9.14.0)(typescript@5.6.3)
+      '@typescript-eslint/utils': 7.1.0(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/visitor-keys': 7.1.0
-      debug: 4.3.4(supports-color@5.5.0)
-      eslint: 9.11.0
+      debug: 4.3.4
+      eslint: 9.14.0
       graphemer: 1.4.0
       ignore: 5.2.4
       natural-compare: 1.4.0
       semver: 7.6.0
-      ts-api-utils: 1.0.1(typescript@5.3.3)
+      ts-api-utils: 1.0.1(typescript@5.6.3)
     optionalDependencies:
-      typescript: 5.3.3
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.5.4))(eslint@9.11.0)(typescript@5.5.4)':
+  '@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
       '@eslint-community/regexpp': 4.11.0
-      '@typescript-eslint/parser': 7.17.0(eslint@9.11.0)(typescript@5.5.4)
+      '@typescript-eslint/parser': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/type-utils': 7.17.0(eslint@9.11.0)(typescript@5.5.4)
-      '@typescript-eslint/utils': 7.17.0(eslint@9.11.0)(typescript@5.5.4)
+      '@typescript-eslint/type-utils': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
+      '@typescript-eslint/utils': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
       '@typescript-eslint/visitor-keys': 7.17.0
-      eslint: 9.11.0
+      eslint: 9.14.0
       graphemer: 1.4.0
       ignore: 5.3.1
       natural-compare: 1.4.0
-      ts-api-utils: 1.3.0(typescript@5.5.4)
+      ts-api-utils: 1.3.0(typescript@5.6.3)
     optionalDependencies:
-      typescript: 5.5.4
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0)(typescript@5.6.2)':
-    dependencies:
-      '@eslint-community/regexpp': 4.11.0
-      '@typescript-eslint/parser': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
-      '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/type-utils': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
-      '@typescript-eslint/utils': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
-      '@typescript-eslint/visitor-keys': 7.17.0
-      eslint: 9.11.0
-      graphemer: 1.4.0
-      ignore: 5.3.1
-      natural-compare: 1.4.0
-      ts-api-utils: 1.3.0(typescript@5.6.2)
-    optionalDependencies:
-      typescript: 5.6.2
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0)(typescript@5.6.2)':
-    dependencies:
-      '@eslint-community/regexpp': 4.11.0
-      '@typescript-eslint/parser': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-      '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/type-utils': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-      '@typescript-eslint/utils': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-      '@typescript-eslint/visitor-keys': 7.17.0
-      eslint: 9.8.0
-      graphemer: 1.4.0
-      ignore: 5.3.1
-      natural-compare: 1.4.0
-      ts-api-utils: 1.3.0(typescript@5.6.2)
-    optionalDependencies:
-      typescript: 5.6.2
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/parser@7.1.0(eslint@9.11.0)(typescript@5.3.3)':
+  '@typescript-eslint/parser@7.1.0(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
       '@typescript-eslint/scope-manager': 7.1.0
       '@typescript-eslint/types': 7.1.0
-      '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3)
+      '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.6.3)
       '@typescript-eslint/visitor-keys': 7.1.0
-      debug: 4.3.4(supports-color@5.5.0)
-      eslint: 9.11.0
+      debug: 4.3.4
+      eslint: 9.14.0
     optionalDependencies:
-      typescript: 5.3.3
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.5.4)':
+  '@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
       '@typescript-eslint/scope-manager': 7.17.0
       '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4)
+      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.3)
       '@typescript-eslint/visitor-keys': 7.17.0
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.11.0
+      debug: 4.3.5
+      eslint: 9.14.0
     optionalDependencies:
-      typescript: 5.5.4
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2)':
-    dependencies:
-      '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.2)
-      '@typescript-eslint/visitor-keys': 7.17.0
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.11.0
-    optionalDependencies:
-      typescript: 5.6.2
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2)':
-    dependencies:
-      '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.2)
-      '@typescript-eslint/visitor-keys': 7.17.0
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.8.0
-    optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
@@ -16005,51 +15310,27 @@ snapshots:
       '@typescript-eslint/types': 7.17.0
       '@typescript-eslint/visitor-keys': 7.17.0
 
-  '@typescript-eslint/type-utils@7.1.0(eslint@9.11.0)(typescript@5.3.3)':
+  '@typescript-eslint/type-utils@7.1.0(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
-      '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3)
-      '@typescript-eslint/utils': 7.1.0(eslint@9.11.0)(typescript@5.3.3)
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.11.0
-      ts-api-utils: 1.0.1(typescript@5.3.3)
+      '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.6.3)
+      '@typescript-eslint/utils': 7.1.0(eslint@9.14.0)(typescript@5.6.3)
+      debug: 4.3.5
+      eslint: 9.14.0
+      ts-api-utils: 1.0.1(typescript@5.6.3)
     optionalDependencies:
-      typescript: 5.3.3
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/type-utils@7.17.0(eslint@9.11.0)(typescript@5.5.4)':
+  '@typescript-eslint/type-utils@7.17.0(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4)
-      '@typescript-eslint/utils': 7.17.0(eslint@9.11.0)(typescript@5.5.4)
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.11.0
-      ts-api-utils: 1.3.0(typescript@5.5.4)
+      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.3)
+      '@typescript-eslint/utils': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
+      debug: 4.3.5
+      eslint: 9.14.0
+      ts-api-utils: 1.3.0(typescript@5.6.3)
     optionalDependencies:
-      typescript: 5.5.4
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/type-utils@7.17.0(eslint@9.11.0)(typescript@5.6.2)':
-    dependencies:
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.2)
-      '@typescript-eslint/utils': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.11.0
-      ts-api-utils: 1.3.0(typescript@5.6.2)
-    optionalDependencies:
-      typescript: 5.6.2
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/type-utils@7.17.0(eslint@9.8.0)(typescript@5.6.2)':
-    dependencies:
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.2)
-      '@typescript-eslint/utils': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.8.0
-      ts-api-utils: 1.3.0(typescript@5.6.2)
-    optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
@@ -16057,94 +15338,57 @@ snapshots:
 
   '@typescript-eslint/types@7.17.0': {}
 
-  '@typescript-eslint/typescript-estree@7.1.0(typescript@5.3.3)':
+  '@typescript-eslint/typescript-estree@7.1.0(typescript@5.6.3)':
     dependencies:
       '@typescript-eslint/types': 7.1.0
       '@typescript-eslint/visitor-keys': 7.1.0
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       globby: 11.1.0
       is-glob: 4.0.3
       minimatch: 9.0.3
       semver: 7.6.0
-      ts-api-utils: 1.0.1(typescript@5.3.3)
+      ts-api-utils: 1.0.1(typescript@5.6.3)
     optionalDependencies:
-      typescript: 5.3.3
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/typescript-estree@7.17.0(typescript@5.5.4)':
+  '@typescript-eslint/typescript-estree@7.17.0(typescript@5.6.3)':
     dependencies:
       '@typescript-eslint/types': 7.17.0
       '@typescript-eslint/visitor-keys': 7.17.0
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       globby: 11.1.0
       is-glob: 4.0.3
       minimatch: 9.0.4
       semver: 7.6.0
-      ts-api-utils: 1.3.0(typescript@5.5.4)
+      ts-api-utils: 1.3.0(typescript@5.6.3)
     optionalDependencies:
-      typescript: 5.5.4
+      typescript: 5.6.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/typescript-estree@7.17.0(typescript@5.6.2)':
+  '@typescript-eslint/utils@7.1.0(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
-      '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/visitor-keys': 7.17.0
-      debug: 4.3.5(supports-color@5.5.0)
-      globby: 11.1.0
-      is-glob: 4.0.3
-      minimatch: 9.0.4
-      semver: 7.6.0
-      ts-api-utils: 1.3.0(typescript@5.6.2)
-    optionalDependencies:
-      typescript: 5.6.2
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/utils@7.1.0(eslint@9.11.0)(typescript@5.3.3)':
-    dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0)
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0)
       '@types/json-schema': 7.0.12
       '@types/semver': 7.5.8
       '@typescript-eslint/scope-manager': 7.1.0
       '@typescript-eslint/types': 7.1.0
-      '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3)
-      eslint: 9.11.0
+      '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.6.3)
+      eslint: 9.14.0
       semver: 7.6.0
     transitivePeerDependencies:
       - supports-color
       - typescript
 
-  '@typescript-eslint/utils@7.17.0(eslint@9.11.0)(typescript@5.5.4)':
+  '@typescript-eslint/utils@7.17.0(eslint@9.14.0)(typescript@5.6.3)':
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0)
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0)
       '@typescript-eslint/scope-manager': 7.17.0
       '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.5.4)
-      eslint: 9.11.0
-    transitivePeerDependencies:
-      - supports-color
-      - typescript
-
-  '@typescript-eslint/utils@7.17.0(eslint@9.11.0)(typescript@5.6.2)':
-    dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0)
-      '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.2)
-      eslint: 9.11.0
-    transitivePeerDependencies:
-      - supports-color
-      - typescript
-
-  '@typescript-eslint/utils@7.17.0(eslint@9.8.0)(typescript@5.6.2)':
-    dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0)
-      '@typescript-eslint/scope-manager': 7.17.0
-      '@typescript-eslint/types': 7.17.0
-      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.2)
-      eslint: 9.8.0
+      '@typescript-eslint/typescript-estree': 7.17.0(typescript@5.6.3)
+      eslint: 9.14.0
     transitivePeerDependencies:
       - supports-color
       - typescript
@@ -16161,21 +15405,21 @@ snapshots:
 
   '@ungap/structured-clone@1.2.0': {}
 
-  '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0))(vue@3.5.11(typescript@5.6.2))':
+  '@vitejs/plugin-vue@5.2.0(vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))':
     dependencies:
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
-      vue: 3.5.11(typescript@5.6.2)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
+      vue: 3.5.12(typescript@5.6.3)
 
-  '@vitejs/plugin-vue@5.1.4(vite@5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0))(vue@3.5.11(typescript@5.6.2))':
+  '@vitejs/plugin-vue@5.2.0(vite@5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))':
     dependencies:
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0)
-      vue: 3.5.11(typescript@5.6.2)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0)
+      vue: 3.5.12(typescript@5.6.3)
 
-  '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0))':
+  '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0))':
     dependencies:
       '@ampproject/remapping': 2.2.1
       '@bcoe/v8-coverage': 0.2.3
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       istanbul-lib-coverage: 3.2.2
       istanbul-lib-report: 3.0.1
       istanbul-lib-source-maps: 5.0.4
@@ -16186,15 +15430,15 @@ snapshots:
       std-env: 3.7.0
       strip-literal: 2.1.0
       test-exclude: 6.0.0
-      vitest: 1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0)
+      vitest: 1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.4)(terser@5.33.0))':
+  '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1)(sass@1.79.4)(terser@5.36.0))':
     dependencies:
       '@ampproject/remapping': 2.2.1
       '@bcoe/v8-coverage': 0.2.3
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       istanbul-lib-coverage: 3.2.2
       istanbul-lib-report: 3.0.1
       istanbul-lib-source-maps: 5.0.4
@@ -16205,7 +15449,7 @@ snapshots:
       std-env: 3.7.0
       strip-literal: 2.1.0
       test-exclude: 6.0.0
-      vitest: 1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.4)(terser@5.33.0)
+      vitest: 1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1)(sass@1.79.4)(terser@5.36.0)
     transitivePeerDependencies:
       - supports-color
 
@@ -16274,43 +15518,27 @@ snapshots:
     dependencies:
       '@volar/source-map': 2.2.0
 
-  '@volar/language-core@2.4.5':
+  '@volar/language-core@2.4.10':
     dependencies:
-      '@volar/source-map': 2.4.5
+      '@volar/source-map': 2.4.10
 
   '@volar/source-map@2.2.0':
     dependencies:
       muggle-string: 0.4.1
 
-  '@volar/source-map@2.4.5': {}
+  '@volar/source-map@2.4.10': {}
 
   '@volar/typescript@2.2.0':
     dependencies:
       '@volar/language-core': 2.2.0
       path-browserify: 1.0.1
 
-  '@volar/typescript@2.4.5':
+  '@volar/typescript@2.4.10':
     dependencies:
-      '@volar/language-core': 2.4.5
+      '@volar/language-core': 2.4.10
       path-browserify: 1.0.1
       vscode-uri: 3.0.8
 
-  '@vue/compiler-core@3.4.37':
-    dependencies:
-      '@babel/parser': 7.25.6
-      '@vue/shared': 3.4.37
-      entities: 5.0.0
-      estree-walker: 2.0.2
-      source-map-js: 1.2.1
-
-  '@vue/compiler-core@3.5.10':
-    dependencies:
-      '@babel/parser': 7.25.6
-      '@vue/shared': 3.5.10
-      entities: 4.5.0
-      estree-walker: 2.0.2
-      source-map-js: 1.2.1
-
   '@vue/compiler-core@3.5.11':
     dependencies:
       '@babel/parser': 7.25.6
@@ -16319,142 +15547,104 @@ snapshots:
       estree-walker: 2.0.2
       source-map-js: 1.2.1
 
-  '@vue/compiler-dom@3.4.37':
+  '@vue/compiler-core@3.5.12':
     dependencies:
-      '@vue/compiler-core': 3.4.37
-      '@vue/shared': 3.4.37
-
-  '@vue/compiler-dom@3.5.10':
-    dependencies:
-      '@vue/compiler-core': 3.5.10
-      '@vue/shared': 3.5.10
+      '@babel/parser': 7.25.6
+      '@vue/shared': 3.5.12
+      entities: 4.5.0
+      estree-walker: 2.0.2
+      source-map-js: 1.2.1
 
   '@vue/compiler-dom@3.5.11':
     dependencies:
       '@vue/compiler-core': 3.5.11
       '@vue/shared': 3.5.11
 
-  '@vue/compiler-sfc@3.4.37':
+  '@vue/compiler-dom@3.5.12':
     dependencies:
-      '@babel/parser': 7.24.7
-      '@vue/compiler-core': 3.4.37
-      '@vue/compiler-dom': 3.4.37
-      '@vue/compiler-ssr': 3.4.37
-      '@vue/shared': 3.4.37
-      estree-walker: 2.0.2
-      magic-string: 0.30.11
-      postcss: 8.4.47
-      source-map-js: 1.2.0
+      '@vue/compiler-core': 3.5.12
+      '@vue/shared': 3.5.12
 
-  '@vue/compiler-sfc@3.5.11':
+  '@vue/compiler-sfc@3.5.12':
     dependencies:
       '@babel/parser': 7.25.6
-      '@vue/compiler-core': 3.5.11
-      '@vue/compiler-dom': 3.5.11
-      '@vue/compiler-ssr': 3.5.11
-      '@vue/shared': 3.5.11
+      '@vue/compiler-core': 3.5.12
+      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-ssr': 3.5.12
+      '@vue/shared': 3.5.12
       estree-walker: 2.0.2
       magic-string: 0.30.11
-      postcss: 8.4.47
+      postcss: 8.4.49
       source-map-js: 1.2.1
 
-  '@vue/compiler-ssr@3.4.37':
+  '@vue/compiler-ssr@3.5.12':
     dependencies:
-      '@vue/compiler-dom': 3.4.37
-      '@vue/shared': 3.4.37
-
-  '@vue/compiler-ssr@3.5.11':
-    dependencies:
-      '@vue/compiler-dom': 3.5.11
-      '@vue/shared': 3.5.11
+      '@vue/compiler-dom': 3.5.12
+      '@vue/shared': 3.5.12
 
   '@vue/compiler-vue2@2.7.16':
     dependencies:
       de-indent: 1.0.2
       he: 1.2.0
 
-  '@vue/language-core@2.0.16(typescript@5.6.2)':
+  '@vue/language-core@2.0.16(typescript@5.6.3)':
     dependencies:
       '@volar/language-core': 2.2.0
-      '@vue/compiler-dom': 3.5.11
-      '@vue/shared': 3.5.11
+      '@vue/compiler-dom': 3.5.12
+      '@vue/shared': 3.5.12
       computeds: 0.0.1
       minimatch: 9.0.4
       path-browserify: 1.0.1
       vue-template-compiler: 2.7.14
     optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
 
-  '@vue/language-core@2.1.6(typescript@5.6.2)':
+  '@vue/language-core@2.1.10(typescript@5.6.3)':
     dependencies:
-      '@volar/language-core': 2.4.5
-      '@vue/compiler-dom': 3.4.37
+      '@volar/language-core': 2.4.10
+      '@vue/compiler-dom': 3.5.11
       '@vue/compiler-vue2': 2.7.16
       '@vue/shared': 3.5.11
-      computeds: 0.0.1
+      alien-signals: 0.2.1
       minimatch: 9.0.4
       muggle-string: 0.4.1
       path-browserify: 1.0.1
     optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
 
-  '@vue/reactivity@3.4.37':
+  '@vue/reactivity@3.5.12':
     dependencies:
-      '@vue/shared': 3.4.37
+      '@vue/shared': 3.5.12
 
-  '@vue/reactivity@3.5.11':
+  '@vue/runtime-core@3.5.12':
     dependencies:
-      '@vue/shared': 3.5.11
+      '@vue/reactivity': 3.5.12
+      '@vue/shared': 3.5.12
 
-  '@vue/runtime-core@3.4.37':
+  '@vue/runtime-dom@3.5.12':
     dependencies:
-      '@vue/reactivity': 3.4.37
-      '@vue/shared': 3.4.37
-
-  '@vue/runtime-core@3.5.11':
-    dependencies:
-      '@vue/reactivity': 3.5.11
-      '@vue/shared': 3.5.11
-
-  '@vue/runtime-dom@3.4.37':
-    dependencies:
-      '@vue/reactivity': 3.4.37
-      '@vue/runtime-core': 3.4.37
-      '@vue/shared': 3.4.37
+      '@vue/reactivity': 3.5.12
+      '@vue/runtime-core': 3.5.12
+      '@vue/shared': 3.5.12
       csstype: 3.1.3
 
-  '@vue/runtime-dom@3.5.11':
+  '@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3))':
     dependencies:
-      '@vue/reactivity': 3.5.11
-      '@vue/runtime-core': 3.5.11
-      '@vue/shared': 3.5.11
-      csstype: 3.1.3
-
-  '@vue/server-renderer@3.4.37(vue@3.4.37(typescript@5.5.4))':
-    dependencies:
-      '@vue/compiler-ssr': 3.4.37
-      '@vue/shared': 3.4.37
-      vue: 3.4.37(typescript@5.5.4)
-
-  '@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2))':
-    dependencies:
-      '@vue/compiler-ssr': 3.5.11
-      '@vue/shared': 3.5.11
-      vue: 3.5.11(typescript@5.6.2)
-
-  '@vue/shared@3.4.37': {}
-
-  '@vue/shared@3.5.10': {}
+      '@vue/compiler-ssr': 3.5.12
+      '@vue/shared': 3.5.12
+      vue: 3.5.12(typescript@5.6.3)
 
   '@vue/shared@3.5.11': {}
 
-  '@vue/test-utils@2.4.1(@vue/server-renderer@3.5.11(vue@3.5.11(typescript@5.6.2)))(vue@3.5.11(typescript@5.6.2))':
+  '@vue/shared@3.5.12': {}
+
+  '@vue/test-utils@2.4.1(@vue/server-renderer@3.5.12(vue@3.5.12(typescript@5.6.3)))(vue@3.5.12(typescript@5.6.3))':
     dependencies:
       js-beautify: 1.14.9
-      vue: 3.5.11(typescript@5.6.2)
+      vue: 3.5.12(typescript@5.6.3)
       vue-component-type-helpers: 1.8.4
     optionalDependencies:
-      '@vue/server-renderer': 3.5.11(vue@3.5.11(typescript@5.6.2))
+      '@vue/server-renderer': 3.5.12(vue@3.5.12(typescript@5.6.3))
 
   '@webgpu/types@0.1.30': {}
 
@@ -16473,30 +15663,19 @@ snapshots:
       mime-types: 2.1.35
       negotiator: 0.6.3
 
-  acorn-import-assertions@1.9.0(acorn@8.12.1):
+  acorn-import-attributes@1.9.5(acorn@8.14.0):
     dependencies:
-      acorn: 8.12.1
-    optional: true
+      acorn: 8.14.0
 
-  acorn-import-attributes@1.9.5(acorn@8.12.1):
+  acorn-jsx@5.3.2(acorn@8.14.0):
     dependencies:
-      acorn: 8.12.1
-
-  acorn-jsx@5.3.2(acorn@7.4.1):
-    dependencies:
-      acorn: 7.4.1
-
-  acorn-jsx@5.3.2(acorn@8.12.1):
-    dependencies:
-      acorn: 8.12.1
-
-  acorn-walk@7.2.0: {}
+      acorn: 8.14.0
 
   acorn-walk@8.3.2: {}
 
   acorn@7.4.1: {}
 
-  acorn@8.12.1: {}
+  acorn@8.14.0: {}
 
   adm-zip@0.5.10:
     optional: true
@@ -16515,7 +15694,7 @@ snapshots:
 
   agent-base@7.1.0:
     dependencies:
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
     transitivePeerDependencies:
       - supports-color
 
@@ -16578,6 +15757,8 @@ snapshots:
       json-schema-traverse: 1.0.0
       require-from-string: 2.0.2
 
+  alien-signals@0.2.1: {}
+
   ansi-colors@4.1.3: {}
 
   ansi-escapes@4.3.2:
@@ -16805,7 +15986,7 @@ snapshots:
   axios@1.7.7(debug@4.3.7):
     dependencies:
       follow-redirects: 1.15.9(debug@4.3.7)
-      form-data: 4.0.0
+      form-data: 4.0.1
       proxy-from-env: 1.1.0
     transitivePeerDependencies:
       - debug
@@ -16838,7 +16019,7 @@ snapshots:
   babel-plugin-jest-hoist@29.6.3:
     dependencies:
       '@babel/template': 7.24.0
-      '@babel/types': 7.24.7
+      '@babel/types': 7.25.6
       '@types/babel__core': 7.20.0
       '@types/babel__traverse': 7.20.0
 
@@ -16892,7 +16073,7 @@ snapshots:
   bin-version-check@5.0.0:
     dependencies:
       bin-version: 6.0.0
-      semver: 7.6.0
+      semver: 7.6.3
       semver-truncate: 2.0.0
 
   bin-version@6.0.0:
@@ -17008,11 +16189,11 @@ snapshots:
       node-gyp-build: 4.6.0
     optional: true
 
-  bullmq@5.15.0:
+  bullmq@5.26.1:
     dependencies:
       cron-parser: 4.8.1
       ioredis: 5.4.1
-      msgpackr: 1.10.1
+      msgpackr: 1.11.2
       node-abort-controller: 3.1.1
       semver: 7.6.3
       tslib: 2.7.0
@@ -17183,26 +16364,26 @@ snapshots:
     dependencies:
       is-regex: 1.1.4
 
-  chart.js@4.4.4:
+  chart.js@4.4.6:
     dependencies:
       '@kurkle/color': 0.3.2
 
-  chartjs-adapter-date-fns@3.0.0(chart.js@4.4.4)(date-fns@2.30.0):
+  chartjs-adapter-date-fns@3.0.0(chart.js@4.4.6)(date-fns@2.30.0):
     dependencies:
-      chart.js: 4.4.4
+      chart.js: 4.4.6
       date-fns: 2.30.0
 
-  chartjs-chart-matrix@2.0.1(chart.js@4.4.4):
+  chartjs-chart-matrix@2.0.1(chart.js@4.4.6):
     dependencies:
-      chart.js: 4.4.4
+      chart.js: 4.4.6
 
-  chartjs-plugin-gradient@0.6.1(chart.js@4.4.4):
+  chartjs-plugin-gradient@0.6.1(chart.js@4.4.6):
     dependencies:
-      chart.js: 4.4.4
+      chart.js: 4.4.6
 
-  chartjs-plugin-zoom@2.0.1(chart.js@4.4.4):
+  chartjs-plugin-zoom@2.0.1(chart.js@4.4.6):
     dependencies:
-      chart.js: 4.4.4
+      chart.js: 4.4.6
       hammerjs: 2.0.8
 
   check-error@1.0.3:
@@ -17230,7 +16411,7 @@ snapshots:
       domutils: 3.1.0
       encoding-sniffer: 0.2.0
       htmlparser2: 9.1.0
-      parse5: 7.1.2
+      parse5: 7.2.1
       parse5-htmlparser2-tree-adapter: 7.0.0
       parse5-parser-stream: 7.1.2
       undici: 6.19.8
@@ -17243,7 +16424,7 @@ snapshots:
       domhandler: 5.0.3
       domutils: 3.0.1
       htmlparser2: 8.0.1
-      parse5: 7.1.2
+      parse5: 7.2.1
       parse5-htmlparser2-tree-adapter: 7.0.0
 
   chokidar@3.5.3:
@@ -17263,10 +16444,12 @@ snapshots:
 
   chownr@2.0.0: {}
 
-  chromatic@11.11.0: {}
+  chromatic@11.18.1: {}
 
   ci-info@3.7.1: {}
 
+  ci-info@4.1.0: {}
+
   cjs-module-lexer@1.2.2: {}
 
   clean-stack@2.2.0: {}
@@ -17288,8 +16471,6 @@ snapshots:
       parse5-htmlparser2-tree-adapter: 6.0.1
       yargs: 16.2.0
 
-  cli-spinners@2.9.2: {}
-
   cli-table3@0.6.3:
     dependencies:
       string-width: 4.2.3
@@ -17384,8 +16565,6 @@ snapshots:
 
   common-tags@1.8.2: {}
 
-  commondir@1.0.1: {}
-
   compare-versions@6.1.1: {}
 
   compress-commons@6.0.2:
@@ -17432,12 +16611,14 @@ snapshots:
 
   cookie-signature@1.0.6: {}
 
-  cookie-signature@1.2.1: {}
-
-  cookie@0.5.0: {}
-
   cookie@0.6.0: {}
 
+  cookie@0.7.1: {}
+
+  cookie@0.7.2: {}
+
+  cookie@1.0.1: {}
+
   core-js@3.29.1: {}
 
   core-util-is@1.0.2: {}
@@ -17456,13 +16637,13 @@ snapshots:
       crc-32: 1.2.2
       readable-stream: 4.3.0
 
-  create-jest@29.7.0(@types/node@20.14.12):
+  create-jest@29.7.0(@types/node@22.9.0):
     dependencies:
       '@jest/types': 29.6.3
       chalk: 4.1.2
       exit: 0.1.2
       graceful-fs: 4.2.11
-      jest-config: 29.7.0(@types/node@20.14.12)
+      jest-config: 29.7.0(@types/node@22.9.0)
       jest-util: 29.7.0
       prompts: 2.4.2
     transitivePeerDependencies:
@@ -17508,9 +16689,9 @@ snapshots:
       shebang-command: 2.0.0
       which: 2.0.2
 
-  css-declaration-sorter@7.2.0(postcss@8.4.47):
+  css-declaration-sorter@7.2.0(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
   css-select@5.1.0:
     dependencies:
@@ -17536,49 +16717,49 @@ snapshots:
 
   cssesc@3.0.0: {}
 
-  cssnano-preset-default@6.1.2(postcss@8.4.47):
+  cssnano-preset-default@6.1.2(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
-      css-declaration-sorter: 7.2.0(postcss@8.4.47)
-      cssnano-utils: 4.0.2(postcss@8.4.47)
-      postcss: 8.4.47
-      postcss-calc: 9.0.1(postcss@8.4.47)
-      postcss-colormin: 6.1.0(postcss@8.4.47)
-      postcss-convert-values: 6.1.0(postcss@8.4.47)
-      postcss-discard-comments: 6.0.2(postcss@8.4.47)
-      postcss-discard-duplicates: 6.0.3(postcss@8.4.47)
-      postcss-discard-empty: 6.0.3(postcss@8.4.47)
-      postcss-discard-overridden: 6.0.2(postcss@8.4.47)
-      postcss-merge-longhand: 6.0.5(postcss@8.4.47)
-      postcss-merge-rules: 6.1.1(postcss@8.4.47)
-      postcss-minify-font-values: 6.1.0(postcss@8.4.47)
-      postcss-minify-gradients: 6.0.3(postcss@8.4.47)
-      postcss-minify-params: 6.1.0(postcss@8.4.47)
-      postcss-minify-selectors: 6.0.4(postcss@8.4.47)
-      postcss-normalize-charset: 6.0.2(postcss@8.4.47)
-      postcss-normalize-display-values: 6.0.2(postcss@8.4.47)
-      postcss-normalize-positions: 6.0.2(postcss@8.4.47)
-      postcss-normalize-repeat-style: 6.0.2(postcss@8.4.47)
-      postcss-normalize-string: 6.0.2(postcss@8.4.47)
-      postcss-normalize-timing-functions: 6.0.2(postcss@8.4.47)
-      postcss-normalize-unicode: 6.1.0(postcss@8.4.47)
-      postcss-normalize-url: 6.0.2(postcss@8.4.47)
-      postcss-normalize-whitespace: 6.0.2(postcss@8.4.47)
-      postcss-ordered-values: 6.0.2(postcss@8.4.47)
-      postcss-reduce-initial: 6.1.0(postcss@8.4.47)
-      postcss-reduce-transforms: 6.0.2(postcss@8.4.47)
-      postcss-svgo: 6.0.3(postcss@8.4.47)
-      postcss-unique-selectors: 6.0.4(postcss@8.4.47)
+      css-declaration-sorter: 7.2.0(postcss@8.4.49)
+      cssnano-utils: 4.0.2(postcss@8.4.49)
+      postcss: 8.4.49
+      postcss-calc: 9.0.1(postcss@8.4.49)
+      postcss-colormin: 6.1.0(postcss@8.4.49)
+      postcss-convert-values: 6.1.0(postcss@8.4.49)
+      postcss-discard-comments: 6.0.2(postcss@8.4.49)
+      postcss-discard-duplicates: 6.0.3(postcss@8.4.49)
+      postcss-discard-empty: 6.0.3(postcss@8.4.49)
+      postcss-discard-overridden: 6.0.2(postcss@8.4.49)
+      postcss-merge-longhand: 6.0.5(postcss@8.4.49)
+      postcss-merge-rules: 6.1.1(postcss@8.4.49)
+      postcss-minify-font-values: 6.1.0(postcss@8.4.49)
+      postcss-minify-gradients: 6.0.3(postcss@8.4.49)
+      postcss-minify-params: 6.1.0(postcss@8.4.49)
+      postcss-minify-selectors: 6.0.4(postcss@8.4.49)
+      postcss-normalize-charset: 6.0.2(postcss@8.4.49)
+      postcss-normalize-display-values: 6.0.2(postcss@8.4.49)
+      postcss-normalize-positions: 6.0.2(postcss@8.4.49)
+      postcss-normalize-repeat-style: 6.0.2(postcss@8.4.49)
+      postcss-normalize-string: 6.0.2(postcss@8.4.49)
+      postcss-normalize-timing-functions: 6.0.2(postcss@8.4.49)
+      postcss-normalize-unicode: 6.1.0(postcss@8.4.49)
+      postcss-normalize-url: 6.0.2(postcss@8.4.49)
+      postcss-normalize-whitespace: 6.0.2(postcss@8.4.49)
+      postcss-ordered-values: 6.0.2(postcss@8.4.49)
+      postcss-reduce-initial: 6.1.0(postcss@8.4.49)
+      postcss-reduce-transforms: 6.0.2(postcss@8.4.49)
+      postcss-svgo: 6.0.3(postcss@8.4.49)
+      postcss-unique-selectors: 6.0.4(postcss@8.4.49)
 
-  cssnano-utils@4.0.2(postcss@8.4.47):
+  cssnano-utils@4.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  cssnano@6.1.2(postcss@8.4.47):
+  cssnano@6.1.2(postcss@8.4.49):
     dependencies:
-      cssnano-preset-default: 6.1.2(postcss@8.4.47)
+      cssnano-preset-default: 6.1.2(postcss@8.4.49)
       lilconfig: 3.1.1
-      postcss: 8.4.47
+      postcss: 8.4.49
 
   csso@5.0.5:
     dependencies:
@@ -17594,54 +16775,9 @@ snapshots:
     dependencies:
       uniq: 1.0.1
 
-  cypress@13.14.2:
+  cypress@13.15.2:
     dependencies:
-      '@cypress/request': 3.0.5
-      '@cypress/xvfb': 1.2.4(supports-color@8.1.1)
-      '@types/sinonjs__fake-timers': 8.1.1
-      '@types/sizzle': 2.3.3
-      arch: 2.2.0
-      blob-util: 2.0.2
-      bluebird: 3.7.2
-      buffer: 5.7.1
-      cachedir: 2.3.0
-      chalk: 4.1.2
-      check-more-types: 2.24.0
-      cli-cursor: 3.1.0
-      cli-table3: 0.6.3
-      commander: 6.2.1
-      common-tags: 1.8.2
-      dayjs: 1.11.10
-      debug: 4.3.5(supports-color@8.1.1)
-      enquirer: 2.3.6
-      eventemitter2: 6.4.7
-      execa: 4.1.0
-      executable: 4.1.1
-      extract-zip: 2.0.1(supports-color@8.1.1)
-      figures: 3.2.0
-      fs-extra: 9.1.0
-      getos: 3.2.1
-      is-ci: 3.0.1
-      is-installed-globally: 0.4.0
-      lazy-ass: 1.6.0
-      listr2: 3.14.0(enquirer@2.3.6)
-      lodash: 4.17.21
-      log-symbols: 4.1.0
-      minimist: 1.2.8
-      ospath: 1.2.2
-      pretty-bytes: 5.6.0
-      process: 0.11.10
-      proxy-from-env: 1.0.0
-      request-progress: 3.0.0
-      semver: 7.6.0
-      supports-color: 8.1.1
-      tmp: 0.2.3
-      untildify: 4.0.0
-      yauzl: 2.10.0
-
-  cypress@13.15.0:
-    dependencies:
-      '@cypress/request': 3.0.5
+      '@cypress/request': 3.0.6
       '@cypress/xvfb': 1.2.4(supports-color@8.1.1)
       '@types/sinonjs__fake-timers': 8.1.1
       '@types/sizzle': 2.3.3
@@ -17652,6 +16788,7 @@ snapshots:
       cachedir: 2.3.0
       chalk: 4.1.2
       check-more-types: 2.24.0
+      ci-info: 4.1.0
       cli-cursor: 3.1.0
       cli-table3: 0.6.3
       commander: 6.2.1
@@ -17666,7 +16803,6 @@ snapshots:
       figures: 3.2.0
       fs-extra: 9.1.0
       getos: 3.2.1
-      is-ci: 3.0.1
       is-installed-globally: 0.4.0
       lazy-ass: 1.6.0
       listr2: 3.14.0(enquirer@2.3.6)
@@ -17681,6 +16817,7 @@ snapshots:
       semver: 7.6.3
       supports-color: 8.1.1
       tmp: 0.2.3
+      tree-kill: 1.2.2
       untildify: 4.0.0
       yauzl: 2.10.0
 
@@ -17733,24 +16870,20 @@ snapshots:
     optionalDependencies:
       supports-color: 8.1.1
 
-  debug@4.3.4(supports-color@5.5.0):
+  debug@4.3.4:
     dependencies:
       ms: 2.1.2
+
+  debug@4.3.5:
+    dependencies:
+      ms: 2.1.2
+
+  debug@4.3.7(supports-color@5.5.0):
+    dependencies:
+      ms: 2.1.3
     optionalDependencies:
       supports-color: 5.5.0
 
-  debug@4.3.5(supports-color@5.5.0):
-    dependencies:
-      ms: 2.1.2
-    optionalDependencies:
-      supports-color: 5.5.0
-
-  debug@4.3.5(supports-color@8.1.1):
-    dependencies:
-      ms: 2.1.2
-    optionalDependencies:
-      supports-color: 8.1.1
-
   debug@4.3.7(supports-color@8.1.1):
     dependencies:
       ms: 2.1.3
@@ -18006,8 +17139,6 @@ snapshots:
 
   entities@4.5.0: {}
 
-  entities@5.0.0: {}
-
   env-paths@2.2.1: {}
 
   err-code@2.0.3: {}
@@ -18125,8 +17256,6 @@ snapshots:
       isarray: 2.0.5
       stop-iteration-iterator: 1.0.0
 
-  es-module-lexer@1.5.4: {}
-
   es-object-atoms@1.0.0:
     dependencies:
       es-errors: 1.3.0
@@ -18157,6 +17286,8 @@ snapshots:
       is-date-object: 1.0.5
       is-symbol: 1.0.4
 
+  es-toolkit@1.27.0: {}
+
   es6-promise@4.2.8:
     optional: true
 
@@ -18165,10 +17296,10 @@ snapshots:
       es6-promise: 4.2.8
     optional: true
 
-  esbuild-register@3.5.0(esbuild@0.23.1):
+  esbuild-register@3.5.0(esbuild@0.24.0):
     dependencies:
       debug: 4.3.7(supports-color@8.1.1)
-      esbuild: 0.23.1
+      esbuild: 0.24.0
     transitivePeerDependencies:
       - supports-color
 
@@ -18197,32 +17328,6 @@ snapshots:
       '@esbuild/win32-ia32': 0.18.20
       '@esbuild/win32-x64': 0.18.20
 
-  esbuild@0.19.11:
-    optionalDependencies:
-      '@esbuild/aix-ppc64': 0.19.11
-      '@esbuild/android-arm': 0.19.11
-      '@esbuild/android-arm64': 0.19.11
-      '@esbuild/android-x64': 0.19.11
-      '@esbuild/darwin-arm64': 0.19.11
-      '@esbuild/darwin-x64': 0.19.11
-      '@esbuild/freebsd-arm64': 0.19.11
-      '@esbuild/freebsd-x64': 0.19.11
-      '@esbuild/linux-arm': 0.19.11
-      '@esbuild/linux-arm64': 0.19.11
-      '@esbuild/linux-ia32': 0.19.11
-      '@esbuild/linux-loong64': 0.19.11
-      '@esbuild/linux-mips64el': 0.19.11
-      '@esbuild/linux-ppc64': 0.19.11
-      '@esbuild/linux-riscv64': 0.19.11
-      '@esbuild/linux-s390x': 0.19.11
-      '@esbuild/linux-x64': 0.19.11
-      '@esbuild/netbsd-x64': 0.19.11
-      '@esbuild/openbsd-x64': 0.19.11
-      '@esbuild/sunos-x64': 0.19.11
-      '@esbuild/win32-arm64': 0.19.11
-      '@esbuild/win32-ia32': 0.19.11
-      '@esbuild/win32-x64': 0.19.11
-
   esbuild@0.21.5:
     optionalDependencies:
       '@esbuild/aix-ppc64': 0.21.5
@@ -18249,59 +17354,32 @@ snapshots:
       '@esbuild/win32-ia32': 0.21.5
       '@esbuild/win32-x64': 0.21.5
 
-  esbuild@0.23.0:
+  esbuild@0.24.0:
     optionalDependencies:
-      '@esbuild/aix-ppc64': 0.23.0
-      '@esbuild/android-arm': 0.23.0
-      '@esbuild/android-arm64': 0.23.0
-      '@esbuild/android-x64': 0.23.0
-      '@esbuild/darwin-arm64': 0.23.0
-      '@esbuild/darwin-x64': 0.23.0
-      '@esbuild/freebsd-arm64': 0.23.0
-      '@esbuild/freebsd-x64': 0.23.0
-      '@esbuild/linux-arm': 0.23.0
-      '@esbuild/linux-arm64': 0.23.0
-      '@esbuild/linux-ia32': 0.23.0
-      '@esbuild/linux-loong64': 0.23.0
-      '@esbuild/linux-mips64el': 0.23.0
-      '@esbuild/linux-ppc64': 0.23.0
-      '@esbuild/linux-riscv64': 0.23.0
-      '@esbuild/linux-s390x': 0.23.0
-      '@esbuild/linux-x64': 0.23.0
-      '@esbuild/netbsd-x64': 0.23.0
-      '@esbuild/openbsd-arm64': 0.23.0
-      '@esbuild/openbsd-x64': 0.23.0
-      '@esbuild/sunos-x64': 0.23.0
-      '@esbuild/win32-arm64': 0.23.0
-      '@esbuild/win32-ia32': 0.23.0
-      '@esbuild/win32-x64': 0.23.0
-
-  esbuild@0.23.1:
-    optionalDependencies:
-      '@esbuild/aix-ppc64': 0.23.1
-      '@esbuild/android-arm': 0.23.1
-      '@esbuild/android-arm64': 0.23.1
-      '@esbuild/android-x64': 0.23.1
-      '@esbuild/darwin-arm64': 0.23.1
-      '@esbuild/darwin-x64': 0.23.1
-      '@esbuild/freebsd-arm64': 0.23.1
-      '@esbuild/freebsd-x64': 0.23.1
-      '@esbuild/linux-arm': 0.23.1
-      '@esbuild/linux-arm64': 0.23.1
-      '@esbuild/linux-ia32': 0.23.1
-      '@esbuild/linux-loong64': 0.23.1
-      '@esbuild/linux-mips64el': 0.23.1
-      '@esbuild/linux-ppc64': 0.23.1
-      '@esbuild/linux-riscv64': 0.23.1
-      '@esbuild/linux-s390x': 0.23.1
-      '@esbuild/linux-x64': 0.23.1
-      '@esbuild/netbsd-x64': 0.23.1
-      '@esbuild/openbsd-arm64': 0.23.1
-      '@esbuild/openbsd-x64': 0.23.1
-      '@esbuild/sunos-x64': 0.23.1
-      '@esbuild/win32-arm64': 0.23.1
-      '@esbuild/win32-ia32': 0.23.1
-      '@esbuild/win32-x64': 0.23.1
+      '@esbuild/aix-ppc64': 0.24.0
+      '@esbuild/android-arm': 0.24.0
+      '@esbuild/android-arm64': 0.24.0
+      '@esbuild/android-x64': 0.24.0
+      '@esbuild/darwin-arm64': 0.24.0
+      '@esbuild/darwin-x64': 0.24.0
+      '@esbuild/freebsd-arm64': 0.24.0
+      '@esbuild/freebsd-x64': 0.24.0
+      '@esbuild/linux-arm': 0.24.0
+      '@esbuild/linux-arm64': 0.24.0
+      '@esbuild/linux-ia32': 0.24.0
+      '@esbuild/linux-loong64': 0.24.0
+      '@esbuild/linux-mips64el': 0.24.0
+      '@esbuild/linux-ppc64': 0.24.0
+      '@esbuild/linux-riscv64': 0.24.0
+      '@esbuild/linux-s390x': 0.24.0
+      '@esbuild/linux-x64': 0.24.0
+      '@esbuild/netbsd-x64': 0.24.0
+      '@esbuild/openbsd-arm64': 0.24.0
+      '@esbuild/openbsd-x64': 0.24.0
+      '@esbuild/sunos-x64': 0.24.0
+      '@esbuild/win32-arm64': 0.24.0
+      '@esbuild/win32-ia32': 0.24.0
+      '@esbuild/win32-x64': 0.24.0
 
   escalade@3.1.1: {}
 
@@ -18319,14 +17397,6 @@ snapshots:
 
   escape-string-regexp@5.0.0: {}
 
-  escodegen@2.1.0:
-    dependencies:
-      esprima: 4.0.1
-      estraverse: 5.3.0
-      esutils: 2.0.3
-    optionalDependencies:
-      source-map: 0.6.1
-
   eslint-formatter-pretty@4.1.0:
     dependencies:
       '@types/eslint': 7.29.0
@@ -18346,37 +17416,27 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  eslint-module-utils@2.11.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint@9.11.0):
+  eslint-module-utils@2.11.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.14.0):
     dependencies:
       debug: 3.2.7(supports-color@8.1.1)
     optionalDependencies:
-      '@typescript-eslint/parser': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
-      eslint: 9.11.0
+      '@typescript-eslint/parser': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
+      eslint: 9.14.0
       eslint-import-resolver-node: 0.3.9
     transitivePeerDependencies:
       - supports-color
 
-  eslint-module-utils@2.12.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint@9.11.0):
+  eslint-module-utils@2.12.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.14.0):
     dependencies:
       debug: 3.2.7(supports-color@8.1.1)
     optionalDependencies:
-      '@typescript-eslint/parser': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
-      eslint: 9.11.0
+      '@typescript-eslint/parser': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
+      eslint: 9.14.0
       eslint-import-resolver-node: 0.3.9
     transitivePeerDependencies:
       - supports-color
 
-  eslint-module-utils@2.12.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint@9.8.0):
-    dependencies:
-      debug: 3.2.7(supports-color@8.1.1)
-    optionalDependencies:
-      '@typescript-eslint/parser': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-      eslint: 9.8.0
-      eslint-import-resolver-node: 0.3.9
-    transitivePeerDependencies:
-      - supports-color
-
-  eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0):
+  eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0):
     dependencies:
       '@rtsao/scc': 1.1.0
       array-includes: 3.1.8
@@ -18385,9 +17445,9 @@ snapshots:
       array.prototype.flatmap: 1.3.2
       debug: 3.2.7(supports-color@8.1.1)
       doctrine: 2.1.0
-      eslint: 9.11.0
+      eslint: 9.14.0
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint@9.11.0)
+      eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.14.0)
       hasown: 2.0.2
       is-core-module: 2.15.1
       is-glob: 4.0.3
@@ -18398,13 +17458,13 @@ snapshots:
       semver: 6.3.1
       tsconfig-paths: 3.15.0
     optionalDependencies:
-      '@typescript-eslint/parser': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+      '@typescript-eslint/parser': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint@9.11.0):
+  eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0):
     dependencies:
       '@rtsao/scc': 1.1.0
       array-includes: 3.1.8
@@ -18413,9 +17473,9 @@ snapshots:
       array.prototype.flatmap: 1.3.2
       debug: 3.2.7(supports-color@8.1.1)
       doctrine: 2.1.0
-      eslint: 9.11.0
+      eslint: 9.14.0
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.17.0(eslint@9.11.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint@9.11.0)
+      eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@9.14.0)
       hasown: 2.0.2
       is-core-module: 2.15.1
       is-glob: 4.0.3
@@ -18427,65 +17487,22 @@ snapshots:
       string.prototype.trimend: 1.0.8
       tsconfig-paths: 3.15.0
     optionalDependencies:
-      '@typescript-eslint/parser': 7.17.0(eslint@9.11.0)(typescript@5.6.2)
+      '@typescript-eslint/parser': 7.17.0(eslint@9.14.0)(typescript@5.6.3)
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint@9.8.0):
+  eslint-plugin-vue@9.31.0(eslint@9.14.0):
     dependencies:
-      '@rtsao/scc': 1.1.0
-      array-includes: 3.1.8
-      array.prototype.findlastindex: 1.2.5
-      array.prototype.flat: 1.3.2
-      array.prototype.flatmap: 1.3.2
-      debug: 3.2.7(supports-color@8.1.1)
-      doctrine: 2.1.0
-      eslint: 9.8.0
-      eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.17.0(eslint@9.8.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint@9.8.0)
-      hasown: 2.0.2
-      is-core-module: 2.15.1
-      is-glob: 4.0.3
-      minimatch: 3.1.2
-      object.fromentries: 2.0.8
-      object.groupby: 1.0.3
-      object.values: 1.2.0
-      semver: 6.3.1
-      string.prototype.trimend: 1.0.8
-      tsconfig-paths: 3.15.0
-    optionalDependencies:
-      '@typescript-eslint/parser': 7.17.0(eslint@9.8.0)(typescript@5.6.2)
-    transitivePeerDependencies:
-      - eslint-import-resolver-typescript
-      - eslint-import-resolver-webpack
-      - supports-color
-
-  eslint-plugin-vue@9.27.0(eslint@9.11.0):
-    dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0)
-      eslint: 9.11.0
-      globals: 13.24.0
-      natural-compare: 1.4.0
-      nth-check: 2.1.1
-      postcss-selector-parser: 6.0.16
-      semver: 7.6.0
-      vue-eslint-parser: 9.4.3(eslint@9.11.0)
-      xml-name-validator: 4.0.0
-    transitivePeerDependencies:
-      - supports-color
-
-  eslint-plugin-vue@9.28.0(eslint@9.11.0):
-    dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0)
-      eslint: 9.11.0
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0)
+      eslint: 9.14.0
       globals: 13.24.0
       natural-compare: 1.4.0
       nth-check: 2.1.1
       postcss-selector-parser: 6.0.16
       semver: 7.6.3
-      vue-eslint-parser: 9.4.3(eslint@9.11.0)
+      vue-eslint-parser: 9.4.3(eslint@9.14.0)
       xml-name-validator: 4.0.0
     transitivePeerDependencies:
       - supports-color
@@ -18497,34 +17514,37 @@ snapshots:
       esrecurse: 4.3.0
       estraverse: 5.3.0
 
-  eslint-scope@8.0.2:
+  eslint-scope@8.2.0:
     dependencies:
       esrecurse: 4.3.0
       estraverse: 5.3.0
 
   eslint-visitor-keys@3.4.3: {}
 
-  eslint-visitor-keys@4.0.0: {}
+  eslint-visitor-keys@4.2.0: {}
 
-  eslint@9.11.0:
+  eslint@9.14.0:
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.11.0)
-      '@eslint-community/regexpp': 4.11.0
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.14.0)
+      '@eslint-community/regexpp': 4.12.1
       '@eslint/config-array': 0.18.0
+      '@eslint/core': 0.7.0
       '@eslint/eslintrc': 3.1.0
-      '@eslint/js': 9.11.0
+      '@eslint/js': 9.14.0
       '@eslint/plugin-kit': 0.2.0
+      '@humanfs/node': 0.16.6
       '@humanwhocodes/module-importer': 1.0.1
-      '@humanwhocodes/retry': 0.3.0
-      '@nodelib/fs.walk': 1.2.8
+      '@humanwhocodes/retry': 0.4.1
+      '@types/estree': 1.0.6
+      '@types/json-schema': 7.0.15
       ajv: 6.12.6
       chalk: 4.1.2
       cross-spawn: 7.0.3
       debug: 4.3.7(supports-color@8.1.1)
       escape-string-regexp: 4.0.0
-      eslint-scope: 8.0.2
-      eslint-visitor-keys: 4.0.0
-      espree: 10.1.0
+      eslint-scope: 8.2.0
+      eslint-visitor-keys: 4.2.0
+      espree: 10.3.0
       esquery: 1.6.0
       esutils: 2.0.3
       fast-deep-equal: 3.1.3
@@ -18534,66 +17554,25 @@ snapshots:
       ignore: 5.3.1
       imurmurhash: 0.1.4
       is-glob: 4.0.3
-      is-path-inside: 3.0.3
       json-stable-stringify-without-jsonify: 1.0.1
       lodash.merge: 4.6.2
       minimatch: 3.1.2
       natural-compare: 1.4.0
       optionator: 0.9.4
-      strip-ansi: 6.0.1
       text-table: 0.2.0
     transitivePeerDependencies:
       - supports-color
 
-  eslint@9.8.0:
+  espree@10.3.0:
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0)
-      '@eslint-community/regexpp': 4.11.0
-      '@eslint/config-array': 0.17.1
-      '@eslint/eslintrc': 3.1.0
-      '@eslint/js': 9.8.0
-      '@humanwhocodes/module-importer': 1.0.1
-      '@humanwhocodes/retry': 0.3.0
-      '@nodelib/fs.walk': 1.2.8
-      ajv: 6.12.6
-      chalk: 4.1.2
-      cross-spawn: 7.0.3
-      debug: 4.3.7(supports-color@8.1.1)
-      escape-string-regexp: 4.0.0
-      eslint-scope: 8.0.2
-      eslint-visitor-keys: 4.0.0
-      espree: 10.1.0
-      esquery: 1.6.0
-      esutils: 2.0.3
-      fast-deep-equal: 3.1.3
-      file-entry-cache: 8.0.0
-      find-up: 5.0.0
-      glob-parent: 6.0.2
-      ignore: 5.3.1
-      imurmurhash: 0.1.4
-      is-glob: 4.0.3
-      is-path-inside: 3.0.3
-      json-stable-stringify-without-jsonify: 1.0.1
-      levn: 0.4.1
-      lodash.merge: 4.6.2
-      minimatch: 3.1.2
-      natural-compare: 1.4.0
-      optionator: 0.9.4
-      strip-ansi: 6.0.1
-      text-table: 0.2.0
-    transitivePeerDependencies:
-      - supports-color
-
-  espree@10.1.0:
-    dependencies:
-      acorn: 8.12.1
-      acorn-jsx: 5.3.2(acorn@8.12.1)
-      eslint-visitor-keys: 4.0.0
+      acorn: 8.14.0
+      acorn-jsx: 5.3.2(acorn@8.14.0)
+      eslint-visitor-keys: 4.2.0
 
   espree@9.6.1:
     dependencies:
-      acorn: 8.12.1
-      acorn-jsx: 5.3.2(acorn@8.12.1)
+      acorn: 8.14.0
+      acorn-jsx: 5.3.2(acorn@8.14.0)
       eslint-visitor-keys: 3.4.3
 
   esprima@4.0.1: {}
@@ -18696,7 +17675,7 @@ snapshots:
       signal-exit: 4.1.0
       strip-final-newline: 3.0.0
 
-  execa@9.4.0:
+  execa@9.5.1:
     dependencies:
       '@sindresorhus/merge-streams': 4.0.0
       cross-spawn: 7.0.3
@@ -18763,6 +17742,42 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
+  express@4.21.1:
+    dependencies:
+      accepts: 1.3.8
+      array-flatten: 1.1.1
+      body-parser: 1.20.3
+      content-disposition: 0.5.4
+      content-type: 1.0.5
+      cookie: 0.7.1
+      cookie-signature: 1.0.6
+      debug: 2.6.9
+      depd: 2.0.0
+      encodeurl: 2.0.0
+      escape-html: 1.0.3
+      etag: 1.8.1
+      finalhandler: 1.3.1
+      fresh: 0.5.2
+      http-errors: 2.0.0
+      merge-descriptors: 1.0.3
+      methods: 1.1.2
+      on-finished: 2.4.1
+      parseurl: 1.3.3
+      path-to-regexp: 0.1.10
+      proxy-addr: 2.0.7
+      qs: 6.13.0
+      range-parser: 1.2.1
+      safe-buffer: 5.2.1
+      send: 0.19.0
+      serve-static: 1.16.2
+      setprototypeof: 1.2.0
+      statuses: 2.0.1
+      type-is: 1.6.18
+      utils-merge: 1.0.1
+      vary: 1.1.2
+    transitivePeerDependencies:
+      - supports-color
+
   ext-list@2.2.2:
     dependencies:
       mime-db: 1.52.0
@@ -18776,7 +17791,7 @@ snapshots:
 
   extract-zip@2.0.1(supports-color@8.1.1):
     dependencies:
-      debug: 4.3.5(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@8.1.1)
       get-stream: 5.2.0
       yauzl: 2.10.0
     optionalDependencies:
@@ -18861,7 +17876,7 @@ snapshots:
       proxy-addr: 2.0.7
       rfdc: 1.4.1
       secure-json-parse: 2.7.0
-      semver: 7.6.0
+      semver: 7.6.3
       toad-cache: 3.7.0
 
   fastq@1.17.1:
@@ -18903,10 +17918,10 @@ snapshots:
       strtok3: 7.0.0
       token-types: 5.0.1
 
-  file-type@19.5.0:
+  file-type@19.6.0:
     dependencies:
       get-stream: 9.0.1
-      strtok3: 8.1.0
+      strtok3: 9.0.1
       token-types: 6.0.0
       uint8array-extras: 1.4.0
 
@@ -18942,12 +17957,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  find-cache-dir@3.3.2:
-    dependencies:
-      commondir: 1.0.1
-      make-dir: 3.1.0
-      pkg-dir: 4.2.0
-
   find-my-way@9.0.1:
     dependencies:
       fast-deep-equal: 3.1.3
@@ -19018,7 +18027,7 @@ snapshots:
       combined-stream: 1.0.8
       mime-types: 2.1.35
 
-  form-data@4.0.0:
+  form-data@4.0.1:
     dependencies:
       asynckit: 0.4.0
       combined-stream: 1.0.8
@@ -19034,12 +18043,6 @@ snapshots:
 
   from@0.1.7: {}
 
-  fs-extra@11.1.1:
-    dependencies:
-      graceful-fs: 4.2.11
-      jsonfile: 6.1.0
-      universalify: 2.0.0
-
   fs-extra@7.0.1:
     dependencies:
       graceful-fs: 4.2.11
@@ -19187,8 +18190,6 @@ snapshots:
     dependencies:
       readable-stream: 1.1.14
 
-  github-slugger@2.0.0: {}
-
   glob-parent@5.1.2:
     dependencies:
       is-glob: 4.0.3
@@ -19248,7 +18249,7 @@ snapshots:
 
   globals@14.0.0: {}
 
-  globals@15.9.0: {}
+  globals@15.12.0: {}
 
   globalthis@1.0.3:
     dependencies:
@@ -19298,9 +18299,9 @@ snapshots:
       p-cancelable: 3.0.0
       responselike: 3.0.0
 
-  got@14.4.2:
+  got@14.4.4:
     dependencies:
-      '@sindresorhus/is': 7.0.0
+      '@sindresorhus/is': 7.0.1
       '@szmarczak/http-timer': 5.0.1
       cacheable-lookup: 7.0.0
       cacheable-request: 12.0.1
@@ -19310,7 +18311,7 @@ snapshots:
       lowercase-keys: 3.0.0
       p-cancelable: 4.0.1
       responselike: 3.0.0
-      type-fest: 4.20.1
+      type-fest: 4.26.1
 
   graceful-fs@4.2.11: {}
 
@@ -19331,7 +18332,7 @@ snapshots:
       whatwg-encoding: 2.0.0
       whatwg-mimetype: 3.0.0
 
-  happy-dom@15.7.4:
+  happy-dom@15.11.4:
     dependencies:
       entities: 4.5.0
       webidl-conversions: 7.0.0
@@ -19391,14 +18392,6 @@ snapshots:
     dependencies:
       function-bind: 1.1.2
 
-  hast-util-heading-rank@3.0.0:
-    dependencies:
-      '@types/hast': 3.0.4
-
-  hast-util-is-element@3.0.0:
-    dependencies:
-      '@types/hast': 3.0.4
-
   hast-util-to-html@9.0.3:
     dependencies:
       '@types/hast': 3.0.4
@@ -19413,10 +18406,6 @@ snapshots:
       stringify-entities: 4.0.4
       zwitch: 2.0.4
 
-  hast-util-to-string@3.0.0:
-    dependencies:
-      '@types/hast': 3.0.4
-
   hast-util-whitespace@3.0.0:
     dependencies:
       '@types/hast': 3.0.4
@@ -19445,8 +18434,6 @@ snapshots:
 
   html-escaper@2.0.2: {}
 
-  html-tags@3.2.0: {}
-
   html-void-elements@3.0.0: {}
 
   htmlescape@1.1.1: {}
@@ -19487,7 +18474,7 @@ snapshots:
   http-proxy-agent@7.0.2:
     dependencies:
       agent-base: 7.1.0
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
     transitivePeerDependencies:
       - supports-color
 
@@ -19526,7 +18513,7 @@ snapshots:
   https-proxy-agent@5.0.1:
     dependencies:
       agent-base: 6.0.2
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
     transitivePeerDependencies:
       - supports-color
     optional: true
@@ -19534,14 +18521,14 @@ snapshots:
   https-proxy-agent@7.0.2:
     dependencies:
       agent-base: 7.1.0
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
     transitivePeerDependencies:
       - supports-color
 
   https-proxy-agent@7.0.5:
     dependencies:
       agent-base: 7.1.0
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
     transitivePeerDependencies:
       - supports-color
 
@@ -19584,21 +18571,13 @@ snapshots:
       parent-module: 1.0.1
       resolve-from: 4.0.0
 
-  import-in-the-middle@1.10.0:
+  import-in-the-middle@1.11.2:
     dependencies:
-      acorn: 8.12.1
-      acorn-import-attributes: 1.9.5(acorn@8.12.1)
+      acorn: 8.14.0
+      acorn-import-attributes: 1.9.5(acorn@8.14.0)
       cjs-module-lexer: 1.2.2
       module-details-from-path: 1.0.3
 
-  import-in-the-middle@1.7.1:
-    dependencies:
-      acorn: 8.12.1
-      acorn-import-assertions: 1.9.0(acorn@8.12.1)
-      cjs-module-lexer: 1.2.2
-      module-details-from-path: 1.0.3
-    optional: true
-
   import-lazy@4.0.0: {}
 
   import-local@3.1.0:
@@ -19645,7 +18624,7 @@ snapshots:
     dependencies:
       '@ioredis/commands': 1.2.0
       cluster-key-slot: 1.1.2
-      debug: 4.3.4(supports-color@5.5.0)
+      debug: 4.3.4
       denque: 2.1.0
       lodash.defaults: 4.2.0
       lodash.isarguments: 3.1.0
@@ -19676,8 +18655,6 @@ snapshots:
 
   irregular-plurals@3.5.0: {}
 
-  is-absolute-url@4.0.1: {}
-
   is-arguments@1.1.1:
     dependencies:
       call-bind: 1.0.2
@@ -19715,10 +18692,6 @@ snapshots:
 
   is-callable@1.2.7: {}
 
-  is-ci@3.0.1:
-    dependencies:
-      ci-info: 3.7.1
-
   is-core-module@2.13.1:
     dependencies:
       hasown: 2.0.0
@@ -19890,7 +18863,7 @@ snapshots:
   istanbul-lib-instrument@6.0.0:
     dependencies:
       '@babel/core': 7.24.7
-      '@babel/parser': 7.24.7
+      '@babel/parser': 7.25.6
       '@istanbuljs/schema': 0.1.3
       istanbul-lib-coverage: 3.2.2
       semver: 7.6.3
@@ -19914,7 +18887,7 @@ snapshots:
   istanbul-lib-source-maps@5.0.4:
     dependencies:
       '@jridgewell/trace-mapping': 0.3.25
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       istanbul-lib-coverage: 3.2.2
     transitivePeerDependencies:
       - supports-color
@@ -19957,7 +18930,7 @@ snapshots:
       '@jest/expect': 29.7.0
       '@jest/test-result': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       chalk: 4.1.2
       co: 4.6.0
       dedent: 1.3.0
@@ -19977,16 +18950,16 @@ snapshots:
       - babel-plugin-macros
       - supports-color
 
-  jest-cli@29.7.0(@types/node@20.14.12):
+  jest-cli@29.7.0(@types/node@22.9.0):
     dependencies:
       '@jest/core': 29.7.0
       '@jest/test-result': 29.7.0
       '@jest/types': 29.6.3
       chalk: 4.1.2
-      create-jest: 29.7.0(@types/node@20.14.12)
+      create-jest: 29.7.0(@types/node@22.9.0)
       exit: 0.1.2
       import-local: 3.1.0
-      jest-config: 29.7.0(@types/node@20.14.12)
+      jest-config: 29.7.0(@types/node@22.9.0)
       jest-util: 29.7.0
       jest-validate: 29.7.0
       yargs: 17.7.2
@@ -19996,7 +18969,7 @@ snapshots:
       - supports-color
       - ts-node
 
-  jest-config@29.7.0(@types/node@20.14.12):
+  jest-config@29.7.0(@types/node@22.9.0):
     dependencies:
       '@babel/core': 7.23.5
       '@jest/test-sequencer': 29.7.0
@@ -20021,7 +18994,7 @@ snapshots:
       slash: 3.0.0
       strip-json-comments: 3.1.1
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
     transitivePeerDependencies:
       - babel-plugin-macros
       - supports-color
@@ -20050,7 +19023,7 @@ snapshots:
       '@jest/environment': 29.7.0
       '@jest/fake-timers': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       jest-mock: 29.7.0
       jest-util: 29.7.0
 
@@ -20067,7 +19040,7 @@ snapshots:
     dependencies:
       '@jest/types': 29.6.3
       '@types/graceful-fs': 4.1.6
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       anymatch: 3.1.3
       fb-watchman: 2.0.2
       graceful-fs: 4.2.11
@@ -20106,7 +19079,7 @@ snapshots:
   jest-mock@29.7.0:
     dependencies:
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       jest-util: 29.7.0
 
   jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
@@ -20141,7 +19114,7 @@ snapshots:
       '@jest/test-result': 29.7.0
       '@jest/transform': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       chalk: 4.1.2
       emittery: 0.13.1
       graceful-fs: 4.2.11
@@ -20169,7 +19142,7 @@ snapshots:
       '@jest/test-result': 29.7.0
       '@jest/transform': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       chalk: 4.1.2
       cjs-module-lexer: 1.2.2
       collect-v8-coverage: 1.0.1
@@ -20215,7 +19188,7 @@ snapshots:
   jest-util@29.7.0:
     dependencies:
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       chalk: 4.1.2
       ci-info: 3.7.1
       graceful-fs: 4.2.11
@@ -20234,7 +19207,7 @@ snapshots:
     dependencies:
       '@jest/test-result': 29.7.0
       '@jest/types': 29.6.3
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       ansi-escapes: 4.3.2
       chalk: 4.1.2
       emittery: 0.13.1
@@ -20248,17 +19221,17 @@ snapshots:
 
   jest-worker@29.7.0:
     dependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       jest-util: 29.7.0
       merge-stream: 2.0.0
       supports-color: 8.1.1
 
-  jest@29.7.0(@types/node@20.14.12):
+  jest@29.7.0(@types/node@22.9.0):
     dependencies:
       '@jest/core': 29.7.0
       '@jest/types': 29.6.3
       import-local: 3.1.0
-      jest-cli: 29.7.0(@types/node@20.14.12)
+      jest-cli: 29.7.0(@types/node@22.9.0)
     transitivePeerDependencies:
       - '@types/node'
       - babel-plugin-macros
@@ -20315,18 +19288,47 @@ snapshots:
 
   jsdoc-type-pratt-parser@4.1.0: {}
 
-  jsdom@24.1.1(bufferutil@4.0.7)(utf-8-validate@6.0.3):
+  jsdom@24.1.1:
     dependencies:
       cssstyle: 4.0.1
       data-urls: 5.0.0
       decimal.js: 10.4.3
-      form-data: 4.0.0
+      form-data: 4.0.1
       html-encoding-sniffer: 4.0.0
       http-proxy-agent: 7.0.2
       https-proxy-agent: 7.0.5
       is-potential-custom-element-name: 1.0.1
       nwsapi: 2.2.12
-      parse5: 7.1.2
+      parse5: 7.2.1
+      rrweb-cssom: 0.7.1
+      saxes: 6.0.0
+      symbol-tree: 3.2.4
+      tough-cookie: 4.1.4
+      w3c-xmlserializer: 5.0.0
+      webidl-conversions: 7.0.0
+      whatwg-encoding: 3.1.1
+      whatwg-mimetype: 4.0.0
+      whatwg-url: 14.0.0
+      ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      xml-name-validator: 5.0.0
+    transitivePeerDependencies:
+      - bufferutil
+      - supports-color
+      - utf-8-validate
+    optional: true
+
+  jsdom@24.1.1(bufferutil@4.0.7)(utf-8-validate@6.0.3):
+    dependencies:
+      cssstyle: 4.0.1
+      data-urls: 5.0.0
+      decimal.js: 10.4.3
+      form-data: 4.0.1
+      html-encoding-sniffer: 4.0.0
+      http-proxy-agent: 7.0.2
+      https-proxy-agent: 7.0.5
+      is-potential-custom-element-name: 1.0.1
+      nwsapi: 2.2.12
+      parse5: 7.2.1
       rrweb-cssom: 0.7.1
       saxes: 6.0.0
       symbol-tree: 3.2.4
@@ -20348,13 +19350,13 @@ snapshots:
       cssstyle: 4.0.1
       data-urls: 5.0.0
       decimal.js: 10.4.3
-      form-data: 4.0.0
+      form-data: 4.0.1
       html-encoding-sniffer: 4.0.0
       http-proxy-agent: 7.0.2
       https-proxy-agent: 7.0.5
       is-potential-custom-element-name: 1.0.1
       nwsapi: 2.2.12
-      parse5: 7.1.2
+      parse5: 7.2.1
       rrweb-cssom: 0.7.1
       saxes: 6.0.0
       symbol-tree: 3.2.4
@@ -20521,7 +19523,7 @@ snapshots:
       colorette: 2.0.19
       log-update: 4.0.0
       p-map: 4.0.0
-      rfdc: 1.3.0
+      rfdc: 1.4.1
       rxjs: 7.8.1
       through: 2.3.8
       wrap-ansi: 7.0.0
@@ -20639,6 +19641,7 @@ snapshots:
   make-dir@3.1.0:
     dependencies:
       semver: 6.3.1
+    optional: true
 
   make-dir@4.0.0:
     dependencies:
@@ -20674,10 +19677,6 @@ snapshots:
 
   markdown-table@3.0.3: {}
 
-  markdown-to-jsx@7.4.7(react@18.3.1):
-    dependencies:
-      react: 18.3.1
-
   matter-js@0.19.0: {}
 
   mdast-util-find-and-replace@3.0.1:
@@ -20799,11 +19798,7 @@ snapshots:
 
   media-typer@0.3.0: {}
 
-  meilisearch@0.42.0(encoding@0.1.13):
-    dependencies:
-      cross-fetch: 3.1.6(encoding@0.1.13)
-    transitivePeerDependencies:
-      - encoding
+  meilisearch@0.45.0: {}
 
   memoizerific@1.11.3:
     dependencies:
@@ -20840,7 +19835,7 @@ snapshots:
 
   microformats-parser@2.0.2:
     dependencies:
-      parse5: 7.1.2
+      parse5: 7.2.1
 
   micromark-core-commonmark@2.0.0:
     dependencies:
@@ -21160,7 +20155,7 @@ snapshots:
 
   mlly@1.5.0:
     dependencies:
-      acorn: 8.12.1
+      acorn: 8.14.0
       pathe: 1.1.2
       pkg-types: 1.0.3
       ufo: 1.3.2
@@ -21193,22 +20188,23 @@ snapshots:
       '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.2
     optional: true
 
-  msgpackr@1.10.1:
+  msgpackr@1.11.2:
     optionalDependencies:
       msgpackr-extract: 3.0.2
 
-  msw-storybook-addon@2.0.3(msw@2.4.9(typescript@5.6.2)):
+  msw-storybook-addon@2.0.4(msw@2.6.4(@types/node@22.9.0)(typescript@5.6.3)):
     dependencies:
       is-node-process: 1.2.0
-      msw: 2.4.9(typescript@5.6.2)
+      msw: 2.6.4(@types/node@22.9.0)(typescript@5.6.3)
 
-  msw@2.3.4(typescript@5.6.2):
+  msw@2.6.4(@types/node@22.9.0)(typescript@5.6.3):
     dependencies:
-      '@bundled-es-modules/cookie': 2.0.0
+      '@bundled-es-modules/cookie': 2.0.1
       '@bundled-es-modules/statuses': 1.0.1
       '@bundled-es-modules/tough-cookie': 0.1.6
-      '@inquirer/confirm': 3.1.6
-      '@mswjs/interceptors': 0.29.1
+      '@inquirer/confirm': 5.0.2(@types/node@22.9.0)
+      '@mswjs/interceptors': 0.36.10
+      '@open-draft/deferred-promise': 2.2.0
       '@open-draft/until': 2.1.0
       '@types/cookie': 0.6.0
       '@types/statuses': 2.0.4
@@ -21216,35 +20212,15 @@ snapshots:
       graphql: 16.8.1
       headers-polyfill: 4.0.2
       is-node-process: 1.2.0
-      outvariant: 1.4.2
-      path-to-regexp: 6.2.1
-      strict-event-emitter: 0.5.1
-      type-fest: 4.20.1
-      yargs: 17.7.2
-    optionalDependencies:
-      typescript: 5.6.2
-
-  msw@2.4.9(typescript@5.6.2):
-    dependencies:
-      '@bundled-es-modules/cookie': 2.0.0
-      '@bundled-es-modules/statuses': 1.0.1
-      '@bundled-es-modules/tough-cookie': 0.1.6
-      '@inquirer/confirm': 3.1.6
-      '@mswjs/interceptors': 0.35.8
-      '@open-draft/until': 2.1.0
-      '@types/cookie': 0.6.0
-      '@types/statuses': 2.0.4
-      chalk: 4.1.2
-      graphql: 16.8.1
-      headers-polyfill: 4.0.2
-      is-node-process: 1.2.0
-      outvariant: 1.4.2
+      outvariant: 1.4.3
       path-to-regexp: 6.3.0
       strict-event-emitter: 0.5.1
-      type-fest: 4.20.1
+      type-fest: 4.26.1
       yargs: 17.7.2
     optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
+    transitivePeerDependencies:
+      - '@types/node'
 
   muggle-string@0.4.1: {}
 
@@ -21260,7 +20236,7 @@ snapshots:
 
   multi-integer-range@3.0.0: {}
 
-  mute-stream@1.0.0: {}
+  mute-stream@2.0.0: {}
 
   mylas@2.1.13: {}
 
@@ -21274,7 +20250,7 @@ snapshots:
 
   nanoid@3.3.7: {}
 
-  nanoid@5.0.7: {}
+  nanoid@5.0.8: {}
 
   natural-compare@1.4.0: {}
 
@@ -21329,7 +20305,7 @@ snapshots:
 
   node-abi@3.62.0:
     dependencies:
-      semver: 7.6.0
+      semver: 7.6.3
 
   node-abort-controller@3.1.1: {}
 
@@ -21383,29 +20359,16 @@ snapshots:
 
   node-releases@2.0.14: {}
 
-  nodemailer@6.9.15: {}
-
-  nodemon@3.0.2:
-    dependencies:
-      chokidar: 3.5.3
-      debug: 4.3.4(supports-color@5.5.0)
-      ignore-by-default: 1.0.1
-      minimatch: 3.1.2
-      pstree.remy: 1.1.8
-      semver: 7.5.4
-      simple-update-notifier: 2.0.0
-      supports-color: 5.5.0
-      touch: 3.1.0
-      undefsafe: 2.0.5
+  nodemailer@6.9.16: {}
 
   nodemon@3.1.7:
     dependencies:
       chokidar: 3.5.3
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.7(supports-color@5.5.0)
       ignore-by-default: 1.0.1
       minimatch: 3.1.2
       pstree.remy: 1.1.8
-      semver: 7.6.0
+      semver: 7.6.3
       simple-update-notifier: 2.0.0
       supports-color: 5.5.0
       touch: 3.1.0
@@ -21597,15 +20560,6 @@ snapshots:
       undici: 5.28.2
       yargs-parser: 21.1.1
 
-  opentelemetry-instrumentation-fetch-node@1.2.3(@opentelemetry/api@1.9.0):
-    dependencies:
-      '@opentelemetry/api': 1.9.0
-      '@opentelemetry/instrumentation': 0.46.0(@opentelemetry/api@1.9.0)
-      '@opentelemetry/semantic-conventions': 1.25.1
-    transitivePeerDependencies:
-      - supports-color
-    optional: true
-
   optionator@0.9.4:
     dependencies:
       deep-is: 0.1.4
@@ -21627,8 +20581,6 @@ snapshots:
     dependencies:
       '@noble/hashes': 1.5.0
 
-  outvariant@1.4.2: {}
-
   outvariant@1.4.3: {}
 
   p-cancelable@2.1.1: {}
@@ -21702,17 +20654,17 @@ snapshots:
   parse5-htmlparser2-tree-adapter@7.0.0:
     dependencies:
       domhandler: 5.0.3
-      parse5: 7.1.2
+      parse5: 7.2.1
 
   parse5-parser-stream@7.1.2:
     dependencies:
-      parse5: 7.1.2
+      parse5: 7.2.1
 
   parse5@5.1.1: {}
 
   parse5@6.0.1: {}
 
-  parse5@7.1.2:
+  parse5@7.2.1:
     dependencies:
       entities: 4.5.0
 
@@ -21750,8 +20702,6 @@ snapshots:
 
   path-to-regexp@3.3.0: {}
 
-  path-to-regexp@6.2.1: {}
-
   path-to-regexp@6.3.0: {}
 
   path-type@4.0.0: {}
@@ -21766,10 +20716,10 @@ snapshots:
     dependencies:
       through: 2.3.8
 
-  peek-readable@5.1.3: {}
-
   peek-readable@5.2.0: {}
 
+  peek-readable@5.3.1: {}
+
   pend@1.2.0: {}
 
   performance-now@2.1.0: {}
@@ -21783,9 +20733,9 @@ snapshots:
 
   pg-numeric@1.0.2: {}
 
-  pg-pool@3.7.0(pg@8.13.0):
+  pg-pool@3.7.0(pg@8.13.1):
     dependencies:
-      pg: 8.13.0
+      pg: 8.13.1
 
   pg-protocol@1.6.1: {}
 
@@ -21809,10 +20759,10 @@ snapshots:
       postgres-interval: 3.0.0
       postgres-range: 1.1.3
 
-  pg@8.13.0:
+  pg@8.13.1:
     dependencies:
       pg-connection-string: 2.7.0
-      pg-pool: 3.7.0(pg@8.13.0)
+      pg-pool: 3.7.0(pg@8.13.1)
       pg-protocol: 1.7.0
       pg-types: 2.2.0
       pgpass: 1.0.5
@@ -21831,8 +20781,12 @@ snapshots:
 
   picocolors@1.1.0: {}
 
+  picocolors@1.1.1: {}
+
   picomatch@2.3.1: {}
 
+  picomatch@4.0.2: {}
+
   pid-port@1.0.0:
     dependencies:
       execa: 8.0.1
@@ -21898,140 +20852,140 @@ snapshots:
 
   possible-typed-array-names@1.0.0: {}
 
-  postcss-calc@9.0.1(postcss@8.4.47):
+  postcss-calc@9.0.1(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-selector-parser: 6.0.16
       postcss-value-parser: 4.2.0
 
-  postcss-colormin@6.1.0(postcss@8.4.47):
+  postcss-colormin@6.1.0(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
       caniuse-api: 3.0.0
       colord: 2.9.3
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-convert-values@6.1.0(postcss@8.4.47):
+  postcss-convert-values@6.1.0(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-discard-comments@6.0.2(postcss@8.4.47):
+  postcss-discard-comments@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  postcss-discard-duplicates@6.0.3(postcss@8.4.47):
+  postcss-discard-duplicates@6.0.3(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  postcss-discard-empty@6.0.3(postcss@8.4.47):
+  postcss-discard-empty@6.0.3(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  postcss-discard-overridden@6.0.2(postcss@8.4.47):
+  postcss-discard-overridden@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  postcss-merge-longhand@6.0.5(postcss@8.4.47):
+  postcss-merge-longhand@6.0.5(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
-      stylehacks: 6.1.1(postcss@8.4.47)
+      stylehacks: 6.1.1(postcss@8.4.49)
 
-  postcss-merge-rules@6.1.1(postcss@8.4.47):
+  postcss-merge-rules@6.1.1(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
       caniuse-api: 3.0.0
-      cssnano-utils: 4.0.2(postcss@8.4.47)
-      postcss: 8.4.47
+      cssnano-utils: 4.0.2(postcss@8.4.49)
+      postcss: 8.4.49
       postcss-selector-parser: 6.0.16
 
-  postcss-minify-font-values@6.1.0(postcss@8.4.47):
+  postcss-minify-font-values@6.1.0(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-minify-gradients@6.0.3(postcss@8.4.47):
+  postcss-minify-gradients@6.0.3(postcss@8.4.49):
     dependencies:
       colord: 2.9.3
-      cssnano-utils: 4.0.2(postcss@8.4.47)
-      postcss: 8.4.47
+      cssnano-utils: 4.0.2(postcss@8.4.49)
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-minify-params@6.1.0(postcss@8.4.47):
+  postcss-minify-params@6.1.0(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
-      cssnano-utils: 4.0.2(postcss@8.4.47)
-      postcss: 8.4.47
+      cssnano-utils: 4.0.2(postcss@8.4.49)
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-minify-selectors@6.0.4(postcss@8.4.47):
+  postcss-minify-selectors@6.0.4(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-selector-parser: 6.0.16
 
-  postcss-normalize-charset@6.0.2(postcss@8.4.47):
+  postcss-normalize-charset@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  postcss-normalize-display-values@6.0.2(postcss@8.4.47):
+  postcss-normalize-display-values@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-positions@6.0.2(postcss@8.4.47):
+  postcss-normalize-positions@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-repeat-style@6.0.2(postcss@8.4.47):
+  postcss-normalize-repeat-style@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-string@6.0.2(postcss@8.4.47):
+  postcss-normalize-string@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-timing-functions@6.0.2(postcss@8.4.47):
+  postcss-normalize-timing-functions@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-unicode@6.1.0(postcss@8.4.47):
+  postcss-normalize-unicode@6.1.0(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-url@6.0.2(postcss@8.4.47):
+  postcss-normalize-url@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-normalize-whitespace@6.0.2(postcss@8.4.47):
+  postcss-normalize-whitespace@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-ordered-values@6.0.2(postcss@8.4.47):
+  postcss-ordered-values@6.0.2(postcss@8.4.49):
     dependencies:
-      cssnano-utils: 4.0.2(postcss@8.4.47)
-      postcss: 8.4.47
+      cssnano-utils: 4.0.2(postcss@8.4.49)
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
-  postcss-reduce-initial@6.1.0(postcss@8.4.47):
+  postcss-reduce-initial@6.1.0(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
       caniuse-api: 3.0.0
-      postcss: 8.4.47
+      postcss: 8.4.49
 
-  postcss-reduce-transforms@6.0.2(postcss@8.4.47):
+  postcss-reduce-transforms@6.0.2(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
 
   postcss-selector-parser@6.0.16:
@@ -22039,15 +20993,15 @@ snapshots:
       cssesc: 3.0.0
       util-deprecate: 1.0.2
 
-  postcss-svgo@6.0.3(postcss@8.4.47):
+  postcss-svgo@6.0.3(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-value-parser: 4.2.0
       svgo: 3.2.0
 
-  postcss-unique-selectors@6.0.4(postcss@8.4.47):
+  postcss-unique-selectors@6.0.4(postcss@8.4.49):
     dependencies:
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-selector-parser: 6.0.16
 
   postcss-value-parser@4.2.0: {}
@@ -22058,6 +21012,12 @@ snapshots:
       picocolors: 1.1.0
       source-map-js: 1.2.1
 
+  postcss@8.4.49:
+    dependencies:
+      nanoid: 3.3.7
+      picocolors: 1.1.1
+      source-map-js: 1.2.1
+
   postgres-array@2.0.0: {}
 
   postgres-array@3.0.2: {}
@@ -22152,12 +21112,6 @@ snapshots:
       kleur: 3.0.3
       sisteransi: 1.0.5
 
-  prop-types@15.8.1:
-    dependencies:
-      loose-envify: 1.4.0
-      object-assign: 4.1.1
-      react-is: 16.13.1
-
   property-information@6.5.0: {}
 
   proto-list@1.2.4: {}
@@ -22327,14 +21281,9 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  react-colorful@5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-docgen-typescript@2.2.2(typescript@5.6.3):
     dependencies:
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-
-  react-docgen-typescript@2.2.2(typescript@5.6.2):
-    dependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
 
   react-docgen@7.0.1:
     dependencies:
@@ -22357,20 +21306,8 @@ snapshots:
       react: 18.3.1
       scheduler: 0.23.2
 
-  react-element-to-jsx-string@15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
-    dependencies:
-      '@base2/pretty-print-object': 1.0.1
-      is-plain-object: 5.0.0
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      react-is: 18.1.0
-
-  react-is@16.13.1: {}
-
   react-is@17.0.2: {}
 
-  react-is@18.1.0: {}
-
   react-is@18.2.0: {}
 
   react@18.3.1:
@@ -22482,23 +21419,6 @@ snapshots:
       es-errors: 1.3.0
       set-function-name: 2.0.2
 
-  rehype-external-links@3.0.0:
-    dependencies:
-      '@types/hast': 3.0.4
-      '@ungap/structured-clone': 1.2.0
-      hast-util-is-element: 3.0.0
-      is-absolute-url: 4.0.1
-      space-separated-tokens: 2.0.2
-      unist-util-visit: 5.0.0
-
-  rehype-slug@6.0.0:
-    dependencies:
-      '@types/hast': 3.0.4
-      github-slugger: 2.0.0
-      hast-util-heading-rank: 3.0.0
-      hast-util-to-string: 3.0.0
-      unist-util-visit: 5.0.0
-
   remark-gfm@4.0.0:
     dependencies:
       '@types/mdast': 4.0.3
@@ -22613,8 +21533,6 @@ snapshots:
 
   reusify@1.0.4: {}
 
-  rfdc@1.3.0: {}
-
   rfdc@1.4.1: {}
 
   rimraf@2.7.1:
@@ -22627,26 +21545,28 @@ snapshots:
       glob: 7.2.3
     optional: true
 
-  rollup@4.22.5:
+  rollup@4.26.0:
     dependencies:
       '@types/estree': 1.0.6
     optionalDependencies:
-      '@rollup/rollup-android-arm-eabi': 4.22.5
-      '@rollup/rollup-android-arm64': 4.22.5
-      '@rollup/rollup-darwin-arm64': 4.22.5
-      '@rollup/rollup-darwin-x64': 4.22.5
-      '@rollup/rollup-linux-arm-gnueabihf': 4.22.5
-      '@rollup/rollup-linux-arm-musleabihf': 4.22.5
-      '@rollup/rollup-linux-arm64-gnu': 4.22.5
-      '@rollup/rollup-linux-arm64-musl': 4.22.5
-      '@rollup/rollup-linux-powerpc64le-gnu': 4.22.5
-      '@rollup/rollup-linux-riscv64-gnu': 4.22.5
-      '@rollup/rollup-linux-s390x-gnu': 4.22.5
-      '@rollup/rollup-linux-x64-gnu': 4.22.5
-      '@rollup/rollup-linux-x64-musl': 4.22.5
-      '@rollup/rollup-win32-arm64-msvc': 4.22.5
-      '@rollup/rollup-win32-ia32-msvc': 4.22.5
-      '@rollup/rollup-win32-x64-msvc': 4.22.5
+      '@rollup/rollup-android-arm-eabi': 4.26.0
+      '@rollup/rollup-android-arm64': 4.26.0
+      '@rollup/rollup-darwin-arm64': 4.26.0
+      '@rollup/rollup-darwin-x64': 4.26.0
+      '@rollup/rollup-freebsd-arm64': 4.26.0
+      '@rollup/rollup-freebsd-x64': 4.26.0
+      '@rollup/rollup-linux-arm-gnueabihf': 4.26.0
+      '@rollup/rollup-linux-arm-musleabihf': 4.26.0
+      '@rollup/rollup-linux-arm64-gnu': 4.26.0
+      '@rollup/rollup-linux-arm64-musl': 4.26.0
+      '@rollup/rollup-linux-powerpc64le-gnu': 4.26.0
+      '@rollup/rollup-linux-riscv64-gnu': 4.26.0
+      '@rollup/rollup-linux-s390x-gnu': 4.26.0
+      '@rollup/rollup-linux-x64-gnu': 4.26.0
+      '@rollup/rollup-linux-x64-musl': 4.26.0
+      '@rollup/rollup-win32-arm64-msvc': 4.26.0
+      '@rollup/rollup-win32-ia32-msvc': 4.26.0
+      '@rollup/rollup-win32-x64-msvc': 4.26.0
       fsevents: 2.3.3
 
   rrweb-cssom@0.6.0: {}
@@ -22855,13 +21775,13 @@ snapshots:
 
   shebang-regex@3.0.0: {}
 
-  shiki@1.21.0:
+  shiki@1.22.2:
     dependencies:
-      '@shikijs/core': 1.21.0
-      '@shikijs/engine-javascript': 1.21.0
-      '@shikijs/engine-oniguruma': 1.21.0
-      '@shikijs/types': 1.21.0
-      '@shikijs/vscode-textmate': 9.2.2
+      '@shikijs/core': 1.22.2
+      '@shikijs/engine-javascript': 1.22.2
+      '@shikijs/engine-oniguruma': 1.22.2
+      '@shikijs/types': 1.22.2
+      '@shikijs/vscode-textmate': 9.3.0
       '@types/hast': 3.0.4
 
   shimmer@1.2.1: {}
@@ -22889,7 +21809,7 @@ snapshots:
     dependencies:
       '@hapi/hoek': 11.0.4
       '@hapi/wreck': 18.0.1
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       joi: 17.11.0
     transitivePeerDependencies:
       - supports-color
@@ -23114,22 +22034,24 @@ snapshots:
     dependencies:
       internal-slot: 1.0.5
 
-  storybook-addon-misskey-theme@https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/components@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/core-events@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/manager-api@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/preview-api@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/theming@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(@storybook/types@8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  storybook-addon-misskey-theme@https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/components@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/core-events@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/manager-api@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/preview-api@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/theming@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(@storybook/types@8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
     dependencies:
-      '@storybook/blocks': 8.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/components': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/core-events': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/manager-api': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/preview-api': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/theming': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
-      '@storybook/types': 8.3.4(storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+      '@storybook/blocks': 8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/components': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/core-events': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/manager-api': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/preview-api': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/theming': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
+      '@storybook/types': 8.4.4(storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4))
     optionalDependencies:
       react: 18.3.1
       react-dom: 18.3.1(react@18.3.1)
 
-  storybook@8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4):
+  storybook@8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4):
     dependencies:
-      '@storybook/core': 8.3.4(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      '@storybook/core': 8.4.4(bufferutil@4.0.8)(prettier@3.3.3)(utf-8-validate@6.0.4)
+    optionalDependencies:
+      prettier: 3.3.3
     transitivePeerDependencies:
       - bufferutil
       - supports-color
@@ -23275,19 +22197,19 @@ snapshots:
   strnum@1.0.5: {}
 
   strtok3@7.0.0:
-    dependencies:
-      '@tokenizer/token': 0.3.0
-      peek-readable: 5.1.3
-
-  strtok3@8.1.0:
     dependencies:
       '@tokenizer/token': 0.3.0
       peek-readable: 5.2.0
 
-  stylehacks@6.1.1(postcss@8.4.47):
+  strtok3@9.0.1:
+    dependencies:
+      '@tokenizer/token': 0.3.0
+      peek-readable: 5.3.1
+
+  stylehacks@6.1.1(postcss@8.4.49):
     dependencies:
       browserslist: 4.23.0
-      postcss: 8.4.47
+      postcss: 8.4.49
       postcss-selector-parser: 6.0.16
 
   supports-color@5.5.0:
@@ -23355,14 +22277,10 @@ snapshots:
     dependencies:
       execa: 6.1.0
 
-  telejson@7.2.0:
-    dependencies:
-      memoizerific: 1.11.3
-
-  terser@5.33.0:
+  terser@5.36.0:
     dependencies:
       '@jridgewell/source-map': 0.3.6
-      acorn: 8.12.1
+      acorn: 8.14.0
       commander: 2.20.3
       source-map-support: 0.5.21
 
@@ -23412,6 +22330,12 @@ snapshots:
 
   tinyspy@3.0.2: {}
 
+  tldts-core@6.1.61: {}
+
+  tldts@6.1.61:
+    dependencies:
+      tldts-core: 6.1.61
+
   tmp@0.2.3: {}
 
   tmpl@1.0.5: {}
@@ -23456,6 +22380,10 @@ snapshots:
       universalify: 0.2.0
       url-parse: 1.5.10
 
+  tough-cookie@5.0.0:
+    dependencies:
+      tldts: 6.1.61
+
   tr46@0.0.3: {}
 
   tr46@5.0.0:
@@ -23464,6 +22392,8 @@ snapshots:
 
   trace-redirect@1.0.6: {}
 
+  tree-kill@1.2.2: {}
+
   trim-lines@3.0.1: {}
 
   trim-newlines@3.0.1: {}
@@ -23474,19 +22404,15 @@ snapshots:
 
   trough@2.2.0: {}
 
-  ts-api-utils@1.0.1(typescript@5.3.3):
+  ts-api-utils@1.0.1(typescript@5.6.3):
     dependencies:
-      typescript: 5.3.3
+      typescript: 5.6.3
 
-  ts-api-utils@1.3.0(typescript@5.5.4):
+  ts-api-utils@1.3.0(typescript@5.6.3):
     dependencies:
-      typescript: 5.5.4
+      typescript: 5.6.3
 
-  ts-api-utils@1.3.0(typescript@5.6.2):
-    dependencies:
-      typescript: 5.6.2
-
-  ts-case-convert@2.0.7: {}
+  ts-case-convert@2.1.0: {}
 
   ts-dedent@2.2.0: {}
 
@@ -23561,7 +22487,7 @@ snapshots:
 
   type-fest@2.19.0: {}
 
-  type-fest@4.20.1: {}
+  type-fest@4.26.1: {}
 
   type-is@1.6.18:
     dependencies:
@@ -23629,7 +22555,7 @@ snapshots:
 
   typedarray@0.0.6: {}
 
-  typeorm@0.3.20(ioredis@5.4.1)(pg@8.13.0):
+  typeorm@0.3.20(ioredis@5.4.1)(pg@8.13.1):
     dependencies:
       '@sqltools/formatter': 1.2.5
       app-root-path: 3.1.0
@@ -23637,7 +22563,7 @@ snapshots:
       chalk: 4.1.2
       cli-highlight: 2.1.11
       dayjs: 1.11.10
-      debug: 4.3.4(supports-color@5.5.0)
+      debug: 4.3.4
       dotenv: 16.0.3
       glob: 10.3.10
       mkdirp: 2.1.6
@@ -23648,17 +22574,13 @@ snapshots:
       yargs: 17.7.2
     optionalDependencies:
       ioredis: 5.4.1
-      pg: 8.13.0
+      pg: 8.13.1
     transitivePeerDependencies:
       - supports-color
 
-  typescript@5.3.3: {}
-
   typescript@5.4.2: {}
 
-  typescript@5.5.4: {}
-
-  typescript@5.6.2: {}
+  typescript@5.6.3: {}
 
   ufo@1.3.2: {}
 
@@ -23681,8 +22603,6 @@ snapshots:
 
   undefsafe@2.0.5: {}
 
-  undici-types@5.26.5: {}
-
   undici-types@6.19.8: {}
 
   undici@5.28.2:
@@ -23748,7 +22668,7 @@ snapshots:
 
   unplugin@1.4.0:
     dependencies:
-      acorn: 8.12.1
+      acorn: 8.14.0
       chokidar: 3.5.3
       webpack-sources: 3.2.3
       webpack-virtual-modules: 0.5.0
@@ -23806,13 +22726,13 @@ snapshots:
 
   uuid@9.0.1: {}
 
-  v-code-diff@1.13.1(vue@3.5.11(typescript@5.6.2)):
+  v-code-diff@1.13.1(vue@3.5.12(typescript@5.6.3)):
     dependencies:
       diff: 5.2.0
       diff-match-patch: 1.0.5
       highlight.js: 11.10.0
-      vue: 3.5.11(typescript@5.6.2)
-      vue-demi: 0.14.7(vue@3.5.11(typescript@5.6.2))
+      vue: 3.5.12(typescript@5.6.3)
+      vue-demi: 0.14.7(vue@3.5.12(typescript@5.6.3))
 
   v8-to-istanbul@9.2.0:
     dependencies:
@@ -23846,13 +22766,13 @@ snapshots:
       unist-util-stringify-position: 4.0.0
       vfile-message: 4.0.2
 
-  vite-node@1.6.0(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0):
+  vite-node@1.6.0(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0):
     dependencies:
       cac: 6.7.14
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       pathe: 1.1.2
       picocolors: 1.0.1
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
     transitivePeerDependencies:
       - '@types/node'
       - less
@@ -23864,13 +22784,13 @@ snapshots:
       - supports-color
       - terser
 
-  vite-node@1.6.0(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0):
+  vite-node@1.6.0(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0):
     dependencies:
       cac: 6.7.14
-      debug: 4.3.5(supports-color@5.5.0)
+      debug: 4.3.5
       pathe: 1.1.2
       picocolors: 1.0.1
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0)
     transitivePeerDependencies:
       - '@types/node'
       - less
@@ -23884,36 +22804,36 @@ snapshots:
 
   vite-plugin-turbosnap@1.0.3: {}
 
-  vite@5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0):
+  vite@5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0):
     dependencies:
       esbuild: 0.21.5
-      postcss: 8.4.47
-      rollup: 4.22.5
+      postcss: 8.4.49
+      rollup: 4.26.0
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       fsevents: 2.3.3
       sass: 1.79.3
-      terser: 5.33.0
+      terser: 5.36.0
 
-  vite@5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0):
+  vite@5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0):
     dependencies:
       esbuild: 0.21.5
-      postcss: 8.4.47
-      rollup: 4.22.5
+      postcss: 8.4.49
+      rollup: 4.26.0
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       fsevents: 2.3.3
       sass: 1.79.4
-      terser: 5.33.0
+      terser: 5.36.0
 
-  vitest-fetch-mock@0.2.2(encoding@0.1.13)(vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0)):
+  vitest-fetch-mock@0.2.2(encoding@0.1.13)(vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0)):
     dependencies:
       cross-fetch: 3.1.6(encoding@0.1.13)
-      vitest: 1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0)
+      vitest: 1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0)
     transitivePeerDependencies:
       - encoding
 
-  vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.33.0):
+  vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.3)(terser@5.36.0):
     dependencies:
       '@vitest/expect': 1.6.0
       '@vitest/runner': 1.6.0
@@ -23922,7 +22842,7 @@ snapshots:
       '@vitest/utils': 1.6.0
       acorn-walk: 8.3.2
       chai: 4.3.10
-      debug: 4.3.4(supports-color@5.5.0)
+      debug: 4.3.4
       execa: 8.0.1
       local-pkg: 0.5.0
       magic-string: 0.30.10
@@ -23932,11 +22852,11 @@ snapshots:
       strip-literal: 2.1.0
       tinybench: 2.6.0
       tinypool: 0.8.4
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
-      vite-node: 1.6.0(@types/node@20.14.12)(sass@1.79.3)(terser@5.33.0)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
+      vite-node: 1.6.0(@types/node@22.9.0)(sass@1.79.3)(terser@5.36.0)
       why-is-node-running: 2.2.2
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       happy-dom: 10.0.3
       jsdom: 24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4)
     transitivePeerDependencies:
@@ -23949,7 +22869,7 @@ snapshots:
       - supports-color
       - terser
 
-  vitest@1.6.0(@types/node@20.14.12)(happy-dom@10.0.3)(jsdom@24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4))(sass@1.79.4)(terser@5.33.0):
+  vitest@1.6.0(@types/node@22.9.0)(happy-dom@10.0.3)(jsdom@24.1.1)(sass@1.79.4)(terser@5.36.0):
     dependencies:
       '@vitest/expect': 1.6.0
       '@vitest/runner': 1.6.0
@@ -23958,7 +22878,7 @@ snapshots:
       '@vitest/utils': 1.6.0
       acorn-walk: 8.3.2
       chai: 4.3.10
-      debug: 4.3.4(supports-color@5.5.0)
+      debug: 4.3.4
       execa: 8.0.1
       local-pkg: 0.5.0
       magic-string: 0.30.10
@@ -23968,13 +22888,13 @@ snapshots:
       strip-literal: 2.1.0
       tinybench: 2.6.0
       tinypool: 0.8.4
-      vite: 5.4.8(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0)
-      vite-node: 1.6.0(@types/node@20.14.12)(sass@1.79.4)(terser@5.33.0)
+      vite: 5.4.11(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0)
+      vite-node: 1.6.0(@types/node@22.9.0)(sass@1.79.4)(terser@5.36.0)
       why-is-node-running: 2.2.2
     optionalDependencies:
-      '@types/node': 20.14.12
+      '@types/node': 22.9.0
       happy-dom: 10.0.3
-      jsdom: 24.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      jsdom: 24.1.1
     transitivePeerDependencies:
       - less
       - lightningcss
@@ -24010,44 +22930,44 @@ snapshots:
 
   vscode-uri@3.0.8: {}
 
-  vue-component-meta@2.0.16(typescript@5.6.2):
+  vue-component-meta@2.0.16(typescript@5.6.3):
     dependencies:
       '@volar/typescript': 2.2.0
-      '@vue/language-core': 2.0.16(typescript@5.6.2)
+      '@vue/language-core': 2.0.16(typescript@5.6.3)
       path-browserify: 1.0.1
       vue-component-type-helpers: 2.0.16
     optionalDependencies:
-      typescript: 5.6.2
+      typescript: 5.6.3
 
   vue-component-type-helpers@1.8.4: {}
 
   vue-component-type-helpers@2.0.16: {}
 
-  vue-component-type-helpers@2.1.6: {}
+  vue-component-type-helpers@2.1.10: {}
 
-  vue-demi@0.14.7(vue@3.5.11(typescript@5.6.2)):
+  vue-demi@0.14.7(vue@3.5.12(typescript@5.6.3)):
     dependencies:
-      vue: 3.5.11(typescript@5.6.2)
+      vue: 3.5.12(typescript@5.6.3)
 
-  vue-docgen-api@4.75.1(vue@3.5.11(typescript@5.6.2)):
+  vue-docgen-api@4.75.1(vue@3.5.12(typescript@5.6.3)):
     dependencies:
       '@babel/parser': 7.25.6
       '@babel/types': 7.25.6
-      '@vue/compiler-dom': 3.5.10
-      '@vue/compiler-sfc': 3.5.11
+      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-sfc': 3.5.12
       ast-types: 0.16.1
       hash-sum: 2.0.0
       lru-cache: 8.0.4
       pug: 3.0.3
       recast: 0.23.6
       ts-map: 1.0.3
-      vue: 3.5.11(typescript@5.6.2)
-      vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.11(typescript@5.6.2))
+      vue: 3.5.12(typescript@5.6.3)
+      vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.12(typescript@5.6.3))
 
-  vue-eslint-parser@9.4.3(eslint@9.11.0):
+  vue-eslint-parser@9.4.3(eslint@9.14.0):
     dependencies:
-      debug: 4.3.5(supports-color@5.5.0)
-      eslint: 9.11.0
+      debug: 4.3.5
+      eslint: 9.14.0
       eslint-scope: 7.2.2
       eslint-visitor-keys: 3.4.3
       espree: 9.6.1
@@ -24057,46 +22977,36 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.5.11(typescript@5.6.2)):
+  vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.5.12(typescript@5.6.3)):
     dependencies:
-      vue: 3.5.11(typescript@5.6.2)
+      vue: 3.5.12(typescript@5.6.3)
 
   vue-template-compiler@2.7.14:
     dependencies:
       de-indent: 1.0.2
       he: 1.2.0
 
-  vue-tsc@2.1.6(typescript@5.6.2):
+  vue-tsc@2.1.10(typescript@5.6.3):
     dependencies:
-      '@volar/typescript': 2.4.5
-      '@vue/language-core': 2.1.6(typescript@5.6.2)
-      semver: 7.6.0
-      typescript: 5.6.2
+      '@volar/typescript': 2.4.10
+      '@vue/language-core': 2.1.10(typescript@5.6.3)
+      semver: 7.6.3
+      typescript: 5.6.3
 
-  vue@3.4.37(typescript@5.5.4):
+  vue@3.5.12(typescript@5.6.3):
     dependencies:
-      '@vue/compiler-dom': 3.4.37
-      '@vue/compiler-sfc': 3.4.37
-      '@vue/runtime-dom': 3.4.37
-      '@vue/server-renderer': 3.4.37(vue@3.4.37(typescript@5.5.4))
-      '@vue/shared': 3.4.37
+      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-sfc': 3.5.12
+      '@vue/runtime-dom': 3.5.12
+      '@vue/server-renderer': 3.5.12(vue@3.5.12(typescript@5.6.3))
+      '@vue/shared': 3.5.12
     optionalDependencies:
-      typescript: 5.5.4
+      typescript: 5.6.3
 
-  vue@3.5.11(typescript@5.6.2):
-    dependencies:
-      '@vue/compiler-dom': 3.5.11
-      '@vue/compiler-sfc': 3.5.11
-      '@vue/runtime-dom': 3.5.11
-      '@vue/server-renderer': 3.5.11(vue@3.5.11(typescript@5.6.2))
-      '@vue/shared': 3.5.11
-    optionalDependencies:
-      typescript: 5.6.2
-
-  vuedraggable@4.1.0(vue@3.5.11(typescript@5.6.2)):
+  vuedraggable@4.1.0(vue@3.5.12(typescript@5.6.3)):
     dependencies:
       sortablejs: 1.14.0
-      vue: 3.5.11(typescript@5.6.2)
+      vue: 3.5.12(typescript@5.6.3)
 
   w3c-xmlserializer@5.0.0:
     dependencies:
@@ -24351,6 +23261,8 @@ snapshots:
 
   yocto-queue@1.0.0: {}
 
+  yoctocolors-cjs@2.1.2: {}
+
   yoctocolors@2.0.2: {}
 
   zip-stream@6.0.1:
diff --git a/scripts/changelog-checker/package.json b/scripts/changelog-checker/package.json
index dccb47d037..b4d7286608 100644
--- a/scripts/changelog-checker/package.json
+++ b/scripts/changelog-checker/package.json
@@ -9,15 +9,15 @@
     "test:coverage": "vitest run --coverage"
   },
   "devDependencies": {
-    "@types/mdast": "4.0.3",
-    "@types/node": "20.10.7",
+    "@types/mdast": "4.0.4",
+    "@types/node": "22.9.0",
     "@vitest/coverage-v8": "1.1.3",
     "mdast-util-to-string": "4.0.0",
     "remark": "15.0.1",
     "remark-parse": "11.0.0",
-    "typescript": "5.3.3",
-    "unified": "11.0.4",
-    "vite": "5.4.6",
+    "typescript": "5.6.3",
+    "unified": "11.0.5",
+    "vite": "5.4.11",
     "vite-node": "1.1.3",
     "vitest": "1.1.3"
   }

From c0d168260482caa974e3fc9e084b121fc32e8ec4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 15 Nov 2024 17:30:54 +0900
Subject: [PATCH 063/125] =?UTF-8?q?feat:=20=E9=80=81=E4=BF=A1=E3=81=97?=
 =?UTF-8?q?=E3=81=9F=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC=E3=83=AA=E3=82=AF?=
 =?UTF-8?q?=E3=82=A8=E3=82=B9=E3=83=88=E3=82=92=E7=A2=BA=E8=AA=8D=E3=81=A7?=
 =?UTF-8?q?=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#14856)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* FEAT: Allow users to view pending follow requests they sent

This commit implements the `following/requests/sent` interface firstly
implemented on Firefish, and provides a UI interface to view the pending
follow requests users sent.

* ux: should not show follow requests tab when have no pending sent follow req

* fix default followreq tab

* fix default followreq tab

* restore missing hasPendingReceivedFollowRequest in navbar

* refactor

* use tabler icons

* tweak design

* Revert "ux: should not show follow requests tab when have no pending sent follow req"

This reverts commit e580b92c37f27c2849c6d27e22ca4c47086081bb.

* Update Changelog

* Update Changelog

* change tab titles

---------

Co-authored-by: Lhc_fl <lhcfl@outlook.com>
Co-authored-by: Hazelnoot <acomputerdog@gmail.com>
---
 CHANGELOG.md                                  |   2 +
 locales/index.d.ts                            |  10 ++
 locales/ja-JP.yml                             |   4 +
 .../backend/src/server/api/EndpointsModule.ts |   3 +
 packages/backend/src/server/api/endpoints.ts  |   2 +
 .../api/endpoints/following/requests/sent.ts  |  77 +++++++++++++
 .../src/components/MkFollowButton.vue         |  10 +-
 packages/frontend/src/navbar.ts               |   1 -
 .../frontend/src/pages/follow-requests.vue    | 105 ++++++++++++------
 packages/misskey-js/etc/misskey-js.api.md     |   8 ++
 .../misskey-js/src/autogen/apiClientJSDoc.ts  |  11 ++
 packages/misskey-js/src/autogen/endpoint.ts   |   3 +
 packages/misskey-js/src/autogen/entities.ts   |   2 +
 packages/misskey-js/src/autogen/types.ts      |  72 ++++++++++++
 14 files changed, 272 insertions(+), 38 deletions(-)
 create mode 100644 packages/backend/src/server/api/endpoints/following/requests/sent.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcbfed5900..232d52d7e1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,8 @@
 - Enhance: カタルーニャ語 (ca-ES) に対応
 - Enhance: 個別お知らせページではMetaタグを出力するように
 - Enhance: ノート詳細画面にロールのバッジを表示
+- Enhance: 過去に送信したフォローリクエストを確認できるように  
+  (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 440f24ac84..18fbfd15f0 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -10579,6 +10579,16 @@ export interface Locale extends ILocale {
          */
         "description3": ParameterizedString<"link">;
     };
+    "_followRequest": {
+        /**
+         * 受け取った申請
+         */
+        "recieved": string;
+        /**
+         * 送った申請
+         */
+        "sent": string;
+    };
 }
 declare const locales: {
     [lang: string]: Locale;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 5d8e1a5e72..439ae708c5 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -2819,3 +2819,7 @@ _selfXssPrevention:
   description1: "ここに何かを貼り付けると、悪意のあるユーザーにアカウントを乗っ取られたり、個人情報を盗まれたりする可能性があります。"
   description2: "貼り付けようとしているものが何なのかを正確に理解していない場合は、%c今すぐ作業を中止してこのウィンドウを閉じてください。"
   description3: "詳しくはこちらをご確認ください。 {link}"
+
+_followRequest:
+  recieved: "受け取った申請"
+  sent: "送った申請"
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index 3557fa40a5..5bb194313d 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -187,6 +187,7 @@ import * as ep___following_invalidate from './endpoints/following/invalidate.js'
 import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
 import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
 import * as ep___following_requests_list from './endpoints/following/requests/list.js';
+import * as ep___following_requests_sent from './endpoints/following/requests/sent.js';
 import * as ep___following_requests_reject from './endpoints/following/requests/reject.js';
 import * as ep___gallery_featured from './endpoints/gallery/featured.js';
 import * as ep___gallery_popular from './endpoints/gallery/popular.js';
@@ -574,6 +575,7 @@ const $following_invalidate: Provider = { provide: 'ep:following/invalidate', us
 const $following_requests_accept: Provider = { provide: 'ep:following/requests/accept', useClass: ep___following_requests_accept.default };
 const $following_requests_cancel: Provider = { provide: 'ep:following/requests/cancel', useClass: ep___following_requests_cancel.default };
 const $following_requests_list: Provider = { provide: 'ep:following/requests/list', useClass: ep___following_requests_list.default };
+const $following_requests_sent: Provider = { provide: 'ep:following/requests/sent', useClass: ep___following_requests_sent.default };
 const $following_requests_reject: Provider = { provide: 'ep:following/requests/reject', useClass: ep___following_requests_reject.default };
 const $gallery_featured: Provider = { provide: 'ep:gallery/featured', useClass: ep___gallery_featured.default };
 const $gallery_popular: Provider = { provide: 'ep:gallery/popular', useClass: ep___gallery_popular.default };
@@ -965,6 +967,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
 		$following_requests_accept,
 		$following_requests_cancel,
 		$following_requests_list,
+		$following_requests_sent,
 		$following_requests_reject,
 		$gallery_featured,
 		$gallery_popular,
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index 49b07d6ced..15809b2678 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -193,6 +193,7 @@ import * as ep___following_invalidate from './endpoints/following/invalidate.js'
 import * as ep___following_requests_accept from './endpoints/following/requests/accept.js';
 import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js';
 import * as ep___following_requests_list from './endpoints/following/requests/list.js';
+import * as ep___following_requests_sent from './endpoints/following/requests/sent.js';
 import * as ep___following_requests_reject from './endpoints/following/requests/reject.js';
 import * as ep___gallery_featured from './endpoints/gallery/featured.js';
 import * as ep___gallery_popular from './endpoints/gallery/popular.js';
@@ -578,6 +579,7 @@ const eps = [
 	['following/requests/accept', ep___following_requests_accept],
 	['following/requests/cancel', ep___following_requests_cancel],
 	['following/requests/list', ep___following_requests_list],
+	['following/requests/sent', ep___following_requests_sent],
 	['following/requests/reject', ep___following_requests_reject],
 	['gallery/featured', ep___gallery_featured],
 	['gallery/popular', ep___gallery_popular],
diff --git a/packages/backend/src/server/api/endpoints/following/requests/sent.ts b/packages/backend/src/server/api/endpoints/following/requests/sent.ts
new file mode 100644
index 0000000000..6325f01bb8
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/following/requests/sent.ts
@@ -0,0 +1,77 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { QueryService } from '@/core/QueryService.js';
+import type { FollowRequestsRepository } from '@/models/_.js';
+import { FollowRequestEntityService } from '@/core/entities/FollowRequestEntityService.js';
+import { DI } from '@/di-symbols.js';
+
+export const meta = {
+	tags: ['following', 'account'],
+
+	requireCredential: true,
+
+	kind: 'read:following',
+
+	res: {
+		type: 'array',
+		optional: false, nullable: false,
+		items: {
+			type: 'object',
+			optional: false, nullable: false,
+			properties: {
+				id: {
+					type: 'string',
+					optional: false, nullable: false,
+					format: 'id',
+				},
+				follower: {
+					type: 'object',
+					optional: false, nullable: false,
+					ref: 'UserLite',
+				},
+				followee: {
+					type: 'object',
+					optional: false, nullable: false,
+					ref: 'UserLite',
+				},
+			},
+		},
+	},
+} as const;
+
+export const paramDef = {
+	type: 'object',
+	properties: {
+		sinceId: { type: 'string', format: 'misskey:id' },
+		untilId: { type: 'string', format: 'misskey:id' },
+		limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
+	},
+	required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+	constructor(
+		@Inject(DI.followRequestsRepository)
+		private followRequestsRepository: FollowRequestsRepository,
+
+		private followRequestEntityService: FollowRequestEntityService,
+		private queryService: QueryService,
+	) {
+		super(meta, paramDef, async (ps, me) => {
+			const query = this.queryService.makePaginationQuery(this.followRequestsRepository.createQueryBuilder('request'), ps.sinceId, ps.untilId)
+				.andWhere('request.followerId = :meId', { meId: me.id });
+
+			const requests = await query
+				.limit(ps.limit)
+				.getMany();
+
+			return await this.followRequestEntityService.packMany(requests, me);
+		});
+	}
+}
diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue
index cc07175907..c1dc67f776 100644
--- a/packages/frontend/src/components/MkFollowButton.vue
+++ b/packages/frontend/src/components/MkFollowButton.vue
@@ -91,7 +91,10 @@ async function onClick() {
 				text: i18n.tsx.unfollowConfirm({ name: props.user.name || props.user.username }),
 			});
 
-			if (canceled) return;
+			if (canceled) {
+				wait.value = false;
+				return;
+			}
 
 			await misskeyApi('following/delete', {
 				userId: props.user.id,
@@ -125,7 +128,10 @@ async function onClick() {
 				});
 				hasPendingFollowRequestFromYou.value = true;
 
-				if ($i == null) return;
+				if ($i == null) {
+					wait.value = false;
+					return;
+				}
 
 				claimAchievement('following1');
 
diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts
index ac730f8021..096d404a57 100644
--- a/packages/frontend/src/navbar.ts
+++ b/packages/frontend/src/navbar.ts
@@ -40,7 +40,6 @@ export const navbarItemDef = reactive({
 	followRequests: {
 		title: i18n.ts.followRequests,
 		icon: 'ti ti-user-plus',
-		show: computed(() => $i != null && $i.isLocked),
 		indicated: computed(() => $i != null && $i.hasPendingReceivedFollowRequest),
 		to: '/my/follow-requests',
 	},
diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue
index a840d0d0b3..8688863c2c 100644
--- a/packages/frontend/src/pages/follow-requests.vue
+++ b/packages/frontend/src/pages/follow-requests.vue
@@ -5,69 +5,104 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <template>
 <MkStickyContainer>
-	<template #header><MkPageHeader/></template>
+	<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
 	<MkSpacer :contentMax="800">
-		<MkPagination ref="paginationComponent" :pagination="pagination">
-			<template #empty>
-				<div class="_fullinfo">
-					<img :src="infoImageUrl" class="_ghost"/>
-					<div>{{ i18n.ts.noFollowRequests }}</div>
-				</div>
-			</template>
-			<template #default="{items}">
-				<div class="mk-follow-requests">
-					<div v-for="req in items" :key="req.id" class="user _panel">
-						<MkAvatar class="avatar" :user="req.follower" indicator link preview/>
-						<div class="body">
-							<div class="name">
-								<MkA v-user-preview="req.follower.id" class="name" :to="userPage(req.follower)"><MkUserName :user="req.follower"/></MkA>
-								<p class="acct">@{{ acct(req.follower) }}</p>
-							</div>
-							<div class="commands">
-								<MkButton class="command" rounded primary @click="accept(req.follower)"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
-								<MkButton class="command" rounded danger @click="reject(req.follower)"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+		<MkHorizontalSwipe v-model:tab="tab" :tabs="headerTabs">
+			<div :key="tab" class="_gaps">
+				<MkPagination ref="paginationComponent" :pagination="pagination">
+					<template #empty>
+						<div class="_fullinfo">
+							<img :src="infoImageUrl" class="_ghost"/>
+							<div>{{ i18n.ts.noFollowRequests }}</div>
+						</div>
+					</template>
+					<template #default="{items}">
+						<div class="mk-follow-requests">
+							<div v-for="req in items" :key="req.id" class="user _panel">
+								<MkAvatar class="avatar" :user="displayUser(req)" indicator link preview/>
+								<div class="body">
+									<div class="name">
+										<MkA v-user-preview="displayUser(req).id" class="name" :to="userPage(displayUser(req))"><MkUserName :user="displayUser(req)"/></MkA>
+										<p class="acct">@{{ acct(displayUser(req)) }}</p>
+									</div>
+									<div v-if="tab === 'list'" class="commands">
+										<MkButton class="command" rounded primary @click="accept(displayUser(req))"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
+										<MkButton class="command" rounded danger @click="reject(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+									</div>
+									<div v-else class="commands">
+										<MkButton class="command" rounded danger @click="cancel(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.cancel }}</MkButton>
+									</div>
+								</div>
 							</div>
 						</div>
-					</div>
-				</div>
-			</template>
-		</MkPagination>
+					</template>
+				</MkPagination>
+			</div>
+		</MkHorizontalSwipe>
 	</MkSpacer>
 </MkStickyContainer>
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed } from 'vue';
-import MkPagination from '@/components/MkPagination.vue';
+import * as Misskey from 'misskey-js';
+import { shallowRef, computed, ref } from 'vue';
+import MkPagination, { type Paging } from '@/components/MkPagination.vue';
 import MkButton from '@/components/MkButton.vue';
 import { userPage, acct } from '@/filters/user.js';
-import { misskeyApi } from '@/scripts/misskey-api.js';
+import * as os from '@/os.js';
 import { i18n } from '@/i18n.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { infoImageUrl } from '@/instance.js';
+import { $i } from '@/account.js';
+import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
 
 const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
 
-const pagination = {
-	endpoint: 'following/requests/list' as const,
+const pagination = computed<Paging>(() => tab.value === 'list' ? {
+	endpoint: 'following/requests/list',
 	limit: 10,
-};
+} : {
+	endpoint: 'following/requests/sent',
+	limit: 10,
+});
 
-function accept(user) {
-	misskeyApi('following/requests/accept', { userId: user.id }).then(() => {
+function accept(user: Misskey.entities.UserLite) {
+	os.apiWithDialog('following/requests/accept', { userId: user.id }).then(() => {
 		paginationComponent.value?.reload();
 	});
 }
 
-function reject(user) {
-	misskeyApi('following/requests/reject', { userId: user.id }).then(() => {
+function reject(user: Misskey.entities.UserLite) {
+	os.apiWithDialog('following/requests/reject', { userId: user.id }).then(() => {
 		paginationComponent.value?.reload();
 	});
 }
 
+function cancel(user: Misskey.entities.UserLite) {
+	os.apiWithDialog('following/requests/cancel', { userId: user.id }).then(() => {
+		paginationComponent.value?.reload();
+	});
+}
+
+function displayUser(req) {
+	return tab.value === 'list' ? req.follower : req.followee;
+}
+
 const headerActions = computed(() => []);
 
-const headerTabs = computed(() => []);
+const headerTabs = computed(() => [
+	{
+		key: 'list',
+		title: i18n.ts._followRequest.recieved,
+		icon: 'ti ti-mail',
+	}, {
+		key: 'sent',
+		title: i18n.ts._followRequest.sent,
+		icon: 'ti ti-send',
+	},
+]);
+
+const tab = ref($i?.isLocked ? 'list' : 'sent');
 
 definePageMetadata(() => ({
 	title: i18n.ts.followRequests,
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index 061b533b72..01a3dbbb30 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -1504,6 +1504,8 @@ declare namespace entities {
         FollowingRequestsCancelResponse,
         FollowingRequestsListRequest,
         FollowingRequestsListResponse,
+        FollowingRequestsSentRequest,
+        FollowingRequestsSentResponse,
         FollowingRequestsRejectRequest,
         GalleryFeaturedRequest,
         GalleryFeaturedResponse,
@@ -2018,6 +2020,12 @@ type FollowingRequestsListResponse = operations['following___requests___list']['
 // @public (undocumented)
 type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json'];
 
+// @public (undocumented)
+type FollowingRequestsSentRequest = operations['following___requests___sent']['requestBody']['content']['application/json'];
+
+// @public (undocumented)
+type FollowingRequestsSentResponse = operations['following___requests___sent']['responses']['200']['content']['application/json'];
+
 // @public (undocumented)
 type FollowingUpdateAllRequest = operations['following___update-all']['requestBody']['content']['application/json'];
 
diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
index e2c7cbba52..1837f3db4f 100644
--- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts
+++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts
@@ -2008,6 +2008,17 @@ declare module '../api.js' {
       credential?: string | null,
     ): Promise<SwitchCaseResponseType<E, P>>;
 
+    /**
+     * No description provided.
+     * 
+     * **Credential required**: *Yes* / **Permission**: *read:following*
+     */
+    request<E extends 'following/requests/sent', P extends Endpoints[E]['req']>(
+      endpoint: E,
+      params: P,
+      credential?: string | null,
+    ): Promise<SwitchCaseResponseType<E, P>>;
+
     /**
      * No description provided.
      * 
diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts
index 5e6bc0a99c..cb1f4dbe96 100644
--- a/packages/misskey-js/src/autogen/endpoint.ts
+++ b/packages/misskey-js/src/autogen/endpoint.ts
@@ -279,6 +279,8 @@ import type {
 	FollowingRequestsCancelResponse,
 	FollowingRequestsListRequest,
 	FollowingRequestsListResponse,
+	FollowingRequestsSentRequest,
+	FollowingRequestsSentResponse,
 	FollowingRequestsRejectRequest,
 	GalleryFeaturedRequest,
 	GalleryFeaturedResponse,
@@ -761,6 +763,7 @@ export type Endpoints = {
 	'following/requests/accept': { req: FollowingRequestsAcceptRequest; res: EmptyResponse };
 	'following/requests/cancel': { req: FollowingRequestsCancelRequest; res: FollowingRequestsCancelResponse };
 	'following/requests/list': { req: FollowingRequestsListRequest; res: FollowingRequestsListResponse };
+	'following/requests/sent': { req: FollowingRequestsSentRequest; res: FollowingRequestsSentResponse };
 	'following/requests/reject': { req: FollowingRequestsRejectRequest; res: EmptyResponse };
 	'gallery/featured': { req: GalleryFeaturedRequest; res: GalleryFeaturedResponse };
 	'gallery/popular': { req: EmptyRequest; res: GalleryPopularResponse };
diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts
index f3ddf64481..a8f474c25c 100644
--- a/packages/misskey-js/src/autogen/entities.ts
+++ b/packages/misskey-js/src/autogen/entities.ts
@@ -282,6 +282,8 @@ export type FollowingRequestsCancelRequest = operations['following___requests___
 export type FollowingRequestsCancelResponse = operations['following___requests___cancel']['responses']['200']['content']['application/json'];
 export type FollowingRequestsListRequest = operations['following___requests___list']['requestBody']['content']['application/json'];
 export type FollowingRequestsListResponse = operations['following___requests___list']['responses']['200']['content']['application/json'];
+export type FollowingRequestsSentRequest = operations['following___requests___sent']['requestBody']['content']['application/json'];
+export type FollowingRequestsSentResponse = operations['following___requests___sent']['responses']['200']['content']['application/json'];
 export type FollowingRequestsRejectRequest = operations['following___requests___reject']['requestBody']['content']['application/json'];
 export type GalleryFeaturedRequest = operations['gallery___featured']['requestBody']['content']['application/json'];
 export type GalleryFeaturedResponse = operations['gallery___featured']['responses']['200']['content']['application/json'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index a5333d4f93..280abba727 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -1753,6 +1753,15 @@ export type paths = {
      */
     post: operations['following___requests___list'];
   };
+  '/following/requests/sent': {
+    /**
+     * following/requests/sent
+     * @description No description provided.
+     *
+     * **Credential required**: *Yes* / **Permission**: *read:following*
+     */
+    post: operations['following___requests___sent'];
+  };
   '/following/requests/reject': {
     /**
      * following/requests/reject
@@ -16040,6 +16049,69 @@ export type operations = {
       };
     };
   };
+  /**
+   * following/requests/sent
+   * @description No description provided.
+   *
+   * **Credential required**: *Yes* / **Permission**: *read:following*
+   */
+  following___requests___sent: {
+    requestBody: {
+      content: {
+        'application/json': {
+          /** Format: misskey:id */
+          sinceId?: string;
+          /** Format: misskey:id */
+          untilId?: string;
+          /** @default 10 */
+          limit?: number;
+        };
+      };
+    };
+    responses: {
+      /** @description OK (with results) */
+      200: {
+        content: {
+          'application/json': {
+              /** Format: id */
+              id: string;
+              follower: components['schemas']['UserLite'];
+              followee: components['schemas']['UserLite'];
+            }[];
+        };
+      };
+      /** @description Client error */
+      400: {
+        content: {
+          'application/json': components['schemas']['Error'];
+        };
+      };
+      /** @description Authentication error */
+      401: {
+        content: {
+          'application/json': components['schemas']['Error'];
+        };
+      };
+      /** @description Forbidden error */
+      403: {
+        content: {
+          'application/json': components['schemas']['Error'];
+        };
+      };
+      /** @description I'm Ai */
+      418: {
+        content: {
+          'application/json': components['schemas']['Error'];
+        };
+      };
+      /** @description Internal server error */
+      500: {
+        content: {
+          'application/json': components['schemas']['Error'];
+        };
+      };
+    };
+  };
   /**
    * following/requests/reject
    * @description No description provided.

From e850462b826b79acd0b0c9fe2629f462fca3ecec Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 15 Nov 2024 17:31:38 +0900
Subject: [PATCH 064/125] New Crowdin updates (#14859)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Simplified)
---
 locales/ca-ES.yml | 173 +++++++++++++++++++++++-----------------------
 locales/de-DE.yml |  40 +++++++++++
 locales/en-US.yml |  10 ++-
 locales/ko-KR.yml |  32 ++++++++-
 locales/sv-SE.yml | 106 ++++++++++++++++++++++++++++
 locales/vi-VN.yml |   3 +
 locales/zh-CN.yml |  33 ++++-----
 locales/zh-TW.yml |   5 +-
 8 files changed, 295 insertions(+), 107 deletions(-)

diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index 748f6f03c0..048abfd781 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -8,37 +8,37 @@ search: "Cercar"
 notifications: "Notificacions"
 username: "Nom d'usuari"
 password: "Contrasenya"
-initialPasswordForSetup: "Contrasenya inicial per la configuració inicial"
+initialPasswordForSetup: "Contrasenya inicial per fer la primera configuració "
 initialPasswordIsIncorrect: "La contrasenya no és correcta."
 initialPasswordForSetupDescription: "Fes servir la contrasenya que has fet servir al fitxer de configuració, si tu mateix has instal·lat Misskey.\nSi fas servir una empresa d'allotjament de Misskey, fes servir la contrasenya que t'han donat.\nSi no has posat cap contrasenya deixar l'espai en blanc."
-forgotPassword: "Contrasenya oblidada"
-fetchingAsApObject: "Cercant en el Fediverse..."
+forgotPassword: "Restableix la contrasenya "
+fetchingAsApObject: "Cercant al Fediverse..."
 ok: "OK"
-gotIt: "Ho he entès!"
+gotIt: "D'acord "
 cancel: "Cancel·lar"
 noThankYou: "No, gràcies"
 enterUsername: "Introdueix el teu nom d'usuari"
 renotedBy: "Impulsat per {user}"
 noNotes: "Cap nota"
 noNotifications: "Cap notificació"
-instance: "Servidor"
+instance: "Instància "
 settings: "Preferències"
-notificationSettings: "Paràmetres de notificacions"
+notificationSettings: "Configurar les notificacions"
 basicSettings: "Configuració bàsica"
-otherSettings: "Configuració avançada"
-openInWindow: "Obrir en una nova finestra"
+otherSettings: "Altres configuracions"
+openInWindow: "Obrir en una finestra nova"
 profile: "Perfil"
 timeline: "Línia de temps"
 noAccountDescription: "Aquest usuari encara no ha escrit la seva biografia."
 login: "Iniciar sessió"
-loggingIn: "Identificant-se"
+loggingIn: "Iniciar la sessió "
 logout: "Tancar la sessió"
 signup: "Registrar-se"
 uploading: "Pujant..."
 save: "Desa"
 users: "Usuaris"
 addUser: "Afegir un usuari"
-favorite: "Afegir a preferits"
+favorite: "Afegeix als preferits"
 favorites: "Favorits"
 unfavorite: "Eliminar dels preferits"
 favorited: "Afegit als preferits."
@@ -50,26 +50,26 @@ copyContent: "Copiar el contingut"
 copyLink: "Copiar l'enllaç"
 copyLinkRenote: "Copiar l'enllaç de la renota"
 delete: "Elimina"
-deleteAndEdit: "Elimina i edita"
+deleteAndEdit: "Eliminar i editar"
 deleteAndEditConfirm: "Segur que vols eliminar aquesta publicació i editar-la? Perdràs totes les reaccions, impulsos i respostes."
 addToList: "Afegir a una llista"
-addToAntenna: "Afegir a l'antena"
+addToAntenna: "Afegir a una antena"
 sendMessage: "Enviar un missatge"
 copyRSS: "Copiar RSS"
 copyUsername: "Copiar nom d'usuari"
 copyUserId: "Copiar ID d'usuari"
-copyNoteId: "Copiar ID de nota"
-copyFileId: "Copiar ID d'arxiu"
-copyFolderId: "Copiar ID de carpeta"
-copyProfileUrl: "Copiar URL del perfil"
+copyNoteId: "Copiar ID de la nota"
+copyFileId: "Copiar ID de l'arxiu"
+copyFolderId: "Copiar ID de la carpeta"
+copyProfileUrl: "Copiar adreça URL del perfil"
 searchUser: "Cercar un usuari"
-searchThisUsersNotes: "Cerca les publicacions de l'usuari"
-reply: "Respondre"
+searchThisUsersNotes: "Cercar les publicacions de l'usuari"
+reply: "Respon"
 loadMore: "Carregar més"
 showMore: "Veure més"
-showLess: "Mostra menys"
+showLess: "Mostrar menys"
 youGotNewFollower: "t'ha seguit"
-receiveFollowRequest: "Sol·licitud de seguiment rebuda"
+receiveFollowRequest: "Has rebut una sol·licitud de seguiment"
 followRequestAccepted: "Sol·licitud de seguiment acceptada"
 mention: "Menció"
 mentions: "Mencions"
@@ -78,25 +78,25 @@ importAndExport: "Importar / Exportar"
 import: "Importar"
 export: "Exporta"
 files: "Fitxers"
-download: "Baixar"
-driveFileDeleteConfirm: "Estàs segur que vols suprimir el fitxer \"{name}\"? Les notes associades a aquest fitxer adjunt també se suprimiran."
-unfollowConfirm: "Estàs segur que vols deixar de seguir {name}?"
-exportRequested: "Has sol·licitat una exportació. Això pot trigar una estona. S'afegirà a la teva unitat un cop completat."
-importRequested: "Has sol·licitat una importació. Això pot trigar una estona."
+download: "Descarregar"
+driveFileDeleteConfirm: "Estàs segur que vols suprimir el fitxer \"{name}\"? Les notes associades a aquest fitxer també seran esborrades."
+unfollowConfirm: "Segur que vols deixar de seguir a {name}?"
+exportRequested: "Has sol·licitat una exportació de dades. Això pot trigar una estona. S'afegirà a la teva unitat de disc un cop estigui completada."
+importRequested: "Has sol·licitat una importació de dades. Això pot trigar una estona."
 lists: "Llistes"
 noLists: "No tens cap llista"
 note: "Nota"
 notes: "Notes"
-following: "Seguint"
+following: "Segueixes "
 followers: "Seguidors"
 followsYou: "Et segueix"
 createList: "Crear llista"
 manageLists: "Gestionar les llistes"
 error: "Error"
 somethingHappened: "S'ha produït un error"
-retry: "Torna-ho a intentar"
+retry: "Torna-ho a provar"
 pageLoadError: "S'ha produït un error en carregar la pàgina"
-pageLoadErrorDescription: "Això normalment es deu a errors de xarxa o a la memòria cau del navegador. Prova d'esborrar la memòria cau i torna-ho a provar després d'esperar una estona."
+pageLoadErrorDescription: "Això normalment és a causa d'errors a la xarxa o a la memòria cau del navegador. Prova d'esborrar la memòria cau i torna-ho a provar després d'esperar un temps."
 serverIsDead: "Aquest servidor no respon. Espera una estona i torna-ho a provar."
 youShouldUpgradeClient: "Per veure aquesta pàgina, actualitzeu-la per actualitzar el vostre client."
 enterListName: "Introdueix un nom per a la llista"
@@ -104,52 +104,52 @@ privacy: "Privadesa"
 makeFollowManuallyApprove: "Les sol·licituds de seguiment requereixen aprovació"
 defaultNoteVisibility: "Visibilitat per defecte"
 follow: "Seguint"
-followRequest: "Enviar la sol·licitud de seguiment"
+followRequest: "Enviar sol·licitud de seguiment"
 followRequests: "Sol·licituds de seguiment"
 unfollow: "Deixar de seguir"
 followRequestPending: "Sol·licituds de seguiment pendents"
 enterEmoji: "Introduir un emoji"
-renote: "Impulsa"
+renote: "Impulsar "
 unrenote: "Anul·la l'impuls"
 renoted: "S'ha impulsat"
 renotedToX: "Impulsat per {name}."
 cantRenote: "No es pot impulsar aquesta publicació"
-cantReRenote: "No es pot impulsar l'impuls."
+cantReRenote: "No es pot impulsar un impuls."
 quote: "Cita"
-inChannelRenote: "Renotar només al Canal"
-inChannelQuote: "Citar només al Canal"
-renoteToChannel: "Impulsa a un canal"
-renoteToOtherChannel: "Impulsa a un altre canal"
+inChannelRenote: "Impulsar només a un canal"
+inChannelQuote: "Citar només a un canal"
+renoteToChannel: "Impulsar a un canal"
+renoteToOtherChannel: "Impulsar a un altre canal"
 pinnedNote: "Nota fixada"
 pinned: "Fixar al perfil"
 you: "Tu"
 clickToShow: "Fes clic per mostrar"
-sensitive: "NSFW"
+sensitive: "Sensible"
 add: "Afegir"
-reaction: "Reaccions"
+reaction: "Reacció "
 reactions: "Reaccions"
-emojiPicker: "Selecció d'emojis"
-pinnedEmojisForReactionSettingDescription: "Selecciona l'emoji amb el qual reaccionar"
-pinnedEmojisSettingDescription: "Selecciona l'emoji amb el qual reaccionar"
-emojiPickerDisplay: "Visualitza el selector d'emojis"
+emojiPicker: "Selector d'emojis"
+pinnedEmojisForReactionSettingDescription: "Selecciona l'emoji amb qui vols reaccionar"
+pinnedEmojisSettingDescription: "Selecciona quins emojis vols deixar fixats i es mostrin en obrir el selector d'emojis"
+emojiPickerDisplay: "Mostrar el selector d'emojis"
 overwriteFromPinnedEmojisForReaction: "Reemplaça els emojis de la reacció"
-overwriteFromPinnedEmojis: "Sobreescriu des dels emojis fixats"
+overwriteFromPinnedEmojis: "Sobreescriu els emojis fixats al panel de reaccions"
 reactionSettingDescription2: "Arrossega per reordenar, fes clic per suprimir, prem \"+\" per afegir."
 rememberNoteVisibility: "Recorda la configuració de visibilitat de les notes"
 attachCancel: "Eliminar el fitxer adjunt"
 deleteFile: "Esborrar l'arxiu "
-markAsSensitive: "Marcar com a NSFW"
+markAsSensitive: "Marcar com a sensible"
 unmarkAsSensitive: "Deixar de marcar com a sensible"
 enterFileName: "Defineix nom del fitxer"
 mute: "Silencia"
 unmute: "Deixa de silenciar"
-renoteMute: "Silenciar Renotes"
-renoteUnmute: "Treure el silenci de les renotes"
+renoteMute: "Silenciar impulsos"
+renoteUnmute: "Treure el silenci dels impulsos"
 block: "Bloqueja"
 unblock: "Desbloqueja"
 suspend: "Suspèn"
 unsuspend: "Deixa de suspendre"
-blockConfirm: "Vols bloquejar?"
+blockConfirm: "Vols bloquejar-lo?"
 unblockConfirm: "Vols desbloquejar-lo?"
 suspendConfirm: "Estàs segur que vols suspendre aquest compte?"
 unsuspendConfirm: "Estàs segur que vols treure la suspensió d'aquest compte?"
@@ -175,11 +175,11 @@ youCanCleanRemoteFilesCache: "Pots netejar la memòria cau fent clic al botó de
 cacheRemoteSensitiveFiles: "Posar a la memòria cau arxius remots sensibles"
 cacheRemoteSensitiveFilesDescription: "Quan aquesta opció és desactiva, els arxius remots sensibles es carregant directament del servidor d'origen sense que es guardin a la memòria cau."
 flagAsBot: "Marca aquest compte com a bot"
-flagAsBotDescription: "Marca aquest compte com a bot"
+flagAsBotDescription: "Activa aquesta opció si el compte el controla un programa. Si s'activa, actuarà com un senyal per altres desenvolupadors per prevenir cadenes d'interacció sense fi i ajustar els paràmetres interns de Misskey pe tractar el compte com un bot."
 flagAsCat: "Marca aquest compte com a gat"
 flagAsCatDescription: "Activeu aquesta opció per marcar aquest compte com a gat."
 flagShowTimelineReplies: "Mostra les respostes a la línia de temps"
-flagShowTimelineRepliesDescription: "Mostra les respostes a la línia de temps"
+flagShowTimelineRepliesDescription: "Mostra les respostes dels usuaris a les notes d'altres usuaris a la línia de temps."
 autoAcceptFollowed: "Aprova automàticament les sol·licituds de seguiment dels usuaris que segueixes"
 addAccount: "Afegeix un compte"
 reloadAccountsList: "Recarregar la llista de contactes"
@@ -204,7 +204,7 @@ selectUser: "Selecciona usuari/a"
 recipient: "Destinatari"
 annotation: "Comentaris"
 federation: "Federació"
-instances: "Servidors"
+instances: "Instàncies "
 registeredAt: "Registrat a"
 latestRequestReceivedAt: "Última petició rebuda"
 latestStatus: "Últim estat"
@@ -213,7 +213,7 @@ charts: "Gràfics"
 perHour: "Per hora"
 perDay: "Per dia"
 stopActivityDelivery: "Deixa d'enviar activitats"
-blockThisInstance: "Deixa d'enviar activitats"
+blockThisInstance: "Bloca aquesta instància "
 silenceThisInstance: "Silencia aquesta instància "
 mediaSilenceThisInstance: "Silenciar els arxius d'aquesta instància "
 operations: "Accions"
@@ -228,7 +228,7 @@ network: "Xarxa"
 disk: "Disc"
 instanceInfo: "Informació del fitxer d'instal·lació"
 statistics: "Estadístiques"
-clearQueue: "Esborrar la cua"
+clearQueue: "Esborra la cua de feina"
 clearQueueConfirmTitle: "Esteu segur que voleu esborrar la cua?"
 clearQueueConfirmText: "Les notes no lliurades que quedin a la cua no es federaran. Normalment aquesta operació no és necessària."
 clearCachedFiles: "Esborra la memòria cau"
@@ -254,7 +254,7 @@ processing: "S'està processant..."
 preview: "Vista prèvia"
 default: "Per defecte"
 defaultValueIs: "Per defecte: {value}"
-noCustomEmojis: "Cap emoji personalitzat"
+noCustomEmojis: "No hi ha emojis personalitzats"
 noJobs: "No hi ha feines"
 federating: "Federant"
 blocked: "Bloquejat"
@@ -268,11 +268,11 @@ instanceFollowers: "Seguidors del servidor"
 instanceUsers: "Usuaris del servidor"
 changePassword: "Canvia la contrasenya"
 security: "Seguretat"
-retypedNotMatch: "L'entrada no coincideix"
+retypedNotMatch: "Les entrades no coincideix"
 currentPassword: "Contrasenya actual"
 newPassword: "Contrasenya nova"
-newPasswordRetype: "Contrasenya nou (repeteix-la)"
-attachFile: "Adjunta fitxers"
+newPasswordRetype: "Contrasenya nova (repeteix-la)"
+attachFile: "Afegeix un arxiu"
 more: "Més"
 featured: "Destacat"
 usernameOrUserId: "Nom o ID d'usuari"
@@ -282,25 +282,25 @@ announcements: "Anuncis"
 imageUrl: "URL de la imatge"
 remove: "Eliminar"
 removed: "Eliminat"
-removeAreYouSure: "Segur que voleu retirar «{x}»?"
-deleteAreYouSure: "Segur que voleu retirar «{x}»?"
-resetAreYouSure: "Segur que voleu restablir-ho?"
-areYouSure: "Està segur?"
+removeAreYouSure: "Segur que vols esborrar «{x}»?"
+deleteAreYouSure: "Segur que vols esborrar «{x}»?"
+resetAreYouSure: "Segur que vols restablir-ho?"
+areYouSure: "Estàs segur?"
 saved: "S'ha desat"
 messaging: "Xat"
 upload: "Puja"
 keepOriginalUploading: "Guarda la imatge original"
-keepOriginalUploadingDescription: "Guarda la imatge pujada com hi és. Si està apagat, una versió per a la visualització a la xarxa serà generada quan sigui pujada."
-fromDrive: "Des de la unitat"
+keepOriginalUploadingDescription: "Guarda la imatge pujada sense modificar. Si està desactivat, es generarà una versió per visualitzar a la web en pujar la imatge."
+fromDrive: "Des del Disc"
 fromUrl: "Des d'un enllaç"
 uploadFromUrl: "Carrega des d'un enllaç"
 uploadFromUrlDescription: "Enllaç del fitxer que vols carregar"
 uploadFromUrlRequested: "Càrrega sol·licitada"
-uploadFromUrlMayTakeTime: "La càrrega des de l'enllaç pot prendre un temps"
+uploadFromUrlMayTakeTime: "La càrrega des de l'enllaç pot trigar un temps"
 explore: "Explora"
 messageRead: "Vist"
-noMoreHistory: "No hi resta més per veure"
-startMessaging: "Començar a xatejar"
+noMoreHistory: "No hi ha res més per veure"
+startMessaging: "Comença a xatejar"
 nUsersRead: "Vist per {n}"
 agreeTo: "Accepto que {0}"
 agree: "Hi estic d'acord"
@@ -312,7 +312,7 @@ home: "Inici"
 remoteUserCaution: "Ja que aquest usuari resideix a una instància remota, la informació mostrada es podria trobar incompleta."
 activity: "Activitat"
 images: "Imatges"
-image: "Imatges"
+image: "Imatge"
 birthday: "Aniversari"
 yearsOld: "{age} anys"
 registeredDate: "Data de registre"
@@ -327,10 +327,10 @@ darkThemes: "Temes foscos"
 syncDeviceDarkMode: "Sincronitza el mode fosc amb la configuració del dispositiu"
 drive: "Unitat"
 fileName: "Nom del Fitxer"
-selectFile: "Selecciona fitxers"
+selectFile: "Selecciona un fitxer"
 selectFiles: "Selecciona fitxers"
 selectFolder: "Selecció de carpeta"
-selectFolders: "Selecció de carpeta"
+selectFolders: "Selecció de carpetes"
 fileNotSelected: "Cap fitxer seleccionat"
 renameFile: "Canvia el nom del fitxer"
 folderName: "Nom de la carpeta"
@@ -359,9 +359,9 @@ reload: "Actualitza"
 doNothing: "Ignora"
 reloadConfirm: "Vols recarregar?"
 watch: "Veure"
-unwatch: "Deixar de veure"
+unwatch: "Deixa de veure"
 accept: "Acceptar"
-reject: "Denegar"
+reject: "Denega"
 normal: "Normal"
 instanceName: "Nom del servidor"
 instanceDescription: "Descripció del servidor"
@@ -382,7 +382,7 @@ enableLocalTimeline: "Activa la línia de temps local"
 enableGlobalTimeline: "Activa la línia de temps global"
 disablingTimelinesInfo: "Fins i tot si aquestes línies de temps són desactivades, els administradors i els moderadors poden continuar visualitzant per conveniència."
 registration: "Registre"
-enableRegistration: "Permet els registres d'usuaris"
+enableRegistration: "Permet el registre de nous usuaris"
 invite: "Convida"
 driveCapacityPerLocalAccount: "Capacitat del disc per usuaris locals"
 driveCapacityPerRemoteAccount: "Capacitat del disc per usuaris remots"
@@ -393,20 +393,20 @@ basicInfo: "Informació bàsica"
 pinnedUsers: "Usuaris fixats"
 pinnedUsersDescription: "Llista d'usuaris, separats per salts de línia, que seran fixats a la pestanya \"Explorar\"."
 pinnedPages: "Pàgines fixades"
-pinnedPagesDescription: "Escriu els camins de les pàgines que vols fixar a la pàgina d'inici d'aquesta instància. Separades per salts de línia."
+pinnedPagesDescription: "Escriu les adreces de les pàgines que vols fixar a la pàgina d'inici d'aquesta instància. Separades per salts de línia."
 pinnedClipId: "ID del retall fixat"
 pinnedNotes: "Nota fixada"
 hcaptcha: "hCaptcha"
-enableHcaptcha: "Activar hCaptcha"
+enableHcaptcha: "Activa hCaptcha"
 hcaptchaSiteKey: "Clau del lloc"
 hcaptchaSecretKey: "Clau secreta"
 mcaptcha: "mCaptcha"
-enableMcaptcha: "Activar mCaptcha"
+enableMcaptcha: "Activa mCaptcha"
 mcaptchaSiteKey: "Clau del lloc"
 mcaptchaSecretKey: "Clau secreta"
 mcaptchaInstanceUrl: "Adreça URL del servidor mCaptcha"
 recaptcha: "reCAPTCHA"
-enableRecaptcha: "Activar reCAPTCHA"
+enableRecaptcha: "Activa reCAPTCHA"
 recaptchaSiteKey: "Clau del lloc"
 recaptchaSecretKey: "Clau secreta"
 turnstile: "Turnstile"
@@ -448,14 +448,14 @@ aboutMisskey: "Quant a Misskey"
 administrator: "Administrador/a"
 token: "Codi de verificació"
 2fa: "Autenticació de doble factor"
-setupOf2fa: "Configurar l'autenticació de doble factor"
+setupOf2fa: "Configura l'autenticació de doble factor"
 totp: "Aplicació d'autenticació"
 totpDescription: "Escriu una contrasenya d'un sol us fent servir l'aplicació d'autenticació"
 moderator: "Moderador/a"
 moderation: "Moderació"
 moderationNote: "Nota de moderació "
 moderationNoteDescription: "Pots escriure notes que es compartiran entre els moderadors."
-addModerationNote: "Afegir una nota de moderació "
+addModerationNote: "Afegeix una nota de moderació "
 moderationLogs: "Registre de moderació "
 nUsersMentioned: "{n} usuaris mencionats"
 securityKeyAndPasskey: "Clau de seguretat / Clau de pas"
@@ -471,13 +471,13 @@ reduceUiAnimation: "Redueix les animacions de la interfície"
 share: "Comparteix"
 notFound: "No s'ha trobat"
 notFoundDescription: "No es troba cap pàgina que correspongui a aquesta adreça"
-uploadFolder: "Carpeta per defecte per pujades"
+uploadFolder: "Carpeta per defecte on desar els arxius pujats"
 markAsReadAllNotifications: "Marca totes les notificacions com a llegides"
 markAsReadAllUnreadNotes: "Marca-ho tot com a llegit"
 markAsReadAllTalkMessages: "Marcar tots els missatges com llegits"
 help: "Ajuda"
 inputMessageHere: "Escriu aquí el teu missatge "
-close: "Tancar"
+close: "Tanca"
 invites: "Convida"
 members: "Membres"
 transfer: "Transferir"
@@ -508,7 +508,7 @@ normalPassword: "Bona contrasenya"
 strongPassword: "Contrasenya segura"
 passwordMatched: "Correcte!"
 passwordNotMatched: "No coincideix"
-signinWith: "Inicia sessió amb amb {x}"
+signinWith: "Inicia sessió amb {x}"
 signinFailed: "Autenticació sense èxit. Intenta-ho un altre cop utilitzant la contrasenya i el nom correctes."
 or: "O"
 language: "Idioma"
@@ -591,7 +591,7 @@ chooseEmoji: "Tria un emoji"
 unableToProcess: "L'operació no pot ser completada "
 recentUsed: "Utilitzat recentment"
 install: "Instal·lació "
-uninstall: "Desinstal·lar "
+uninstall: "Desinstal·la"
 installedApps: "Aplicacions autoritzades "
 nothing: "No hi ha res per veure aquí "
 installedDate: "Data d'instal·lació"
@@ -608,13 +608,13 @@ output: "Sortida"
 script: "Script"
 disablePagesScript: "Desactivar AiScript a les pàgines "
 updateRemoteUser: "Actualitzar la informació de l'usuari remot"
-unsetUserAvatar: "Desactivar l'avatar "
+unsetUserAvatar: "Desactiva l'avatar "
 unsetUserAvatarConfirm: "Segur que vols desactivar l'avatar?"
-unsetUserBanner: "Desactivar el bàner "
+unsetUserBanner: "Desactiva el bàner "
 unsetUserBannerConfirm: "Segur que vols desactivar el bàner?"
-deleteAllFiles: "Esborrar tots els arxius"
+deleteAllFiles: "Esborra tots els arxius"
 deleteAllFilesConfirm: "Segur que vols esborrar tots els arxius?"
-removeAllFollowing: "Deixar de seguir tots els usuaris seguits"
+removeAllFollowing: "Deixa de seguir tots els usuaris seguits"
 removeAllFollowingDescription: "El fet d'executar això, et farà deixar de seguir a tots els usuaris de {host}. Si us plau, executa això si l'amfitrió, per exemple, ja no existeix."
 userSuspended: "Aquest usuari ha sigut suspès"
 userSilenced: "Aquest usuari està sent silenciat"
@@ -1183,8 +1183,8 @@ currentAnnouncements: "Informes actuals"
 pastAnnouncements: "Informes passats"
 youHaveUnreadAnnouncements: "Tens informes per llegir."
 useSecurityKey: "Segueix les instruccions del teu navegador O dispositiu per fer servir el teu passkey."
-replies: "Respondre"
-renotes: "Impulsa"
+replies: "Respon"
+renotes: "Impulsar "
 loadReplies: "Mostrar les respostes"
 loadConversation: "Mostrar la conversació "
 pinnedList: "Llista fixada"
@@ -1299,6 +1299,7 @@ yourNameContainsProhibitedWordsDescription: "Si de veritat vols fer servir aques
 thisContentsAreMarkedAsSigninRequiredByAuthor: "L'autor requereix l'inici de sessió per poder veure"
 lockdown: "Bloquejat"
 pleaseSelectAccount: "Seleccionar un compte"
+availableRoles: "Roles disponibles "
 _accountSettings:
   requireSigninToViewContents: "És obligatori l'inici de sessió per poder veure el contingut"
   requireSigninToViewContentsDescription1: "Es requereix l'inici de sessió per poder veure totes les notes i el contingut que has creat. Amb això esperem evitar que els rastrejadors recopilin informació."
diff --git a/locales/de-DE.yml b/locales/de-DE.yml
index 4e2bd06934..1aacbabbba 100644
--- a/locales/de-DE.yml
+++ b/locales/de-DE.yml
@@ -8,6 +8,8 @@ search: "Suchen"
 notifications: "Benachrichtigungen"
 username: "Benutzername"
 password: "Passwort"
+initialPasswordForSetup: "Initiales Passwort für die Einrichtung"
+initialPasswordIsIncorrect: "Das initiale Passwort für die Einrichtung ist falsch"
 forgotPassword: "Passwort vergessen"
 fetchingAsApObject: "Wird aus dem Fediverse angefragt …"
 ok: "OK"
@@ -60,6 +62,7 @@ copyFileId: "Datei-ID kopieren"
 copyFolderId: "Ordner-ID kopieren"
 copyProfileUrl: "Profil-URL kopieren"
 searchUser: "Nach einem Benutzer suchen"
+searchThisUsersNotes: "Notizen dieses Benutzers suchen"
 reply: "Antworten"
 loadMore: "Mehr laden"
 showMore: "Mehr anzeigen"
@@ -150,6 +153,7 @@ editList: "Liste bearbeiten"
 selectChannel: "Kanal auswählen"
 selectAntenna: "Antenne auswählen"
 editAntenna: "Antenne bearbeiten"
+createAntenna: "Erstelle eine Antenne"
 selectWidget: "Widget auswählen"
 editWidgets: "Widgets bearbeiten"
 editWidgetsExit: "Fertig"
@@ -186,6 +190,7 @@ followConfirm: "Möchtest du {name} wirklich folgen?"
 proxyAccount: "Proxy-Benutzerkonto"
 proxyAccountDescription: "Ein Proxy-Konto ist ein Benutzerkonto, das unter bestimmten Bedingungen als Follower für Benutzer fremder Instanzen fungiert. Wenn zum Beispiel ein Benutzer einen Benutzer einer fremden Instanz zu einer Liste hinzufügt, werden die Aktivitäten des entfernten Benutzers nicht an die Instanz übermittelt, wenn kein lokaler Benutzer diesem Benutzer folgt; stattdessen folgt das Proxy-Konto."
 host: "Hostname"
+selectSelf: "Mich auswählen"
 selectUser: "Benutzer auswählen"
 recipient: "Empfänger"
 annotation: "Anmerkung"
@@ -312,6 +317,7 @@ selectFile: "Datei auswählen"
 selectFiles: "Dateien auswählen"
 selectFolder: "Ordner auswählen"
 selectFolders: "Ordner auswählen"
+fileNotSelected: "Keine Datei ausgewählt"
 renameFile: "Datei umbenennen"
 folderName: "Ordnername"
 createFolder: "Ordner erstellen"
@@ -399,6 +405,7 @@ name: "Name"
 antennaSource: "Antennenquelle"
 antennaKeywords: "Zu beobachtende Schlüsselwörter"
 antennaExcludeKeywords: "Zu ignorierende Schlüsselwörter"
+antennaExcludeBots: "Bot-Accounts ausschließen"
 antennaKeywordsDescription: "Zum Nutzen einer \"UND\"-Verknüpfung Einträge mit Leerzeichen trennen, zum Nutzen einer \"ODER\"-Verknüpfung Einträge mit einem Zeilenumbruch trennen"
 notifyAntenna: "Über neue Notizen benachrichtigen"
 withFileAntenna: "Nur Notizen mit Dateien"
@@ -885,6 +892,7 @@ unmuteThread: "Threadstummschaltung aufheben"
 continueThread: "Weiteren Threadverlauf anzeigen"
 deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?"
 incorrectPassword: "Falsches Passwort."
+incorrectTotp: "Das Einmalpasswort ist falsch oder abgelaufen."
 voteConfirm: "Wirklich für „{choice}“ abstimmen?"
 hide: "Inhalt verbergen"
 useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen"
@@ -909,6 +917,9 @@ oneHour: "Eine Stunde"
 oneDay: "Einen Tag"
 oneWeek: "Eine Woche"
 oneMonth: "1 Monat"
+threeMonths: "3 Monate"
+oneYear: "1 Jahr"
+threeDays: "3 Tage"
 reflectMayTakeTime: "Es kann etwas dauern, bis sich dies widerspiegelt."
 failedToFetchAccountInformation: "Benutzerkontoinformationen konnten nicht abgefragt werden"
 rateLimitExceeded: "Versuchsanzahl überschritten"
@@ -982,6 +993,7 @@ neverShow: "Nicht wieder anzeigen"
 remindMeLater: "Vielleicht später"
 didYouLikeMisskey: "Gefällt dir Misskey?"
 pleaseDonate: "Misskey ist die kostenlose Software, die von {host} verwendet wird. Wir würden uns über Spenden freuen, damit dessen Entwicklung weitergeführt werden kann!"
+correspondingSourceIsAvailable: "Der entsprechende Quellcode ist verfügbar unter {anchor}"
 roles: "Rollen"
 role: "Rolle"
 noRole: "Rolle nicht gefunden"
@@ -1032,6 +1044,7 @@ resetPasswordConfirm: "Wirklich Passwort zurücksetzen?"
 sensitiveWords: "Sensible Wörter"
 sensitiveWordsDescription: "Die Notizsichtbarkeit aller Notizen, die diese Wörter enthalten, wird automatisch auf \"Startseite\" gesetzt. Durch Zeilenumbrüche können mehrere konfiguriert werden."
 sensitiveWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-Verknüpfungen angegeben werden und durch das Umgeben von Schrägstrichen können reguläre Ausdrücke verwendet werden."
+prohibitedWords: "Verbotene Wörter"
 prohibitedWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-Verknüpfungen angegeben werden und durch das Umgeben von Schrägstrichen können reguläre Ausdrücke verwendet werden."
 hiddenTags: "Ausgeblendete Hashtags"
 hiddenTagsDescription: "Die hier eingestellten Tags werden nicht mehr in den Trends angezeigt. Mit der Umschalttaste können mehrere ausgewählt werden."
@@ -1078,6 +1091,8 @@ preservedUsernames: "Reservierte Benutzernamen"
 preservedUsernamesDescription: "Gib zu reservierende Benutzernamen durch Zeilenumbrüche getrennt an. Diese werden für die Registrierung gesperrt, können aber von Administratoren zur manuellen Erstellung von Konten verwendet werden. Existierende Konten, die diese Namen bereits verwenden, werden nicht beeinträchtigt."
 createNoteFromTheFile: "Notiz für diese Datei schreiben"
 archive: "Archivieren"
+archived: "Archiviert"
+unarchive: "Dearchivieren"
 channelArchiveConfirmTitle: "{name} wirklich archivieren?"
 channelArchiveConfirmDescription: "Ein archivierter Kanal taucht nicht mehr in der Kanalliste oder in Suchergebnissen auf. Zudem können ihm keine Beiträge mehr hinzugefügt werden."
 thisChannelArchived: "Dieser Kanal wurde archiviert."
@@ -1176,15 +1191,35 @@ signupPendingError: "Beim Überprüfen der Mailadresse ist etwas schiefgelaufen.
 cwNotationRequired: "Ist \"Inhaltswarnung verwenden\" aktiviert, muss eine Beschreibung gegeben werden."
 doReaction: "Reagieren"
 code: "Code"
+remainingN: "Verbleibend: {n}"
 decorate: "Dekorieren"
 addMfmFunction: "MFM hinzufügen"
 sfx: "Soundeffekte"
+showReplay: "Wiederholung anzeigen"
 lastNDays: "Letzten {n} Tage"
 surrender: "Abbrechen"
+keepOriginalFilename: "Ursprünglichen Dateinamen beibehalten"
+tryAgain: "Bitte später erneut versuchen"
+confirmWhenRevealingSensitiveMedia: "Das Anzeigen von sensiblen Medien bestätigen"
+createdLists: "Erstellte Listen"
+createdAntennas: "Erstellte Antennen"
+genEmbedCode: "Einbettungscode generieren"
+noteOfThisUser: "Notizen dieses Benutzers"
+clipNoteLimitExceeded: "Zu diesem Clip können keine weiteren Notizen hinzugefügt werden."
+discard: "Verwerfen"
+signinWithPasskey: "Mit Passkey anmelden"
+passkeyVerificationFailed: "Die Passkey-Verifizierung ist fehlgeschlagen."
+passkeyVerificationSucceededButPasswordlessLoginDisabled: "Die Verifizierung des Passkeys war erfolgreich, aber die passwortlose Anmeldung ist deaktiviert."
+pleaseSelectAccount: "Bitte Konto auswählen"
+availableRoles: "Verfügbare Rollen"
+_abuseUserReport:
+  forward: "Weiterleiten"
 _delivery:
   stop: "Gesperrt"
   _type:
     none: "Wird veröffentlicht"
+_bubbleGame:
+  howToPlay: "Wie man spielt"
 _announcement:
   forExistingUsers: "Nur für existierende Nutzer"
   forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt."
@@ -1515,6 +1550,10 @@ _achievements:
       description: "Betätige den Benachrichtigungstest mehrfach innerhalb einer extrem kurzen Zeitspanne"
     _tutorialCompleted:
       description: "Tutorial abgeschlossen"
+    _bubbleGameExplodingHead:
+      title: "🤯"
+    _bubbleGameDoubleExplodingHead:
+      title: "Doppel🤯"
 _role:
   new: "Rolle erstellen"
   edit: "Rolle bearbeiten"
@@ -2115,6 +2154,7 @@ _notification:
   pollEnded: "Umfrageergebnisse sind verfügbar"
   newNote: "Neue Notiz"
   unreadAntennaNote: "Antenne {name}"
+  roleAssigned: "Rolle zugewiesen"
   emptyPushNotificationMessage: "Push-Benachrichtigungen wurden aktualisiert"
   achievementEarned: "Errungenschaft freigeschaltet"
   testNotification: "Testbenachrichtigung"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 8570addfa2..6703d1cf3a 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -331,6 +331,7 @@ selectFile: "Select a file"
 selectFiles: "Select files"
 selectFolder: "Select a folder"
 selectFolders: "Select folders"
+fileNotSelected: "No file selected"
 renameFile: "Rename file"
 folderName: "Folder name"
 createFolder: "Create a folder"
@@ -1298,6 +1299,7 @@ yourNameContainsProhibitedWordsDescription: "If you wish to use this name, pleas
 thisContentsAreMarkedAsSigninRequiredByAuthor: "Set by the author to require login to view"
 lockdown: "Lockdown"
 pleaseSelectAccount: "Select an account"
+availableRoles: "Available roles"
 _accountSettings:
   requireSigninToViewContents: "Require sign-in to view contents"
   requireSigninToViewContentsDescription1: "Require login to view all notes and other content you have created. This will have the effect of preventing crawlers from collecting your information."
@@ -2223,7 +2225,7 @@ _widgets:
   _userList:
     chooseList: "Select a list"
   clicker: "Clicker"
-  birthdayFollowings: "Users who celebrate their birthday today"
+  birthdayFollowings: "Today's Birthdays"
 _cw:
   hide: "Hide"
   show: "Show content"
@@ -2730,3 +2732,9 @@ _embedCodeGen:
   generateCode: "Generate embed code"
   codeGenerated: "The code has been generated"
   codeGeneratedDescription: "Paste the generated code into your website to embed the content."
+_selfXssPrevention:
+  warning: "WARNING"
+  title: "\"Paste something on this screen\" is all a scam."
+  description1: "If you paste something here, a malicious user could hijack your account or steal your personal information."
+  description2: "If you do not understand exactly what you are trying to paste, %cstop working right now and close this window."
+  description3: "For more information, please refer to this. {link}"
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index 414202adab..5d07ebe244 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -42,7 +42,7 @@ favorite: "즐겨찾기"
 favorites: "즐겨찾기"
 unfavorite: "즐겨찾기에서 제거"
 favorited: "즐겨찾기에 등록했습니다."
-alreadyFavorited: "이미 즐겨찾기에 등록했습니다."
+alreadyFavorited: "이미 즐겨찾기에 등록되어 있습니다."
 cantFavorite: "즐겨찾기에 등록하지 못했습니다."
 pin: "프로필에 고정"
 unpin: "프로필에서 고정 해제"
@@ -947,6 +947,9 @@ oneHour: "1시간"
 oneDay: "1일"
 oneWeek: "일주일"
 oneMonth: "1개월"
+threeMonths: "3개월"
+oneYear: "1년"
+threeDays: "3일"
 reflectMayTakeTime: "반영되기까지 시간이 걸릴 수 있습니다."
 failedToFetchAccountInformation: "계정 정보를 가져오지 못했습니다"
 rateLimitExceeded: "요청 제한 횟수를 초과하였습니다"
@@ -1286,13 +1289,29 @@ signinWithPasskey: "패스키로 로그인"
 unknownWebAuthnKey: "등록되지 않은 패스키입니다."
 passkeyVerificationFailed: "패스키 검증을 실패했습니다."
 passkeyVerificationSucceededButPasswordlessLoginDisabled: "패스키를 검증했으나, 비밀번호 없이 로그인하기가 꺼져 있습니다."
-messageToFollower: "팔로워에 보낼 메시지"
+messageToFollower: "팔로워에게 보낼 메시지"
 target: "대상"
 testCaptchaWarning: "CAPTCHA를 테스트하기 위한 기능입니다. <strong>실제 환경에서는 사용하지 마세요.</strong>"
 prohibitedWordsForNameOfUser: "금지 단어 (사용자 이름)"
 prohibitedWordsForNameOfUserDescription: "이 목록에 포함되는 키워드가 사용자 이름에 있는 경우, 일반 사용자는 이름을 바꿀 수 없습니다. 모더레이터 권한을 가진 사용자는 제한 대상에서 제외됩니다."
 yourNameContainsProhibitedWords: "바꾸려는 이름에 금지된 키워드가 포함되어 있습니다."
 yourNameContainsProhibitedWordsDescription: "이름에 금지된 키워드가 있습니다. 이름을 사용해야 하는 경우, 서버 관리자에 문의하세요."
+thisContentsAreMarkedAsSigninRequiredByAuthor: "게시자에 의해 로그인해야 볼 수 있도록 설정되어 있습니다."
+lockdown: "잠금"
+pleaseSelectAccount: "계정을 선택해주세요."
+availableRoles: "사용 가능한 역할"
+_accountSettings:
+  requireSigninToViewContents: "콘텐츠 열람을 위해 로그인으 필수로 설정하기"
+  requireSigninToViewContentsDescription1: "자신이 작성한 모든 노트 등의 콘텐츠를 보기 위해 로그인을 필수로 설정합니다. 크롤러가 정보 수집하는 것을 방지하는 효과를 기대할 수 있습니다."
+  requireSigninToViewContentsDescription2: "URL 미리보기(OGP), 웹페이지에 삽입, 노트 인용을 지원하지 않는 서버에서 볼 수 없게 됩니다."
+  requireSigninToViewContentsDescription3: "원격 서버에 연합된 콘텐츠에는 이러한 제한이 적용되지 않을 수 있습니다."
+  makeNotesFollowersOnlyBefore: "과거 노트는 팔로워만 볼 수 있도록 설정하기"
+  makeNotesFollowersOnlyBeforeDescription: "이 기능이 활성화되어 있는 동안, 설정된 날짜 및 시간보다 과거 또는 설정된 시간이 지난 노트는 팔로워만 볼 수 있게 됩니다.비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다."
+  makeNotesHiddenBefore: "과거 노트 비공개로 전환하기"
+  makeNotesHiddenBeforeDescription: "이 기능이 활성화되어 있는 동안 설정한 날짜 및 시간보다 과거 또는 설정한 시간이 지난 노트는 본인만 볼 수 있게(비공개로 전환) 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다."
+  mayNotEffectForFederatedNotes: "원격 서버에 연합된 노트에는 효과가 없을 수도 있습니다."
+  notesHavePassedSpecifiedPeriod: "지정한 시간이 경과된 노트"
+  notesOlderThanSpecifiedDateAndTime: "지정된 날짜 및 시간 이전의 노트"
 _abuseUserReport:
   forward: "전달"
   forwardDescription: "익명 시스템 계정을 사용하여 리모트 서버에 신고 내용을 전달할 수 있습니다."
@@ -2157,8 +2176,11 @@ _auth:
   permissionAsk: "이 앱은 다음의 권한을 요청합니다"
   pleaseGoBack: "앱으로 돌아가서 시도해 주세요"
   callback: "앱으로 돌아갑니다"
+  accepted: "접근 권한이 부여되었습니다."
   denied: "접근이 거부되었습니다"
+  scopeUser: "다음 사용자로 활동하고 있습니다."
   pleaseLogin: "어플리케이션의 접근을 허가하려면 로그인하십시오."
+  byClickingYouWillBeRedirectedToThisUrl: "접근을 허용하면 자동으로 다음 URL로 이동합니다."
 _antennaSources:
   all: "모든 노트"
   homeTimeline: "팔로우중인 유저의 노트"
@@ -2710,3 +2732,9 @@ _embedCodeGen:
   generateCode: "임베디드 코드를 만들기"
   codeGenerated: "코드를 만들었습니다."
   codeGeneratedDescription: "만들어진 코드를 웹 사이트에 붙여서 사용하세요."
+_selfXssPrevention:
+  warning: "경고"
+  title: "“이 화면에 뭔가를 붙여넣어라\"는 것은 모두 사기입니다."
+  description1: "여기에 무언가를 붙여넣으면 악의적인 사용자에게 계정을 탈취당하거나 개인정보를 도용당할 수 있습니다."
+  description2: "붙여 넣으려는 항목이 무엇인지 정확히 이해하지 못하는 경우, %c지금 바로 작업을 중단하고 이 창을 닫으십시오."
+  description3: "자세한 내용은 여기를 확인해 주세요.  {link}"
diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml
index 5a0de660e8..4945e0f677 100644
--- a/locales/sv-SE.yml
+++ b/locales/sv-SE.yml
@@ -385,6 +385,7 @@ passwordLessLoginDescription: "Tillåter lösenordsfri inloggning med endast en
 resetPassword: "Återställ Lösenord"
 newPasswordIs: "Det nya lösenordet är \"{password}\""
 share: "Dela"
+markAsReadAllTalkMessages: "Markera alla meddelanden som lästa"
 help: "Hjälp"
 close: "Stäng"
 invites: "Inbjudan"
@@ -393,12 +394,15 @@ transfer: "Överför"
 text: "Text"
 enable: "Aktivera"
 next: "Nästa"
+retype: "Ange igen"
+noMessagesYet: "Inga meddelanden än"
 invitations: "Inbjudan"
 invitationCode: "Inbjudningskod"
 available: "Tillgängligt"
 weakPassword: "Svagt Lösenord"
 normalPassword: "Medel Lösenord"
 strongPassword: "Starkt Lösenord"
+signinWith: "Logga in med {x}"
 signinFailed: "Kan inte logga in. Det angivna användarnamnet eller lösenordet är felaktigt."
 or: "eller"
 language: "Språk"
@@ -410,70 +414,122 @@ existingAccount: "Existerande konto"
 regenerate: "Regenerera"
 fontSize: "Textstorlek"
 openImageInNewTab: "Öppna bild i ny flik"
+appearance: "Utseende"
 clientSettings: "Klientinställningar"
 accountSettings: "Kontoinställningar"
 numberOfDays: "Antal dagar"
+objectStorageUseSSL: "Använd SSL"
+serverLogs: "Serverloggar"
 deleteAll: "Radera alla"
 sounds: "Ljud"
 sound: "Ljud"
 listen: "Lyssna"
 none: "Ingen"
 volume: "Volym"
+notUseSound: "Inaktivera ljud"
 chooseEmoji: "Välj en emoji"
 recentUsed: "Senast använd"
 install: "Installera"
 uninstall: "Avinstallera"
+deleteAllFiles: "Radera alla filer"
+deleteAllFilesConfirm: "Är du säker på att du vill radera alla filer?"
 menu: "Meny"
+addItem: "Lägg till objekt"
 serviceworkerInfo: "Måste vara aktiverad för pushnotiser."
 enableInfiniteScroll: "Ladda mer automatiskt"
 enablePlayer: "Öppna videospelare"
+description: "Beskrivning"
 permission: "Behörigheter"
 enableAll: "Aktivera alla"
+disableAll: "Inaktivera alla"
 edit: "Ändra"
 enableEmail: "Aktivera epost-utskick"
 email: "E-post"
+emailAddress: "E-postadress"
 smtpHost: "Värd"
 smtpUser: "Användarnamn"
 smtpPass: "Lösenord"
 emptyToDisableSmtpAuth: "Lämna användarnamn och lösenord tomt för att avaktivera SMTP verifiering"
+makeActive: "Aktivera"
+copy: "Kopiera"
+overview: "Översikt"
 logs: "Logg"
+database: "Databas"
 channel: "kanal"
 create: "Skapa"
 other: "Mer"
+abuseReports: "Rapporter"
+reportAbuse: "Rapporter"
+reportAbuseOf: "Rapportera {name}"
+abuseReported: "Din rapport har skickats. Tack så mycket."
 send: "Skicka"
 openInNewTab: "Öppna i ny flik"
 createNew: "Skapa ny"
+private: "Privat"
 i18nInfo: "Misskey översätts till många olika språk av volontärer. Du kan hjälpa till med översättningen på {link}."
 accountInfo: "Kontoinformation"
+followersCount: "Antal följare"
+yes: "Ja"
+no: "Nej"
 clips: "Klipp"
 duplicate: "Duplicera"
 reloadToApplySetting: "Inställningen tillämpas efter sidan laddas om. Vill du göra det nu?"
 clearCache: "Rensa cache"
 onlineUsersCount: "{n} användare är online"
+nUsers: "{n} användare"
 nNotes: "{n} Noter"
 backgroundColor: "Bakgrundsbild"
 textColor: "Text"
+saveAs: "Spara som..."
 youAreRunningUpToDateClient: "Klienten du använder är uppdaterat."
 newVersionOfClientAvailable: "Ny version av klienten är tillgänglig."
+editCode: "Redigera kod"
 publish: "Publicera"
 typingUsers: "{users} skriver"
+goBack: "Tillbaka"
+addDescription: "Lägg till beskrivning"
 info: "Om"
+online: "Online"
+active: "Aktiv"
+offline: "Offline"
 enabled: "Aktiverad"
+quickAction: "Snabbåtgärder"
 user: "Användare"
+gallery: "Galleri"
+popularPosts: "Populära inlägg"
 customCssWarn: "Den här inställningen borde bara ändrats av en som har rätta kunskaper. Om du ställer in det här fel så kan klienten sluta fungera rätt."
 global: "Global"
 squareAvatars: "Visa fyrkantiga profilbilder"
 sent: "Skicka"
+searchResult: "Sökresultat"
+learnMore: "Läs mer"
 misskeyUpdated: "Misskey har uppdaterats!"
+translate: "Översätt"
+controlPanel: "Kontrollpanel"
+manageAccounts: "Hantera konton"
 incorrectPassword: "Fel lösenord."
+hide: "Dölj"
 welcomeBackWithName: "Välkommen tillbaka, {name}"
 clickToFinishEmailVerification: "Tryck på [{ok}] för att slutföra bekräftelsen på e-postadressen."
+size: "Storlek"
 searchByGoogle: "Sök"
+indefinitely: "Aldrig"
+tenMinutes: "10 minuter"
+oneHour: "En timme"
+oneDay: "En dag"
+oneWeek: "En vecka"
+oneMonth: "En månad"
+threeMonths: "3 månader"
+oneYear: "1 år"
+threeDays: "3 dagar"
 file: "Filer"
+label: "Etikett"
 cannotUploadBecauseNoFreeSpace: "Kan inte ladda upp filen för att det finns inget lagringsutrymme kvar."
 cannotUploadBecauseExceedsFileSizeLimit: "Kan inte ladda upp filen för att den är större än filstorleksgränsen."
+beta: "Beta"
 enableAutoSensitive: "Automatisk NSFW markering"
 enableAutoSensitiveDescription: "Tillåter automatiskt detektering och marketing av NSFW media genom Maskininlärning när möjligt. Även om denna inställningen är avaktiverad, kan det vara aktiverat på hela instansen."
+move: "Flytta"
 pushNotification: "Pushnotiser"
 subscribePushNotification: "Aktivera pushnotiser"
 unsubscribePushNotification: "Avaktivera pushnotiser"
@@ -482,16 +538,38 @@ pushNotificationNotSupported: "Din webbläsare eller instans har inte stöd för
 windowMaximize: "Maximera"
 windowMinimize: "Minimera"
 windowRestore: "Återställ"
+tools: "Verktyg"
+like: "Gilla"
 pleaseDonate: "Misskey är en gratis programvara som används på {host}. Donera gärna för att göra utvecklingen ständigt, tack!"
+roles: "Roll"
+role: "Roll"
+color: "Färg"
 resetPasswordConfirm: "Återställ verkligen ditt lösenord?"
 dataSaver: "Databesparing"
 icon: "Profilbild"
+forYou: "För dig"
 replies: "Svara"
 renotes: "Omnotera"
+loadReplies: "Visa svar"
+loadConversation: "Visa konversation"
+authentication: "Autentisering"
+sourceCode: "Källkod"
+doReaction: "Lägg till reaktion"
+code: "Kod"
+gameRetry: "Försök igen"
+inquiry: "Kontakt"
+tryAgain: "Försök igen senare"
+signinWithPasskey: "Logga in med nyckel"
+unknownWebAuthnKey: "Okänd nyckel"
 _delivery:
   stop: "Suspenderad"
   _type:
     none: "Publiceras"
+_initialAccountSetting:
+  profileSetting: "Profilinställningar"
+_initialTutorial:
+  _reaction:
+    title: "Vad är reaktioner?"
 _achievements:
   _types:
     _open3windows:
@@ -499,13 +577,25 @@ _achievements:
       description: "Ha minst 3 fönster öppna samtidigt"
 _ffVisibility:
   public: "Publicera"
+  private: "Privat"
+_ad:
+  back: "Tillbaka"
+_gallery:
+  like: "Gilla"
 _email:
   _follow:
     title: "följde dig"
+_aboutMisskey:
+  source: "Källkod"
 _channel:
   setBanner: "Välj banner"
   removeBanner: "Ta bort banner"
+  nameAndDescription: "Namn och beskrivning"
+_menuDisplay:
+  hide: "Dölj"
 _theme:
+  description: "Beskrivning"
+  color: "Färg"
   keys:
     mention: "Nämn"
     renote: "Omnotera"
@@ -530,13 +620,19 @@ _widgets:
   _userList:
     chooseList: "Välj lista"
 _cw:
+  hide: "Dölj"
   show: "Ladda mer"
+  chars: "{count} tecken"
+  files: "{count} fil(er)"
+_poll:
+  infinite: "Aldrig"
 _visibility:
   home: "Hem"
   followers: "Följare"
 _profile:
   name: "Namn"
   username: "Användarnamn"
+  metadataLabel: "Etikett"
   changeAvatar: "Ändra profilbild"
   changeBanner: "Ändra banner"
 _exportOrImport:
@@ -547,9 +643,12 @@ _exportOrImport:
   userLists: "Listor"
 _charts:
   federation: "Federation"
+  activeUsers: "Aktiva användare"
 _timelines:
   home: "Hem"
   global: "Global"
+_play:
+  summary: "Beskrivning"
 _pages:
   blocks:
     image: "Bilder"
@@ -584,3 +683,10 @@ _abuseReport:
 _moderationLogTypes:
   suspend: "Suspendera"
   resetPassword: "Återställ Lösenord"
+_reversi:
+  blackOrWhite: "Svart/Vit"
+  rules: "Regler"
+  black: "Svart"
+  white: "Vit"
+_selfXssPrevention:
+  warning: "VARNING"
diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml
index 235497d844..fb8e898bf1 100644
--- a/locales/vi-VN.yml
+++ b/locales/vi-VN.yml
@@ -8,6 +8,9 @@ search: "Tìm kiếm"
 notifications: "Thông báo"
 username: "Tên người dùng"
 password: "Mật khẩu"
+initialPasswordForSetup: "Mật khẩu ban đầu để thiết lập"
+initialPasswordIsIncorrect: "Mật khẩu ban đầu đã nhập sai"
+initialPasswordForSetupDescription: "Nếu bạn tự cài đặt Misskey, hãy sử dụng mật khẩu ban đầu của bạn đã nhập trong tệp cấu hình.\nNếu bạn đang sử dụng dịch vụ nào đó giống như dịch vụ lưu trữ của Misskey, hãy sử dụng mật khẩu ban đầu được cung cấp.\nNếu bạn chưa đặt mật khẩu ban đầu, vui lòng để trống và tiếp tục."
 forgotPassword: "Quên mật khẩu"
 fetchingAsApObject: "Đang nạp dữ liệu từ Fediverse..."
 ok: "Đồng ý"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 93804608c2..7a11f247ca 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -107,7 +107,7 @@ follow: "关注"
 followRequest: "关注申请"
 followRequests: "关注申请"
 unfollow: "取消关注"
-followRequestPending: "关注请求批准中"
+followRequestPending: "关注请求待批准"
 enterEmoji: "输入表情符号"
 renote: "转发"
 unrenote: "取消转发"
@@ -136,7 +136,7 @@ overwriteFromPinnedEmojisForReaction: "从「置顶(回应)」设置覆盖"
 overwriteFromPinnedEmojis: "从全局设置覆盖"
 reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
 rememberNoteVisibility: "保存上次设置的可见性"
-attachCancel: "删除附件"
+attachCancel: "取消添加附件"
 deleteFile: "删除文件"
 markAsSensitive: "标记为敏感内容"
 unmarkAsSensitive: "取消标记为敏感内容"
@@ -603,7 +603,7 @@ descendingOrder: "降序"
 scratchpad: "AiScript 控制台"
 scratchpadDescription: "AiScript 控制台为 AiScript 提供了实验环境。您可以编写代码与 Misskey 交互,运行并查看结果。"
 uiInspector: "UI 检查器"
-uiInspectorDescription: "查看所有内存中由 UI 组件生成出的实例。UI 组件由 UI:C 系列函数所生成。"
+uiInspectorDescription: "查看内存中所有由 UI 组件生成出的实例。UI 组件由 UI:C 系列函数所生成。"
 output: "输出"
 script: "脚本"
 disablePagesScript: "禁用页面脚本"
@@ -856,9 +856,9 @@ user: "用户"
 administration: "管理"
 accounts: "账户"
 switch: "切换"
-noMaintainerInformationWarning: "管理人员信息未设置。"
+noMaintainerInformationWarning: "尚未设置管理员信息。"
 noInquiryUrlWarning: "尚未设置联络地址。"
-noBotProtectionWarning: "Bot 防御未设置。"
+noBotProtectionWarning: "尚未设置 Bot 防御。"
 configure: "设置"
 postToGallery: "发送到图库"
 postToHashtag: "投稿到这个标签"
@@ -874,11 +874,11 @@ priority: "优先级"
 high: "高"
 middle: "中"
 low: "低"
-emailNotConfiguredWarning: "电子邮件地址未设置。"
+emailNotConfiguredWarning: "尚未设置电子邮件地址。"
 ratio: "比率"
 previewNoteText: "预览文本"
 customCss: "自定义 CSS"
-customCssWarn: "这些设置必须有相关的基础知识,不当的配置可能导致客户端无法正常使用!"
+customCssWarn: "这些设置必须有相关的基础知识,不当的配置可能导致客户端无法正常使用。"
 global: "全局"
 squareAvatars: "显示方形头像图标"
 sent: "发送"
@@ -1057,7 +1057,7 @@ internalServerErrorDescription: "内部服务器发生了预期外的错误"
 copyErrorInfo: "复制错误信息"
 joinThisServer: "在本服务器上注册"
 exploreOtherServers: "探索其他服务器"
-letsLookAtTimeline: "时间线"
+letsLookAtTimeline: "看看时间线"
 disableFederationConfirm: "确定要禁用联合?"
 disableFederationConfirmWarn: "禁用联合不会将帖子设为私有。在大多数情况下,不需要禁用联合。"
 disableFederationOk: "联合禁用"
@@ -1076,7 +1076,7 @@ sensitiveWords: "敏感词"
 sensitiveWordsDescription: "包含这些词的帖子将只在首页可见。可用换行来设定多个词。"
 sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
 prohibitedWords: "禁用词"
-prohibitedWordsDescription: "发布包含设定词汇的帖子时将出错。可用换行设定多个关键字"
+prohibitedWordsDescription: "发布包含设定词汇的帖子时将出错。可用换行设定多个关键字。"
 prohibitedWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
 hiddenTags: "隐藏标签"
 hiddenTagsDescription: "设定的标签将不会在时间线上显示。可使用换行来设置多个标签。"
@@ -1119,7 +1119,7 @@ vertical: "纵向"
 horizontal: "横向"
 position: "位置"
 serverRules: "服务器规则"
-pleaseConfirmBelowBeforeSignup: "在这个服务器上注册账号前,请确认以下信息。"
+pleaseConfirmBelowBeforeSignup: "如果要在此服务器上注册,需要确认并同意以下内容。"
 pleaseAgreeAllToContinue: "必须全部勾选「同意」才能够继续。"
 continue: "继续"
 preservedUsernames: "保留的用户名"
@@ -1159,10 +1159,10 @@ turnOffToImprovePerformance: "关闭该选项可以提高性能。"
 createInviteCode: "生成邀请码"
 createWithOptions: "使用选项来创建"
 createCount: "发行数"
-inviteCodeCreated: "已创建邀请码"
-inviteLimitExceeded: "可供发行的邀请码已达上限。"
-createLimitRemaining: "可供发行的邀请码:剩余{limit}个"
-inviteLimitResetCycle: "可以在{time}内发行最多{limit}个邀请码。"
+inviteCodeCreated: "已生成邀请码"
+inviteLimitExceeded: "可供生成的邀请码已达上限。"
+createLimitRemaining: "可供生成的邀请码:剩余 {limit} 个"
+inviteLimitResetCycle: "可以在 {time} 内生成最多 {limit} 个邀请码。"
 expirationDate: "有效日期"
 noExpirationDate: "不设置有效日期"
 inviteCodeUsedAt: "邀请码被使用的日期和时间"
@@ -1299,6 +1299,7 @@ yourNameContainsProhibitedWordsDescription: "用户名内含有违禁词。若
 thisContentsAreMarkedAsSigninRequiredByAuthor: "根据发帖者的设定,需要登录才能显示"
 lockdown: "锁定"
 pleaseSelectAccount: "请选择帐户"
+availableRoles: "可用角色"
 _accountSettings:
   requireSigninToViewContents: "需要登录才能显示内容"
   requireSigninToViewContentsDescription1: "您发布的所有帖子将变成需要登入后才会显示。有望防止爬虫收集各种信息。"
@@ -1426,8 +1427,8 @@ _initialTutorial:
     description: "对于服务器方针所要求要求的,又或者不适合直接展示的附件,请添加「敏感」标记。\n"
     tryThisFile: "试试看,将附加到此窗口的图像标注为敏感!"
     _exampleNote:
-      note: "拆纳豆包装时出错了…"
-    method: "要标注附件为敏感内容,请单击该文件以打开菜单,然后单击“标记为敏感内容”。"
+      note: "拆纳豆包装时失手了…"
+    method: "要标注附件为敏感内容,请单击该文件以打开菜单,然后单击「标记为敏感内容」。"
     sensitiveSucceeded: "附加文件时,请遵循服务器的条款来设置正确敏感设定。\n"
     doItToContinue: "将图像标记为敏感后才能够继续"
   _done:
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index 16afeed0f8..b7c9def26f 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -8,8 +8,8 @@ search: "搜尋"
 notifications: "通知"
 username: "使用者名稱"
 password: "密碼"
-initialPasswordForSetup: "初始設定用的密碼"
-initialPasswordIsIncorrect: "初始設定用的密碼錯誤。"
+initialPasswordForSetup: "啟動初始設定的密碼"
+initialPasswordIsIncorrect: "啟動初始設定的密碼錯誤。"
 initialPasswordForSetupDescription: "如果您自己安裝了 Misskey,請使用您在設定檔中輸入的密碼。\n如果您使用 Misskey 的託管服務之類的服務,請使用提供的密碼。\n如果您尚未設定密碼,請將其留空並繼續。"
 forgotPassword: "忘記密碼"
 fetchingAsApObject: "從聯邦宇宙取得中..."
@@ -1299,6 +1299,7 @@ yourNameContainsProhibitedWordsDescription: "名稱中包含禁止使用的字
 thisContentsAreMarkedAsSigninRequiredByAuthor: "作者將其設定為需要登入才能顯示。"
 lockdown: "鎖定"
 pleaseSelectAccount: "請選擇帳戶"
+availableRoles: "可用角色"
 _accountSettings:
   requireSigninToViewContents: "須登入以顯示內容"
   requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。"

From ac3bf57644c520c36ac7fd91784ef6501f6d010e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 15 Nov 2024 17:32:28 +0900
Subject: [PATCH 065/125] chore(deps): bump codecov/codecov-action from 4 to 5
 (#14961)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 .github/workflows/test-backend.yml    | 4 ++--
 .github/workflows/test-frontend.yml   | 2 +-
 .github/workflows/test-misskey-js.yml | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml
index cedcf16ecd..fc614dcf85 100644
--- a/.github/workflows/test-backend.yml
+++ b/.github/workflows/test-backend.yml
@@ -61,7 +61,7 @@ jobs:
     - name: Test
       run: pnpm --filter backend test-and-coverage
     - name: Upload to Codecov
-      uses: codecov/codecov-action@v4
+      uses: codecov/codecov-action@v5
       with:
         token: ${{ secrets.CODECOV_TOKEN }}
         files: ./packages/backend/coverage/coverage-final.json
@@ -108,7 +108,7 @@ jobs:
       - name: Test
         run: pnpm --filter backend test-and-coverage:e2e
       - name: Upload to Codecov
-        uses: codecov/codecov-action@v4
+        uses: codecov/codecov-action@v5
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: ./packages/backend/coverage/coverage-final.json
diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml
index eca596c7c7..6128abb502 100644
--- a/.github/workflows/test-frontend.yml
+++ b/.github/workflows/test-frontend.yml
@@ -50,7 +50,7 @@ jobs:
     - name: Test
       run: pnpm --filter frontend test-and-coverage
     - name: Upload Coverage
-      uses: codecov/codecov-action@v4
+      uses: codecov/codecov-action@v5
       with:
         token: ${{ secrets.CODECOV_TOKEN }}
         files: ./packages/frontend/coverage/coverage-final.json
diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml
index 054c10bf61..c7bb0753a8 100644
--- a/.github/workflows/test-misskey-js.yml
+++ b/.github/workflows/test-misskey-js.yml
@@ -51,7 +51,7 @@ jobs:
           CI: true
 
       - name: Upload Coverage
-        uses: codecov/codecov-action@v4
+        uses: codecov/codecov-action@v5
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           files: ./packages/misskey-js/coverage/coverage-final.json

From d0cdc0b7a1524c7b6f464078c30d7f7fe7a222a6 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 15 Nov 2024 18:00:20 +0900
Subject: [PATCH 066/125] chore(frontend): tweak animation style

---
 packages/frontend/src/style.scss | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss
index 4204c5af59..48aacf10bc 100644
--- a/packages/frontend/src/style.scss
+++ b/packages/frontend/src/style.scss
@@ -497,20 +497,17 @@ html[data-color-scheme=dark] ._woodenFrame {
 
 	10%,
 	20% {
-		transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
+		transform: scale3d(0.91, 0.91, 0.91) rotate3d(0, 0, 1, -2deg);
 	}
 
 	30%,
-	50%,
-	70%,
-	90% {
-		transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+	70% {
+		transform: scale3d(1.09, 1.09, 1.09) rotate3d(0, 0, 1, 2deg);
 	}
 
-	40%,
-	60%,
-	80% {
-		transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+	50%,
+	90% {
+		transform: scale3d(1.09, 1.09, 1.09) rotate3d(0, 0, 1, -2deg);
 	}
 
 	to {

From cf7df050239474d2bdb4c497b7f75bbe493a51dd Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Fri, 15 Nov 2024 09:06:13 +0000
Subject: [PATCH 067/125] Bump version to 2024.11.0-alpha.1

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 3b29007b68..a0c165b1c2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.11.0-alpha.0",
+	"version": "2024.11.0-alpha.1",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 6fff5ce38f..a5f34fa794 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.11.0-alpha.0",
+	"version": "2024.11.0-alpha.1",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From ce1f84e5a3c4c906ca611a4c4aa558f5012394d9 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 15 Nov 2024 19:33:50 +0900
Subject: [PATCH 068/125] use nodemon 3.0.2

#14966
---
 packages/backend/package.json             |  2 +-
 packages/frontend-embed/package.json      |  2 +-
 packages/frontend/package.json            |  2 +-
 packages/misskey-bubble-game/package.json |  2 +-
 packages/misskey-js/package.json          |  2 +-
 packages/misskey-reversi/package.json     |  2 +-
 packages/sw/package.json                  |  2 +-
 pnpm-lock.yaml                            | 36 +++++++++++------------
 8 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/packages/backend/package.json b/packages/backend/package.json
index 5055f50235..fb37344960 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -238,7 +238,7 @@
 		"fkill": "9.0.0",
 		"jest": "29.7.0",
 		"jest-mock": "29.7.0",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"pid-port": "1.0.0",
 		"simple-oauth2": "5.1.0"
 	}
diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json
index 59b744e43a..32e4f3d607 100644
--- a/packages/frontend-embed/package.json
+++ b/packages/frontend-embed/package.json
@@ -61,7 +61,7 @@
 		"intersection-observer": "0.12.2",
 		"micromatch": "4.0.8",
 		"msw": "2.6.4",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"prettier": "3.3.3",
 		"start-server-and-test": "2.0.8",
 		"vite-plugin-turbosnap": "1.0.3",
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index 4f132ab500..aaac240078 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -123,7 +123,7 @@
 		"micromatch": "4.0.8",
 		"msw": "2.6.4",
 		"msw-storybook-addon": "2.0.4",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"prettier": "3.3.3",
 		"react": "18.3.1",
 		"react-dom": "18.3.1",
diff --git a/packages/misskey-bubble-game/package.json b/packages/misskey-bubble-game/package.json
index 08d5062641..e579a3e370 100644
--- a/packages/misskey-bubble-game/package.json
+++ b/packages/misskey-bubble-game/package.json
@@ -27,7 +27,7 @@
 		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"execa": "9.5.1",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index a5f34fa794..01dc5f9ef6 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -46,7 +46,7 @@
 		"jest-websocket-mock": "2.5.0",
 		"mock-socket": "9.3.1",
 		"ncp": "2.0.0",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"execa": "9.5.1",
 		"tsd": "0.31.2",
 		"typescript": "5.6.3",
diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json
index 1cd6b0de2e..e59db5d42a 100644
--- a/packages/misskey-reversi/package.json
+++ b/packages/misskey-reversi/package.json
@@ -26,7 +26,7 @@
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
 		"execa": "9.5.1",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
 		"glob": "11.0.0"
diff --git a/packages/sw/package.json b/packages/sw/package.json
index dddd6e8bd7..cad7623d5a 100644
--- a/packages/sw/package.json
+++ b/packages/sw/package.json
@@ -17,7 +17,7 @@
 		"@typescript-eslint/parser": "7.17.0",
 		"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
 		"eslint-plugin-import": "2.30.0",
-		"nodemon": "3.1.7",
+		"nodemon": "3.0.2",
 		"typescript": "5.6.3"
 	},
 	"type": "module"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d5fe19ed64..4a24aa4dc3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -680,8 +680,8 @@ importers:
         specifier: 29.7.0
         version: 29.7.0
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       pid-port:
         specifier: 1.0.0
         version: 1.0.0
@@ -1005,8 +1005,8 @@ importers:
         specifier: 2.0.4
         version: 2.0.4(msw@2.6.4(@types/node@22.9.0)(typescript@5.6.3))
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       prettier:
         specifier: 3.3.3
         version: 3.3.3
@@ -1195,8 +1195,8 @@ importers:
         specifier: 2.6.4
         version: 2.6.4(@types/node@22.9.0)(typescript@5.6.3)
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       prettier:
         specifier: 3.3.3
         version: 3.3.3
@@ -1284,8 +1284,8 @@ importers:
         specifier: 11.0.0
         version: 11.0.0
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       typescript:
         specifier: 5.6.3
         version: 5.6.3
@@ -1345,8 +1345,8 @@ importers:
         specifier: 2.0.0
         version: 2.0.0
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       tsd:
         specifier: 0.31.2
         version: 0.31.2
@@ -1409,8 +1409,8 @@ importers:
         specifier: 11.0.0
         version: 11.0.0
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       typescript:
         specifier: 5.6.3
         version: 5.6.3
@@ -1437,8 +1437,8 @@ importers:
         specifier: 2.30.0
         version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       nodemon:
-        specifier: 3.1.7
-        version: 3.1.7
+        specifier: 3.0.2
+        version: 3.0.2
       typescript:
         specifier: 5.6.3
         version: 5.6.3
@@ -8555,8 +8555,8 @@ packages:
     resolution: {integrity: sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==}
     engines: {node: '>=6.0.0'}
 
-  nodemon@3.1.7:
-    resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==}
+  nodemon@3.0.2:
+    resolution: {integrity: sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==}
     engines: {node: '>=10'}
     hasBin: true
 
@@ -20361,7 +20361,7 @@ snapshots:
 
   nodemailer@6.9.16: {}
 
-  nodemon@3.1.7:
+  nodemon@3.0.2:
     dependencies:
       chokidar: 3.5.3
       debug: 4.3.7(supports-color@5.5.0)
@@ -21820,7 +21820,7 @@ snapshots:
 
   simple-update-notifier@2.0.0:
     dependencies:
-      semver: 7.6.0
+      semver: 7.6.3
 
   sinon@16.1.3:
     dependencies:

From d9d92bcfbf82b7094a1b9b586ac811fc07e35468 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 15 Nov 2024 19:40:12 +0900
Subject: [PATCH 069/125] Revert "use nodemon 3.0.2"

This reverts commit ce1f84e5a3c4c906ca611a4c4aa558f5012394d9.
---
 packages/backend/package.json             |  2 +-
 packages/frontend-embed/package.json      |  2 +-
 packages/frontend/package.json            |  2 +-
 packages/misskey-bubble-game/package.json |  2 +-
 packages/misskey-js/package.json          |  2 +-
 packages/misskey-reversi/package.json     |  2 +-
 packages/sw/package.json                  |  2 +-
 pnpm-lock.yaml                            | 36 +++++++++++------------
 8 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/packages/backend/package.json b/packages/backend/package.json
index fb37344960..5055f50235 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -238,7 +238,7 @@
 		"fkill": "9.0.0",
 		"jest": "29.7.0",
 		"jest-mock": "29.7.0",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"pid-port": "1.0.0",
 		"simple-oauth2": "5.1.0"
 	}
diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json
index 32e4f3d607..59b744e43a 100644
--- a/packages/frontend-embed/package.json
+++ b/packages/frontend-embed/package.json
@@ -61,7 +61,7 @@
 		"intersection-observer": "0.12.2",
 		"micromatch": "4.0.8",
 		"msw": "2.6.4",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"prettier": "3.3.3",
 		"start-server-and-test": "2.0.8",
 		"vite-plugin-turbosnap": "1.0.3",
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index aaac240078..4f132ab500 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -123,7 +123,7 @@
 		"micromatch": "4.0.8",
 		"msw": "2.6.4",
 		"msw-storybook-addon": "2.0.4",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"prettier": "3.3.3",
 		"react": "18.3.1",
 		"react-dom": "18.3.1",
diff --git a/packages/misskey-bubble-game/package.json b/packages/misskey-bubble-game/package.json
index e579a3e370..08d5062641 100644
--- a/packages/misskey-bubble-game/package.json
+++ b/packages/misskey-bubble-game/package.json
@@ -27,7 +27,7 @@
 		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"execa": "9.5.1",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 01dc5f9ef6..a5f34fa794 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -46,7 +46,7 @@
 		"jest-websocket-mock": "2.5.0",
 		"mock-socket": "9.3.1",
 		"ncp": "2.0.0",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"execa": "9.5.1",
 		"tsd": "0.31.2",
 		"typescript": "5.6.3",
diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json
index e59db5d42a..1cd6b0de2e 100644
--- a/packages/misskey-reversi/package.json
+++ b/packages/misskey-reversi/package.json
@@ -26,7 +26,7 @@
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
 		"execa": "9.5.1",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
 		"glob": "11.0.0"
diff --git a/packages/sw/package.json b/packages/sw/package.json
index cad7623d5a..dddd6e8bd7 100644
--- a/packages/sw/package.json
+++ b/packages/sw/package.json
@@ -17,7 +17,7 @@
 		"@typescript-eslint/parser": "7.17.0",
 		"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
 		"eslint-plugin-import": "2.30.0",
-		"nodemon": "3.0.2",
+		"nodemon": "3.1.7",
 		"typescript": "5.6.3"
 	},
 	"type": "module"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4a24aa4dc3..d5fe19ed64 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -680,8 +680,8 @@ importers:
         specifier: 29.7.0
         version: 29.7.0
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       pid-port:
         specifier: 1.0.0
         version: 1.0.0
@@ -1005,8 +1005,8 @@ importers:
         specifier: 2.0.4
         version: 2.0.4(msw@2.6.4(@types/node@22.9.0)(typescript@5.6.3))
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       prettier:
         specifier: 3.3.3
         version: 3.3.3
@@ -1195,8 +1195,8 @@ importers:
         specifier: 2.6.4
         version: 2.6.4(@types/node@22.9.0)(typescript@5.6.3)
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       prettier:
         specifier: 3.3.3
         version: 3.3.3
@@ -1284,8 +1284,8 @@ importers:
         specifier: 11.0.0
         version: 11.0.0
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       typescript:
         specifier: 5.6.3
         version: 5.6.3
@@ -1345,8 +1345,8 @@ importers:
         specifier: 2.0.0
         version: 2.0.0
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       tsd:
         specifier: 0.31.2
         version: 0.31.2
@@ -1409,8 +1409,8 @@ importers:
         specifier: 11.0.0
         version: 11.0.0
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       typescript:
         specifier: 5.6.3
         version: 5.6.3
@@ -1437,8 +1437,8 @@ importers:
         specifier: 2.30.0
         version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       nodemon:
-        specifier: 3.0.2
-        version: 3.0.2
+        specifier: 3.1.7
+        version: 3.1.7
       typescript:
         specifier: 5.6.3
         version: 5.6.3
@@ -8555,8 +8555,8 @@ packages:
     resolution: {integrity: sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==}
     engines: {node: '>=6.0.0'}
 
-  nodemon@3.0.2:
-    resolution: {integrity: sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==}
+  nodemon@3.1.7:
+    resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==}
     engines: {node: '>=10'}
     hasBin: true
 
@@ -20361,7 +20361,7 @@ snapshots:
 
   nodemailer@6.9.16: {}
 
-  nodemon@3.0.2:
+  nodemon@3.1.7:
     dependencies:
       chokidar: 3.5.3
       debug: 4.3.7(supports-color@5.5.0)
@@ -21820,7 +21820,7 @@ snapshots:
 
   simple-update-notifier@2.0.0:
     dependencies:
-      semver: 7.6.3
+      semver: 7.6.0
 
   sinon@16.1.3:
     dependencies:

From eef0c895bc15b7c149a755ab15b620852b5e2332 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 15 Nov 2024 19:48:31 +0900
Subject: [PATCH 070/125] use execa 8.0.1

#14966
---
 package.json                              |   2 +-
 packages/backend/package.json             |   2 +-
 packages/misskey-bubble-game/package.json |   2 +-
 packages/misskey-js/package.json          |   2 +-
 packages/misskey-reversi/package.json     |   2 +-
 pnpm-lock.yaml                            | 148 ++++------------------
 6 files changed, 32 insertions(+), 126 deletions(-)

diff --git a/package.json b/package.json
index a0c165b1c2..63043d62e0 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
 	},
 	"dependencies": {
 		"cssnano": "6.1.2",
-		"execa": "9.5.1",
+		"execa": "8.0.1",
 		"fast-glob": "3.3.2",
 		"ignore-walk": "6.0.5",
 		"js-yaml": "4.1.0",
diff --git a/packages/backend/package.json b/packages/backend/package.json
index 5055f50235..f56a737eea 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -234,7 +234,7 @@
 		"aws-sdk-client-mock": "4.0.1",
 		"cross-env": "7.0.3",
 		"eslint-plugin-import": "2.30.0",
-		"execa": "9.5.1",
+		"execa": "8.0.1",
 		"fkill": "9.0.0",
 		"jest": "29.7.0",
 		"jest-mock": "29.7.0",
diff --git a/packages/misskey-bubble-game/package.json b/packages/misskey-bubble-game/package.json
index 08d5062641..97620e484a 100644
--- a/packages/misskey-bubble-game/package.json
+++ b/packages/misskey-bubble-game/package.json
@@ -28,7 +28,7 @@
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
 		"nodemon": "3.1.7",
-		"execa": "9.5.1",
+		"execa": "8.0.1",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
 		"glob": "11.0.0"
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index a5f34fa794..8166dcedad 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -47,7 +47,7 @@
 		"mock-socket": "9.3.1",
 		"ncp": "2.0.0",
 		"nodemon": "3.1.7",
-		"execa": "9.5.1",
+		"execa": "8.0.1",
 		"tsd": "0.31.2",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json
index 1cd6b0de2e..951dd1c65a 100644
--- a/packages/misskey-reversi/package.json
+++ b/packages/misskey-reversi/package.json
@@ -25,7 +25,7 @@
 		"@types/node": "22.9.0",
 		"@typescript-eslint/eslint-plugin": "7.1.0",
 		"@typescript-eslint/parser": "7.1.0",
-		"execa": "9.5.1",
+		"execa": "8.0.1",
 		"nodemon": "3.1.7",
 		"typescript": "5.6.3",
 		"esbuild": "0.24.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d5fe19ed64..c0ec950181 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,8 +19,8 @@ importers:
         specifier: 0.24.0
         version: 0.24.0
       execa:
-        specifier: 9.5.1
-        version: 9.5.1
+        specifier: 8.0.1
+        version: 8.0.1
       fast-glob:
         specifier: 3.3.2
         version: 3.3.2
@@ -668,8 +668,8 @@ importers:
         specifier: 2.30.0
         version: 2.30.0(@typescript-eslint/parser@7.17.0(eslint@9.14.0)(typescript@5.6.3))(eslint@9.14.0)
       execa:
-        specifier: 9.5.1
-        version: 9.5.1
+        specifier: 8.0.1
+        version: 8.0.1
       fkill:
         specifier: 9.0.0
         version: 9.0.0
@@ -1278,8 +1278,8 @@ importers:
         specifier: 0.24.0
         version: 0.24.0
       execa:
-        specifier: 9.5.1
-        version: 9.5.1
+        specifier: 8.0.1
+        version: 8.0.1
       glob:
         specifier: 11.0.0
         version: 11.0.0
@@ -1324,8 +1324,8 @@ importers:
         specifier: 0.24.0
         version: 0.24.0
       execa:
-        specifier: 9.5.1
-        version: 9.5.1
+        specifier: 8.0.1
+        version: 8.0.1
       glob:
         specifier: 11.0.0
         version: 11.0.0
@@ -1403,8 +1403,8 @@ importers:
         specifier: 0.24.0
         version: 0.24.0
       execa:
-        specifier: 9.5.1
-        version: 9.5.1
+        specifier: 8.0.1
+        version: 8.0.1
       glob:
         specifier: 11.0.0
         version: 11.0.0
@@ -3551,10 +3551,6 @@ packages:
     resolution: {integrity: sha512-QWLl2P+rsCJeofkDNIT3WFmb6NrRud1SUYW8dIhXK/46XFV8Q/g7Bsvib0Askb0reRLe+WYPeeE+l5cH7SlkuQ==}
     engines: {node: '>=18'}
 
-  '@sindresorhus/merge-streams@4.0.0':
-    resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
-    engines: {node: '>=18'}
-
   '@sinonjs/commons@2.0.0':
     resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==}
 
@@ -6485,10 +6481,6 @@ packages:
     resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
     engines: {node: '>=16.17'}
 
-  execa@9.5.1:
-    resolution: {integrity: sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==}
-    engines: {node: ^18.19.0 || >=20.5.0}
-
   executable@4.1.1:
     resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==}
     engines: {node: '>=4'}
@@ -6615,10 +6607,6 @@ packages:
     resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
     engines: {node: '>=8'}
 
-  figures@6.1.0:
-    resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
-    engines: {node: '>=18'}
-
   file-entry-cache@8.0.0:
     resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
     engines: {node: '>=16.0.0'}
@@ -7158,10 +7146,6 @@ packages:
     resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
     engines: {node: '>=16.17.0'}
 
-  human-signals@8.0.0:
-    resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==}
-    engines: {node: '>=18.18.0'}
-
   iconv-lite@0.4.24:
     resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
     engines: {node: '>=0.10.0'}
@@ -7481,10 +7465,6 @@ packages:
     resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
     engines: {node: '>=10'}
 
-  is-unicode-supported@2.0.0:
-    resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==}
-    engines: {node: '>=18'}
-
   is-weakmap@2.0.1:
     resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
 
@@ -8610,18 +8590,10 @@ packages:
     resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
     engines: {node: '>=8'}
 
-  npm-run-path@5.1.0:
-    resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==}
-    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
   npm-run-path@5.3.0:
     resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
 
-  npm-run-path@6.0.0:
-    resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
-    engines: {node: '>=18'}
-
   npmlog@5.0.1:
     resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
     deprecated: This package is no longer supported.
@@ -8820,10 +8792,6 @@ packages:
     resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
     engines: {node: '>=8'}
 
-  parse-ms@4.0.0:
-    resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
-    engines: {node: '>=18'}
-
   parse-srcset@1.0.2:
     resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==}
 
@@ -9291,10 +9259,6 @@ packages:
     resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
 
-  pretty-ms@9.0.0:
-    resolution: {integrity: sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==}
-    engines: {node: '>=18'}
-
   private-ip@2.3.3:
     resolution: {integrity: sha512-5zyFfekIVUOTVbL92hc8LJOtE/gyGHeREHkJ2yTyByP8Q2YZVoBqLg3EfYLeF0oVvGqtaEX2t2Qovja0/gStXw==}
 
@@ -10249,10 +10213,6 @@ packages:
     resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
     engines: {node: '>=12'}
 
-  strip-final-newline@4.0.0:
-    resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
-    engines: {node: '>=18'}
-
   strip-indent@3.0.0:
     resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
     engines: {node: '>=8'}
@@ -10731,10 +10691,6 @@ packages:
     resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==}
     engines: {node: '>=18.17'}
 
-  unicorn-magic@0.3.0:
-    resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
-    engines: {node: '>=18'}
-
   unified@11.0.4:
     resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==}
 
@@ -11264,10 +11220,6 @@ packages:
     resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
     engines: {node: '>=18'}
 
-  yoctocolors@2.0.2:
-    resolution: {integrity: sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==}
-    engines: {node: '>=18'}
-
   zip-stream@6.0.1:
     resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
     engines: {node: '>= 14'}
@@ -11828,7 +11780,7 @@ snapshots:
       '@babel/traverse': 7.23.5
       '@babel/types': 7.24.7
       convert-source-map: 2.0.0
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       gensync: 1.0.0-beta.2
       json5: 2.2.3
       semver: 6.3.1
@@ -11848,7 +11800,7 @@ snapshots:
       '@babel/traverse': 7.24.7
       '@babel/types': 7.24.7
       convert-source-map: 2.0.0
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       gensync: 1.0.0-beta.2
       json5: 2.2.3
       semver: 6.3.1
@@ -12107,7 +12059,7 @@ snapshots:
       '@babel/helper-split-export-declaration': 7.22.6
       '@babel/parser': 7.25.6
       '@babel/types': 7.24.7
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
@@ -12122,7 +12074,7 @@ snapshots:
       '@babel/helper-split-export-declaration': 7.24.7
       '@babel/parser': 7.25.6
       '@babel/types': 7.25.6
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
@@ -12513,7 +12465,7 @@ snapshots:
   '@eslint/config-array@0.18.0':
     dependencies:
       '@eslint/object-schema': 2.1.4
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       minimatch: 3.1.2
     transitivePeerDependencies:
       - supports-color
@@ -12523,7 +12475,7 @@ snapshots:
   '@eslint/eslintrc@3.1.0':
     dependencies:
       ajv: 6.12.6
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       espree: 10.3.0
       globals: 14.0.0
       ignore: 5.3.1
@@ -13932,8 +13884,6 @@ snapshots:
 
   '@sindresorhus/is@7.0.1': {}
 
-  '@sindresorhus/merge-streams@4.0.0': {}
-
   '@sinonjs/commons@2.0.0':
     dependencies:
       type-detect: 4.0.8
@@ -15687,7 +15637,7 @@ snapshots:
 
   agent-base@6.0.2:
     dependencies:
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
     transitivePeerDependencies:
       - supports-color
     optional: true
@@ -17298,7 +17248,7 @@ snapshots:
 
   esbuild-register@3.5.0(esbuild@0.24.0):
     dependencies:
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       esbuild: 0.24.0
     transitivePeerDependencies:
       - supports-color
@@ -17540,7 +17490,7 @@ snapshots:
       ajv: 6.12.6
       chalk: 4.1.2
       cross-spawn: 7.0.3
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       escape-string-regexp: 4.0.0
       eslint-scope: 8.2.0
       eslint-visitor-keys: 4.2.0
@@ -17670,26 +17620,11 @@ snapshots:
       human-signals: 5.0.0
       is-stream: 3.0.0
       merge-stream: 2.0.0
-      npm-run-path: 5.1.0
+      npm-run-path: 5.3.0
       onetime: 6.0.0
       signal-exit: 4.1.0
       strip-final-newline: 3.0.0
 
-  execa@9.5.1:
-    dependencies:
-      '@sindresorhus/merge-streams': 4.0.0
-      cross-spawn: 7.0.3
-      figures: 6.1.0
-      get-stream: 9.0.1
-      human-signals: 8.0.0
-      is-plain-obj: 4.1.0
-      is-stream: 4.0.1
-      npm-run-path: 6.0.0
-      pretty-ms: 9.0.0
-      signal-exit: 4.1.0
-      strip-final-newline: 4.0.0
-      yoctocolors: 2.0.2
-
   executable@4.1.1:
     dependencies:
       pify: 2.3.0
@@ -17904,10 +17839,6 @@ snapshots:
     dependencies:
       escape-string-regexp: 1.0.5
 
-  figures@6.1.0:
-    dependencies:
-      is-unicode-supported: 2.0.0
-
   file-entry-cache@8.0.0:
     dependencies:
       flat-cache: 4.0.1
@@ -18004,7 +17935,7 @@ snapshots:
 
   follow-redirects@1.15.9(debug@4.3.7):
     optionalDependencies:
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
 
   for-each@0.3.3:
     dependencies:
@@ -18540,8 +18471,6 @@ snapshots:
 
   human-signals@5.0.0: {}
 
-  human-signals@8.0.0: {}
-
   iconv-lite@0.4.24:
     dependencies:
       safer-buffer: 2.1.2
@@ -18819,8 +18748,6 @@ snapshots:
 
   is-unicode-supported@0.1.0: {}
 
-  is-unicode-supported@2.0.0: {}
-
   is-weakmap@2.0.1: {}
 
   is-weakref@1.0.2:
@@ -18878,7 +18805,7 @@ snapshots:
 
   istanbul-lib-source-maps@4.0.1:
     dependencies:
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       istanbul-lib-coverage: 3.2.2
       source-map: 0.6.1
     transitivePeerDependencies:
@@ -19309,7 +19236,7 @@ snapshots:
       whatwg-encoding: 3.1.1
       whatwg-mimetype: 4.0.0
       whatwg-url: 14.0.0
-      ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+      ws: 8.18.0(bufferutil@4.0.7)(utf-8-validate@6.0.3)
       xml-name-validator: 5.0.0
     transitivePeerDependencies:
       - bufferutil
@@ -20009,7 +19936,7 @@ snapshots:
   micromark@4.0.0:
     dependencies:
       '@types/debug': 4.1.12
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       decode-named-character-reference: 1.0.2
       devlop: 1.1.0
       micromark-core-commonmark: 2.0.0
@@ -20421,19 +20348,10 @@ snapshots:
     dependencies:
       path-key: 3.1.1
 
-  npm-run-path@5.1.0:
-    dependencies:
-      path-key: 4.0.0
-
   npm-run-path@5.3.0:
     dependencies:
       path-key: 4.0.0
 
-  npm-run-path@6.0.0:
-    dependencies:
-      path-key: 4.0.0
-      unicorn-magic: 0.3.0
-
   npmlog@5.0.1:
     dependencies:
       are-we-there-yet: 2.0.0
@@ -20643,8 +20561,6 @@ snapshots:
       json-parse-even-better-errors: 2.3.1
       lines-and-columns: 1.2.4
 
-  parse-ms@4.0.0: {}
-
   parse-srcset@1.0.2: {}
 
   parse5-htmlparser2-tree-adapter@6.0.1:
@@ -21058,10 +20974,6 @@ snapshots:
       ansi-styles: 5.2.0
       react-is: 18.2.0
 
-  pretty-ms@9.0.0:
-    dependencies:
-      parse-ms: 4.0.0
-
   private-ip@2.3.3:
     dependencies:
       ip-regex: 4.3.0
@@ -21484,7 +21396,7 @@ snapshots:
 
   require-in-the-middle@7.3.0:
     dependencies:
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       module-details-from-path: 1.0.3
       resolve: 1.22.8
     transitivePeerDependencies:
@@ -21909,7 +21821,7 @@ snapshots:
   socks-proxy-agent@8.0.2:
     dependencies:
       agent-base: 7.1.0
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       socks: 2.7.1
     transitivePeerDependencies:
       - supports-color
@@ -22018,7 +21930,7 @@ snapshots:
       arg: 5.0.2
       bluebird: 3.7.2
       check-more-types: 2.24.0
-      debug: 4.3.7(supports-color@8.1.1)
+      debug: 4.3.7(supports-color@5.5.0)
       execa: 5.1.1
       lazy-ass: 1.6.0
       ps-tree: 1.2.0
@@ -22176,8 +22088,6 @@ snapshots:
 
   strip-final-newline@3.0.0: {}
 
-  strip-final-newline@4.0.0: {}
-
   strip-indent@3.0.0:
     dependencies:
       min-indent: 1.0.1
@@ -22611,8 +22521,6 @@ snapshots:
 
   undici@6.19.8: {}
 
-  unicorn-magic@0.3.0: {}
-
   unified@11.0.4:
     dependencies:
       '@types/unist': 3.0.2
@@ -23263,8 +23171,6 @@ snapshots:
 
   yoctocolors-cjs@2.1.2: {}
 
-  yoctocolors@2.0.2: {}
-
   zip-stream@6.0.1:
     dependencies:
       archiver-utils: 5.0.2

From 459449864c1cc3bc28d2d38cb686d85e967fe20b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 16 Nov 2024 10:16:11 +0900
Subject: [PATCH 071/125] =?UTF-8?q?=F0=9F=8E=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/pages/follow-requests.vue | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue
index 8688863c2c..5d819e7993 100644
--- a/packages/frontend/src/pages/follow-requests.vue
+++ b/packages/frontend/src/pages/follow-requests.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 						</div>
 					</template>
 					<template #default="{items}">
-						<div class="mk-follow-requests">
+						<div class="mk-follow-requests _gaps">
 							<div v-for="req in items" :key="req.id" class="user _panel">
 								<MkAvatar class="avatar" :user="displayUser(req)" indicator link preview/>
 								<div class="body">
@@ -94,11 +94,11 @@ const headerTabs = computed(() => [
 	{
 		key: 'list',
 		title: i18n.ts._followRequest.recieved,
-		icon: 'ti ti-mail',
+		icon: 'ti ti-download',
 	}, {
 		key: 'sent',
 		title: i18n.ts._followRequest.sent,
-		icon: 'ti ti-send',
+		icon: 'ti ti-upload',
 	},
 ]);
 

From 2e0f3936a88797e66a9be86de1b5f34d6b9b1c91 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 16 Nov 2024 15:32:51 +0900
Subject: [PATCH 072/125] Update .gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 5b8a798ba6..ac7502f384 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,8 @@ misskey-assets
 # Vite temporary files
 vite.config.js.timestamp-*
 vite.config.ts.timestamp-*
+vite.config.local-dev.js.timestamp-*
+vite.config.local-dev.ts.timestamp-*
 
 # blender backups
 *.blend1

From cf1b7c7064f62fea3e9a264516e704279cd659fc Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 16 Nov 2024 17:22:34 +0900
Subject: [PATCH 073/125] add warning for open registration (#14963)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* wip

* wip

* Update ja-JP.yml

* Update index.d.ts

* ✌️
---
 locales/index.d.ts                            | 16 ++++++++++----
 locales/ja-JP.yml                             |  4 +++-
 .../frontend/src/pages/admin/moderation.vue   | 21 +++++++++++++++----
 3 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/locales/index.d.ts b/locales/index.d.ts
index 18fbfd15f0..24613419ce 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -1546,10 +1546,6 @@ export interface Locale extends ILocale {
      * 登録
      */
     "registration": string;
-    /**
-     * 誰でも新規登録できるようにする
-     */
-    "enableRegistration": string;
     /**
      * 招待
      */
@@ -5218,6 +5214,10 @@ export interface Locale extends ILocale {
      * 利用可能なロール
      */
     "availableRoles": string;
+    /**
+     * 注意事項を理解した上でオンにします。
+     */
+    "acknowledgeNotesAndEnable": string;
     "_accountSettings": {
         /**
          * コンテンツの表示にログインを必須にする
@@ -5794,6 +5794,14 @@ export interface Locale extends ILocale {
          * サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定します。
          */
         "inquiryUrlDescription": string;
+        /**
+         * アカウントの作成をオープンにする
+         */
+        "openRegistration": string;
+        /**
+         * 登録を開放することはリスクが伴います。サーバーを常に監視し、トラブルが発生した際にすぐに対応できる体制がある場合のみオンにすることを推奨します。
+         */
+        "openRegistrationWarning": string;
         /**
          * 一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。
          */
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 439ae708c5..9f32969a79 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "ローカルタイムラインを有効にする"
 enableGlobalTimeline: "グローバルタイムラインを有効にする"
 disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
 registration: "登録"
-enableRegistration: "誰でも新規登録できるようにする"
 invite: "招待"
 driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量"
 driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量"
@@ -1300,6 +1299,7 @@ thisContentsAreMarkedAsSigninRequiredByAuthor: "投稿者により、表示に
 lockdown: "ロックダウン"
 pleaseSelectAccount: "アカウントを選択してください"
 availableRoles: "利用可能なロール"
+acknowledgeNotesAndEnable: "注意事項を理解した上でオンにします。"
 
 _accountSettings:
   requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
@@ -1466,6 +1466,8 @@ _serverSettings:
   reactionsBufferingDescription: "有効にすると、リアクション作成時のパフォーマンスが大幅に向上し、データベースへの負荷を軽減することが可能です。ただし、Redisのメモリ使用量は増加します。"
   inquiryUrl: "問い合わせ先URL"
   inquiryUrlDescription: "サーバー運営者へのお問い合わせフォームのURLや、運営者の連絡先等が記載されたWebページのURLを指定します。"
+  openRegistration: "アカウントの作成をオープンにする"
+  openRegistrationWarning: "登録を開放することはリスクが伴います。サーバーを常に監視し、トラブルが発生した際にすぐに対応できる体制がある場合のみオンにすることを推奨します。"
   thisSettingWillAutomaticallyOffWhenModeratorsInactive: "一定期間モデレーターのアクティビティが検出されなかった場合、スパム防止のためこの設定は自動でオフになります。"
 
 _accountMigration:
diff --git a/packages/frontend/src/pages/admin/moderation.vue b/packages/frontend/src/pages/admin/moderation.vue
index 5d8a581b2e..ac1fe7783c 100644
--- a/packages/frontend/src/pages/admin/moderation.vue
+++ b/packages/frontend/src/pages/admin/moderation.vue
@@ -10,9 +10,12 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
 			<FormSuspense :p="init">
 				<div class="_gaps_m">
-					<MkSwitch v-model="enableRegistration" @change="onChange_enableRegistration">
-						<template #label>{{ i18n.ts.enableRegistration }}</template>
-						<template #caption>{{ i18n.ts._serverSettings.thisSettingWillAutomaticallyOffWhenModeratorsInactive }}</template>
+					<MkSwitch :modelValue="enableRegistration" @update:modelValue="onChange_enableRegistration">
+						<template #label>{{ i18n.ts._serverSettings.openRegistration }}</template>
+						<template #caption>
+							<div>{{ i18n.ts._serverSettings.thisSettingWillAutomaticallyOffWhenModeratorsInactive }}</div>
+							<div><i class="ti ti-alert-triangle" style="color: var(--MI_THEME-warn);"></i> {{ i18n.ts._serverSettings.openRegistrationWarning }}</div>
+						</template>
 					</MkSwitch>
 
 					<MkSwitch v-model="emailRequiredForSignup" @change="onChange_emailRequiredForSignup">
@@ -164,7 +167,17 @@ async function init() {
 	mediaSilencedHosts.value = meta.mediaSilencedHosts.join('\n');
 }
 
-function onChange_enableRegistration(value: boolean) {
+async function onChange_enableRegistration(value: boolean) {
+	if (value) {
+		const { canceled } = await os.confirm({
+			type: 'warning',
+			text: i18n.ts.acknowledgeNotesAndEnable,
+		});
+		if (canceled) return;
+	}
+
+	enableRegistration.value = value;
+
 	os.apiWithDialog('admin/update-meta', {
 		disableRegistration: !value,
 	}).then(() => {

From b3c2de2b2643d777d360de0171ae573f39411c02 Mon Sep 17 00:00:00 2001
From: CDN <cardinal@codeword.info>
Date: Sat, 16 Nov 2024 17:53:28 +0800
Subject: [PATCH 074/125] fix(backend): fallback sharedInbox to null in
 ApPersonService (#14970)

---
 .../backend/src/core/activitypub/models/ApPersonService.ts  | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index c9de67b3a0..8c4e40c561 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -355,7 +355,7 @@ export class ApPersonService implements OnModuleInit {
 					usernameLower: person.preferredUsername?.toLowerCase(),
 					host,
 					inbox: person.inbox,
-					sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox,
+					sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox ?? null,
 					followersUri: person.followers ? getApId(person.followers) : undefined,
 					featured: person.featured ? getApId(person.featured) : undefined,
 					uri: person.id,
@@ -521,7 +521,7 @@ export class ApPersonService implements OnModuleInit {
 		const updates = {
 			lastFetchedAt: new Date(),
 			inbox: person.inbox,
-			sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox,
+			sharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox ?? null,
 			followersUri: person.followers ? getApId(person.followers) : undefined,
 			featured: person.featured,
 			emojis: emojiNames,
@@ -593,7 +593,7 @@ export class ApPersonService implements OnModuleInit {
 		// 該当ユーザーが既にフォロワーになっていた場合はFollowingもアップデートする
 		await this.followingsRepository.update(
 			{ followerId: exist.id },
-			{ followerSharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox },
+			{ followerSharedInbox: person.sharedInbox ?? person.endpoints?.sharedInbox ?? null },
 		);
 
 		await this.updateFeatured(exist.id, resolver).catch(err => this.logger.error(err));

From 9614f74bf842c9522c877f0592a1e0de0ca51140 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 16 Nov 2024 20:24:31 +0900
Subject: [PATCH 075/125] =?UTF-8?q?=F0=9F=8E=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/pages/settings/privacy.vue | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/packages/frontend/src/pages/settings/privacy.vue b/packages/frontend/src/pages/settings/privacy.vue
index da3d36b31a..40d9be0f60 100644
--- a/packages/frontend/src/pages/settings/privacy.vue
+++ b/packages/frontend/src/pages/settings/privacy.vue
@@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 		<template #label>{{ i18n.ts.lockdown }}<span class="_beta">{{ i18n.ts.beta }}</span></template>
 
 		<div class="_gaps_m">
-			<MkSwitch v-model="requireSigninToViewContents" @update:modelValue="save()">
+			<MkSwitch :modelValue="requireSigninToViewContents" @update:modelValue="update_requireSigninToViewContents">
 				{{ i18n.ts._accountSettings.requireSigninToViewContents }}
 				<template #caption>
 					<div>{{ i18n.ts._accountSettings.requireSigninToViewContentsDescription1 }}</div>
@@ -172,6 +172,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
 import FormSlot from '@/components/form/slot.vue';
 import { formatDateTimeString } from '@/scripts/format-time-string.js';
 import MkInput from '@/components/MkInput.vue';
+import * as os from '@/os.js';
 
 const $i = signinRequired();
 
@@ -217,6 +218,19 @@ watch([makeNotesFollowersOnlyBefore, makeNotesHiddenBefore], () => {
 	save();
 });
 
+async function update_requireSigninToViewContents(value: boolean) {
+	if (value) {
+		const { canceled } = await os.confirm({
+			type: 'warning',
+			text: i18n.ts.acknowledgeNotesAndEnable,
+		});
+		if (canceled) return;
+	}
+
+	requireSigninToViewContents.value = value;
+	save();
+}
+
 function save() {
 	misskeyApi('i/update', {
 		isLocked: !!isLocked.value,

From a730045bdde20409ff01d95afcf3b7571e371aa5 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 17 Nov 2024 12:44:44 +0900
Subject: [PATCH 076/125] Update CHANGELOG.md

---
 CHANGELOG.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 232d52d7e1..65ff53eff1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,6 +44,8 @@
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
 - Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
+- Fix: sharedInboxが無いActorに紐づくリモートユーザーを照会できない
+- Fix: Aproving request from GtS appears with some delay
 - Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
 - Fix: Nested proxy requestsを検出した際にブロックするように
   [ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)

From 9aebf0c168405910118c25d34686e8eed9a459c0 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 17 Nov 2024 14:15:38 +0900
Subject: [PATCH 077/125] Update CHANGELOG.md

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 65ff53eff1..aabd9f000c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 ### Note
 - Node.js 20.xは非推奨になりました。Node.js 22.x (LTS)の利用を推奨します。
+  - なお、Node.js 23.xは対応していません。
 - DockerのNode.jsが22.11.0に更新されました
 
 ### General

From 00b8d0c0720406e5003bf193b8046ee9d11ee1df Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 17 Nov 2024 17:32:28 +0900
Subject: [PATCH 078/125] Update CONTRIBUTING.md

---
 CONTRIBUTING.md | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f8af6b3df0..fcce19405b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -101,6 +101,20 @@ Be willing to comment on the good points and not just the things you want fixed
 	- Are there any omissions or gaps?
 	- Does it check for anomalies?
 
+## Security Advisory
+### For reporter
+Thank you for your reporting!
+
+If you can also create a patch to fix the vulnerability, please create a PR on the private fork.
+
+> ![note]
+> There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please follow the develop branch.
+
+### For misskey-dev member
+修正PRがdevelopに追従されていないとマージできないので、マージできなかったら
+> Could you merge or rebase onto upstream develop branch?
+などと伝える。
+
 ## Deploy
 The `/deploy` command by issue comment can be used to deploy the contents of a PR to the preview environment.
 ```

From 032dfc782d14d33544559ca9249b396fbd0df41b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 17 Nov 2024 17:33:12 +0900
Subject: [PATCH 079/125] Update CONTRIBUTING.md

---
 CONTRIBUTING.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fcce19405b..53d3e57efb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -107,7 +107,7 @@ Thank you for your reporting!
 
 If you can also create a patch to fix the vulnerability, please create a PR on the private fork.
 
-> ![note]
+> [!note]
 > There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please follow the develop branch.
 
 ### For misskey-dev member

From 42f9586fc69c5d394a87c94cc89ab152b23f9f8f Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 17 Nov 2024 17:33:50 +0900
Subject: [PATCH 080/125] Update CONTRIBUTING.md

---
 CONTRIBUTING.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 53d3e57efb..1c777259d2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -108,11 +108,13 @@ Thank you for your reporting!
 If you can also create a patch to fix the vulnerability, please create a PR on the private fork.
 
 > [!note]
-> There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please follow the develop branch.
+> There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please keep follow the develop branch.
 
 ### For misskey-dev member
 修正PRがdevelopに追従されていないとマージできないので、マージできなかったら
+
 > Could you merge or rebase onto upstream develop branch?
+
 などと伝える。
 
 ## Deploy

From eed45c7915b3b03832d4831263b6b3140a1584be Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sun, 17 Nov 2024 17:35:27 +0900
Subject: [PATCH 081/125] Update SECURITY.md

---
 SECURITY.md | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/SECURITY.md b/SECURITY.md
index fc5dec5de4..04567baf07 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -6,3 +6,10 @@ This will allow us to assess the risk, and make a fix available before we add a
 bug report to the GitHub repository.
 
 Thanks for helping make Misskey safe for everyone.
+
+## When create a patch
+
+If you can also create a patch to fix the vulnerability, please create a PR on the private fork.
+
+> [!note]
+> There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please keep follow the develop branch.

From 0df6c7917217adb49697049e074934d798139509 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?=
 <46447427+samunohito@users.noreply.github.com>
Date: Mon, 18 Nov 2024 10:36:51 +0900
Subject: [PATCH 082/125] =?UTF-8?q?enhance(frontend):=20=E3=83=87=E3=83=83?=
 =?UTF-8?q?=E3=82=AD=E8=A1=A8=E7=A4=BA=E6=99=82=E3=81=AB=E3=82=B5=E3=82=A4?=
 =?UTF-8?q?=E3=83=89=E3=83=90=E3=83=BC=E3=82=92=E5=B1=95=E9=96=8B=E3=83=BB?=
 =?UTF-8?q?=E6=8A=98=E3=82=8A=E3=81=9F=E3=81=9F=E3=81=BF=E3=81=A7=E3=81=8D?=
 =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#14983)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(frontend): デッキ表示時にサイドバーを展開・折りたたみできるように

* wip

* wip

* Update navbar.vue

* ✌️

* Update CHANGELOG.md

* 🎨

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 CHANGELOG.md                                  |  1 +
 .../frontend/src/pages/settings/navbar.vue    |  4 --
 packages/frontend/src/ui/_common_/navbar.vue  | 67 ++++++++++++++++++-
 3 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index aabd9f000c..53cb13d273 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@
 - Enhance: ノート詳細画面にロールのバッジを表示
 - Enhance: 過去に送信したフォローリクエストを確認できるように  
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
+- Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/packages/frontend/src/pages/settings/navbar.vue b/packages/frontend/src/pages/settings/navbar.vue
index b189db0f8f..c38cdc4fc2 100644
--- a/packages/frontend/src/pages/settings/navbar.vue
+++ b/packages/frontend/src/pages/settings/navbar.vue
@@ -100,10 +100,6 @@ function reset() {
 	}));
 }
 
-watch(menuDisplay, async () => {
-	await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
-});
-
 const headerActions = computed(() => []);
 
 const headerTabs = computed(() => []);
diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue
index 8ae11efa2c..8fc76741e3 100644
--- a/packages/frontend/src/ui/_common_/navbar.vue
+++ b/packages/frontend/src/ui/_common_/navbar.vue
@@ -56,6 +56,21 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</button>
 		</div>
 	</div>
+	<button v-if="!forceIconOnly" class="_button" :class="$style.toggleButton" @click="toggleIconOnly">
+		<!--
+		<svg viewBox="0 0 16 48" :class="$style.toggleButtonShape">
+			<g transform="matrix(0.333333,0,0,0.222222,0.000895785,13.3333)">
+				<path d="M23.935,-24C37.223,-24 47.995,-7.842 47.995,12.09C47.995,34.077 47.995,62.07 47.995,84.034C47.995,93.573 45.469,102.721 40.972,109.466C36.475,116.211 30.377,120 24.018,120L23.997,120C10.743,120 -0.003,136.118 -0.003,156C-0.003,156 -0.003,156 -0.003,156L-0.003,-60L-0.003,-59.901C-0.003,-50.379 2.519,-41.248 7.007,-34.515C11.496,-27.782 17.584,-24 23.931,-24C23.932,-24 23.934,-24 23.935,-24Z" style="fill:var(--MI_THEME-navBg);"/>
+			</g>
+		</svg>
+		-->
+		<svg viewBox="0 0 16 64" :class="$style.toggleButtonShape">
+			<g transform="matrix(0.333333,0,0,0.222222,0.000895785,21.3333)">
+				<path d="M47.488,7.995C47.79,10.11 47.943,12.266 47.943,14.429C47.997,26.989 47.997,84 47.997,84C47.997,84 44.018,118.246 23.997,133.5C-0.374,152.07 -0.003,192 -0.003,192L-0.003,-96C-0.003,-96 0.151,-56.216 23.997,-37.5C40.861,-24.265 46.043,-1.243 47.488,7.995Z" style="fill:var(--MI_THEME-navBg);"/>
+			</g>
+		</svg>
+		<i :class="'ti ' + `ti-chevron-${ iconOnly ? 'right' : 'left' }`" style="font-size: 12px; margin-left: -8px;"></i>
+	</button>
 </div>
 </template>
 
@@ -80,9 +95,11 @@ const otherMenuItemIndicated = computed(() => {
 	return false;
 });
 
-const calcViewState = () => {
-	iconOnly.value = (window.innerWidth <= 1279) || (defaultStore.state.menuDisplay === 'sideIcon');
-};
+const forceIconOnly = window.innerWidth <= 1279;
+
+function calcViewState() {
+	iconOnly.value = forceIconOnly || (defaultStore.state.menuDisplay === 'sideIcon');
+}
 
 calcViewState();
 
@@ -92,6 +109,10 @@ watch(defaultStore.reactiveState.menuDisplay, () => {
 	calcViewState();
 });
 
+function toggleIconOnly() {
+	defaultStore.set('menuDisplay', iconOnly.value ? 'sideFull' : 'sideIcon');
+}
+
 function openAccountMenu(ev: MouseEvent) {
 	openAccountMenu_({
 		withExtraOperation: true,
@@ -133,6 +154,38 @@ function more(ev: MouseEvent) {
 	contain: strict;
 	display: flex;
 	flex-direction: column;
+	direction: rtl; // スクロールバーを左に表示したいため
+}
+
+.top {
+	direction: ltr;
+}
+
+.middle {
+	direction: ltr;
+}
+
+.bottom {
+	direction: ltr;
+}
+
+.toggleButton {
+	position: fixed;
+	bottom: 20px;
+	left: var(--nav-width);
+	z-index: 1001;
+	width: 16px;
+	height: 64px;
+	box-sizing: border-box;
+}
+
+.toggleButtonShape {
+	position: absolute;
+	z-index: -1;
+	top: 0;
+	left: 0;
+	width: 16px;
+	height: 64px;
 }
 
 .root:not(.iconOnly) {
@@ -363,6 +416,10 @@ function more(ev: MouseEvent) {
 		position: relative;
 		font-size: 0.9em;
 	}
+
+	.toggleButton {
+		left: var(--nav-width);
+	}
 }
 
 .root.iconOnly {
@@ -563,5 +620,9 @@ function more(ev: MouseEvent) {
 			font-size: 10px;
 		}
 	}
+
+	.toggleButton {
+		left: var(--nav-icon-only-width);
+	}
 }
 </style>

From 81348f1277f598c442c425292597c53c183570d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Tue, 19 Nov 2024 10:22:47 +0900
Subject: [PATCH 083/125] =?UTF-8?q?fix(frontend):=20TypeScript=E3=81=AE?=
 =?UTF-8?q?=E5=9E=8B=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E5=AF=BE=E8=B1=A1?=
 =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92=E9=99=90=E5=AE=9A?=
 =?UTF-8?q?=E3=81=97=E3=81=A6=E9=AB=98=E9=80=9F=E5=8C=96=E3=81=99=E3=82=8B?=
 =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=20(#14994)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix frontend tsconfig includes

* fix frontend-embed tsconfig includes

* fix eslint in frontend / frontend-embed

* Update Changelog

---------

Co-authored-by: Hazelnoot <acomputerdog@gmail.com>
---
 CHANGELOG.md                          | 2 ++
 packages/frontend-embed/tsconfig.json | 7 ++++---
 packages/frontend/tsconfig.json       | 7 +++++--
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53cb13d273..9bafcebfa5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,8 @@
 - Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
 - Fix: 画面幅が狭い環境でデザインが崩れる問題を修正  
 	(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/815)
+- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように  
+	(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/725)
 
 ### Server
 - Enhance: DockerのNode.jsを22.11.0に更新
diff --git a/packages/frontend-embed/tsconfig.json b/packages/frontend-embed/tsconfig.json
index 3701343623..45f933dc28 100644
--- a/packages/frontend-embed/tsconfig.json
+++ b/packages/frontend-embed/tsconfig.json
@@ -33,7 +33,7 @@
 			"./node_modules"
 		],
 		"types": [
-			"vite/client",
+			"vite/client"
 		],
 		"lib": [
 			"esnext",
@@ -44,8 +44,9 @@
 	},
 	"compileOnSave": false,
 	"include": [
-		"./**/*.ts",
-		"./**/*.vue"
+		"./src/**/*.ts",
+		"./src/**/*.vue",
+		"./@types/**/*.ts"
 	],
 	"exclude": [
 		".storybook/**/*"
diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json
index b88773b598..4e5ca7f559 100644
--- a/packages/frontend/tsconfig.json
+++ b/packages/frontend/tsconfig.json
@@ -45,8 +45,11 @@
 	},
 	"compileOnSave": false,
 	"include": [
-		"./**/*.ts",
-		"./**/*.vue"
+		"./src/**/*.ts",
+		"./src/**/*.vue",
+		"./test/**/*.ts",
+		"./test/**/*.vue",
+		"./@types/**/*.ts"
 	],
 	"exclude": [
 		".storybook/**/*"

From e800c0f85ad968dc1505463cc5e4cf0c8ea862fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A5=BA=E5=AD=90w=20=28Yumechi=29?=
 <35571479+eternal-flame-AD@users.noreply.github.com>
Date: Mon, 18 Nov 2024 19:29:42 -0600
Subject: [PATCH 084/125] =?UTF-8?q?fix(backend):=20=E3=81=8A=E7=9F=A5?=
 =?UTF-8?q?=E3=82=89=E3=81=9B=E4=BD=9C=E6=88=90=E6=99=82=E3=81=AB=E7=94=BB?=
 =?UTF-8?q?=E5=83=8FURL=E5=85=A5=E5=8A=9B=E6=AC=84=E3=82=92=E7=A9=BA?=
 =?UTF-8?q?=E6=AC=84=E3=81=AB=E5=A4=89=E6=9B=B4=E3=81=A7=E3=81=8D=E3=81=AA?=
 =?UTF-8?q?=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3=20=20(#14990)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(backend): アナウンスメントを作成ときに画像URLを後悔できないのを修正

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* Update CHANGELOG.md

Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>

---------

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
---
 CHANGELOG.md                                                 | 1 +
 packages/backend/src/core/AnnouncementService.ts             | 2 +-
 .../src/server/api/endpoints/admin/announcements/create.ts   | 5 +++--
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9bafcebfa5..fe132a2098 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように
 - Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
+- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
 - Enhance: 依存関係の更新
 - Enhance: l10nの更新
 
diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts
index d4fcf19439..a9f6731977 100644
--- a/packages/backend/src/core/AnnouncementService.ts
+++ b/packages/backend/src/core/AnnouncementService.ts
@@ -72,7 +72,7 @@ export class AnnouncementService {
 			updatedAt: null,
 			title: values.title,
 			text: values.text,
-			imageUrl: values.imageUrl,
+			imageUrl: values.imageUrl || null,
 			icon: values.icon,
 			display: values.display,
 			forExistingUsers: values.forExistingUsers,
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
index 2dae1df87d..b8bfda73a4 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
@@ -55,7 +55,7 @@ export const paramDef = {
 	properties: {
 		title: { type: 'string', minLength: 1 },
 		text: { type: 'string', minLength: 1 },
-		imageUrl: { type: 'string', nullable: true, minLength: 1 },
+		imageUrl: { type: 'string', nullable: true, minLength: 0 },
 		icon: { type: 'string', enum: ['info', 'warning', 'error', 'success'], default: 'info' },
 		display: { type: 'string', enum: ['normal', 'banner', 'dialog'], default: 'normal' },
 		forExistingUsers: { type: 'boolean', default: false },
@@ -76,7 +76,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				updatedAt: null,
 				title: ps.title,
 				text: ps.text,
-				imageUrl: ps.imageUrl,
+				/* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- 空の文字列の場合、nullを渡すようにするため */
+				imageUrl: ps.imageUrl || null,
 				icon: ps.icon,
 				display: ps.display,
 				forExistingUsers: ps.forExistingUsers,

From c271534abafe3a05783eab49ba21707ae2dcd531 Mon Sep 17 00:00:00 2001
From: FineArchs <133759614+FineArchs@users.noreply.github.com>
Date: Tue, 19 Nov 2024 10:34:33 +0900
Subject: [PATCH 085/125] =?UTF-8?q?=E3=83=AA=E3=83=8E=E3=83=BC=E3=83=88?=
 =?UTF-8?q?=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC=E3=81=AB=E3=80=8C=E3=83=AA?=
 =?UTF-8?q?=E3=83=8E=E3=83=BC=E3=83=88=E3=81=AE=E8=A9=B3=E7=B4=B0=E3=80=8D?=
 =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=20(#14985)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* add renote-detail menu

* changelog

* Apply suggestions from code review

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>

* Update CHANGELOG.md

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
---
 CHANGELOG.md                                |  1 +
 locales/index.d.ts                          |  4 ++++
 locales/ja-JP.yml                           |  1 +
 packages/frontend/src/components/MkNote.vue | 10 ++++++++++
 4 files changed, 16 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe132a2098..058e41c486 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@
 - Enhance: 過去に送信したフォローリクエストを確認できるように  
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
 - Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
+- Enhance: リノートメニューに「リノートの詳細」を追加
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 24613419ce..0ae188f1f7 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -2362,6 +2362,10 @@ export interface Locale extends ILocale {
      * 詳細
      */
     "details": string;
+    /**
+     * リノートの詳細
+     */
+    "renoteDetails": string;
     /**
      * 絵文字を選択
      */
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 9f32969a79..1b59708d85 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -586,6 +586,7 @@ masterVolume: "マスター音量"
 notUseSound: "サウンドを出力しない"
 useSoundOnlyWhenActive: "Misskeyがアクティブな時のみサウンドを出力する"
 details: "詳細"
+renoteDetails: "リノートの詳細"
 chooseEmoji: "絵文字を選択"
 unableToProcess: "操作を完了できません"
 recentUsed: "最近使用"
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index cf0d0787b1..1a8814b7cb 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -187,6 +187,7 @@ import MkUrlPreview from '@/components/MkUrlPreview.vue';
 import MkInstanceTicker from '@/components/MkInstanceTicker.vue';
 import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js';
 import { checkWordMute } from '@/scripts/check-word-mute.js';
+import { notePage } from '@/filters/note.js';
 import { userPage } from '@/filters/user.js';
 import number from '@/filters/number.js';
 import * as os from '@/os.js';
@@ -566,15 +567,24 @@ function showRenoteMenu(): void {
 		};
 	}
 
+	const renoteDetailsMenu: MenuItem = {
+		type: 'link',
+		text: i18n.ts.renoteDetails,
+		icon: 'ti ti-info-circle',
+		to: notePage(note.value),
+	};
+
 	if (isMyRenote) {
 		pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 		os.popupMenu([
+			renoteDetailsMenu,
 			getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote),
 			{ type: 'divider' },
 			getUnrenote(),
 		], renoteTime.value);
 	} else {
 		os.popupMenu([
+			renoteDetailsMenu,
 			getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote),
 			{ type: 'divider' },
 			getAbuseNoteMenu(note.value, i18n.ts.reportAbuseRenote),

From 7b9c884a5d550b126c627fac18064fc3a8ca177a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?=
 <46447427+samunohito@users.noreply.github.com>
Date: Tue, 19 Nov 2024 10:41:39 +0900
Subject: [PATCH 086/125] =?UTF-8?q?refactor(backend):=20SystemWebhook?=
 =?UTF-8?q?=E3=81=A7=E9=80=81=E4=BF=A1=E3=81=95=E3=82=8C=E3=82=8B=E3=83=9A?=
 =?UTF-8?q?=E3=82=A4=E3=83=AD=E3=83=BC=E3=83=89=E3=81=AE=E5=9E=8B=E3=82=92?=
 =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20(#14980)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../core/AbuseReportNotificationService.ts    |  6 ++--
 packages/backend/src/core/QueueService.ts     | 13 +++----
 .../backend/src/core/SystemWebhookService.ts  | 33 ++++++++++++++++-
 .../backend/src/core/WebhookTestService.ts    | 36 +++++++++----------
 .../backend/src/models/AbuseUserReport.ts     |  4 ++-
 5 files changed, 63 insertions(+), 29 deletions(-)

diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts
index 25e265f2b1..742e2621fd 100644
--- a/packages/backend/src/core/AbuseReportNotificationService.ts
+++ b/packages/backend/src/core/AbuseReportNotificationService.ts
@@ -154,9 +154,9 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
 		const convertedReports = abuseReports.map(it => {
 			return {
 				...it,
-				reporter: usersMap.get(it.reporterId),
-				targetUser: usersMap.get(it.targetUserId),
-				assignee: it.assigneeId ? usersMap.get(it.assigneeId) : null,
+				reporter: usersMap.get(it.reporterId) ?? null,
+				targetUser: usersMap.get(it.targetUserId) ?? null,
+				assignee: it.assigneeId ? (usersMap.get(it.assigneeId) ?? null) : null,
 			};
 		});
 
diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts
index 50f08da241..da76dd1284 100644
--- a/packages/backend/src/core/QueueService.ts
+++ b/packages/backend/src/core/QueueService.ts
@@ -7,13 +7,15 @@ import { randomUUID } from 'node:crypto';
 import { Inject, Injectable } from '@nestjs/common';
 import type { IActivity } from '@/core/activitypub/type.js';
 import type { MiDriveFile } from '@/models/DriveFile.js';
-import type { MiWebhook, WebhookEventTypes, webhookEventTypes } from '@/models/Webhook.js';
+import type { MiWebhook, WebhookEventTypes } from '@/models/Webhook.js';
 import type { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js';
 import type { Config } from '@/config.js';
 import { DI } from '@/di-symbols.js';
 import { bindThis } from '@/decorators.js';
 import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js';
 import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js';
+import { type SystemWebhookPayload } from '@/core/SystemWebhookService.js';
+import { type UserWebhookPayload } from './UserWebhookService.js';
 import type {
 	DbJobData,
 	DeliverJobData,
@@ -30,12 +32,11 @@ import type {
 	ObjectStorageQueue,
 	RelationshipQueue,
 	SystemQueue,
-	UserWebhookDeliverQueue,
 	SystemWebhookDeliverQueue,
+	UserWebhookDeliverQueue,
 } from './QueueModule.js';
 import type httpSignature from '@peertube/http-signature';
 import type * as Bull from 'bullmq';
-import { type UserWebhookPayload } from './UserWebhookService.js';
 
 @Injectable()
 export class QueueService {
@@ -501,10 +502,10 @@ export class QueueService {
 	 * @see SystemWebhookDeliverProcessorService
 	 */
 	@bindThis
-	public systemWebhookDeliver(
+	public systemWebhookDeliver<T extends SystemWebhookEventType>(
 		webhook: MiSystemWebhook,
-		type: SystemWebhookEventType,
-		content: unknown,
+		type: T,
+		content: SystemWebhookPayload<T>,
 		opts?: { attempts?: number },
 	) {
 		const data: SystemWebhookDeliverJobData = {
diff --git a/packages/backend/src/core/SystemWebhookService.ts b/packages/backend/src/core/SystemWebhookService.ts
index db6407dcb3..de00169612 100644
--- a/packages/backend/src/core/SystemWebhookService.ts
+++ b/packages/backend/src/core/SystemWebhookService.ts
@@ -15,8 +15,39 @@ import { QueueService } from '@/core/QueueService.js';
 import { ModerationLogService } from '@/core/ModerationLogService.js';
 import { LoggerService } from '@/core/LoggerService.js';
 import Logger from '@/logger.js';
+import { Packed } from '@/misc/json-schema.js';
+import { AbuseReportResolveType } from '@/models/AbuseUserReport.js';
+import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModeratorsActivityProcessorService.js';
 import type { OnApplicationShutdown } from '@nestjs/common';
 
+export type AbuseReportPayload = {
+	id: string;
+	targetUserId: string;
+	targetUser: Packed<'UserLite'> | null;
+	targetUserHost: string | null;
+	reporterId: string;
+	reporter: Packed<'UserLite'> | null;
+	reporterHost: string | null;
+	assigneeId: string | null;
+	assignee: Packed<'UserLite'> | null;
+	resolved: boolean;
+	forwarded: boolean;
+	comment: string;
+	moderationNote: string;
+	resolvedAs: AbuseReportResolveType | null;
+};
+
+export type InactiveModeratorsWarningPayload = {
+	remainingTime: ModeratorInactivityRemainingTime;
+};
+
+export type SystemWebhookPayload<T extends SystemWebhookEventType> =
+	T extends 'abuseReport' | 'abuseReportResolved' ? AbuseReportPayload :
+	T extends 'userCreated' ? Packed<'UserLite'> :
+	T extends 'inactiveModeratorsWarning' ? InactiveModeratorsWarningPayload :
+	T extends 'inactiveModeratorsInvitationOnlyChanged' ? Record<string, never> :
+		never;
+
 @Injectable()
 export class SystemWebhookService implements OnApplicationShutdown {
 	private logger: Logger;
@@ -168,7 +199,7 @@ export class SystemWebhookService implements OnApplicationShutdown {
 	public async enqueueSystemWebhook<T extends SystemWebhookEventType>(
 		webhook: MiSystemWebhook | MiSystemWebhook['id'],
 		type: T,
-		content: unknown,
+		content: SystemWebhookPayload<T>,
 	) {
 		const webhookEntity = typeof webhook === 'string'
 			? (await this.fetchActiveSystemWebhooks()).find(a => a.id === webhook)
diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts
index b1ea7974fb..555a39f71c 100644
--- a/packages/backend/src/core/WebhookTestService.ts
+++ b/packages/backend/src/core/WebhookTestService.ts
@@ -7,7 +7,7 @@ import { Injectable } from '@nestjs/common';
 import { MiAbuseUserReport, MiNote, MiUser, MiWebhook } from '@/models/_.js';
 import { bindThis } from '@/decorators.js';
 import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js';
-import { SystemWebhookService } from '@/core/SystemWebhookService.js';
+import { AbuseReportPayload, SystemWebhookPayload, SystemWebhookService } from '@/core/SystemWebhookService.js';
 import { Packed } from '@/misc/json-schema.js';
 import { type WebhookEventTypes } from '@/models/Webhook.js';
 import { type UserWebhookPayload, UserWebhookService } from '@/core/UserWebhookService.js';
@@ -16,13 +16,7 @@ import { ModeratorInactivityRemainingTime } from '@/queue/processors/CheckModera
 
 const oneDayMillis = 24 * 60 * 60 * 1000;
 
-type AbuseUserReportDto = Omit<MiAbuseUserReport, 'targetUser' | 'reporter' | 'assignee'> & {
-	targetUser: Packed<'UserLite'> | null,
-	reporter: Packed<'UserLite'> | null,
-	assignee: Packed<'UserLite'> | null,
-};
-
-function generateAbuseReport(override?: Partial<MiAbuseUserReport>): AbuseUserReportDto {
+function generateAbuseReport(override?: Partial<MiAbuseUserReport>): AbuseReportPayload {
 	const result: MiAbuseUserReport = {
 		id: 'dummy-abuse-report1',
 		targetUserId: 'dummy-target-user',
@@ -389,7 +383,8 @@ export class WebhookTestService {
 				break;
 			}
 			// まだ実装されていない (#9485)
-			case 'reaction': return;
+			case 'reaction':
+				return;
 			default: {
 				// eslint-disable-next-line @typescript-eslint/no-unused-vars
 				const _exhaustiveAssertion: never = params.type;
@@ -407,10 +402,10 @@ export class WebhookTestService {
 	 * - 送信対象イベント(on)に関する設定
 	 */
 	@bindThis
-	public async testSystemWebhook(
+	public async testSystemWebhook<T extends SystemWebhookEventType>(
 		params: {
 			webhookId: MiSystemWebhook['id'],
-			type: SystemWebhookEventType,
+			type: T,
 			override?: Partial<Omit<MiSystemWebhook, 'id'>>,
 		},
 	) {
@@ -420,7 +415,7 @@ export class WebhookTestService {
 		}
 
 		const webhook = webhooks[0];
-		const send = (contents: unknown) => {
+		const send = <U extends SystemWebhookEventType>(type: U, contents: SystemWebhookPayload<U>) => {
 			const merged = {
 				...webhook,
 				...params.override,
@@ -428,12 +423,12 @@ export class WebhookTestService {
 
 			// テスト目的なのでSystemWebhookServiceの機能を経由せず直接キューに追加する(チェック処理などをスキップする意図).
 			// また、Jobの試行回数も1回だけ.
-			this.queueService.systemWebhookDeliver(merged, params.type, contents, { attempts: 1 });
+			this.queueService.systemWebhookDeliver(merged, type, contents, { attempts: 1 });
 		};
 
 		switch (params.type) {
 			case 'abuseReport': {
-				send(generateAbuseReport({
+				send('abuseReport', generateAbuseReport({
 					targetUserId: dummyUser1.id,
 					targetUser: dummyUser1,
 					reporterId: dummyUser2.id,
@@ -442,7 +437,7 @@ export class WebhookTestService {
 				break;
 			}
 			case 'abuseReportResolved': {
-				send(generateAbuseReport({
+				send('abuseReportResolved', generateAbuseReport({
 					targetUserId: dummyUser1.id,
 					targetUser: dummyUser1,
 					reporterId: dummyUser2.id,
@@ -454,7 +449,7 @@ export class WebhookTestService {
 				break;
 			}
 			case 'userCreated': {
-				send(toPackedUserLite(dummyUser1));
+				send('userCreated', toPackedUserLite(dummyUser1));
 				break;
 			}
 			case 'inactiveModeratorsWarning': {
@@ -464,15 +459,20 @@ export class WebhookTestService {
 					asHours: 24,
 				};
 
-				send({
+				send('inactiveModeratorsWarning', {
 					remainingTime: dummyTime,
 				});
 				break;
 			}
 			case 'inactiveModeratorsInvitationOnlyChanged': {
-				send({});
+				send('inactiveModeratorsInvitationOnlyChanged', {});
 				break;
 			}
+			default: {
+				// eslint-disable-next-line @typescript-eslint/no-unused-vars
+				const _exhaustiveAssertion: never = params.type;
+				return;
+			}
 		}
 	}
 }
diff --git a/packages/backend/src/models/AbuseUserReport.ts b/packages/backend/src/models/AbuseUserReport.ts
index cb5672e4ac..d43ebf9342 100644
--- a/packages/backend/src/models/AbuseUserReport.ts
+++ b/packages/backend/src/models/AbuseUserReport.ts
@@ -7,6 +7,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typ
 import { id } from './util/id.js';
 import { MiUser } from './User.js';
 
+export type AbuseReportResolveType = 'accept' | 'reject';
+
 @Entity('abuse_user_report')
 export class MiAbuseUserReport {
 	@PrimaryColumn(id())
@@ -76,7 +78,7 @@ export class MiAbuseUserReport {
 	@Column('varchar', {
 		length: 128, nullable: true,
 	})
-	public resolvedAs: 'accept' | 'reject' | null;
+	public resolvedAs: AbuseReportResolveType | null;
 
 	//#region Denormalized fields
 	@Index()

From 968f5956060bb15bfcbd5bd79075ea7c8a775d3e Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 19 Nov 2024 12:50:04 +0900
Subject: [PATCH 087/125] New Crowdin updates (#14965)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Dutch)

* New translations ja-jp.yml (Norwegian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Turkish)

* New translations ja-jp.yml (Ukrainian)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Uzbek)

* New translations ja-jp.yml (Lao)

* New translations ja-jp.yml (Japanese, Kansai)

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Chinese Simplified)
---
 locales/ar-SA.yml |   1 -
 locales/bn-BD.yml |   1 -
 locales/ca-ES.yml |   7 +-
 locales/cs-CZ.yml |   1 -
 locales/de-DE.yml | 146 ++++++++++++++++++++++++++++++++-
 locales/en-US.yml |   3 +-
 locales/es-ES.yml |   1 -
 locales/fr-FR.yml | 201 ++++++++++++++++++++++++++++++++++++++++++++--
 locales/id-ID.yml |   1 -
 locales/it-IT.yml |   1 -
 locales/ja-KS.yml |   1 -
 locales/ko-GS.yml |   1 -
 locales/ko-KR.yml |   3 +-
 locales/lo-LA.yml |   1 -
 locales/nl-NL.yml |   1 -
 locales/no-NO.yml |   1 -
 locales/pl-PL.yml |  27 ++++++-
 locales/pt-PT.yml |   1 -
 locales/ro-RO.yml |   1 -
 locales/ru-RU.yml |   1 -
 locales/sk-SK.yml |   1 -
 locales/sv-SE.yml |  19 ++++-
 locales/th-TH.yml |   1 -
 locales/tr-TR.yml |   1 -
 locales/uk-UA.yml |   1 -
 locales/uz-UZ.yml |   1 -
 locales/vi-VN.yml |   1 -
 locales/zh-CN.yml |   8 +-
 locales/zh-TW.yml |   9 ++-
 29 files changed, 404 insertions(+), 39 deletions(-)

diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml
index de24ad4bb9..2f1b391b53 100644
--- a/locales/ar-SA.yml
+++ b/locales/ar-SA.yml
@@ -343,7 +343,6 @@ enableLocalTimeline: "تفعيل الخيط المحلي"
 enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
 disablingTimelinesInfo: "سيتمكن المديرون والمشرفون من الوصول إلى كل الخيوط الزمنية حتى وإن لم تفعّل."
 registration: "إنشاء حساب"
-enableRegistration: "تفعيل إنشاء الحسابات الجديدة"
 invite: "دعوة"
 driveCapacityPerLocalAccount: "حصة التخزين لكل مستخدم محلي"
 driveCapacityPerRemoteAccount: "حصة التخزين لكل مستخدم بعيد"
diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml
index 0e761b0743..6cd577b4a9 100644
--- a/locales/bn-BD.yml
+++ b/locales/bn-BD.yml
@@ -339,7 +339,6 @@ enableLocalTimeline: "স্থানীয় টাইমলাইন চাল
 enableGlobalTimeline: "গ্লোবাল টাইমলাইন চালু করুন"
 disablingTimelinesInfo: "আপনি এই টাইমলাইনগুলি বন্ধ করলেও প্রশাসক এবং মডারেটররা এই টাইমলাইনগুলি ব্যাবহার করতে পারবে"
 registration: "নিবন্ধন"
-enableRegistration: "নতুন ব্যাবহারকারী নিবন্ধন চালু করুন"
 invite: "আমন্ত্রণ"
 driveCapacityPerLocalAccount: "প্রত্যেক স্থানীয় ব্যাবহারকারীর জন্য ড্রাইভের জায়গা"
 driveCapacityPerRemoteAccount: "প্রত্যেক রিমোট ব্যাবহারকারীর জন্য ড্রাইভের জায়গা"
diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index 048abfd781..b301780972 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "Activa la línia de temps local"
 enableGlobalTimeline: "Activa la línia de temps global"
 disablingTimelinesInfo: "Fins i tot si aquestes línies de temps són desactivades, els administradors i els moderadors poden continuar visualitzant per conveniència."
 registration: "Registre"
-enableRegistration: "Permet el registre de nous usuaris"
 invite: "Convida"
 driveCapacityPerLocalAccount: "Capacitat del disc per usuaris locals"
 driveCapacityPerRemoteAccount: "Capacitat del disc per usuaris remots"
@@ -1300,6 +1299,7 @@ thisContentsAreMarkedAsSigninRequiredByAuthor: "L'autor requereix l'inici de ses
 lockdown: "Bloquejat"
 pleaseSelectAccount: "Seleccionar un compte"
 availableRoles: "Roles disponibles "
+acknowledgeNotesAndEnable: "Activa'l després de comprendre els possibles perills."
 _accountSettings:
   requireSigninToViewContents: "És obligatori l'inici de sessió per poder veure el contingut"
   requireSigninToViewContentsDescription1: "Es requereix l'inici de sessió per poder veure totes les notes i el contingut que has creat. Amb això esperem evitar que els rastrejadors recopilin informació."
@@ -1456,6 +1456,8 @@ _serverSettings:
   reactionsBufferingDescription: "Quan s'activa aquesta opció millora bastant el rendiment en recuperar les línies de temps reduint la càrrega de la base. Com a contrapunt, augmentarà  l'ús de memòria de Redís. Desactiva aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes d'inestabilitat."
   inquiryUrl: "URL de consulta "
   inquiryUrlDescription: "Escriu adreça URL per al formulari de consulta per al mantenidor del servidor o una pàgina web amb el contacte d'informació."
+  openRegistration: "Registres oberts"
+  openRegistrationWarning: "Obrir els registres és arriscat. Es recomana obrir-los només si el servidor és monitorat constantment i per respondre immediatament davant qualsevol problema."
   thisSettingWillAutomaticallyOffWhenModeratorsInactive: "Si no es detecta activitat per part del moderador durant un període de temps, aquesta opció es desactiva automàticament per evitar el correu brossa."
 _accountMigration:
   moveFrom: "Migrar un altre compte a aquest"
@@ -2738,3 +2740,6 @@ _selfXssPrevention:
   description1: "Si posa alguna cosa al seu compte, un usuari malintencionat podria segrestar-la o robar-li les dades."
   description2: "Si no entens que estàs fent %cpara ara mateix i tanca la finestra."
   description3: "Per obtenir més informació. {link}"
+_followRequest:
+  recieved: "Sol·licituds rebudes"
+  sent: "Sol·licituds enviades"
diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml
index caf6d6e163..504ba1f8c8 100644
--- a/locales/cs-CZ.yml
+++ b/locales/cs-CZ.yml
@@ -348,7 +348,6 @@ enableLocalTimeline: "Povolit lokální čas"
 enableGlobalTimeline: "Povolit globální čas"
 disablingTimelinesInfo: "Administrátoři a Moderátoři budou mít stálý přístup ke všem časovým osám i přes to že nejsou zapnuté."
 registration: "Registrace"
-enableRegistration: "Povolit registraci novým uživatelům"
 invite: "Pozvat"
 driveCapacityPerLocalAccount: "Kapacita disku na lokálního uživatele"
 driveCapacityPerRemoteAccount: "Kapacita disku na vzdáleného uživatele"
diff --git a/locales/de-DE.yml b/locales/de-DE.yml
index 1aacbabbba..1b3925ef38 100644
--- a/locales/de-DE.yml
+++ b/locales/de-DE.yml
@@ -10,6 +10,7 @@ username: "Benutzername"
 password: "Passwort"
 initialPasswordForSetup: "Initiales Passwort für die Einrichtung"
 initialPasswordIsIncorrect: "Das initiale Passwort für die Einrichtung ist falsch"
+initialPasswordForSetupDescription: "Verwende das in der Konfigurationsdatei angegebene Passwort, wenn du Misskey selbst installiert hast.\nWenn du einen Misskey-Hostingdienst o.ä. nutzt, verwende das dort angegebene Kennwort.\nWenn du kein Passwort festgelegt hast, lasse es leer, um fortzufahren."
 forgotPassword: "Passwort vergessen"
 fetchingAsApObject: "Wird aus dem Fediverse angefragt …"
 ok: "OK"
@@ -111,11 +112,14 @@ enterEmoji: "Gib ein Emoji ein"
 renote: "Renote"
 unrenote: "Renote zurücknehmen"
 renoted: "Renote getätigt."
+renotedToX: "Renoted zu {name}."
 cantRenote: "Renote dieses Beitrags nicht möglich."
 cantReRenote: "Renote einer Renote nicht möglich."
 quote: "Zitieren"
 inChannelRenote: "Kanal-interner Renote"
 inChannelQuote: "Kanal-internes Zitat"
+renoteToChannel: "Renote zu Kanal"
+renoteToOtherChannel: "Renote zu anderem Kanal"
 pinnedNote: "Angeheftete Notiz"
 pinned: "Angeheftet"
 you: "Du"
@@ -127,12 +131,13 @@ reactions: "Reaktionen"
 emojiPicker: "Emoji auswählen"
 pinnedEmojisForReactionSettingDescription: "Lege Emojis fest, die angepinnt werden sollen, um sie beim Reagieren als Erstes anzuzeigen."
 pinnedEmojisSettingDescription: "Lege Emojis fest, die angepinnt werden sollen, um sie in der Emoji-Auswahl als Erstes anzuzeigen"
+emojiPickerDisplay: "Anzeige der Emoji-Auswahl"
 overwriteFromPinnedEmojisForReaction: "Überschreiben mit den Reaktions-Einstellungen"
 overwriteFromPinnedEmojis: "Überschreiben mit den allgemeinen Einstellungen"
 reactionSettingDescription2: "Ziehe um Anzuordnen, klicke um zu löschen, drücke „+“ um hinzuzufügen"
 rememberNoteVisibility: "Notizsichtbarkeit merken"
 attachCancel: "Anhang entfernen"
-deleteFile: "Datei gelöscht"
+deleteFile: "Datei löschen"
 markAsSensitive: "Als sensibel markieren"
 unmarkAsSensitive: "Als nicht sensibel markieren"
 enterFileName: "Dateinamen eingeben"
@@ -180,6 +185,8 @@ addAccount: "Benutzerkonto hinzufügen"
 reloadAccountsList: "Benutzerkontoliste aktualisieren"
 loginFailed: "Anmeldung fehlgeschlagen"
 showOnRemote: "Auf Ursprungsinstanz ansehen"
+chooseServerOnMisskeyHub: "Wähle einen Server aus dem Misskey Hub"
+inputHostName: "Gib die Domain an"
 general: "Allgemein"
 wallpaper: "Hintergrund"
 setWallpaper: "Hintergrund festlegen"
@@ -206,6 +213,7 @@ perDay: "Pro Tag"
 stopActivityDelivery: "Senden von Aktivitäten einstellen"
 blockThisInstance: "Diese Instanz blockieren"
 silenceThisInstance: "Instanz stummschalten"
+mediaSilenceThisInstance: "Medien dieses Servers stummschalten"
 operations: "Aktionen"
 software: "Software"
 version: "Version"
@@ -227,6 +235,8 @@ blockedInstances: "Blockierte Instanzen"
 blockedInstancesDescription: "Gib die Hostnamen der Instanzen, welche blockiert werden sollen, durch Zeilenumbrüche getrennt an. Blockierte Instanzen können mit dieser instanz nicht mehr kommunizieren."
 silencedInstances: "Stummgeschaltete Instanzen"
 silencedInstancesDescription: "Gib die Hostnamen der Instanzen, welche stummgeschaltet werden sollen, durch Zeilenumbrüche getrennt an. Alle Konten dieser Instanzen werden als stummgeschaltet behandelt, können nur noch Follow-Anfragen stellen und wenn nicht gefolgt keine lokalen Konten erwähnen. Blockierte Instanzen sind davon nicht betroffen."
+mediaSilencedInstances: "Medien-stummgeschaltete Server"
+mediaSilencedInstancesDescription: "Gib pro Zeile die Hostnamen der Server ein, dessen Medien du stummschalten möchtest. Alle Benutzerkonten der aufgeführten Server werden als sensibel behandelt und können keine benutzerdefinierten Emojis verwenden. Gesperrte Server sind davon nicht betroffen."
 muteAndBlock: "Stummschaltungen und Blockierungen"
 mutedUsers: "Stummgeschaltete Benutzer"
 blockedUsers: "Blockierte Benutzer"
@@ -325,6 +335,7 @@ renameFolder: "Ordner umbenennen"
 deleteFolder: "Ordner löschen"
 folder: "Ordner"
 addFile: "Datei hinzufügen"
+showFile: "Datei anzeigen"
 emptyDrive: "Deine Drive ist leer"
 emptyFolder: "Dieser Ordner ist leer"
 unableToDelete: "Nicht löschbar"
@@ -367,7 +378,6 @@ enableLocalTimeline: "Lokale Chronik aktivieren"
 enableGlobalTimeline: "Globale Chronik aktivieren"
 disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
 registration: "Registrieren"
-enableRegistration: "Registrierung neuer Benutzer erlauben"
 invite: "Einladen"
 driveCapacityPerLocalAccount: "Drive-Kapazität pro lokalem Benutzerkonto"
 driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer fremder Instanzen"
@@ -473,6 +483,7 @@ retype: "Erneut eingeben"
 noteOf: "Notiz von {user}"
 quoteAttached: "Zitat"
 quoteQuestion: "Als Zitat anhängen?"
+attachAsFileQuestion: "Der Text in der Zwischenablage ist lang. Möchtest du ihn als Textdatei anhängen?"
 noMessagesYet: "Noch keine Nachrichten vorhanden"
 newMessageExists: "Du hast eine neue Nachricht"
 onlyOneFileCanBeAttached: "Es kann pro Nachricht nur eine Datei angehängt werden"
@@ -498,7 +509,11 @@ uiLanguage: "Sprache der Benutzeroberfläche"
 aboutX: "Über {x}"
 emojiStyle: "Emoji-Stil"
 native: "Nativ"
+menuStyle: "Menü Stil"
+style: "Stil"
+popup: "Pop-up"
 showNoteActionsOnlyHover: "Notizmenü nur bei Mouseover anzeigen"
+showReactionsCount: "Zeige die Anzahl der Reaktionen auf Notizen an"
 noHistory: "Kein Verlauf gefunden"
 signinHistory: "Anmeldungsverlauf"
 enableAdvancedMfm: "Erweitertes MFM aktivieren"
@@ -579,6 +594,7 @@ ascendingOrder: "Aufsteigende Reihenfolge"
 descendingOrder: "Absteigende Reihenfolge"
 scratchpad: "Testumgebung"
 scratchpadDescription: "Die Testumgebung bietet einen Bereich für AiScript-Experimente. Dort kannst du AiScript schreiben, ausführen sowie dessen Auswirkungen auf Misskey überprüfen."
+uiInspector: "UI-Inspektor"
 output: "Ausgabe"
 script: "Skript"
 disablePagesScript: "AiScript auf Seiten deaktivieren"
@@ -659,6 +675,7 @@ smtpSecure: "Für SMTP-Verbindungen implizit SSL/TLS verwenden"
 smtpSecureInfo: "Schalte dies aus, falls du STARTTLS verwendest."
 testEmail: "Emailversand testen"
 wordMute: "Wortstummschaltung"
+hardWordMute: "Harte Wort-Stummschaltung"
 regexpError: "Fehler in einem regulären Ausdruck"
 regexpErrorDescription: "Im regulären Ausdruck deiner in Zeile {line} von {tab}en Wortstummschaltungen ist ein Fehler aufgetreten:"
 instanceMute: "Instanzstummschaltungen"
@@ -680,6 +697,7 @@ useGlobalSettingDesc: "Ist diese Option aktiviert, werden die Benachrichtigungse
 other: "Anderes"
 regenerateLoginToken: "Anmeldetoken regenerieren"
 regenerateLoginTokenDescription: "Den zur Anmeldung intern verwendeten Token regenerieren. Normalerweise wird dies nicht benötigt. Bei Regeneration werden alle Geräte ausgeloggt."
+theKeywordWhenSearchingForCustomEmoji: "Das ist das Schlagwort beim Suchen von benutzerdefinierten Emojis."
 setMultipleBySeparatingWithSpace: "Trenne Elemente durch ein Leerzeichen um mehrere Einstellungen zu kofigurieren."
 fileIdOrUrl: "Datei-ID oder URL"
 behavior: "Verhalten"
@@ -889,6 +907,8 @@ makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktion
 classic: "Classic"
 muteThread: "Thread stummschalten"
 unmuteThread: "Threadstummschaltung aufheben"
+followingVisibility: "Sichtbarkeit der Gefolgten"
+followersVisibility: "Sichtbarkeit der Folgenden"
 continueThread: "Weiteren Threadverlauf anzeigen"
 deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?"
 incorrectPassword: "Falsches Passwort."
@@ -1021,6 +1041,7 @@ thisPostMayBeAnnoyingHome: "Zur Startseite schicken"
 thisPostMayBeAnnoyingCancel: "Abbrechen"
 thisPostMayBeAnnoyingIgnore: "Trotzdem schicken"
 collapseRenotes: "Bereits gesehene Renotes verkürzt anzeigen"
+collapseRenotesDescription: "Klappe Notizen ein, auf die du bereits reagiert oder die du renoted hast."
 internalServerError: "Serverinterner Fehler"
 internalServerErrorDescription: "Im Server ist ein unerwarteter Fehler aufgetreten."
 copyErrorInfo: "Fehlerdetails kopieren"
@@ -1045,6 +1066,7 @@ sensitiveWords: "Sensible Wörter"
 sensitiveWordsDescription: "Die Notizsichtbarkeit aller Notizen, die diese Wörter enthalten, wird automatisch auf \"Startseite\" gesetzt. Durch Zeilenumbrüche können mehrere konfiguriert werden."
 sensitiveWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-Verknüpfungen angegeben werden und durch das Umgeben von Schrägstrichen können reguläre Ausdrücke verwendet werden."
 prohibitedWords: "Verbotene Wörter"
+prohibitedWordsDescription: "Aktiviert eine Fehlermeldung, wenn versucht wird, eine Notiz zu veröffentlichen, die das/die eingestellte(n) Wort(e) enthält. Mehrere Begriffe können durch Zeilenumbrüche getrennt festgelegt werden."
 prohibitedWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-Verknüpfungen angegeben werden und durch das Umgeben von Schrägstrichen können reguläre Ausdrücke verwendet werden."
 hiddenTags: "Ausgeblendete Hashtags"
 hiddenTagsDescription: "Die hier eingestellten Tags werden nicht mehr in den Trends angezeigt. Mit der Umschalttaste können mehrere ausgewählt werden."
@@ -1170,6 +1192,9 @@ confirmShowRepliesAll: "Dies ist eine unwiderrufliche Aktion. Wirklich Antworten
 confirmHideRepliesAll: "Dies ist eine unwiderrufliche Aktion. Wirklich Antworten von allen momentan gefolgten Benutzern nicht in der Chronik anzeigen?"
 externalServices: "Externe Dienste"
 sourceCode: "Quellcode"
+sourceCodeIsNotYetProvided: "Der Quellcode ist noch nicht verfügbar. Kontaktiere den Administrator, um das Problem zu lösen."
+repositoryUrl: "Repository URL"
+repositoryUrlOrTarballRequired: "Wenn du kein Repository veröffentlicht hast, musst du stattdessen einen Tarball bereitstellen. Siehe .config/example.yml für weitere Informationen."
 impressum: "Impressum"
 impressumUrl: "Impressums-URL"
 impressumDescription: "In manchen Ländern, wie Deutschland und dessen Umgebung, ist die Angabe von Betreiberinformationen (ein Impressum) bei kommerziellem Betrieb zwingend."
@@ -1192,34 +1217,76 @@ cwNotationRequired: "Ist \"Inhaltswarnung verwenden\" aktiviert, muss eine Besch
 doReaction: "Reagieren"
 code: "Code"
 remainingN: "Verbleibend: {n}"
+overwriteContentConfirm: "Bist du sicher, dass du den aktuellen Inhalt überschreiben willst?"
+seasonalScreenEffect: "Saisonaler Bildschirmeffekt"
 decorate: "Dekorieren"
 addMfmFunction: "MFM hinzufügen"
+enableQuickAddMfmFunction: "Erweiterte MFM-Auswahl anzeigen"
 sfx: "Soundeffekte"
+soundWillBePlayed: "Es wird Ton wiedergegeben"
 showReplay: "Wiederholung anzeigen"
+ranking: "Rangliste"
 lastNDays: "Letzten {n} Tage"
+backToTitle: "Zurück zum Startbildschirm"
+enableHorizontalSwipe: "Wischen, um zwischen Tabs zu wechseln"
+loading: "Laden"
 surrender: "Abbrechen"
+gameRetry: "Erneut versuchen"
+notUsePleaseLeaveBlank: "Leer lassen, wenn nicht verwendet"
+useTotp: "Gib das Einmalpasswort ein"
+useBackupCode: "Verwende die Backup-Codes"
+launchApp: "Starte die App"
+useNativeUIForVideoAudioPlayer: "Browser-Benutzeroberfläche für die Video- und Audiowiedergabe verwenden"
 keepOriginalFilename: "Ursprünglichen Dateinamen beibehalten"
+keepOriginalFilenameDescription: "Wenn diese Einstellung deaktiviert ist, wird der Dateiname beim Hochladen automatisch durch eine zufällige Zeichenfolge ersetzt."
+noDescription: "Keine Beschreibung vorhanden"
 tryAgain: "Bitte später erneut versuchen"
 confirmWhenRevealingSensitiveMedia: "Das Anzeigen von sensiblen Medien bestätigen"
 createdLists: "Erstellte Listen"
 createdAntennas: "Erstellte Antennen"
+fromX: "Von {x}"
 genEmbedCode: "Einbettungscode generieren"
 noteOfThisUser: "Notizen dieses Benutzers"
 clipNoteLimitExceeded: "Zu diesem Clip können keine weiteren Notizen hinzugefügt werden."
 discard: "Verwerfen"
+thereAreNChanges: "Es gibt {n} Änderung(en)"
 signinWithPasskey: "Mit Passkey anmelden"
 passkeyVerificationFailed: "Die Passkey-Verifizierung ist fehlgeschlagen."
 passkeyVerificationSucceededButPasswordlessLoginDisabled: "Die Verifizierung des Passkeys war erfolgreich, aber die passwortlose Anmeldung ist deaktiviert."
+prohibitedWordsForNameOfUser: "Verbotene Begriffe für Benutzernamen"
+prohibitedWordsForNameOfUserDescription: "Wenn eine Zeichenfolge aus dieser Liste im Namen eines Benutzers enthalten ist, wird der Benutzername abgelehnt. Benutzer mit Moderatorenrechten sind von dieser Einschränkung nicht betroffen."
+yourNameContainsProhibitedWords: "Dein Name enthält einen verbotenen Begriff"
+yourNameContainsProhibitedWordsDescription: "Der Name enthält eine verbotene Zeichenfolge. Wende dich an deinen Serveradministrator, wenn du diesen Namen verwenden möchtest."
 pleaseSelectAccount: "Bitte Konto auswählen"
 availableRoles: "Verfügbare Rollen"
+_accountSettings:
+  requireSigninToViewContents: "Anmeldung erfordern, um Inhalte anzuzeigen"
+  requireSigninToViewContentsDescription1: "Erfordere eine Anmeldung, um alle Notizen und andere Inhalte anzuzeigen, die du erstellt hast. Dadurch wird verhindert, dass Crawler deine Informationen sammeln."
+  requireSigninToViewContentsDescription3: "Diese Einschränkungen gelten möglicherweise nicht für föderierte Inhalte von anderen Servern."
+  makeNotesFollowersOnlyBefore: "Macht frühere Notizen nur für Follower sichtbar"
+  mayNotEffectForFederatedNotes: "Dies hat möglicherweise keine Auswirkungen auf Notizen, die an andere Server föderiert werden."
 _abuseUserReport:
   forward: "Weiterleiten"
+  forwardDescription: "Leite die Meldung an einen entfernten Server als anonymes Systemkonto weiter."
+  accept: "Akzeptieren"
+  reject: "Ablehnen"
 _delivery:
   stop: "Gesperrt"
   _type:
     none: "Wird veröffentlicht"
 _bubbleGame:
   howToPlay: "Wie man spielt"
+  hold: "Halten"
+  _score:
+    score: "Spielstand"
+    scoreYen: "Verdienter Geldbetrag"
+    highScore: "Höchstpunktzahl"
+    maxChain: "Maximale Anzahl an Verkettungen"
+    yen: "{yen} Yen"
+  _howToPlay:
+    section1: "Passe die Position an und lasse das Objekt in das Spielfeld fallen."
+    section2: "Wenn sich zwei Objekte der gleichen Art berühren, verwandeln sie sich in ein anderes Objekt und du bekommst Punkte."
+    section3: "Das Spiel ist vorbei, wenn die Objekte aus dem Spielfeld herausragen. Versuche eine hohe Punktzahl zu erreichen, indem du die Objekte miteinander verschmelzt, ohne dass das Spielfeld überläuft!"
 _announcement:
   forExistingUsers: "Nur für existierende Nutzer"
   forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt."
@@ -1263,8 +1330,18 @@ _initialTutorial:
     reply: "Klicke auf diesen Button, um auf eine Nachricht zu antworten. Es ist auch möglich, auf Antworten zu antworten und die Unterhaltung wie einen Thread fortzusetzen."
   _reaction:
     title: "Was sind Reaktionen?"
+    description: "Auf Notizen kann mit verschiedenen Emojis reagiert werden. Reaktionen ermöglichen es dir, Nuancen auszudrücken, die mit einem einfachen „Gefällt mir“ vielleicht nicht ausgedrückt werden können."
+    letsTryReacting: "Reaktionen können durch Klicken auf die Schaltfläche „+“ in der Notiz hinzugefügt werden. Versuche, auf diese Beispielnotiz zu reagieren!"
     reactToContinue: "Füge eine Reaktion hinzu, um fortzufahren."
     reactNotification: "Du erhältst Echtzeit-Benachrichtigungen, wenn jemand auf deine Notiz reagiert."
+    reactDone: "Du kannst eine Reaktion zurücknehmen, indem du auf den '-' Button drückst."
+  _timeline:
+    title: "So funktionieren die Chroniken"
+    home: "Du kannst Beiträge von den Konten sehen, denen du folgst."
+    local: "Du kannst Beiträge aller Benutzer auf diesem Server sehen."
+    social: "Notizen von der Startseite und der lokalen Chronik werden angezeigt."
+    global: "Du kannst Notizen von allen föderierten Servern sehen."
+    description2: "Du kannst jederzeit am oberen Rand des Bildschirms zwischen den jeweiligen Chroniken wechseln."
   _postNote:
     _visibility:
       description: "Du kannst einschränken, wer deine Notiz sehen kann."
@@ -1272,8 +1349,16 @@ _initialTutorial:
       doNotSendConfidencialOnDirect1: "Sei vorsichtig, wenn du sensible Informationen verschickst!"
     _cw:
       title: "Inhaltswarnung"
+      _exampleNote:
+        note: "Ich hatte gerade einen Donut mit Schokoladenüberzug 🍩😋"
+  _howToMakeAttachmentsSensitive:
+    tryThisFile: "Versuche, das angehängte Bild als sensibel zu markieren!"
+    method: "Um einen Anhang als sensibel zu kennzeichnen, klicke auf das Vorschaubild der Datei, um das Menü zu öffnen, und klicke auf „Als sensibel markieren“."
+    sensitiveSucceeded: "Wenn du Dateien anhängst, stelle bitte die Sensibilität entsprechend der Serverrichtlinien ein."
+    doItToContinue: "Markiere die angehängte Datei als sensibel, um fortzufahren."
   _done:
     title: "Du hast das Tutorial abgeschlossen! 🎉"
+    description: "Die hier beschriebenen Funktionen sind nur ein kleiner Teil dessen, was Misskey zu bieten hat; um mehr darüber zu erfahren, wie du Misskey benutzen kannst, besuche bitte {link}."
 _timelineDescription:
   local: "In der lokalen Chronik siehst du Notizen von allen Benutzern auf diesem Server."
   global: "In der globalen Chronik siehst du Notizen von allen föderierten Servern."
@@ -1291,6 +1376,7 @@ _serverSettings:
   fanoutTimelineDescription: "Ist diese Option aktiviert, kann eine erhebliche Verbesserung im Abrufen von Chroniken und eine Reduzierung der Datenbankbelastung erzielt werden, im Gegenzug zu einer Steigerung in der Speichernutzung von Redis. Bei geringem Serverspeicher oder Serverinstabilität kann diese Option deaktiviert werden."
   fanoutTimelineDbFallback: "Auf die Datenbank zurückfallen"
   fanoutTimelineDbFallbackDescription: "Ist diese Option aktiviert, wird die Chronik auf zusätzliche Abfragen in der Datenbank zurückgreifen, wenn sich die Chronik nicht im Cache befindet. Eine Deaktivierung führt zu geringerer Serverlast, aber schränkt den Zeitraum der abrufbaren Chronik ein. "
+  thisSettingWillAutomaticallyOffWhenModeratorsInactive: "Wenn über einen bestimmten Zeitraum keine Moderatorenaktivität festgestellt wird, wird diese Einstellung automatisch deaktiviert, um Spam zu verhindern."
 _accountMigration:
   moveFrom: "Von einem anderen Konto zu diesem migrieren"
   moveFromSub: "Alias für ein anderes Konto erstellen"
@@ -1549,6 +1635,7 @@ _achievements:
       title: "Testüberfluss"
       description: "Betätige den Benachrichtigungstest mehrfach innerhalb einer extrem kurzen Zeitspanne"
     _tutorialCompleted:
+      title: "Misskey Grundkurs-Diplom"
       description: "Tutorial abgeschlossen"
     _bubbleGameExplodingHead:
       title: "🤯"
@@ -1594,6 +1681,7 @@ _role:
     gtlAvailable: "Kann auf die globale Chronik zugreifen"
     ltlAvailable: "Kann auf die lokale Chronik zugreifen"
     canPublicNote: "Kann öffentliche Notizen erstellen"
+    mentionMax: "Maximale Anzahl von Erwähnungen in einer Notiz"
     canInvite: "Erstellung von Einladungscodes für diese Instanz"
     inviteLimit: "Maximalanzahl an Einladungen"
     inviteLimitCycle: "Zyklus des Einladungslimits"
@@ -1616,9 +1704,12 @@ _role:
     canSearchNotes: "Nutzung der Notizsuchfunktion"
     canUseTranslator: "Verwendung des Übersetzers"
     avatarDecorationLimit: "Maximale Anzahl an Profilbilddekorationen, die angebracht werden können"
+    canImportAntennas: "Importieren von Antennen erlauben"
   _condition:
     isLocal: "Lokaler Benutzer"
     isRemote: "Benutzer fremder Instanz"
+    isCat: "Katzen-Benutzer"
+    isBot: "Bot-Benutzer"
     createdLessThan: "Kontoerstellung liegt weniger als X zurück"
     createdMoreThan: "Kontoerstellung liegt mehr als X zurück"
     followersLessThanOrEq: "Hat X oder weniger Follower"
@@ -1834,6 +1925,12 @@ _sfx:
   note: "Notizen"
   noteMy: "Meine Notizen"
   notification: "Benachrichtigungen"
+_soundSettings:
+  driveFile: "Audiodatei aus dem Drive verwenden"
+  driveFileWarn: "Wähle eine Audiodatei aus dem Drive"
+  driveFileTypeWarn: "Diese Datei wird nicht unterstützt"
+  driveFileTypeWarnDescription: "Bitte wähle eine Audiodatei"
+  driveFileDurationWarn: "Audio zu lang."
 _ago:
   future: "Zukunft"
   justNow: "Gerade eben"
@@ -1915,6 +2012,23 @@ _permissions:
   "write:flash": "Deine Plays bearbeiten oder löschen"
   "read:flash-likes": "Liste der Plays, die mir gefallen, lesen"
   "write:flash-likes": "Liste der Plays, die mir gefallen, bearbeiten"
+  "write:admin:delete-account": "Benutzerkonto löschen"
+  "write:admin:delete-all-files-of-a-user": "Alle Dateien eines Benutzers löschen"
+  "read:admin:index-stats": "Statistiken zu Datenbankindizes einsehen"
+  "read:admin:table-stats": "Statistiken zu Datenbanktabellen einsehen"
+  "read:admin:user-ips": "IP-Adressen von Benutzern anzeigen"
+  "read:admin:meta": "Metadaten der Instanz einsehen"
+  "write:admin:reset-password": "Benutzerpasswort zurücksetzen"
+  "write:admin:send-email": "E-Mail versenden"
+  "read:admin:server-info": "Serverinformationen anzeigen"
+  "read:admin:show-moderation-log": "Moderationsprotokoll einsehen"
+  "read:admin:show-user": "Private Benutzerinformationen einsehen"
+  "write:admin:invite-codes": "Einladungscodes verwalten"
+  "read:admin:invite-codes": "Einladungscodes anzeigen"
+  "write:admin:announcements": "Ankündigungen verwalten"
+  "read:admin:announcements": "Ankündigungen einsehen"
+  "write:admin:avatar-decorations": "Kann Avatar-Dekorationen verwalten"
+  "read:admin:avatar-decorations": "Avatar-Dekorationen ansehen"
 _auth:
   shareAccessTitle: "Verteilung von App-Berechtigungen"
   shareAccess: "Möchtest du „{name}“ authorisieren, auf dieses Benutzerkonto zugreifen zu können?"
@@ -2329,3 +2443,31 @@ _reversi:
   black: "Schwarz"
   white: "Weiß"
   total: "Gesamt"
+_offlineScreen:
+  header: "Verbindung zum Server nicht möglich"
+_urlPreviewSetting:
+  title: "Einstellungen der URL-Vorschau"
+  enable: "URL-Vorschau aktivieren"
+  timeout: "Zeitüberschreitung beim Abrufen der Vorschau (ms)"
+  maximumContentLength: "Maximale Content-Length (Bytes)"
+_mediaControls:
+  playbackRate: "Wiedergabegeschwindigkeit"
+_contextMenu:
+  title: "Kontextmenü"
+  app: "Anwendung"
+_embedCodeGen:
+  title: "Einbettungscode anpassen"
+  header: "Kopfzeile anzeigen"
+  autoload: "Automatisch mehr laden (veraltet)"
+  maxHeight: "Maximale Höhe"
+  maxHeightDescription: "Der Wert 0 deaktiviert die Einstellung der maximalen Höhe. Gib einen Wert an, um zu verhindern, dass das Widget weiterhin vertikal vergrößert wird."
+  maxHeightWarn: "Die Begrenzung der maximalen Höhe ist deaktiviert (0). Wenn dies nicht beabsichtigt war, setze die maximale Höhe auf einen Wert fest."
+  applyToPreview: "Auf die Vorschau anwenden"
+  generateCode: "Einbettungscode generieren"
+  codeGenerated: "Der Code wurde generiert"
+  codeGeneratedDescription: "Füge den generierten Code in deine Website ein, um den Inhalt einzubetten."
+_selfXssPrevention:
+  warning: "WARNUNG"
+  title: "„Füge in diesen Bereich etwas ein“ ist eine Betrugsmasche."
+  description1: "Wenn du hier etwas einfügst, könnte ein böswilliger Benutzer dein Konto übernehmen oder deine persönlichen Daten stehlen."
+  description3: "Weitere Informationen findest du hier. {link}"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 6703d1cf3a..658914d3bc 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "Enable local timeline"
 enableGlobalTimeline: "Enable global timeline"
 disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all timelines, even if they are not enabled."
 registration: "Register"
-enableRegistration: "Enable new user registration"
 invite: "Invite"
 driveCapacityPerLocalAccount: "Drive capacity per local user"
 driveCapacityPerRemoteAccount: "Drive capacity per remote user"
@@ -1309,7 +1308,7 @@ _accountSettings:
   makeNotesFollowersOnlyBeforeDescription: "While this feature is enabled, only followers can see notes past the set date and time or have been visible for a set time. When it is deactivated, the note publication status will also be restored."
   makeNotesHiddenBefore: "Make past notes private"
   makeNotesHiddenBeforeDescription: "While this feature is enabled, notes that are past the set date and time or have been visible only to you. When it is deactivated, the note publication status will also be restored."
-  mayNotEffectForFederatedNotes: "Notes federated to a remote server may not be effective."
+  mayNotEffectForFederatedNotes: "Notes federated to a remote server may not be affected."
   notesHavePassedSpecifiedPeriod: "Note that the specified time has passed"
   notesOlderThanSpecifiedDateAndTime: "Notes before the specified date and time"
 _abuseUserReport:
diff --git a/locales/es-ES.yml b/locales/es-ES.yml
index 7731598152..a4ec114b15 100644
--- a/locales/es-ES.yml
+++ b/locales/es-ES.yml
@@ -373,7 +373,6 @@ enableLocalTimeline: "Habilitar linea de tiempo local"
 enableGlobalTimeline: "Habilitar linea de tiempo global"
 disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia el administrador y los moderadores pueden seguir usándolos"
 registration: "Registro"
-enableRegistration: "Permitir nuevos registros"
 invite: "Invitar"
 driveCapacityPerLocalAccount: "Capacidad del drive por usuario local"
 driveCapacityPerRemoteAccount: "Capacidad del drive por usuario remoto"
diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml
index a7060c06fc..b105a86b5e 100644
--- a/locales/fr-FR.yml
+++ b/locales/fr-FR.yml
@@ -8,6 +8,9 @@ search: "Rechercher"
 notifications: "Notifications"
 username: "Nom d’utilisateur·rice"
 password: "Mot de passe"
+initialPasswordForSetup: "Mot de passe initial pour la configuration"
+initialPasswordIsIncorrect: "Mot de passe initial pour la configuration est incorrecte"
+initialPasswordForSetupDescription: "Utilisez le mot de passe que vous avez entré pour le fichier de configuration si vous avez installé Misskey vous-même.\nSi vous utilisez un service d'hébergement Misskey, utilisez le mot de passe fourni.\nSi vous n'avez pas défini de mot de passe, laissez le champ vide pour continuer."
 forgotPassword: "Mot de passe oublié"
 fetchingAsApObject: "Récupération depuis le fédiverse …"
 ok: "OK"
@@ -60,6 +63,7 @@ copyFileId: "Copier l'identifiant du fichier"
 copyFolderId: "Copier l'identifiant du dossier"
 copyProfileUrl: "Copier l'URL du profil"
 searchUser: "Chercher un·e utilisateur·rice"
+searchThisUsersNotes: "Cherchez les notes de cet·te utilisateur·rice"
 reply: "Répondre"
 loadMore: "Afficher plus …"
 showMore: "Voir plus"
@@ -108,6 +112,7 @@ enterEmoji: "Insérer un émoji"
 renote: "Renoter"
 unrenote: "Annuler la Renote"
 renoted: "Renoté !"
+renotedToX: "Renoté en {name}"
 cantRenote: "Ce message ne peut pas être renoté."
 cantReRenote: "Impossible de renoter une Renote."
 quote: "Citer"
@@ -151,6 +156,7 @@ editList: "Modifier la liste"
 selectChannel: "Sélectionner un canal"
 selectAntenna: "Sélectionner une antenne"
 editAntenna: "Modifier l'antenne"
+createAntenna: "Créer une antenne"
 selectWidget: "Sélectionner un widget"
 editWidgets: "Modifier les widgets"
 editWidgetsExit: "Valider les modifications"
@@ -177,6 +183,7 @@ addAccount: "Ajouter un compte"
 reloadAccountsList: "Rafraichir la liste des comptes"
 loginFailed: "Échec de la connexion"
 showOnRemote: "Voir sur l’instance distante"
+continueOnRemote: "Continuer sur l'instance distante"
 general: "Général"
 wallpaper: "Fond d’écran"
 setWallpaper: "Définir le fond d’écran"
@@ -187,6 +194,7 @@ followConfirm: "Êtes-vous sûr·e de vouloir suivre {name} ?"
 proxyAccount: "Compte proxy"
 proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions, comme un·e abonné·e distant·e pour les utilisateurs d'autres instances. Par exemple, quand un·e utilisateur·rice ajoute un·e utilisateur·rice distant·e à une liste, ses notes ne seront pas visibles sur l'instance si personne ne suit cet·te utilisateur·rice. Le compte proxy va donc suivre cet·te utilisateur·rice pour que ses notes soient acheminées."
 host: "Serveur distant"
+selectSelf: "Sélectionner manuellement"
 selectUser: "Sélectionner un·e utilisateur·rice"
 recipient: "Destinataire"
 annotation: "Commentaires"
@@ -320,6 +328,7 @@ renameFolder: "Renommer le dossier"
 deleteFolder: "Supprimer le dossier"
 folder: "Dossier"
 addFile: "Ajouter un fichier"
+showFile: "Voir les fichiers"
 emptyDrive: "Le Disque est vide"
 emptyFolder: "Le dossier est vide"
 unableToDelete: "Suppression impossible"
@@ -362,7 +371,6 @@ enableLocalTimeline: "Activer le fil local"
 enableGlobalTimeline: "Activer le fil global"
 disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s et les modérateur·rice·s pourront toujours y accéder."
 registration: "S’inscrire"
-enableRegistration: "Autoriser les nouvelles inscriptions"
 invite: "Inviter"
 driveCapacityPerLocalAccount: "Capacité de stockage du Disque par utilisateur local"
 driveCapacityPerRemoteAccount: "Capacité de stockage du Disque par utilisateur distant"
@@ -430,10 +438,11 @@ token: "Jeton"
 2fa: "Authentification à deux facteurs"
 setupOf2fa: "Configuration de l’authentification à deux facteurs"
 totp: "Application d'authentification"
-totpDescription: "Entrez un mot de passe à usage unique à l'aide d'une application d'authentification"
+totpDescription: "Entrer un mot de passe à usage unique à l'aide d'une application d'authentification"
 moderator: "Modérateur·rice·s"
 moderation: "Modérations"
 moderationNote: "Note de modération"
+moderationNoteDescription: "Vous pouvez remplir des notes qui seront partagés seulement entre modérateurs."
 addModerationNote: "Ajouter une note de modération"
 moderationLogs: "Journal de modération"
 nUsersMentioned: "{n} utilisateur·rice·s mentionné·e·s"
@@ -493,6 +502,10 @@ uiLanguage: "Langue d’affichage de l’interface"
 aboutX: "À propos de {x}"
 emojiStyle: "Style des émojis"
 native: "Natif"
+menuStyle: "Style du menu"
+style: "Style"
+drawer: "Sélecteur"
+popup: "Pop-up"
 showNoteActionsOnlyHover: "Afficher les actions de note uniquement au survol"
 showReactionsCount: "Afficher le nombre de réactions des notes"
 noHistory: "Pas d'historique"
@@ -575,6 +588,7 @@ ascendingOrder: "Ascendant"
 descendingOrder: "Descendant"
 scratchpad: "ScratchPad"
 scratchpadDescription: "ScratchPad fournit un environnement expérimental pour AiScript. Vous pouvez vérifier la rédaction de votre code, sa bonne exécution et le résultat de son interaction avec Misskey."
+uiInspector: "Inspecteur UI"
 output: "Sortie"
 script: "Script"
 disablePagesScript: "Désactiver AiScript sur les Pages"
@@ -618,7 +632,7 @@ description: "Description"
 describeFile: "Ajouter une description d'image"
 enterFileDescription: "Saisissez une description"
 author: "Auteur·rice"
-leaveConfirm: "Vous avez des modifications non-sauvegardées. Voulez-vous les ignorer ?"
+leaveConfirm: "Vous avez des modifications non sauvegardées. Voulez-vous les ignorer ?"
 manage: "Gestion"
 plugins: "Extensions"
 preferencesBackups: "Sauvegarder les paramètres"
@@ -828,6 +842,7 @@ administration: "Gestion"
 accounts: "Comptes"
 switch: "Remplacer"
 noMaintainerInformationWarning: "Informations administrateur non configurées."
+noInquiryUrlWarning: "L'URL demandé n'est pas définie"
 noBotProtectionWarning: "La protection contre les bots n'est pas configurée."
 configure: "Configurer"
 postToGallery: "Publier dans la galerie"
@@ -892,6 +907,7 @@ followersVisibility: "Visibilité des abonnés"
 continueThread: "Afficher la suite du fil"
 deleteAccountConfirm: "Votre compte sera supprimé. Êtes vous certain ?"
 incorrectPassword: "Le mot de passe est incorrect."
+incorrectTotp: "Le mot de passe à usage unique est incorrect ou a expiré."
 voteConfirm: "Confirmez-vous votre vote pour « {choice} » ?"
 hide: "Masquer"
 useDrawerReactionPickerForMobile: "Afficher le sélecteur de réactions en tant que panneau sur mobile"
@@ -916,6 +932,9 @@ oneHour: "1 heure"
 oneDay: "1 jour"
 oneWeek: "1 semaine"
 oneMonth: "Un mois"
+threeMonths: "3 mois"
+oneYear: "1 an"
+threeDays: "3 jours"
 reflectMayTakeTime: "Cela peut prendre un certain temps avant que cela ne se termine."
 failedToFetchAccountInformation: "Impossible de récupérer les informations du compte."
 rateLimitExceeded: "Limite de taux dépassée"
@@ -923,7 +942,7 @@ cropImage: "Recadrer l'image"
 cropImageAsk: "Voulez-vous recadrer cette image ?"
 cropYes: "Rogner"
 cropNo: "Utiliser en l'état"
-file: "Fichiers"
+file: "Fichier"
 recentNHours: "Dernières {n} heures"
 recentNDays: "Derniers {n} jours"
 noEmailServerWarning: "Serveur de courrier non configuré."
@@ -1055,6 +1074,7 @@ retryAllQueuesConfirmTitle: "Vraiment réessayer ?"
 retryAllQueuesConfirmText: "Cela peut augmenter temporairement la charge du serveur."
 enableChartsForRemoteUser: "Générer les graphiques pour les utilisateurs distants"
 enableChartsForFederatedInstances: "Générer les graphiques pour les instances distantes"
+enableStatsForFederatedInstances: "Recevoir les statistiques des instances distantes"
 showClipButtonInNoteFooter: "Ajouter « Clip » au menu d'action de la note"
 reactionsDisplaySize: "Taille de l'affichage des réactions"
 limitWidthOfReaction: "Limiter la largeur maximale des réactions et les afficher en taille réduite"
@@ -1102,6 +1122,8 @@ preventAiLearning: "Refuser l'usage dans l'apprentissage automatique d'IA géné
 preventAiLearningDescription: "Demander aux robots d'indexation de ne pas utiliser le contenu publié, tel que les notes et les images, dans l'apprentissage automatique d'IA générative. Cela est réalisé en incluant le drapeau « noai » dans la réponse HTML. Une prévention complète n'est toutefois pas possible, car il est au robot d'indexation de respecter cette demande."
 options: "Options"
 specifyUser: "Spécifier l'utilisateur·rice"
+openTagPageConfirm: "Ouvrir une page d'hashtags ?"
+specifyHost: "Spécifier un serveur distant"
 failedToPreviewUrl: "Aperçu d'URL échoué"
 update: "Mettre à jour"
 rolesThatCanBeUsedThisEmojiAsReaction: "Rôles qui peuvent utiliser cet émoji comme réaction"
@@ -1222,13 +1244,55 @@ enableHorizontalSwipe: "Glisser pour changer d'onglet"
 loading: "Chargement en cours"
 surrender: "Annuler"
 gameRetry: "Réessayer"
+notUsePleaseLeaveBlank: "Laisser vide si non utilisé"
+useTotp: "Entrer un mot de passe à usage unique"
+useBackupCode: "Utiliser le codes de secours"
 launchApp: "Lancer l'app"
+useNativeUIForVideoAudioPlayer: "Lire les vidéos et audios en utilisant l'UI du navigateur"
+keepOriginalFilename: "Garder le nom original du fichier"
+keepOriginalFilenameDescription: "Si vous désactivez ce paramètre, les noms de fichiers seront automatiquement remplacés par des noms aléatoires lorsque vous téléchargerez des fichiers."
+noDescription: "Il n'y a pas de description"
+alwaysConfirmFollow: "Confirmer lors d'un abonnement"
 inquiry: "Contact"
+tryAgain: "Veuillez réessayer plus tard"
+confirmWhenRevealingSensitiveMedia: "Confirmer pour révéler du contenu sensible"
+sensitiveMediaRevealConfirm: "Ceci pourrait être du contenu sensible. Voulez-vous l'afficher ?"
+createdLists: "Listes créées"
+createdAntennas: "Antennes créées"
+fromX: "De {x}"
+genEmbedCode: "Générer le code d'intégration"
+noteOfThisUser: "Notes de cet·te utilisateur·rice"
+clipNoteLimitExceeded: "Aucune note supplémentaire ne peut être ajoutée à ce clip."
+performance: "Performance"
+modified: "Modifié"
+discard: "Annuler"
+thereAreNChanges: "Il y a {n} modification(s)"
+signinWithPasskey: "Se connecter avec une clé d'accès"
+unknownWebAuthnKey: "Clé d'accès inconnue."
+passkeyVerificationFailed: "La vérification de la clé d'accès a échoué."
+passkeyVerificationSucceededButPasswordlessLoginDisabled: "La vérification de la clé d'accès a réussi, mais la connexion sans mot de passe est désactivée."
+messageToFollower: "Message aux abonné·es"
+target: "Destinataire"
+prohibitedWordsForNameOfUser: "Mots interdits pour les noms d'utilisateur·rices"
+lockdown: "Verrouiller"
+pleaseSelectAccount: "Sélectionner un compte"
+availableRoles: "Rôles disponibles"
+_abuseUserReport:
+  forward: "Transférer"
+  forwardDescription: "Transférer le signalement vers une instance distante en tant qu'anonyme."
+  resolve: "Résoudre"
+  accept: "Accepter"
+  reject: "Rejeter"
+  resolveTutorial: "Si le signalement est légitime dans son contenu, sélectionnez « Accepter » pour marquer le cas comme résolu par l'affirmative.\nSi le contenu du rapport n'est pas légitime, sélectionnez « Rejeter » pour marquer le cas comme résolu par la négative."
 _delivery:
   status: "Statut de la diffusion"
   stop: "Suspendu·e"
+  resume: "Reprendre"
   _type:
     none: "Publié"
+    manuallySuspended: "Suspendre manuellement"
+    goneSuspended: "L'instance est suspendue en raison de la suppression de ce dernier"
+    autoSuspendedForNotResponding: "L'instance est suspendue car elle ne répond pas"
 _bubbleGame:
   howToPlay: "Comment jouer"
   hold: "Réserver"
@@ -1239,6 +1303,7 @@ _bubbleGame:
     maxChain: "Nombre maximum de chaînes"
     yen: "{yen} yens"
     estimatedQty: "{qty} pièces"
+    scoreSweets: "{onigiriQtyWithUnit} Onigiri(s)"
 _announcement:
   forExistingUsers: "Pour les utilisateurs existants seulement"
   needConfirmationToRead: "Exiger la confirmation de la lecture"
@@ -1258,6 +1323,7 @@ _initialAccountSetting:
   profileSetting: "Paramètres du profil"
   privacySetting: "Paramètres de confidentialité"
   initialAccountSettingCompleted: "Configuration du profil terminée avec succès !"
+  haveFun: "Profitez de {name} !"
   youCanContinueTutorial: "Vous pouvez procéder au tutoriel sur l'utilisation de {name}(Misskey) ou vous arrêter ici et commencer à l'utiliser immédiatement."
   startTutorial: "Démarrer le tutoriel"
   skipAreYouSure: "Désirez-vous ignorer la configuration du profil ?"
@@ -1351,18 +1417,60 @@ _achievements:
       flavor: "Passez un bon moment avec Misskey !"
     _notes10:
       title: "Quelques notes"
+      description: "Poster 10 notes"
     _notes100:
       title: "Beaucoup de notes"
+      description: "Poster 100 notes"
+    _notes500:
+      title: "Couvert de notes"
+      description: "Poster 500 notes"
+    _notes1000:
+      title: "Une montagne de notes"
+      description: "Poster 1000 notes"
+    _notes5000:
+      title: "Débordement de notes"
+      description: "Poster 5 000 notes"
+    _notes10000:
+      title: "Super note"
+      description: "Poster 10 000 notes"
+    _notes20000:
+      title: "Encore... plus... de... notes..."
+      description: "Poster 20 000 notes"
+    _notes30000:
+      title: "Notes notes notes !"
+      description: "Poster 30 000 notes"
+    _notes40000:
+      title: "Usine de notes"
+      description: "Poster 40 000 notes"
+    _notes50000:
+      title: "Planète des notes"
+      description: "Poster 50 000 notes"
+    _notes60000:
+      title: "Quasar de note"
+      description: "Poster 50 000 notes"
+    _notes70000:
+      title: "Trou noir de notes"
+      description: "Poster 70 000 notes"
+    _notes80000:
+      title: "Galaxie de notes"
+      description: "Poster 80 000 notes"
+    _notes90000:
+      title: "Univers de notes"
+      description: "Poster 90 000 notes"
     _notes100000:
       title: "ALL YOUR NOTE ARE BELONG TO US"
+      description: "Poster 100 000 notes"
+      flavor: "Avez-vous tant de choses à dire ?"
     _login3:
-      title: "Débutant Ⅰ"
+      title: "Débutant I"
       description: "Se connecter pour un total de 3 jours"
+      flavor: "Dès maintenant, appelez-moi Misskeynaute"
     _login7:
-      title: "Débutant Ⅱ"
+      title: "Débutant II"
       description: "Se connecter pour un total de 7 jours"
+      flavor: "On s'habitue ?"
     _login15:
-      title: "Débutant Ⅲ"
+      title: "Débutant III"
       description: "Se connecter pour un total de 15 jours"
     _login30:
       title: "Misskeynaute I"
@@ -1386,6 +1494,7 @@ _achievements:
     _login500:
       title: "Expert I"
       description: "Se connecter pour un total de 500 jours"
+      flavor: "Non, mes amis, j'aime les notes"
     _login600:
       title: "Expert II"
       description: "Se connecter pour un total de 600 jours"
@@ -1393,11 +1502,18 @@ _achievements:
       title: "Expert III"
       description: "Se connecter pour un total de 700 jours"
     _login800:
+      title: "Maître des notes I"
       description: "Se connecter pour un total de 800 jours"
     _login900:
+      title: "Maître des notes II"
       description: "Se connecter pour un total de 900 jours"
     _login1000:
+      title: "Maître des notes III"
+      description: "Se connecter pour un total de 1 000 jours"
       flavor: "Merci d'utiliser Misskey !"
+    _noteClipped1:
+      title: "Je... dois... clip..."
+      description: "Ajouter sa première note aux clips"
     _profileFilled:
       title: "Bien préparé"
       description: "Configuration de votre profil"
@@ -1456,21 +1572,31 @@ _achievements:
     _driveFolderCircularReference:
       title: "Référence circulaire"
     _setNameToSyuilo:
+      title: "Complexe de dieu"
       description: "Vous avez spécifié « syuilo » comme nom"
     _passedSinceAccountCreated1:
       title: "Premier anniversaire"
+      description: "Un an est passé depuis la création du compte"
     _passedSinceAccountCreated2:
       title: "Second anniversaire"
+      description: "Deux ans sont passés depuis la création du compte"
     _passedSinceAccountCreated3:
       title: "3ème anniversaire"
+      description: "Trois ans sont passés depuis la création du compte"
     _loggedInOnBirthday:
       title: "Joyeux Anniversaire !"
       description: "Vous vous êtes connecté à la date de votre anniversaire"
     _loggedInOnNewYearsDay:
       title: "Bonne année !"
+      description: "Vous vous êtes connecté le premier jour de l'année"
+      flavor: "Merci pour le soutient continue sur cette instance."
     _cookieClicked:
+      title: "Jeu de clic sur des cookies"
+      description: "Cliqué sur un cookie"
       flavor: "Attendez une minute, vous êtes sur le mauvais site web ?"
     _brainDiver:
+      title: "Brain Diver"
+      description: "Poster le lien sur Brain Diver"
       flavor: "Misskey-Misskey La-Tu-Ma"
     _smashTestNotificationButton:
       title: "Débordement de tests"
@@ -1478,6 +1604,11 @@ _achievements:
     _tutorialCompleted:
       title: "Diplôme de la course élémentaire de Misskey"
       description: "Terminer le tutoriel"
+    _bubbleGameExplodingHead:
+      title: "🤯"
+      description: "Le plus gros objet du jeu de bulles"
+    _bubbleGameDoubleExplodingHead:
+      title: "Double🤯"
 _role:
   new: "Nouveau rôle"
   edit: "Modifier le rôle"
@@ -1508,9 +1639,11 @@ _role:
     canManageCustomEmojis: "Gestion des émojis personnalisés"
     canManageAvatarDecorations: "Gestion des décorations d'avatar"
     driveCapacity: "Capacité de stockage du Disque"
+    antennaMax: "Nombre maximum d'antennes"
     wordMuteMax: "Nombre maximal de caractères dans le filtre de mots"
     canUseTranslator: "Usage de la fonctionnalité de traduction"
     avatarDecorationLimit: "Nombre maximal de décorations d'avatar"
+    canImportAntennas: "Autoriser l'importation d'antennes"
 _sensitiveMediaDetection:
   description: "L'apprentissage automatique peut être utilisé pour détecter automatiquement les médias sensibles à modérer. La sollicitation des serveurs augmente légèrement."
   sensitivity: "Sensibilité de la détection"
@@ -1793,6 +1926,29 @@ _permissions:
   "write:gallery": "Éditer la galerie"
   "read:gallery-likes": "Voir les mentions « J'aime » dans la galerie"
   "write:gallery-likes": "Gérer les mentions « J'aime » dans la galerie"
+  "read:flash": "Voir le Play"
+  "write:flash": "Modifier le Play"
+  "read:flash-likes": "Lire vos mentions j'aime des Play"
+  "write:flash-likes": "Modifier vos mentions j'aime des Play"
+  "read:admin:abuse-user-reports": "Voir les utilisateurs signalés"
+  "write:admin:delete-account": "Supprimer le compte d'utilisateur"
+  "write:admin:delete-all-files-of-a-user": "Supprimer tous les fichiers d'un utilisateur"
+  "read:admin:index-stats": "Voir les statistiques sur les index de base de données"
+  "read:admin:table-stats": "Voir les statistiques sur les index de base de données"
+  "read:admin:user-ips": "Voir l'adresse IP de l'utilisateur"
+  "read:admin:meta": "Voir les métadonnées de l'instance"
+  "write:admin:reset-password": "Réinitialiser le mot de passe de l'utilisateur"
+  "write:admin:resolve-abuse-user-report": "Résoudre le signalement d'un utilisateur"
+  "write:admin:send-email": "Envoyer un mail"
+  "read:admin:server-info": "Voir les informations de l'instance"
+  "read:admin:show-moderation-log": "Voir les logs de modération"
+  "read:admin:show-user": "Voir les informations privées de l'utilisateur"
+  "write:admin:suspend-user": "Suspendre l'utilisateur"
+  "write:admin:unset-user-avatar": "Retirer l'avatar de l'utilisateur"
+  "write:admin:unset-user-banner": "Retirer la bannière de l'utilisateur"
+  "write:admin:unsuspend-user": "Lever la suspension d'un utilisateur"
+  "write:admin:meta": "Gérer les métadonnées de l'instance"
+  "write:admin:roles": "Gérer les rôles"
 _auth:
   shareAccess: "Autoriser \"{name}\" à accéder à votre compte ?"
   shareAccessAsk: "Voulez-vous vraiment autoriser cette application à accéder à votre compte?"
@@ -1944,7 +2100,16 @@ _timelines:
   social: "Social"
   global: "Global"
 _play:
+  new: "Créer un Play"
+  edit: "Modifier un Play"
+  created: "Play créé"
+  updated: "Play édité"
+  deleted: "Play supprimé"
+  pageSetting: "Configuration du Play"
+  editThisPage: "Modifier ce Play"
   viewSource: "Afficher la source"
+  my: "Mes Play"
+  liked: "Play aimés"
   featured: "Populaire"
   title: "Titre"
   script: "Script"
@@ -2018,10 +2183,13 @@ _notification:
   achievementEarned: "Accomplissement déverrouillé"
   testNotification: "Tester la notification"
   reactedBySomeUsers: "{n} utilisateur·rice·s ont réagi"
+  likedBySomeUsers: "{n} utilisateurs ont aimé votre note"
   renotedBySomeUsers: "{n} utilisateur·rice·s ont renoté"
   followedBySomeUsers: "{n} utilisateur·rice·s se sont abonné·e·s à vous"
+  login: "Quelqu'un s'est connecté"
   _types:
     all: "Toutes"
+    note: "Nouvelles notes"
     follow: "Nouvel·le abonné·e"
     mention: "Mentions"
     reply: "Réponses"
@@ -2071,11 +2239,14 @@ _drivecleaner:
   orderByCreatedAtAsc: "Date d'ajout ascendante"
 _webhookSettings:
   name: "Nom"
+  secret: "Secret"
+  trigger: "Activateur"
   active: "Activé"
 _abuseReport:
   _notificationRecipient:
     _recipientType:
       mail: "E-mail "
+    keywords: "Mots clés "
 _moderationLogTypes:
   createRole: "Rôle créé"
   deleteRole: "Rôle supprimé"
@@ -2112,6 +2283,7 @@ _moderationLogTypes:
   deleteAvatarDecoration: "Décoration d'avatar supprimée"
   unsetUserAvatar: "Supprimer l'avatar de l'utilisateur·rice"
   unsetUserBanner: "Supprimer la bannière de l'utilisateur·rice"
+  deleteFlash: "Supprimer le Play"
 _fileViewer:
   title: "Détails du fichier"
   type: "Type du fichier"
@@ -2175,5 +2347,20 @@ _dataSaver:
     title: "Mise en évidence du code"
     description: "Si la notation de mise en évidence du code est utilisée, par exemple dans la MFM, elle ne sera pas chargée tant qu'elle n'aura pas été tapée. La mise en évidence du code nécessite le chargement du fichier de définition de chaque langue à mettre en évidence, mais comme ces fichiers ne sont plus chargés automatiquement, on peut s'attendre à une réduction du trafic de données."
 _reversi:
+  reversi: "Reversi"
+  blackIs: "{name} joue les noirs"
+  rules: "Règles"
   waitingBoth: "Préparez-vous"
+  myTurn: "C’est votre tour"
+  turnOf: "C'est le tour de {name}"
+  pastTurnOf: "Tour de {name}"
+  surrender: "Se rendre"
+  surrendered: "Par abandon"
   total: "Total"
+  playing: "En cours"
+  lookingForPlayer: "Recherche d'adversaire"
+_mediaControls:
+  playbackRate: "Vitesse de lecture"
+_embedCodeGen:
+  title: "Personnaliser le code d'intégration"
+  generateCode: "Générer le code d'intégration"
diff --git a/locales/id-ID.yml b/locales/id-ID.yml
index 5d51d2dc78..fe3f207618 100644
--- a/locales/id-ID.yml
+++ b/locales/id-ID.yml
@@ -375,7 +375,6 @@ enableLocalTimeline: "Nyalakan lini masa lokal"
 enableGlobalTimeline: "Nyalakan lini masa global"
 disablingTimelinesInfo: "Admin dan Moderator akan selalu memiliki akses ke semua lini masa meskipun lini masa tersebut tidak diaktifkan."
 registration: "Pendaftaran"
-enableRegistration: "Nyalakan pendaftaran pengguna baru"
 invite: "Undang"
 driveCapacityPerLocalAccount: "Kapasitas drive per pengguna lokal"
 driveCapacityPerRemoteAccount: "Kapasitas drive per pengguna remote"
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index 8fb6dcd6f2..66ca935b1b 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "Abilita la timeline locale"
 enableGlobalTimeline: "Abilita la timeline federata"
 disablingTimelinesInfo: "Anche disabilitandole, gli Amministratori e i Moderatori potranno comunque accedervi."
 registration: "Iscriviti"
-enableRegistration: "Consenti a chiunque di registrarsi"
 invite: "Invita"
 driveCapacityPerLocalAccount: "Capienza del Drive per profilo locale"
 driveCapacityPerRemoteAccount: "Capienza del Drive per profilo remoto"
diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml
index 50132c0645..c3e0096926 100644
--- a/locales/ja-KS.yml
+++ b/locales/ja-KS.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "ローカルタイムラインを使えるようにする
 enableGlobalTimeline: "グローバルタイムラインを使えるようにするわ"
 disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
 registration: "登録"
-enableRegistration: "一見さんでも誰でもいらっしゃ~い"
 invite: "来てや"
 driveCapacityPerLocalAccount: "ローカルユーザーはんひとりあたりのドライブ容量"
 driveCapacityPerRemoteAccount: "リモートユーザーはんひとりあたりのドライブ容量"
diff --git a/locales/ko-GS.yml b/locales/ko-GS.yml
index 1f7faba23a..60b82d5db9 100644
--- a/locales/ko-GS.yml
+++ b/locales/ko-GS.yml
@@ -356,7 +356,6 @@ enableLocalTimeline: "로컬 타임라인 키기"
 enableGlobalTimeline: "글로벌 타임라인 키기"
 disablingTimelinesInfo: "요 타임라인얼 꺼도 간리자하고 중재자넌 고대로 설 수 잇십니다."
 registration: "맨걸기"
-enableRegistration: "누라도 새로 맨걸 수 잇거로 하기"
 invite: "초대하기"
 driveCapacityPerLocalAccount: "로컬 사용자 하나마중 드라이브 커기"
 driveCapacityPerRemoteAccount: "웬겍 사용자 하나마중 드라이브 커기"
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index 5d07ebe244..d20a9754b1 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "로컬 타임라인 활성화"
 enableGlobalTimeline: "글로벌 타임라인 활성화"
 disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
 registration: "등록"
-enableRegistration: "신규 회원가입을 활성화"
 invite: "초대"
 driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량"
 driveCapacityPerRemoteAccount: "원격 사용자별 드라이브 용량"
@@ -1257,7 +1256,7 @@ lastNDays: "최근 {n}일"
 backToTitle: "타이틀로 가기"
 hemisphere: "거주 지역"
 withSensitive: "민감한 파일이 포함된 노트 보기"
-userSaysSomethingSensitive: "{name} 같은 민감한 파일이 포함된 글"
+userSaysSomethingSensitive: "{name}의 민감한 파일이 포함된 게시물"
 enableHorizontalSwipe: "스와이프하여 탭 전환"
 loading: "불러오는 중"
 surrender: "그만두기"
diff --git a/locales/lo-LA.yml b/locales/lo-LA.yml
index b100d0300f..38965119fe 100644
--- a/locales/lo-LA.yml
+++ b/locales/lo-LA.yml
@@ -299,7 +299,6 @@ enableLocalTimeline: "ເປີດໃຊ້ທາມລາຍທ້ອງຖິ
 enableGlobalTimeline: "ເປີດໃຊ້ທາມລາຍທົ່ວໂລກ"
 disablingTimelinesInfo: "ຜູ້ດູແລລະບບແລະຜູ້ຄວບຄຸມຈະສາມາດເຂົ້າເຖີງໄທມ໌ໄລນ໌ທັ້ງເບີດ ເຖີງວ່າຈະບໍ່ໄດ້ເປີດໃຊ້ງານກໍ່ຕາມ"
 registration: "ລົງທະບຽນ"
-enableRegistration: "ເປີດໃຊ້ການລົງທະບຽນຜູ້ໃຊ້ໃໝ່"
 invite: "ເຊີນ"
 driveCapacityPerLocalAccount: "ຄວາມຈຸຂອງ drive ຕໍ່ຜູ້ໃຊ້ທ້ອງຖິ່ນ"
 driveCapacityPerRemoteAccount: "ຄວາມຈຸຂອງ drive ຕໍ່ຜູ້ໃຊ້ໄລຍະໄກ"
diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml
index dde3035357..7e5e9cbbfb 100644
--- a/locales/nl-NL.yml
+++ b/locales/nl-NL.yml
@@ -333,7 +333,6 @@ enableLocalTimeline: "Inschakelen lokale tijdlijn"
 enableGlobalTimeline: "Inschakelen globale tijdlijn "
 disablingTimelinesInfo: "Beheerders en moderators hebben altijd toegang tot alle tijdlijnen, ook als ze niet actief zijn."
 registration: "Registreren"
-enableRegistration: "Inschakelen registratie nieuwe gebruikers "
 invite: "Uitnodigen"
 driveCapacityPerLocalAccount: "Opslagruimte per lokale gebruiker"
 driveCapacityPerRemoteAccount: "Opslagruimte per externe gebruiker"
diff --git a/locales/no-NO.yml b/locales/no-NO.yml
index c5f61db745..87ea01764d 100644
--- a/locales/no-NO.yml
+++ b/locales/no-NO.yml
@@ -260,7 +260,6 @@ enableLocalTimeline: "Aktiver lokal tidslinje"
 enableGlobalTimeline: "Aktiver global tidslinje"
 disablingTimelinesInfo: "Administratorer og Moderatorer vil alltid ha tilgang til alle tidslinjer, selv om de ikke er aktivert."
 registration: "Registrer"
-enableRegistration: "Aktiver registrering av nye brukere"
 invite: "Inviter"
 basicInfo: "Grunnleggende informasjon"
 pinnedUsers: "Festede brukrere"
diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml
index d7afd57760..203f44b334 100644
--- a/locales/pl-PL.yml
+++ b/locales/pl-PL.yml
@@ -362,7 +362,6 @@ enableLocalTimeline: "Włącz lokalną oś czasu"
 enableGlobalTimeline: "Włącz globalną oś czasu"
 disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do wszystkich osi czasu, nawet gdy są one wyłączone."
 registration: "Zarejestruj się"
-enableRegistration: "Włącz rejestrację nowych użytkowników"
 invite: "Zaproś"
 driveCapacityPerLocalAccount: "Powierzchnia dyskowa na lokalnego użytkownika"
 driveCapacityPerRemoteAccount: "Powierzchnia dyskowa na zdalnego użytkownika"
@@ -492,6 +491,10 @@ uiLanguage: "Język wyświetlania UI"
 aboutX: "O {x}"
 emojiStyle: "Styl emoji"
 native: "Natywny"
+menuStyle: "Styl Menu"
+style: "Styl"
+drawer: "Schowek"
+popup: "Wyskakujące okienka"
 showNoteActionsOnlyHover: "Pokazuj akcje notatek tylko po najechaniu myszką"
 showReactionsCount: "Wyświetl liczbę reakcji na notatkę"
 noHistory: "Brak historii"
@@ -574,6 +577,7 @@ ascendingOrder: "Rosnąco"
 descendingOrder: "Malejąco"
 scratchpad: "Brudnopis"
 scratchpadDescription: "Brudnopis zawiera eksperymentalne środowisko dla AiScript. Możesz pisać, wykonywać i sprawdzać wyniki w interakcji z Misskey."
+uiInspector: "Inspektor UI"
 output: "Wyjście"
 script: "Skrypt"
 disablePagesScript: "Wyłącz AiScript na Stronach"
@@ -654,6 +658,7 @@ smtpSecure: "Użyj niejawnego SSL/TLS dla połączeń SMTP"
 smtpSecureInfo: "Wyłącz, jeżeli używasz STARTTLS"
 testEmail: "Przetestuj dostarczanie wiadomości e-mail"
 wordMute: "Wyciszenie słowa"
+hardWordMute: "Wyciszaj przekleństwa"
 regexpError: "Błąd wyrażenia regularnego"
 regexpErrorDescription: "Wystąpił błąd w wyrażeniu regularnym w linii {line} twoich {tab} wyciszeń:"
 instanceMute: "Wyciszone instancje"
@@ -826,6 +831,7 @@ administration: "Zarządzanie"
 accounts: "Konta"
 switch: "Przełącz"
 noMaintainerInformationWarning: "Informacje o administratorze nie są skonfigurowane."
+noInquiryUrlWarning: "Adres URL zapytania nie został ustawiony"
 noBotProtectionWarning: "Zabezpieczenie przed botami nie jest skonfigurowane."
 configure: "Skonfiguruj"
 postToGallery: "Opublikuj w galerii"
@@ -890,6 +896,7 @@ followersVisibility: "Widoczność obserwujących"
 continueThread: "Pokaż kontynuację wątku"
 deleteAccountConfirm: "Spowoduje to nieodwracalne usunięcie Twojego konta. Kontynuować?"
 incorrectPassword: "Nieprawidłowe hasło."
+incorrectTotp: "Hasło pojedynczego użytku jest nie poprawne, lub straciło ważność"
 voteConfirm: "Potwierdzić swój głos na \"{choice}\"?"
 hide: "Ukryj"
 useDrawerReactionPickerForMobile: "Wyświetlaj wybornik reakcji jako szufladę na urządzeniach mobilnych"
@@ -914,6 +921,10 @@ oneHour: "1 godzina"
 oneDay: "1 dzień"
 oneWeek: "1 tydzień"
 oneMonth: "jeden miesiąc"
+threeMonths: "3 miesiące"
+oneYear: "Rok"
+threeDays: "3 dni"
+reflectMayTakeTime: "Może minąć trochę czasu, zanim będzie to uwzględnione"
 failedToFetchAccountInformation: "Nie udało się uzyskać informacji o koncie"
 rateLimitExceeded: "Limit szybkości przekroczony"
 cropImage: "Przytnij obraz"
@@ -924,9 +935,11 @@ file: "Pliki"
 recentNHours: "W ciągu ostatnich {n} godzin"
 recentNDays: "W ciągu ostatnich {n} dni"
 noEmailServerWarning: "Serwer Email nie jest skonfigurowany"
+thereIsUnresolvedAbuseReportWarning: "Istnieją niewyjaśnione raporty"
 recommended: "Zalecane"
 check: "Zweryfikuj"
 driveCapOverrideLabel: "Zmień limit pojemności dysku użytkownika"
+driveCapOverrideCaption: "Resetuje pojemność do wartości domyślnej, przez wpisanie wartości 0 lub niższej"
 requireAdminForView: "Aby to zobaczyć, musisz być administratorem"
 isSystemAccount: "To jest konto stworzone i zarządzane przez system"
 typeToConfirm: "Wprowadź {x}, aby potwierdzić"
@@ -995,17 +1008,29 @@ unassign: "Cofnij przydzielenie"
 color: "Kolor"
 manageCustomEmojis: "Zarządzaj niestandardowymi Emoji"
 manageAvatarDecorations: "Zarządzaj dekoracjami awatara"
+youCannotCreateAnymore: "Limit kreacji został przekroczony"
+cannotPerformTemporary: "Opcja tymczasowo niedostępna"
+cannotPerformTemporaryDescription: "Ta akcja nie może zostać wykonana, z powodu przekroczenia limitu wykonań. Prosimy poczekać chwilę i spróbować ponownie"
 invalidParamError: "Błąd parametrów"
+invalidParamErrorDescription: "Wartości, które zostały podane są niepoprawne. Zwykle jest to spowodowane bugiem, lecz również może być to spowodowane przekroczeniem limitu wartości, lub podobnym problemem"
 permissionDeniedError: "Odrzucono operacje"
 permissionDeniedErrorDescription: "Konto nie posiada uprawnień"
 preset: "Konfiguracja"
 selectFromPresets: "Wybierz konfiguracje"
 achievements: "Osiągnięcia"
+gotInvalidResponseError: "Niepoprawna odpowiedź serwera"
+gotInvalidResponseErrorDescription: "Wystąpił problem z Twoim połączeniem z Internetem, lub z serwerem. {Spróbuj ponownie} wkrótce."
+thisPostMayBeAnnoying: "Ten wpis może obrażać pozostałych użytkowników"
+thisPostMayBeAnnoyingHome: "Opublikuj na domowej osi czasu"
 thisPostMayBeAnnoyingCancel: "Odrzuć"
+thisPostMayBeAnnoyingIgnore: "Zignoruj i wyślij"
+collapseRenotes: "Zwiń wpisy, które już zobaczyłeś"
+collapseRenotesDescription: "Zwiń wpisy, na które już zareagowałeś lub udostępniłeś"
 internalServerError: "Wewnętrzny błąd serwera"
 internalServerErrorDescription: "Niespodziewany błąd po stronie serwera"
 copyErrorInfo: "Kopiuj informacje o błędzie"
 joinThisServer: "Dołącz do chaty"
+exploreOtherServers: "Szukaj innej instancji"
 disableFederationOk: "Wyłącz federacje"
 invitationRequiredToRegister: "Ten serwer wymaga zaproszenia. Tylko osoby z zaproszeniem mogą się zarejestrować"
 emailNotSupported: "Wysyłanie wiadomości E-mail nie jest obsługiwane na tym serwerze"
diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml
index 9039fd2141..7ef9e3a946 100644
--- a/locales/pt-PT.yml
+++ b/locales/pt-PT.yml
@@ -376,7 +376,6 @@ enableLocalTimeline: "Ativar linha do tempo local"
 enableGlobalTimeline: "Ativar linha do tempo global"
 disablingTimelinesInfo: "Se você desabilitar essas linhas do tempo, administradores e moderadores ainda poderão usá-las por conveniência."
 registration: "Registar"
-enableRegistration: "Permitir que qualquer pessoa se registre"
 invite: "Convidar"
 driveCapacityPerLocalAccount: "Capacidade do drive por usuário local"
 driveCapacityPerRemoteAccount: "Capacidade do drive por usuário remoto"
diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml
index 3cc09aa5c2..71dc1dc94c 100644
--- a/locales/ro-RO.yml
+++ b/locales/ro-RO.yml
@@ -341,7 +341,6 @@ enableLocalTimeline: "Activează cronologia locală"
 enableGlobalTimeline: "Activeaza cronologia globală"
 disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate cronologiile, chiar dacă nu sunt activate."
 registration: "Inregistrare"
-enableRegistration: "Activează înregistrările pentru utilizatori noi"
 invite: "Invită"
 driveCapacityPerLocalAccount: "Capacitatea Drive-ului per utilizator local"
 driveCapacityPerRemoteAccount: "Capacitatea Drive-ului per utilizator extern"
diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml
index 8174675880..537e99036c 100644
--- a/locales/ru-RU.yml
+++ b/locales/ru-RU.yml
@@ -377,7 +377,6 @@ enableLocalTimeline: "Включить локальную ленту"
 enableGlobalTimeline: "Включить глобальную ленту"
 disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам, даже если они отключены."
 registration: "Регистрация"
-enableRegistration: "Разрешить регистрацию"
 invite: "Пригласить"
 driveCapacityPerLocalAccount: "Объём Диска на одного локального пользователя"
 driveCapacityPerRemoteAccount: "Объём Диска на одного пользователя с другого экземпляра"
diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml
index 60ce45a6b9..f3f43ee6a6 100644
--- a/locales/sk-SK.yml
+++ b/locales/sk-SK.yml
@@ -331,7 +331,6 @@ enableLocalTimeline: "Povoliť lokálnu časovú os"
 enableGlobalTimeline: "Povoliť globálnu časovú os"
 disablingTimelinesInfo: "Administrátori a moderátori majú vždy prístup ku všetkým časovým osiam, aj keď sú vypnuté."
 registration: "Registrácia"
-enableRegistration: "Povoliť registráciu nových používateľov"
 invite: "Pozvať"
 driveCapacityPerLocalAccount: "Kapacita disku pre používateľa"
 driveCapacityPerRemoteAccount: "Kapacita disku pre vzdialeného používateľa"
diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml
index 4945e0f677..5961605645 100644
--- a/locales/sv-SE.yml
+++ b/locales/sv-SE.yml
@@ -333,7 +333,6 @@ disconnectService: "Koppla från"
 enableLocalTimeline: "Aktivera lokal tidslinje"
 enableGlobalTimeline: "Aktivera global tidslinje"
 registration: "Registrera"
-enableRegistration: "Aktivera registrering av nya användare"
 invite: "Inbjudan"
 inMb: "I megabyte"
 bannerUrl: "URL till banner-bilden"
@@ -481,6 +480,7 @@ nNotes: "{n} Noter"
 backgroundColor: "Bakgrundsbild"
 textColor: "Text"
 saveAs: "Spara som..."
+saveConfirm: "Spara ändringar?"
 youAreRunningUpToDateClient: "Klienten du använder är uppdaterat."
 newVersionOfClientAvailable: "Ny version av klienten är tillgänglig."
 editCode: "Redigera kod"
@@ -523,6 +523,7 @@ threeMonths: "3 månader"
 oneYear: "1 år"
 threeDays: "3 dagar"
 file: "Filer"
+deleteAccount: "Radera konto"
 label: "Etikett"
 cannotUploadBecauseNoFreeSpace: "Kan inte ladda upp filen för att det finns inget lagringsutrymme kvar."
 cannotUploadBecauseExceedsFileSizeLimit: "Kan inte ladda upp filen för att den är större än filstorleksgränsen."
@@ -575,9 +576,13 @@ _achievements:
     _open3windows:
       title: "Flera Fönster"
       description: "Ha minst 3 fönster öppna samtidigt"
+_role:
+  edit: "Redigera roll"
 _ffVisibility:
   public: "Publicera"
   private: "Privat"
+_accountDelete:
+  accountDelete: "Radera konto"
 _ad:
   back: "Tillbaka"
 _gallery:
@@ -587,6 +592,7 @@ _email:
     title: "följde dig"
 _aboutMisskey:
   source: "Källkod"
+  projectMembers: "Projektmedlemmar"
 _channel:
   setBanner: "Välj banner"
   removeBanner: "Ta bort banner"
@@ -602,8 +608,17 @@ _theme:
 _sfx:
   note: "Noter"
   notification: "Notifikationer"
+_ago:
+  justNow: "Just nu"
 _2fa:
+  step3Title: "Ange en autentiseringskod"
   renewTOTPCancel: "Nej tack"
+_permissions:
+  "read:reactions": "Visa dina reaktioner"
+  "write:reactions": "Redigera dina reaktioner"
+  "write:admin:delete-account": "Radera användarkonto"
+  "write:admin:roles": "Hantera roller"
+  "read:admin:roles": "Visa roller"
 _antennaSources:
   all: "Alla noter"
   homeTimeline: "Noter från följda användare"
@@ -666,6 +681,8 @@ _notification:
     reply: "Svara"
     renote: "Omnotera"
 _deck:
+  addColumn: "Lägg till kolumn"
+  deleteProfile: "Radera profil"
   _columns:
     notifications: "Notifikationer"
     tl: "Tidslinje"
diff --git a/locales/th-TH.yml b/locales/th-TH.yml
index 58cf8f068c..c725282d50 100644
--- a/locales/th-TH.yml
+++ b/locales/th-TH.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "เปิดใช้งานไทม์ไลน์ท
 enableGlobalTimeline: "เปิดใช้งานไทม์ไลน์ทั่วโลก"
 disablingTimelinesInfo: "ผู้ดูแลระบบและผู้ควบคุมจะสามารถเข้าถึงไทม์ไลน์ทั้งหมด ถึงแม้ว่าจะไม่ได้เปิดใช้งานก็ตาม"
 registration: "ลงทะเบียน"
-enableRegistration: "เปิดใช้งานการลงทะเบียนผู้ใช้ใหม่"
 invite: "คำเชิญ"
 driveCapacityPerLocalAccount: "ความจุของไดรฟ์ต่อผู้ใช้ท้องถิ่น"
 driveCapacityPerRemoteAccount: "ความจุของไดรฟ์ต่อผู้ใช้ระยะไกล"
diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml
index fe2f158ff6..69892fedc8 100644
--- a/locales/tr-TR.yml
+++ b/locales/tr-TR.yml
@@ -344,7 +344,6 @@ today: "Bugün"
 monthX: "{month} ay"
 pages: "Sayfalar"
 integration: "Entegrasyon"
-enableRegistration: "Kayıtlara izin ver"
 basicInfo: "Temel bilgiler"
 pinnedUsers: "Sabitlenmiş kullanıcılar"
 pinnedNotes: "Sabitlenen"
diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml
index f2262cd71f..1b21854650 100644
--- a/locales/uk-UA.yml
+++ b/locales/uk-UA.yml
@@ -334,7 +334,6 @@ enableLocalTimeline: "Увімкнути локальну стрічку"
 enableGlobalTimeline: "Увімкнути глобальну стрічку"
 disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті."
 registration: "Реєстрація"
-enableRegistration: "Дозволити реєстрацію"
 invite: "Запросити"
 driveCapacityPerLocalAccount: "Об'єм диска на одного локального користувача"
 driveCapacityPerRemoteAccount: "Об'єм диска на одного віддаленого користувача"
diff --git a/locales/uz-UZ.yml b/locales/uz-UZ.yml
index 37a550008a..051a4ae6c5 100644
--- a/locales/uz-UZ.yml
+++ b/locales/uz-UZ.yml
@@ -349,7 +349,6 @@ enableLocalTimeline: "Mahalliy vaqt mintaqasini yoqing"
 enableGlobalTimeline: "Global vaqt mintaqasini yoqing"
 disablingTimelinesInfo: "Administratorlar va Moderatorlar har doim barcha vaqt jadvallariga kirish huquqiga ega bo'ladilar, hatto ular yoqilmagan bo'lsa ham."
 registration: "Ro'yxatdan o'tish"
-enableRegistration: "Ro'yxatdan o'tishni yoqing"
 invite: "Taklif qilish"
 driveCapacityPerLocalAccount: "Har bir mahalliy foydalanuvchi uchun disk maydoni"
 driveCapacityPerRemoteAccount: "Har bir masofaviy foydalanuvchi uchun disk maydoni"
diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml
index fb8e898bf1..24faa4b94c 100644
--- a/locales/vi-VN.yml
+++ b/locales/vi-VN.yml
@@ -357,7 +357,6 @@ enableLocalTimeline: "Bật bảng tin máy chủ"
 enableGlobalTimeline: "Bật bảng tin liên hợp"
 disablingTimelinesInfo: "Quản trị viên và Kiểm duyệt viên luôn có quyền truy cập mọi bảng tin, kể cả khi chúng không được bật."
 registration: "Đăng ký"
-enableRegistration: "Cho phép đăng ký mới"
 invite: "Mời"
 driveCapacityPerLocalAccount: "Dung lượng ổ đĩa tối đa cho mỗi người dùng"
 driveCapacityPerRemoteAccount: "Dung lượng ổ đĩa tối đa cho mỗi người dùng từ xa"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 7a11f247ca..c5a581035d 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "启用本地时间线"
 enableGlobalTimeline: "启用全局时间线"
 disablingTimelinesInfo: "即使时间线功能被禁用,出于方便,管理员和监察员也可以继续使用。"
 registration: "注册"
-enableRegistration: "允许任何人注册"
 invite: "邀请"
 driveCapacityPerLocalAccount: "每个用户的网盘容量"
 driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
@@ -587,6 +586,7 @@ masterVolume: "主音量"
 notUseSound: "静音"
 useSoundOnlyWhenActive: "仅在 Misskey 活跃时输出声音"
 details: "详情"
+renoteDetails: "转帖详情"
 chooseEmoji: "选择表情符号"
 unableToProcess: "操作无法完成"
 recentUsed: "最近使用"
@@ -1300,6 +1300,7 @@ thisContentsAreMarkedAsSigninRequiredByAuthor: "根据发帖者的设定,需
 lockdown: "锁定"
 pleaseSelectAccount: "请选择帐户"
 availableRoles: "可用角色"
+acknowledgeNotesAndEnable: "理解注意事项后再开启。"
 _accountSettings:
   requireSigninToViewContents: "需要登录才能显示内容"
   requireSigninToViewContentsDescription1: "您发布的所有帖子将变成需要登入后才会显示。有望防止爬虫收集各种信息。"
@@ -1456,6 +1457,8 @@ _serverSettings:
   reactionsBufferingDescription: "开启时可显著提高发送回应时的性能,及减轻数据库负荷。但 Redis 的内存用量会相应增加。"
   inquiryUrl: "联络地址"
   inquiryUrlDescription: "用来指定诸如向服务运营商咨询的论坛地址,或记载了运营商联系方式之类的网页地址。"
+  openRegistration: "开放注册"
+  openRegistrationWarning: "开放注册有风险。建议仅当能够持续监控服务器并在出现问题时能够立即响应时才打开它。"
   thisSettingWillAutomaticallyOffWhenModeratorsInactive: "若在一段时间内没有检测到管理活动,为防止垃圾信息,此设定将自动关闭。"
 _accountMigration:
   moveFrom: "从别的账号迁移到此账户"
@@ -2738,3 +2741,6 @@ _selfXssPrevention:
   description1: "如果在此处粘贴了什么,恶意用户可能会接管账户或者盗取个人资料。"
   description2: "如果不能完全理解将要粘贴的内容,%c 请立即停止操作并关闭这个窗口。"
   description3: "详情请看这里。{link}"
+_followRequest:
+  recieved: "已收到申请"
+  sent: "已发送申请"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index b7c9def26f..1e8e27c7bd 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -382,7 +382,6 @@ enableLocalTimeline: "啟用本地時間軸"
 enableGlobalTimeline: "啟用全域時間軸"
 disablingTimelinesInfo: "為了方便,即使您關閉了時間軸功能,管理員和審查員仍可以繼續使用。"
 registration: "註冊"
-enableRegistration: "開放新使用者註冊"
 invite: "邀請"
 driveCapacityPerLocalAccount: "每個本地使用者的雲端硬碟容量"
 driveCapacityPerRemoteAccount: "每個非本地用戶的雲端空間大小"
@@ -1119,7 +1118,7 @@ vertical: "直向"
 horizontal: "橫向"
 position: "位置"
 serverRules: "伺服器規則"
-pleaseConfirmBelowBeforeSignup: "在本伺服器註冊之前,請確認下列事項。"
+pleaseConfirmBelowBeforeSignup: "在本伺服器註冊之前,必須確認並同意以下內容。"
 pleaseAgreeAllToContinue: "必須全部勾選「同意」才能繼續。"
 continue: "繼續"
 preservedUsernames: "保留的使用者名稱"
@@ -1300,6 +1299,7 @@ thisContentsAreMarkedAsSigninRequiredByAuthor: "作者將其設定為需要登
 lockdown: "鎖定"
 pleaseSelectAccount: "請選擇帳戶"
 availableRoles: "可用角色"
+acknowledgeNotesAndEnable: "了解注意事項後再開啟。"
 _accountSettings:
   requireSigninToViewContents: "須登入以顯示內容"
   requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。"
@@ -1456,6 +1456,8 @@ _serverSettings:
   reactionsBufferingDescription: "啟用時,可以顯著提高建立反應時的效能並減少資料庫的負載。 但是,Redis 記憶體使用量會增加。"
   inquiryUrl: "聯絡表單網址"
   inquiryUrlDescription: "指定伺服器運營者的聯絡表單網址,或包含運營者聯絡資訊網頁的網址。"
+  openRegistration: "允許建立帳戶"
+  openRegistrationWarning: "開放註冊伴隨著風險。 建議只有在伺服器受到持續監控,並準備好在出現問題時能立即處理的情況下才開放註冊。"
   thisSettingWillAutomaticallyOffWhenModeratorsInactive: "為了防止 spam,如果一段期間內沒有偵測到審查員的活動,此設定將自動關閉。"
 _accountMigration:
   moveFrom: "從其他帳戶遷移到這個帳戶"
@@ -2738,3 +2740,6 @@ _selfXssPrevention:
   description1: "如果您在此處貼上任何內容,惡意使用者可能會接管您的帳戶或竊取您的個人資訊。"
   description2: "如果您不確切知道要貼上的內容,%c 請立即停止工作並關閉此視窗。"
   description3: "細節請看這裡。{link}"
+_followRequest:
+  recieved: "收到的請求"
+  sent: "送出的請求"

From 6c5d3113c679988d54a00ac9c5b0c77bf1e7e93e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Tue, 19 Nov 2024 03:56:50 +0000
Subject: [PATCH 088/125] Bump version to 2024.11.0-alpha.2

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 63043d62e0..4dd411c10f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.11.0-alpha.1",
+	"version": "2024.11.0-alpha.2",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 8166dcedad..f57656db0b 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.11.0-alpha.1",
+	"version": "2024.11.0-alpha.2",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 763c708253161d67358a8e36c27af3b02d133298 Mon Sep 17 00:00:00 2001
From: "zawa-ch." <satellite.2e1834097@gmail.com>
Date: Tue, 19 Nov 2024 21:12:40 +0900
Subject: [PATCH 089/125] =?UTF-8?q?Fix(backend):=20=E3=82=A2=E3=82=AB?=
 =?UTF-8?q?=E3=82=A6=E3=83=B3=E3=83=88=E5=89=8A=E9=99=A4=E3=81=AE=E3=83=A2?=
 =?UTF-8?q?=E3=83=87=E3=83=AC=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=83=AD?=
 =?UTF-8?q?=E3=82=B0=E3=81=8C=E5=8B=95=E4=BD=9C=E3=81=97=E3=81=A6=E3=81=84?=
 =?UTF-8?q?=E3=81=AA=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1499?=
 =?UTF-8?q?6)=20(#14997)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* アカウント削除のモデレーションログが動作していないのを修正

* update CHANGELOG
---
 CHANGELOG.md                                                  | 1 +
 .../backend/src/server/api/endpoints/admin/accounts/delete.ts | 2 +-
 .../backend/src/server/api/endpoints/admin/delete-account.ts  | 4 ++--
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 058e41c486..befe237b09 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -64,6 +64,7 @@
 - Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
 - Fix: User Webhookテスト機能のMock Payloadを修正  
+- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)  
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
index 01dea703a3..ece1984cff 100644
--- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
@@ -46,7 +46,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				throw new Error('cannot delete a root account');
 			}
 
-			await this.deleteAccoountService.deleteAccount(user);
+			await this.deleteAccoountService.deleteAccount(user, me);
 		});
 	}
 }
diff --git a/packages/backend/src/server/api/endpoints/admin/delete-account.ts b/packages/backend/src/server/api/endpoints/admin/delete-account.ts
index b6f0f22d60..9065a71f6a 100644
--- a/packages/backend/src/server/api/endpoints/admin/delete-account.ts
+++ b/packages/backend/src/server/api/endpoints/admin/delete-account.ts
@@ -33,13 +33,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 
 		private deleteAccountService: DeleteAccountService,
 	) {
-		super(meta, paramDef, async (ps) => {
+		super(meta, paramDef, async (ps, me) => {
 			const user = await this.usersRepository.findOneByOrFail({ id: ps.userId });
 			if (user.isDeleted) {
 				return;
 			}
 
-			await this.deleteAccountService.deleteAccount(user);
+			await this.deleteAccountService.deleteAccount(user, me);
 		});
 	}
 }

From 4603ab67bb96da39f6c4186ab655e8011fdcb740 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=B4=87=E5=B3=B0=20=E6=9C=94=E8=8F=AF?=
 <160555157+sakuhanight@users.noreply.github.com>
Date: Wed, 20 Nov 2024 20:08:26 +0900
Subject: [PATCH 090/125] =?UTF-8?q?feat:=20=E7=B5=B5=E6=96=87=E5=AD=97?=
 =?UTF-8?q?=E3=81=AE=E3=83=9D=E3=83=83=E3=83=97=E3=82=A2=E3=83=83=E3=83=97?=
 =?UTF-8?q?=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC=E3=81=AB=E7=B7=A8=E9=9B=86?=
 =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=20(#15004)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Mod: 絵文字のポップアップメニューに編集を追加

* fix: code styleの修正

* fix: code styleの修正

* fix
---
 .../src/components/global/MkCustomEmoji.vue   | 29 +++++++++++++++++--
 packages/frontend/src/pages/emojis.emoji.vue  | 28 ++++++++++++++++--
 2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index 66f82a7898..ec1d859080 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -25,17 +25,18 @@ SPDX-License-Identifier: AGPL-3.0-only
 </template>
 
 <script lang="ts" setup>
-import { computed, inject, ref } from 'vue';
+import { computed, defineAsyncComponent, inject, ref } from 'vue';
+import type { MenuItem } from '@/types/menu.js';
 import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js';
 import { defaultStore } from '@/store.js';
 import { customEmojisMap } from '@/custom-emojis.js';
 import * as os from '@/os.js';
-import { misskeyApiGet } from '@/scripts/misskey-api.js';
+import { misskeyApi, misskeyApiGet } from '@/scripts/misskey-api.js';
 import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
 import * as sound from '@/scripts/sound.js';
 import { i18n } from '@/i18n.js';
 import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
-import type { MenuItem } from '@/types/menu.js';
+import { $i } from '@/account.js';
 
 const props = defineProps<{
 	name: string;
@@ -125,9 +126,31 @@ function onClick(ev: MouseEvent) {
 			},
 		});
 
+		if ($i?.isModerator ?? $i?.isAdmin) {
+			menuItems.push({
+				text: i18n.ts.edit,
+				icon: 'ti ti-pencil',
+				action: async () => {
+					await edit(props.name);
+				},
+			});
+		}
+
 		os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
 	}
 }
+
+async function edit(name: string) {
+	const emoji = await misskeyApi('emoji', {
+		name: name,
+	});
+	const { dispose } = os.popup(defineAsyncComponent(() => import('@/pages/emoji-edit-dialog.vue')), {
+		emoji: emoji,
+	}, {
+		closed: () => dispose(),
+	});
+}
+
 </script>
 
 <style lang="scss" module>
diff --git a/packages/frontend/src/pages/emojis.emoji.vue b/packages/frontend/src/pages/emojis.emoji.vue
index fcd22155b7..979d50966e 100644
--- a/packages/frontend/src/pages/emojis.emoji.vue
+++ b/packages/frontend/src/pages/emojis.emoji.vue
@@ -15,18 +15,22 @@ SPDX-License-Identifier: AGPL-3.0-only
 
 <script lang="ts" setup>
 import * as Misskey from 'misskey-js';
+import { defineAsyncComponent } from 'vue';
+import type { MenuItem } from '@/types/menu.js';
 import * as os from '@/os.js';
 import { misskeyApiGet } from '@/scripts/misskey-api.js';
 import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
 import { i18n } from '@/i18n.js';
 import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
+import { $i } from '@/account.js';
 
 const props = defineProps<{
   emoji: Misskey.entities.EmojiSimple;
 }>();
 
 function menu(ev) {
-	os.popupMenu([{
+	const menuItems: MenuItem[] = [];
+	menuItems.push({
 		type: 'label',
 		text: ':' + props.emoji.name + ':',
 	}, {
@@ -48,8 +52,28 @@ function menu(ev) {
 				closed: () => dispose(),
 			});
 		},
-	}], ev.currentTarget ?? ev.target);
+	});
+
+	if ($i?.isModerator ?? $i?.isAdmin) {
+		menuItems.push({
+			text: i18n.ts.edit,
+			icon: 'ti ti-pencil',
+			action: () => {
+				edit(props.emoji);
+			},
+		});
+	}
+
+	os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
 }
+
+const edit = async (emoji) => {
+	const { dispose } = os.popup(defineAsyncComponent(() => import('@/pages/emoji-edit-dialog.vue')), {
+		emoji: emoji,
+	}, {
+		closed: () => dispose(),
+	});
+};
 </script>
 
 <style lang="scss" module>

From f0c3a4cc0b47b392dd155ebabea0d5587df2753d Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 21 Nov 2024 07:58:34 +0900
Subject: [PATCH 091/125] perf(frontend): reduce api requests for non-logged-in
 enviroment (#15001)

* wip

* Update CHANGELOG.md

* wip
---
 CHANGELOG.md                                  |  1 +
 .../src/server/web/ClientServerService.ts     | 14 ++++++++++-
 .../backend/src/server/web/views/base.pug     |  3 +++
 packages/frontend/src/pages/clip.vue          | 14 ++++++++---
 packages/frontend/src/pages/note.vue          | 11 ++++++++-
 packages/frontend/src/pages/user/index.vue    | 18 +++++++++++++--
 packages/frontend/src/server-context.ts       | 23 +++++++++++++++++++
 7 files changed, 77 insertions(+), 7 deletions(-)
 create mode 100644 packages/frontend/src/server-context.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index befe237b09..58b9c4d0cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@
   (Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
 - Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
 - Enhance: リノートメニューに「リノートの詳細」を追加
+- Enhance: 非ログイン状態でMisskeyを開いた際のパフォーマンスを向上
 - Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
 - Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正  
   (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index 5ebec4ffd0..1b8873214b 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -559,7 +559,7 @@ export class ClientServerService {
 			}
 		});
 
-		//#region SSR (for crawlers)
+		//#region SSR
 		// User
 		fastify.get<{ Params: { user: string; sub?: string; } }>('/@:user/:sub?', async (request, reply) => {
 			const { username, host } = Acct.parse(request.params.user);
@@ -584,11 +584,17 @@ export class ClientServerService {
 					reply.header('X-Robots-Tag', 'noimageai');
 					reply.header('X-Robots-Tag', 'noai');
 				}
+
+				const _user = await this.userEntityService.pack(user);
+
 				return await reply.view('user', {
 					user, profile, me,
 					avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
 					sub: request.params.sub,
 					...await this.generateCommonPugData(this.meta),
+					clientCtx: htmlSafeJsonStringify({
+						user: _user,
+					}),
 				});
 			} else {
 				// リモートユーザーなので
@@ -641,6 +647,9 @@ export class ClientServerService {
 					// TODO: Let locale changeable by instance setting
 					summary: getNoteSummary(_note),
 					...await this.generateCommonPugData(this.meta),
+					clientCtx: htmlSafeJsonStringify({
+						note: _note,
+					}),
 				});
 			} else {
 				return await renderBase(reply);
@@ -729,6 +738,9 @@ export class ClientServerService {
 					profile,
 					avatarUrl: _clip.user.avatarUrl,
 					...await this.generateCommonPugData(this.meta),
+					clientCtx: htmlSafeJsonStringify({
+						clip: _clip,
+					}),
 				});
 			} else {
 				return await renderBase(reply);
diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug
index 280a5923c2..3883b5e5ab 100644
--- a/packages/backend/src/server/web/views/base.pug
+++ b/packages/backend/src/server/web/views/base.pug
@@ -74,6 +74,9 @@ html
 		script(type='application/json' id='misskey_meta' data-generated-at=now)
 			!= metaJson
 
+		script(type='application/json' id='misskey_clientCtx' data-generated-at=now)
+			!= clientCtx
+
 		script
 			include ../boot.js
 
diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue
index 7b1737fece..891d59d605 100644
--- a/packages/frontend/src/pages/clip.vue
+++ b/packages/frontend/src/pages/clip.vue
@@ -33,25 +33,28 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { computed, watch, provide, ref } from 'vue';
 import * as Misskey from 'misskey-js';
+import { url } from '@@/js/config.js';
+import type { MenuItem } from '@/types/menu.js';
 import MkNotes from '@/components/MkNotes.vue';
 import { $i } from '@/account.js';
 import { i18n } from '@/i18n.js';
 import * as os from '@/os.js';
 import { misskeyApi } from '@/scripts/misskey-api.js';
 import { definePageMetadata } from '@/scripts/page-metadata.js';
-import { url } from '@@/js/config.js';
 import MkButton from '@/components/MkButton.vue';
 import { clipsCache } from '@/cache.js';
 import { isSupportShare } from '@/scripts/navigator.js';
 import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
 import { genEmbedCode } from '@/scripts/get-embed-code.js';
-import type { MenuItem } from '@/types/menu.js';
+import { getServerContext } from '@/server-context.js';
+
+const CTX_CLIP = getServerContext('clip');
 
 const props = defineProps<{
 	clipId: string,
 }>();
 
-const clip = ref<Misskey.entities.Clip | null>(null);
+const clip = ref<Misskey.entities.Clip | null>(CTX_CLIP);
 const favorited = ref(false);
 const pagination = {
 	endpoint: 'clips/notes' as const,
@@ -64,6 +67,11 @@ const pagination = {
 const isOwned = computed<boolean | null>(() => $i && clip.value && ($i.id === clip.value.userId));
 
 watch(() => props.clipId, async () => {
+	if (CTX_CLIP && CTX_CLIP.id === props.clipId) {
+		clip.value = CTX_CLIP;
+		return;
+	}
+
 	clip.value = await misskeyApi('clips/show', {
 		clipId: props.clipId,
 	});
diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue
index 454ee3c6bc..3e1d04bd6d 100644
--- a/packages/frontend/src/pages/note.vue
+++ b/packages/frontend/src/pages/note.vue
@@ -62,13 +62,16 @@ import { dateString } from '@/filters/date.js';
 import MkClipPreview from '@/components/MkClipPreview.vue';
 import { defaultStore } from '@/store.js';
 import { pleaseLogin } from '@/scripts/please-login.js';
+import { getServerContext } from '@/server-context.js';
+
+const CTX_NOTE = getServerContext('note');
 
 const props = defineProps<{
 	noteId: string;
 	initialTab?: string;
 }>();
 
-const note = ref<null | Misskey.entities.Note>();
+const note = ref<null | Misskey.entities.Note>(CTX_NOTE);
 const clips = ref<Misskey.entities.Clip[]>();
 const showPrev = ref<'user' | 'channel' | false>(false);
 const showNext = ref<'user' | 'channel' | false>(false);
@@ -116,6 +119,12 @@ function fetchNote() {
 	showPrev.value = false;
 	showNext.value = false;
 	note.value = null;
+
+	if (CTX_NOTE && CTX_NOTE.id === props.noteId) {
+		note.value = CTX_NOTE;
+		return;
+	}
+
 	misskeyApi('notes/show', {
 		noteId: props.noteId,
 	}).then(res => {
diff --git a/packages/frontend/src/pages/user/index.vue b/packages/frontend/src/pages/user/index.vue
index a6244e2a93..d862387401 100644
--- a/packages/frontend/src/pages/user/index.vue
+++ b/packages/frontend/src/pages/user/index.vue
@@ -39,6 +39,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
 import { i18n } from '@/i18n.js';
 import { $i } from '@/account.js';
 import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
+import { getServerContext } from '@/server-context.js';
 
 const XHome = defineAsyncComponent(() => import('./home.vue'));
 const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
@@ -52,6 +53,8 @@ const XFlashs = defineAsyncComponent(() => import('./flashs.vue'));
 const XGallery = defineAsyncComponent(() => import('./gallery.vue'));
 const XRaw = defineAsyncComponent(() => import('./raw.vue'));
 
+const CTX_USER = getServerContext('user');
+
 const props = withDefaults(defineProps<{
 	acct: string;
 	page?: string;
@@ -61,13 +64,24 @@ const props = withDefaults(defineProps<{
 
 const tab = ref(props.page);
 
-const user = ref<null | Misskey.entities.UserDetailed>(null);
+const user = ref<null | Misskey.entities.UserDetailed>(CTX_USER);
 const error = ref<any>(null);
 
 function fetchUser(): void {
 	if (props.acct == null) return;
+
+	const { username, host } = Misskey.acct.parse(props.acct);
+
+	if (CTX_USER && CTX_USER.username === username && CTX_USER.host === host) {
+		user.value = CTX_USER;
+		return;
+	}
+
 	user.value = null;
-	misskeyApi('users/show', Misskey.acct.parse(props.acct)).then(u => {
+	misskeyApi('users/show', {
+		username,
+		host,
+	}).then(u => {
 		user.value = u;
 	}).catch(err => {
 		error.value = err;
diff --git a/packages/frontend/src/server-context.ts b/packages/frontend/src/server-context.ts
new file mode 100644
index 0000000000..aa44a10290
--- /dev/null
+++ b/packages/frontend/src/server-context.ts
@@ -0,0 +1,23 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import * as Misskey from 'misskey-js';
+import { $i } from '@/account.js';
+
+const providedContextEl = document.getElementById('misskey_clientCtx');
+
+export type ServerContext = {
+	clip?: Misskey.entities.Clip;
+	note?: Misskey.entities.Note;
+	user?: Misskey.entities.UserLite;
+} | null;
+
+export const serverContext: ServerContext = (providedContextEl && providedContextEl.textContent) ? JSON.parse(providedContextEl.textContent) : null;
+
+export function getServerContext<K extends keyof NonNullable<ServerContext>>(entity: K): Required<Pick<NonNullable<ServerContext>, K>> | null {
+	// contextは非ログイン状態の情報しかないためログイン時は利用できない
+	if ($i) return null;
+
+	return serverContext ? (serverContext[entity] ?? null) : null;
+}

From aa48a0e207fbf37150363052b19a8b41ffcf1630 Mon Sep 17 00:00:00 2001
From: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:00:50 +0900
Subject: [PATCH 092/125] =?UTF-8?q?Fix:=20=E3=83=AA=E3=83=8E=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E3=83=9F=E3=83=A5=E3=83=BC=E3=83=88=E3=81=8C=E6=96=B0?=
 =?UTF-8?q?=E8=A6=8F=E6=8A=95=E7=A8=BF=E9=80=9A=E7=9F=A5=E3=81=AB=E5=AF=BE?=
 =?UTF-8?q?=E3=81=97=E3=81=A6=E4=BD=9C=E7=94=A8=E3=81=97=E3=81=A6=E3=81=84?=
 =?UTF-8?q?=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F=E9=A1=8C=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#15006)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(backend): renoteMute doesn't work for note notification

* docs(changelog): update changelog
---
 CHANGELOG.md                                   |  1 +
 packages/backend/src/core/NoteCreateService.ts | 18 ++++++++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58b9c4d0cd..0718150fc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -66,6 +66,7 @@
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
 - Fix: User Webhookテスト機能のMock Payloadを修正  
 - Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)  
+- Fix: リノートミュートが新規投稿通知に対して作用していなかった問題を修正
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
index 3647fa7231..56ddcefd7c 100644
--- a/packages/backend/src/core/NoteCreateService.ts
+++ b/packages/backend/src/core/NoteCreateService.ts
@@ -56,6 +56,7 @@ import { isReply } from '@/misc/is-reply.js';
 import { trackPromise } from '@/misc/promise-tracker.js';
 import { IdentifiableError } from '@/misc/identifiable-error.js';
 import { CollapsedQueue } from '@/misc/collapsed-queue.js';
+import { CacheService } from '@/core/CacheService.js';
 
 type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
 
@@ -217,6 +218,7 @@ export class NoteCreateService implements OnApplicationShutdown {
 		private instanceChart: InstanceChart,
 		private utilityService: UtilityService,
 		private userBlockingService: UserBlockingService,
+		private cacheService: CacheService,
 	) {
 		this.updateNotesCountQueue = new CollapsedQueue(process.env.NODE_ENV !== 'test' ? 60 * 1000 * 5 : 0, this.collapseNotesCount, this.performUpdateNotesCount);
 	}
@@ -543,13 +545,21 @@ export class NoteCreateService implements OnApplicationShutdown {
 			this.followingsRepository.findBy({
 				followeeId: user.id,
 				notify: 'normal',
-			}).then(followings => {
+			}).then(async followings => {
 				if (note.visibility !== 'specified') {
+					const isPureRenote = this.isRenote(data) && !this.isQuote(data) ? true : false;
 					for (const following of followings) {
 						// TODO: ワードミュート考慮
-						this.notificationService.createNotification(following.followerId, 'note', {
-							noteId: note.id,
-						}, user.id);
+						let isRenoteMuted = false;
+						if (isPureRenote) {
+							const userIdsWhoMeMutingRenotes = await this.cacheService.renoteMutingsCache.fetch(following.followerId);
+							isRenoteMuted = userIdsWhoMeMutingRenotes.has(user.id);
+						}
+						if (!isRenoteMuted) {
+							this.notificationService.createNotification(following.followerId, 'note', {
+								noteId: note.id,
+							}, user.id);
+						}
 					}
 				}
 			});

From 1c284c81546b97ecec0abcbb12a2069d2178a11b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:01:42 +0900
Subject: [PATCH 093/125] New Crowdin updates (#15000)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Traditional)

* New translations ja-jp.yml (German)
---
 locales/ca-ES.yml | 1 +
 locales/de-DE.yml | 5 +++++
 locales/en-US.yml | 1 +
 locales/ko-KR.yml | 7 +++++++
 locales/zh-CN.yml | 4 ++--
 locales/zh-TW.yml | 1 +
 6 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index b301780972..1aca3390e6 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -586,6 +586,7 @@ masterVolume: "Volum principal"
 notUseSound: "Sense so"
 useSoundOnlyWhenActive: "Reproduir sons només quan Misskey estigui actiu"
 details: "Detalls"
+renoteDetails: "Més informació sobre l'impuls "
 chooseEmoji: "Tria un emoji"
 unableToProcess: "L'operació no pot ser completada "
 recentUsed: "Utilitzat recentment"
diff --git a/locales/de-DE.yml b/locales/de-DE.yml
index 1b3925ef38..d85c930b73 100644
--- a/locales/de-DE.yml
+++ b/locales/de-DE.yml
@@ -1242,6 +1242,7 @@ keepOriginalFilenameDescription: "Wenn diese Einstellung deaktiviert ist, wird d
 noDescription: "Keine Beschreibung vorhanden"
 tryAgain: "Bitte später erneut versuchen"
 confirmWhenRevealingSensitiveMedia: "Das Anzeigen von sensiblen Medien bestätigen"
+sensitiveMediaRevealConfirm: "Es könnte sich um sensible Medien handeln. Möchtest du sie anzeigen?"
 createdLists: "Erstellte Listen"
 createdAntennas: "Erstellte Antennen"
 fromX: "Von {x}"
@@ -1253,6 +1254,8 @@ thereAreNChanges: "Es gibt {n} Änderung(en)"
 signinWithPasskey: "Mit Passkey anmelden"
 passkeyVerificationFailed: "Die Passkey-Verifizierung ist fehlgeschlagen."
 passkeyVerificationSucceededButPasswordlessLoginDisabled: "Die Verifizierung des Passkeys war erfolgreich, aber die passwortlose Anmeldung ist deaktiviert."
+messageToFollower: "Nachricht an die Follower"
+testCaptchaWarning: "Diese Funktion ist für CAPTCHA-Testzwecke gedacht.\n<strong>Nicht in einer Produktivumgebung verwenden.</strong>"
 prohibitedWordsForNameOfUser: "Verbotene Begriffe für Benutzernamen"
 prohibitedWordsForNameOfUserDescription: "Wenn eine Zeichenfolge aus dieser Liste im Namen eines Benutzers enthalten ist, wird der Benutzername abgelehnt. Benutzer mit Moderatorenrechten sind von dieser Einschränkung nicht betroffen."
 yourNameContainsProhibitedWords: "Dein Name enthält einen verbotenen Begriff"
@@ -1264,6 +1267,7 @@ _accountSettings:
   requireSigninToViewContentsDescription1: "Erfordere eine Anmeldung, um alle Notizen und andere Inhalte anzuzeigen, die du erstellt hast. Dadurch wird verhindert, dass Crawler deine Informationen sammeln."
   requireSigninToViewContentsDescription3: "Diese Einschränkungen gelten möglicherweise nicht für föderierte Inhalte von anderen Servern."
   makeNotesFollowersOnlyBefore: "Macht frühere Notizen nur für Follower sichtbar"
+  makeNotesHiddenBefore: "Frühere Notizen privat machen"
   mayNotEffectForFederatedNotes: "Dies hat möglicherweise keine Auswirkungen auf Notizen, die an andere Server föderiert werden."
 _abuseUserReport:
   forward: "Weiterleiten"
@@ -1274,6 +1278,7 @@ _delivery:
   stop: "Gesperrt"
   _type:
     none: "Wird veröffentlicht"
+    manuallySuspended: "Manuell gesperrt"
 _bubbleGame:
   howToPlay: "Wie man spielt"
   hold: "Halten"
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 658914d3bc..69e6da1a6f 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -586,6 +586,7 @@ masterVolume: "Master volume"
 notUseSound: "Disable sound"
 useSoundOnlyWhenActive: "Output sounds only if Misskey is active."
 details: "Details"
+renoteDetails: "Renote details"
 chooseEmoji: "Select an emoji"
 unableToProcess: "The operation could not be completed"
 recentUsed: "Recently used"
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index d20a9754b1..d694d2dbae 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -586,6 +586,7 @@ masterVolume: "마스터 볼륨"
 notUseSound: "음소거 하기"
 useSoundOnlyWhenActive: "Misskey를 활성화한 때에만 소리를 출력하기"
 details: "자세히"
+renoteDetails: "리노트 상세 내용"
 chooseEmoji: "이모지 선택"
 unableToProcess: "작업을 완료할 수 없습니다"
 recentUsed: "최근 사용"
@@ -1299,6 +1300,7 @@ thisContentsAreMarkedAsSigninRequiredByAuthor: "게시자에 의해 로그인해
 lockdown: "잠금"
 pleaseSelectAccount: "계정을 선택해주세요."
 availableRoles: "사용 가능한 역할"
+acknowledgeNotesAndEnable: "활성화 하기 전에 주의 사항을 확인했습니다."
 _accountSettings:
   requireSigninToViewContents: "콘텐츠 열람을 위해 로그인으 필수로 설정하기"
   requireSigninToViewContentsDescription1: "자신이 작성한 모든 노트 등의 콘텐츠를 보기 위해 로그인을 필수로 설정합니다. 크롤러가 정보 수집하는 것을 방지하는 효과를 기대할 수 있습니다."
@@ -1455,6 +1457,8 @@ _serverSettings:
   reactionsBufferingDescription: "활성화 한 경우, 리액션 작성 퍼포먼스가 대폭 향상되어 DB의 부하를 줄일 수 있으나, Redis의 메모리 사용량이 많아집니다."
   inquiryUrl: "문의처 URL"
   inquiryUrlDescription: "서버 운영자에게 보내는 문의 양식의 URL이나 운영자의 연락처 등이 적힌 웹 페이지의 URL을 설정합니다."
+  openRegistration: "회원 가입을 활성화 하기"
+  openRegistrationWarning: "회원 가입을 개방하는 것은 리스크가 따릅니다. 서버를 항상 감시할 수 있고, 문제가 발생했을 때 바로 대응할 수 있는 상태에서만 활성화 하는 것을 권장합니다."
   thisSettingWillAutomaticallyOffWhenModeratorsInactive: "일정 기간동안 모더레이터의 활동이 감지되지 않는 경우, 스팸 방지를 위해 이 설정은 자동으로 꺼집니다."
 _accountMigration:
   moveFrom: "다른 계정에서 이 계정으로 이사"
@@ -2737,3 +2741,6 @@ _selfXssPrevention:
   description1: "여기에 무언가를 붙여넣으면 악의적인 사용자에게 계정을 탈취당하거나 개인정보를 도용당할 수 있습니다."
   description2: "붙여 넣으려는 항목이 무엇인지 정확히 이해하지 못하는 경우, %c지금 바로 작업을 중단하고 이 창을 닫으십시오."
   description3: "자세한 내용은 여기를 확인해 주세요.  {link}"
+_followRequest:
+  recieved: "받은 신청"
+  sent: "보낸 신청"
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index c5a581035d..08e007df7f 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -1707,9 +1707,9 @@ _achievements:
       description: "在元旦登入"
       flavor: "今年也请对本服务器多多指教!"
     _cookieClicked:
-      title: "点击饼干小游戏"
+      title: "饼干点点乐"
       description: "点击了饼干"
-      flavor: "用错软件了?"
+      flavor: "穿越了?"
     _brainDiver:
       title: "Brain Diver"
       description: "发布了包含 Brain Diver 链接的帖子"
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index 1e8e27c7bd..d4ffb28c76 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -586,6 +586,7 @@ masterVolume: "主音量"
 notUseSound: "關閉音效"
 useSoundOnlyWhenActive: "瀏覽器在前景運作時,Misskey 才會發出音效"
 details: "詳細資訊"
+renoteDetails: "轉發貼文的細節"
 chooseEmoji: "選擇您的表情符號"
 unableToProcess: "操作無法完成"
 recentUsed: "最近使用"

From 5f675201f261d5db6a58d3099a190372bb2f09f0 Mon Sep 17 00:00:00 2001
From: Julia <julia@insertdomain.name>
Date: Wed, 20 Nov 2024 18:20:09 -0500
Subject: [PATCH 094/125] Merge commit from fork

* enhance: Add a few validation fixes from Sharkey

See the original MR on the GitLab instance:
https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/484

Co-Authored-By: Dakkar <dakkar@thenautilus.net>

* fix: primitive 2: acceptance of cross-origin alternate

Co-Authored-By: Laura Hausmann <laura@hausmann.dev>

* fix: primitive 3: validation of non-final url

* fix: primitive 4: missing same-origin identifier validation of collection-wrapped activities

* fix: primitives 5 & 8: reject activities with non
string identifiers

Co-Authored-By: Laura Hausmann <laura@hausmann.dev>

* fix: primitive 6: reject anonymous objects that were fetched by their id

* fix: primitives 9, 10 & 11: http signature validation
doesn't enforce required headers or specify auth header name

Co-Authored-By: Laura Hausmann <laura@hausmann.dev>

* fix: primitive 14: improper validation of outbox, followers, following & shared inbox collections

* fix: code style for primitive 14

* fix: primitive 15: improper same-origin validation for
note uri and url

Co-Authored-By: Laura Hausmann <laura@hausmann.dev>

* fix: primitive 16: improper same-origin validation for user uri and url

* fix: primitive 17: note same-origin identifier validation can be bypassed by wrapping the id in an array

* fix: code style for primitive 17

* fix: check attribution against actor in notes

While this isn't strictly required to fix the exploits at hand, this
mirrors the fix in `ApQuestionService` for GHSA-5h8r-gq97-xv69, as a
preemptive countermeasure.

* fix: primitive 18: `ap/get` bypasses access checks

One might argue that we could make this one actually preform access
checks against the returned activity object, but I feel like that's a
lot more work than just restricting it to administrators, since, to me
at least, it seems more like a debugging tool than anything else.

* fix: primitive 19 & 20: respect blocks and hide more

Ideally, the user property should also be hidden (as leaving it in leaks
information slightly), but given the schema of the note endpoint, I
don't think that would be possible without introducing some kind of
"ghost" user, who is attributed for posts by users who have you blocked.

* fix: primitives 21, 22, and 23: reuse resolver

This also increases the default `recursionLimit` for `Resolver`, as it
theoretically will go higher that it previously would and could possibly
fail on non-malicious collection activities.

* fix: primitives 25-33: proper local instance checks

* revert: fix: primitive 19 & 20

This reverts commit 465a9fe6591de90f78bd3d084e3c01e65dc3cf3c.

---------

Co-authored-by: Dakkar <dakkar@thenautilus.net>
Co-authored-by: Laura Hausmann <laura@hausmann.dev>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 .../backend/src/core/HttpRequestService.ts    |  8 +-
 .../src/core/RemoteUserResolveService.ts      |  4 +-
 packages/backend/src/core/UtilityService.ts   | 14 ++-
 .../core/activitypub/ApDbResolverService.ts   |  6 +-
 .../src/core/activitypub/ApInboxService.ts    | 93 +++++++++++--------
 .../src/core/activitypub/ApRequestService.ts  | 12 ++-
 .../src/core/activitypub/ApResolverService.ts | 19 +++-
 .../activitypub/misc/check-against-url.ts     | 19 ++++
 .../core/activitypub/models/ApNoteService.ts  | 42 ++++++---
 .../activitypub/models/ApPersonService.ts     | 72 ++++++++++----
 .../activitypub/models/ApQuestionService.ts   |  4 +-
 .../queue/processors/InboxProcessorService.ts |  2 +
 .../src/server/ActivityPubServerService.ts    |  2 +-
 .../src/server/api/endpoints/ap/get.ts        |  1 +
 .../src/server/api/endpoints/ap/show.ts       |  5 +
 15 files changed, 227 insertions(+), 76 deletions(-)
 create mode 100644 packages/backend/src/core/activitypub/misc/check-against-url.ts

diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts
index 7f3cac7c58..08e9f46b2d 100644
--- a/packages/backend/src/core/HttpRequestService.ts
+++ b/packages/backend/src/core/HttpRequestService.ts
@@ -15,6 +15,7 @@ import type { Config } from '@/config.js';
 import { StatusError } from '@/misc/status-error.js';
 import { bindThis } from '@/decorators.js';
 import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
+import { assertActivityMatchesUrls } from '@/core/activitypub/misc/check-against-url.js';
 import type { IObject } from '@/core/activitypub/type.js';
 import type { Response } from 'node-fetch';
 import type { URL } from 'node:url';
@@ -125,7 +126,12 @@ export class HttpRequestService {
 			validators: [validateContentTypeSetAsActivityPub],
 		});
 
-		return await res.json() as IObject;
+		const finalUrl = res.url; // redirects may have been involved
+		const activity = await res.json() as IObject;
+
+		assertActivityMatchesUrls(activity, [finalUrl]);
+
+		return activity;
 	}
 
 	@bindThis
diff --git a/packages/backend/src/core/RemoteUserResolveService.ts b/packages/backend/src/core/RemoteUserResolveService.ts
index f5a55eb8bc..678da0cfa6 100644
--- a/packages/backend/src/core/RemoteUserResolveService.ts
+++ b/packages/backend/src/core/RemoteUserResolveService.ts
@@ -54,9 +54,9 @@ export class RemoteUserResolveService {
 			}) as MiLocalUser;
 		}
 
-		host = this.utilityService.toPuny(host);
+		host = this.utilityService.punyHost(host);
 
-		if (this.config.host === host) {
+		if (host === this.utilityService.toPuny(this.config.host)) {
 			this.logger.info(`return local user: ${usernameLower}`);
 			return await this.usersRepository.findOneBy({ usernameLower, host: IsNull() }).then(u => {
 				if (u == null) {
diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts
index 86082ccdcd..9a2ba72ed3 100644
--- a/packages/backend/src/core/UtilityService.ts
+++ b/packages/backend/src/core/UtilityService.ts
@@ -34,6 +34,11 @@ export class UtilityService {
 		return this.toPuny(this.config.host) === this.toPuny(host);
 	}
 
+	@bindThis
+	public isUriLocal(uri: string): boolean {
+		return this.punyHost(uri) === this.toPuny(this.config.host);
+	}
+
 	@bindThis
 	public isBlockedHost(blockedHosts: string[], host: string | null): boolean {
 		if (host == null) return false;
@@ -96,7 +101,7 @@ export class UtilityService {
 	@bindThis
 	public extractDbHost(uri: string): string {
 		const url = new URL(uri);
-		return this.toPuny(url.hostname);
+		return this.toPuny(url.host);
 	}
 
 	@bindThis
@@ -110,6 +115,13 @@ export class UtilityService {
 		return toASCII(host.toLowerCase());
 	}
 
+	@bindThis
+	public punyHost(url: string): string {
+		const urlObj = new URL(url);
+		const host = `${this.toPuny(urlObj.hostname)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`;
+		return host;
+	}
+
 	@bindThis
 	public isFederationAllowedHost(host: string): boolean {
 		if (this.meta.federation === 'none') return false;
diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts
index 4192e8659a..5c16744a77 100644
--- a/packages/backend/src/core/activitypub/ApDbResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts
@@ -10,6 +10,7 @@ import type { Config } from '@/config.js';
 import { MemoryKVCache } from '@/misc/cache.js';
 import type { MiUserPublickey } from '@/models/UserPublickey.js';
 import { CacheService } from '@/core/CacheService.js';
+import { UtilityService } from '@/core/UtilityService.js';
 import type { MiNote } from '@/models/Note.js';
 import { bindThis } from '@/decorators.js';
 import { MiLocalUser, MiRemoteUser } from '@/models/User.js';
@@ -53,6 +54,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
 
 		private cacheService: CacheService,
 		private apPersonService: ApPersonService,
+		private utilityService: UtilityService,
 	) {
 		this.publicKeyCache = new MemoryKVCache<MiUserPublickey | null>(1000 * 60 * 60 * 12); // 12h
 		this.publicKeyByUserIdCache = new MemoryKVCache<MiUserPublickey | null>(1000 * 60 * 60 * 12); // 12h
@@ -63,7 +65,9 @@ export class ApDbResolverService implements OnApplicationShutdown {
 		const separator = '/';
 
 		const uri = new URL(getApId(value));
-		if (uri.origin !== this.config.url) return { local: false, uri: uri.href };
+		if (this.utilityService.toPuny(uri.host) !== this.utilityService.toPuny(this.config.host)) {
+			return { local: false, uri: uri.href };
+		}
 
 		const [, type, id, ...rest] = uri.pathname.split(separator);
 		return {
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 376c9c0151..8e8ec223cb 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -89,15 +89,26 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	public async performActivity(actor: MiRemoteUser, activity: IObject): Promise<string | void> {
+	public async performActivity(actor: MiRemoteUser, activity: IObject, resolver?: Resolver): Promise<string | void> {
 		let result = undefined as string | void;
 		if (isCollectionOrOrderedCollection(activity)) {
 			const results = [] as [string, string | void][];
-			const resolver = this.apResolverService.createResolver();
-			for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) {
+			// eslint-disable-next-line no-param-reassign
+			resolver ??= this.apResolverService.createResolver();
+
+			const items = toArray(isCollection(activity) ? activity.items : activity.orderedItems);
+			if (items.length >= resolver.getRecursionLimit()) {
+				throw new Error(`skipping activity: collection would surpass recursion limit: ${this.utilityService.extractDbHost(actor.uri)}`);
+			}
+
+			for (const item of items) {
 				const act = await resolver.resolve(item);
+				if (act.id == null || this.utilityService.extractDbHost(act.id) !== this.utilityService.extractDbHost(actor.uri)) {
+					this.logger.debug('skipping activity: activity id is null or mismatching');
+					continue;
+				}
 				try {
-					results.push([getApId(item), await this.performOneActivity(actor, act)]);
+					results.push([getApId(item), await this.performOneActivity(actor, act, resolver)]);
 				} catch (err) {
 					if (err instanceof Error || typeof err === 'string') {
 						this.logger.error(err);
@@ -112,7 +123,7 @@ export class ApInboxService {
 				result = results.map(([id, reason]) => `${id}: ${reason}`).join('\n');
 			}
 		} else {
-			result = await this.performOneActivity(actor, activity);
+			result = await this.performOneActivity(actor, activity, resolver);
 		}
 
 		// ついでにリモートユーザーの情報が古かったら更新しておく
@@ -127,37 +138,37 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	public async performOneActivity(actor: MiRemoteUser, activity: IObject): Promise<string | void> {
+	public async performOneActivity(actor: MiRemoteUser, activity: IObject, resolver?: Resolver): Promise<string | void> {
 		if (actor.isSuspended) return;
 
 		if (isCreate(activity)) {
-			return await this.create(actor, activity);
+			return await this.create(actor, activity, resolver);
 		} else if (isDelete(activity)) {
 			return await this.delete(actor, activity);
 		} else if (isUpdate(activity)) {
-			return await this.update(actor, activity);
+			return await this.update(actor, activity, resolver);
 		} else if (isFollow(activity)) {
 			return await this.follow(actor, activity);
 		} else if (isAccept(activity)) {
-			return await this.accept(actor, activity);
+			return await this.accept(actor, activity, resolver);
 		} else if (isReject(activity)) {
-			return await this.reject(actor, activity);
+			return await this.reject(actor, activity, resolver);
 		} else if (isAdd(activity)) {
-			return await this.add(actor, activity);
+			return await this.add(actor, activity, resolver);
 		} else if (isRemove(activity)) {
-			return await this.remove(actor, activity);
+			return await this.remove(actor, activity, resolver);
 		} else if (isAnnounce(activity)) {
-			return await this.announce(actor, activity);
+			return await this.announce(actor, activity, resolver);
 		} else if (isLike(activity)) {
 			return await this.like(actor, activity);
 		} else if (isUndo(activity)) {
-			return await this.undo(actor, activity);
+			return await this.undo(actor, activity, resolver);
 		} else if (isBlock(activity)) {
 			return await this.block(actor, activity);
 		} else if (isFlag(activity)) {
 			return await this.flag(actor, activity);
 		} else if (isMove(activity)) {
-			return await this.move(actor, activity);
+			return await this.move(actor, activity, resolver);
 		} else {
 			return `unrecognized activity type: ${activity.type}`;
 		}
@@ -199,12 +210,13 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async accept(actor: MiRemoteUser, activity: IAccept): Promise<string> {
+	private async accept(actor: MiRemoteUser, activity: IAccept, resolver?: Resolver): Promise<string> {
 		const uri = activity.id ?? activity;
 
 		this.logger.info(`Accept: ${uri}`);
 
-		const resolver = this.apResolverService.createResolver();
+		// eslint-disable-next-line no-param-reassign
+		resolver ??= this.apResolverService.createResolver();
 
 		const object = await resolver.resolve(activity.object).catch(err => {
 			this.logger.error(`Resolution failed: ${err}`);
@@ -241,7 +253,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async add(actor: MiRemoteUser, activity: IAdd): Promise<string | void> {
+	private async add(actor: MiRemoteUser, activity: IAdd, resolver?: Resolver): Promise<string | void> {
 		if (actor.uri !== activity.actor) {
 			return 'invalid actor';
 		}
@@ -251,7 +263,7 @@ export class ApInboxService {
 		}
 
 		if (activity.target === actor.featured) {
-			const note = await this.apNoteService.resolveNote(activity.object);
+			const note = await this.apNoteService.resolveNote(activity.object, { resolver });
 			if (note == null) return 'note not found';
 			await this.notePiningService.addPinned(actor, note.id);
 			return;
@@ -261,12 +273,13 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async announce(actor: MiRemoteUser, activity: IAnnounce): Promise<string | void> {
+	private async announce(actor: MiRemoteUser, activity: IAnnounce, resolver?: Resolver): Promise<string | void> {
 		const uri = getApId(activity);
 
 		this.logger.info(`Announce: ${uri}`);
 
-		const resolver = this.apResolverService.createResolver();
+		// eslint-disable-next-line no-param-reassign
+		resolver ??= this.apResolverService.createResolver();
 
 		if (!activity.object) return 'skip: activity has no object property';
 		const targetUri = getApId(activity.object);
@@ -283,7 +296,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async announceNote(actor: MiRemoteUser, activity: IAnnounce, target: IPost): Promise<string | void> {
+	private async announceNote(actor: MiRemoteUser, activity: IAnnounce, target: IPost, resolver?: Resolver): Promise<string | void> {
 		const uri = getApId(activity);
 
 		if (actor.isSuspended) {
@@ -305,7 +318,7 @@ export class ApInboxService {
 			// Announce対象をresolve
 			let renote;
 			try {
-				renote = await this.apNoteService.resolveNote(target);
+				renote = await this.apNoteService.resolveNote(target, { resolver });
 				if (renote == null) return 'announce target is null';
 			} catch (err) {
 				// 対象が4xxならスキップ
@@ -324,7 +337,7 @@ export class ApInboxService {
 
 			this.logger.info(`Creating the (Re)Note: ${uri}`);
 
-			const activityAudience = await this.apAudienceService.parseAudience(actor, activity.to, activity.cc);
+			const activityAudience = await this.apAudienceService.parseAudience(actor, activity.to, activity.cc, resolver);
 			const createdAt = activity.published ? new Date(activity.published) : null;
 
 			if (createdAt && createdAt < this.idService.parse(renote.id).date) {
@@ -362,7 +375,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async create(actor: MiRemoteUser, activity: ICreate): Promise<string | void> {
+	private async create(actor: MiRemoteUser, activity: ICreate, resolver?: Resolver): Promise<string | void> {
 		const uri = getApId(activity);
 
 		this.logger.info(`Create: ${uri}`);
@@ -387,7 +400,8 @@ export class ApInboxService {
 			activity.object.attributedTo = activity.actor;
 		}
 
-		const resolver = this.apResolverService.createResolver();
+		// eslint-disable-next-line no-param-reassign
+		resolver ??= this.apResolverService.createResolver();
 
 		const object = await resolver.resolve(activity.object).catch(e => {
 			this.logger.error(`Resolution failed: ${e}`);
@@ -414,6 +428,8 @@ export class ApInboxService {
 				if (this.utilityService.extractDbHost(actor.uri) !== this.utilityService.extractDbHost(note.id)) {
 					return 'skip: host in actor.uri !== note.id';
 				}
+			} else {
+				return 'skip: note.id is not a string';
 			}
 		}
 
@@ -423,7 +439,7 @@ export class ApInboxService {
 			const exist = await this.apNoteService.fetchNote(note);
 			if (exist) return 'skip: note exists';
 
-			await this.apNoteService.createNote(note, resolver, silent);
+			await this.apNoteService.createNote(note, actor, resolver, silent);
 			return 'ok';
 		} catch (err) {
 			if (err instanceof StatusError && !err.isRetryable) {
@@ -555,12 +571,13 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async reject(actor: MiRemoteUser, activity: IReject): Promise<string> {
+	private async reject(actor: MiRemoteUser, activity: IReject, resolver?: Resolver): Promise<string> {
 		const uri = activity.id ?? activity;
 
 		this.logger.info(`Reject: ${uri}`);
 
-		const resolver = this.apResolverService.createResolver();
+		// eslint-disable-next-line no-param-reassign
+		resolver ??= this.apResolverService.createResolver();
 
 		const object = await resolver.resolve(activity.object).catch(e => {
 			this.logger.error(`Resolution failed: ${e}`);
@@ -597,7 +614,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async remove(actor: MiRemoteUser, activity: IRemove): Promise<string | void> {
+	private async remove(actor: MiRemoteUser, activity: IRemove, resolver?: Resolver): Promise<string | void> {
 		if (actor.uri !== activity.actor) {
 			return 'invalid actor';
 		}
@@ -607,7 +624,7 @@ export class ApInboxService {
 		}
 
 		if (activity.target === actor.featured) {
-			const note = await this.apNoteService.resolveNote(activity.object);
+			const note = await this.apNoteService.resolveNote(activity.object, { resolver });
 			if (note == null) return 'note not found';
 			await this.notePiningService.removePinned(actor, note.id);
 			return;
@@ -617,7 +634,7 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async undo(actor: MiRemoteUser, activity: IUndo): Promise<string> {
+	private async undo(actor: MiRemoteUser, activity: IUndo, resolver?: Resolver): Promise<string> {
 		if (actor.uri !== activity.actor) {
 			return 'invalid actor';
 		}
@@ -626,7 +643,8 @@ export class ApInboxService {
 
 		this.logger.info(`Undo: ${uri}`);
 
-		const resolver = this.apResolverService.createResolver();
+		// eslint-disable-next-line no-param-reassign
+		resolver ??= this.apResolverService.createResolver();
 
 		const object = await resolver.resolve(activity.object).catch(e => {
 			this.logger.error(`Resolution failed: ${e}`);
@@ -750,14 +768,15 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async update(actor: MiRemoteUser, activity: IUpdate): Promise<string> {
+	private async update(actor: MiRemoteUser, activity: IUpdate, resolver?: Resolver): Promise<string> {
 		if (actor.uri !== activity.actor) {
 			return 'skip: invalid actor';
 		}
 
 		this.logger.debug('Update');
 
-		const resolver = this.apResolverService.createResolver();
+		// eslint-disable-next-line no-param-reassign
+		resolver ??= this.apResolverService.createResolver();
 
 		const object = await resolver.resolve(activity.object).catch(e => {
 			this.logger.error(`Resolution failed: ${e}`);
@@ -776,11 +795,11 @@ export class ApInboxService {
 	}
 
 	@bindThis
-	private async move(actor: MiRemoteUser, activity: IMove): Promise<string> {
+	private async move(actor: MiRemoteUser, activity: IMove, resolver?: Resolver): Promise<string> {
 		// fetch the new and old accounts
 		const targetUri = getApHrefNullable(activity.target);
 		if (!targetUri) return 'skip: invalid activity target';
 
-		return await this.apPersonService.updatePerson(actor.uri) ?? 'skip: nothing to do';
+		return await this.apPersonService.updatePerson(actor.uri, resolver) ?? 'skip: nothing to do';
 	}
 }
diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts
index c7d19adfd5..8c3b7295e4 100644
--- a/packages/backend/src/core/activitypub/ApRequestService.ts
+++ b/packages/backend/src/core/activitypub/ApRequestService.ts
@@ -11,11 +11,14 @@ import { DI } from '@/di-symbols.js';
 import type { Config } from '@/config.js';
 import type { MiUser } from '@/models/User.js';
 import { UserKeypairService } from '@/core/UserKeypairService.js';
+import { UtilityService } from '@/core/UtilityService.js';
 import { HttpRequestService } from '@/core/HttpRequestService.js';
 import { LoggerService } from '@/core/LoggerService.js';
 import { bindThis } from '@/decorators.js';
 import type Logger from '@/logger.js';
 import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
+import { assertActivityMatchesUrls } from '@/core/activitypub/misc/check-against-url.js';
+import type { IObject } from './type.js';
 
 type Request = {
 	url: string;
@@ -145,6 +148,7 @@ export class ApRequestService {
 		private userKeypairService: UserKeypairService,
 		private httpRequestService: HttpRequestService,
 		private loggerService: LoggerService,
+		private utilityService: UtilityService,
 	) {
 		// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
 		this.logger = this.loggerService?.getLogger('ap-request'); // なぜか TypeError: Cannot read properties of undefined (reading 'getLogger') と言われる
@@ -238,7 +242,7 @@ export class ApRequestService {
 				const alternate = document.querySelector('head > link[rel="alternate"][type="application/activity+json"]');
 				if (alternate) {
 					const href = alternate.getAttribute('href');
-					if (href) {
+					if (href && this.utilityService.punyHost(url) === this.utilityService.punyHost(href)) {
 						return await this.signedGet(href, user, false);
 					}
 				}
@@ -251,7 +255,11 @@ export class ApRequestService {
 		//#endregion
 
 		validateContentTypeSetAsActivityPub(res);
+		const finalUrl = res.url; // redirects may have been involved
+		const activity = await res.json() as IObject;
 
-		return await res.json();
+		assertActivityMatchesUrls(activity, [finalUrl]);
+
+		return activity;
 	}
 }
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index ca35608d9b..b0b35274ea 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -41,7 +41,7 @@ export class Resolver {
 		private apRendererService: ApRendererService,
 		private apDbResolverService: ApDbResolverService,
 		private loggerService: LoggerService,
-		private recursionLimit = 100,
+		private recursionLimit = 256,
 	) {
 		this.history = new Set();
 		this.logger = this.loggerService.getLogger('ap-resolve');
@@ -52,6 +52,11 @@ export class Resolver {
 		return Array.from(this.history);
 	}
 
+	@bindThis
+	public getRecursionLimit(): number {
+		return this.recursionLimit;
+	}
+
 	@bindThis
 	public async resolveCollection(value: string | IObject): Promise<ICollection | IOrderedCollection> {
 		const collection = typeof value === 'string'
@@ -113,6 +118,18 @@ export class Resolver {
 			throw new Error('invalid response');
 		}
 
+		// HttpRequestService / ApRequestService have already checked that
+		// `object.id` or `object.url` matches the URL used to fetch the
+		// object after redirects; here we double-check that no redirects
+		// bounced between hosts
+		if (object.id == null) {
+			throw new Error('invalid AP object: missing id');
+		}
+
+		if (this.utilityService.punyHost(object.id) !== this.utilityService.punyHost(value)) {
+			throw new Error(`invalid AP object ${value}: id ${object.id} has different host`);
+		}
+
 		return object;
 	}
 
diff --git a/packages/backend/src/core/activitypub/misc/check-against-url.ts b/packages/backend/src/core/activitypub/misc/check-against-url.ts
new file mode 100644
index 0000000000..78ba891a2e
--- /dev/null
+++ b/packages/backend/src/core/activitypub/misc/check-against-url.ts
@@ -0,0 +1,19 @@
+/*
+ * SPDX-FileCopyrightText: dakkar and sharkey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import type { IObject } from '../type.js';
+
+export function assertActivityMatchesUrls(activity: IObject, urls: string[]) {
+	const idOk = activity.id !== undefined && urls.includes(activity.id);
+
+	// technically `activity.url` could be an `ApObject = IObject |
+	// string | (IObject | string)[]`, but if it's a complicated thing
+	// and the `activity.id` doesn't match, I think we're fine
+	// rejecting the activity
+	const urlOk = typeof(activity.url) === 'string' && urls.includes(activity.url);
+
+	if (!idOk && !urlOk) {
+		throw new Error(`bad Activity: neither id(${activity?.id}) nor url(${activity?.url}) match location(${urls})`);
+	}
+}
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index 2d333b3634..eb2e771a38 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -77,7 +77,7 @@ export class ApNoteService {
 	}
 
 	@bindThis
-	public validateNote(object: IObject, uri: string): Error | null {
+	public validateNote(object: IObject, uri: string, actor?: MiRemoteUser): Error | null {
 		const expectHost = this.utilityService.extractDbHost(uri);
 		const apType = getApType(object);
 
@@ -98,6 +98,14 @@ export class ApNoteService {
 			return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', 'invalid Note: published timestamp is malformed');
 		}
 
+		if (actor) {
+			const attribution = (object.attributedTo) ? getOneApId(object.attributedTo) : actor.uri;
+
+			if (attribution !== actor.uri) {
+				return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: attribution does not match the actor that send it. attribution: ${attribution}, actor: ${actor.uri}`);
+			}
+		}
+
 		return null;
 	}
 
@@ -115,14 +123,14 @@ export class ApNoteService {
 	 * Noteを作成します。
 	 */
 	@bindThis
-	public async createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise<MiNote | null> {
+	public async createNote(value: string | IObject, actor?: MiRemoteUser, resolver?: Resolver, silent = false): Promise<MiNote | null> {
 		// eslint-disable-next-line no-param-reassign
 		if (resolver == null) resolver = this.apResolverService.createResolver();
 
 		const object = await resolver.resolve(value);
 
 		const entryUri = getApId(value);
-		const err = this.validateNote(object, entryUri);
+		const err = this.validateNote(object, entryUri, actor);
 		if (err) {
 			this.logger.error(err.message, {
 				resolver: { history: resolver.getHistory() },
@@ -136,14 +144,24 @@ export class ApNoteService {
 
 		this.logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`);
 
-		if (note.id && !checkHttps(note.id)) {
+		if (note.id == null) {
+			throw new Error('Refusing to create note without id');
+		}
+
+		if (!checkHttps(note.id)) {
 			throw new Error('unexpected schema of note.id: ' + note.id);
 		}
 
 		const url = getOneApHrefNullable(note.url);
 
-		if (url && !checkHttps(url)) {
-			throw new Error('unexpected schema of note url: ' + url);
+		if (url != null) {
+			if (!checkHttps(url)) {
+				throw new Error('unexpected schema of note url: ' + url);
+			}
+
+			if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(note.id)) {
+				throw new Error(`note url & uri host mismatch: note url: ${url}, note uri: ${note.id}`);
+			}
 		}
 
 		this.logger.info(`Creating the Note: ${note.id}`);
@@ -156,8 +174,9 @@ export class ApNoteService {
 		const uri = getOneApId(note.attributedTo);
 
 		// ローカルで投稿者を検索し、もし凍結されていたらスキップ
-		const cachedActor = await this.apPersonService.fetchPerson(uri) as MiRemoteUser;
-		if (cachedActor && cachedActor.isSuspended) {
+		// eslint-disable-next-line no-param-reassign
+		actor ??= await this.apPersonService.fetchPerson(uri) as MiRemoteUser | undefined;
+		if (actor && actor.isSuspended) {
 			throw new IdentifiableError('85ab9bd7-3a41-4530-959d-f07073900109', 'actor has been suspended');
 		}
 
@@ -189,7 +208,8 @@ export class ApNoteService {
 		}
 		//#endregion
 
-		const actor = cachedActor ?? await this.apPersonService.resolvePerson(uri, resolver) as MiRemoteUser;
+		// eslint-disable-next-line no-param-reassign
+		actor ??= await this.apPersonService.resolvePerson(uri, resolver) as MiRemoteUser;
 
 		// 解決した投稿者が凍結されていたらスキップ
 		if (actor.isSuspended) {
@@ -348,7 +368,7 @@ export class ApNoteService {
 			if (exist) return exist;
 			//#endregion
 
-			if (uri.startsWith(this.config.url)) {
+			if (this.utilityService.isUriLocal(uri)) {
 				throw new StatusError('cannot resolve local note', 400, 'cannot resolve local note');
 			}
 
@@ -356,7 +376,7 @@ export class ApNoteService {
 			// ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにノートが生成されるが
 			// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
 			const createFrom = options.sentFrom?.origin === new URL(uri).origin ? value : uri;
-			return await this.createNote(createFrom, options.resolver, true);
+			return await this.createNote(createFrom, undefined, options.resolver, true);
 		} finally {
 			unlock();
 		}
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 8c4e40c561..026ddb6ece 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -129,12 +129,6 @@ export class ApPersonService implements OnModuleInit {
 		this.logger = this.apLoggerService.logger;
 	}
 
-	private punyHost(url: string): string {
-		const urlObj = new URL(url);
-		const host = `${this.utilityService.toPuny(urlObj.hostname)}${urlObj.port.length > 0 ? ':' + urlObj.port : ''}`;
-		return host;
-	}
-
 	/**
 	 * Validate and convert to actor object
 	 * @param x Fetched object
@@ -142,7 +136,7 @@ export class ApPersonService implements OnModuleInit {
 	 */
 	@bindThis
 	private validateActor(x: IObject, uri: string): IActor {
-		const expectHost = this.punyHost(uri);
+		const expectHost = this.utilityService.punyHost(uri);
 
 		if (!isActor(x)) {
 			throw new Error(`invalid Actor type '${x.type}'`);
@@ -156,6 +150,29 @@ export class ApPersonService implements OnModuleInit {
 			throw new Error('invalid Actor: wrong inbox');
 		}
 
+		if (this.utilityService.punyHost(x.inbox) !== expectHost) {
+			throw new Error('invalid Actor: inbox has different host');
+		}
+
+		const sharedInboxObject = x.sharedInbox ?? (x.endpoints ? x.endpoints.sharedInbox : undefined);
+		if (sharedInboxObject != null) {
+			const sharedInbox = getApId(sharedInboxObject);
+			if (!(typeof sharedInbox === 'string' && sharedInbox.length > 0 && this.utilityService.punyHost(sharedInbox) === expectHost)) {
+				throw new Error('invalid Actor: wrong shared inbox');
+			}
+		}
+
+		for (const collection of ['outbox', 'followers', 'following'] as (keyof IActor)[]) {
+			const collectionUri = getApId((x as IActor)[collection]);
+			if (typeof collectionUri === 'string' && collectionUri.length > 0) {
+				if (this.utilityService.punyHost(collectionUri) !== expectHost) {
+					throw new Error(`invalid Actor: ${collection} has different host`);
+				}
+			} else if (collectionUri != null) {
+				throw new Error(`invalid Actor: wrong ${collection}`);
+			}
+		}
+
 		if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) {
 			throw new Error('invalid Actor: wrong username');
 		}
@@ -179,7 +196,7 @@ export class ApPersonService implements OnModuleInit {
 			x.summary = truncate(x.summary, summaryLength);
 		}
 
-		const idHost = this.punyHost(x.id);
+		const idHost = this.utilityService.punyHost(x.id);
 		if (idHost !== expectHost) {
 			throw new Error('invalid Actor: id has different host');
 		}
@@ -189,7 +206,7 @@ export class ApPersonService implements OnModuleInit {
 				throw new Error('invalid Actor: publicKey.id is not a string');
 			}
 
-			const publicKeyIdHost = this.punyHost(x.publicKey.id);
+			const publicKeyIdHost = this.utilityService.punyHost(x.publicKey.id);
 			if (publicKeyIdHost !== expectHost) {
 				throw new Error('invalid Actor: publicKey.id has different host');
 			}
@@ -280,7 +297,8 @@ export class ApPersonService implements OnModuleInit {
 	public async createPerson(uri: string, resolver?: Resolver): Promise<MiRemoteUser> {
 		if (typeof uri !== 'string') throw new Error('uri is not string');
 
-		if (uri.startsWith(this.config.url)) {
+		const host = this.utilityService.punyHost(uri);
+		if (host === this.utilityService.toPuny(this.config.host)) {
 			throw new StatusError('cannot resolve local user', 400, 'cannot resolve local user');
 		}
 
@@ -294,8 +312,6 @@ export class ApPersonService implements OnModuleInit {
 
 		this.logger.info(`Creating the Person: ${person.id}`);
 
-		const host = this.punyHost(object.id);
-
 		const fields = this.analyzeAttachments(person.attachment ?? []);
 
 		const tags = extractApHashtags(person.tag).map(normalizeForSearch).splice(0, 32);
@@ -321,8 +337,18 @@ export class ApPersonService implements OnModuleInit {
 
 		const url = getOneApHrefNullable(person.url);
 
-		if (url && !checkHttps(url)) {
-			throw new Error('unexpected schema of person url: ' + url);
+		if (person.id == null) {
+			throw new Error('Refusing to create person without id');
+		}
+
+		if (url != null) {
+			if (!checkHttps(url)) {
+				throw new Error('unexpected schema of person url: ' + url);
+			}
+
+			if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) {
+				throw new Error(`person url <> uri host mismatch: ${url} <> ${person.id}`);
+			}
 		}
 
 		// Create user
@@ -465,7 +491,7 @@ export class ApPersonService implements OnModuleInit {
 		if (typeof uri !== 'string') throw new Error('uri is not string');
 
 		// URIがこのサーバーを指しているならスキップ
-		if (uri.startsWith(`${this.config.url}/`)) return;
+		if (this.utilityService.isUriLocal(uri)) return;
 
 		//#region このサーバーに既に登録されているか
 		const exist = await this.fetchPerson(uri) as MiRemoteUser | null;
@@ -514,8 +540,18 @@ export class ApPersonService implements OnModuleInit {
 
 		const url = getOneApHrefNullable(person.url);
 
-		if (url && !checkHttps(url)) {
-			throw new Error('unexpected schema of person url: ' + url);
+		if (person.id == null) {
+			throw new Error('Refusing to update person without id');
+		}
+
+		if (url != null) {
+			if (!checkHttps(url)) {
+				throw new Error('unexpected schema of person url: ' + url);
+			}
+
+			if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) {
+				throw new Error(`person url <> uri host mismatch: ${url} <> ${person.id}`);
+			}
 		}
 
 		const updates = {
@@ -728,7 +764,7 @@ export class ApPersonService implements OnModuleInit {
 			await this.updatePerson(src.movedToUri, undefined, undefined, [...movePreventUris, src.uri]);
 			dst = await this.fetchPerson(src.movedToUri) ?? dst;
 		} else {
-			if (src.movedToUri.startsWith(`${this.config.url}/`)) {
+			if (this.utilityService.isUriLocal(src.movedToUri)) {
 				// ローカルユーザーっぽいのにfetchPersonで見つからないということはmovedToUriが間違っている
 				return 'failed: movedTo is local but not found';
 			}
diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
index 73004d10b0..1655a307c4 100644
--- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts
+++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
@@ -10,6 +10,7 @@ import type { Config } from '@/config.js';
 import type { IPoll } from '@/models/Poll.js';
 import type Logger from '@/logger.js';
 import { bindThis } from '@/decorators.js';
+import { UtilityService } from '@/core/UtilityService.js';
 import { isQuestion } from '../type.js';
 import { ApLoggerService } from '../ApLoggerService.js';
 import { ApResolverService } from '../ApResolverService.js';
@@ -32,6 +33,7 @@ export class ApQuestionService {
 
 		private apResolverService: ApResolverService,
 		private apLoggerService: ApLoggerService,
+		private utilityService: UtilityService,
 	) {
 		this.logger = this.apLoggerService.logger;
 	}
@@ -70,7 +72,7 @@ export class ApQuestionService {
 		if (uri == null) throw new Error('uri is null');
 
 		// URIがこのサーバーを指しているならスキップ
-		if (uri.startsWith(this.config.url + '/')) throw new Error('uri points local');
+		if (this.utilityService.isUriLocal(uri)) throw new Error('uri points local');
 
 		//#region このサーバーに既に登録されているか
 		const note = await this.notesRepository.findOneBy({ uri });
diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts
index 95d764e4d8..004fe1382d 100644
--- a/packages/backend/src/queue/processors/InboxProcessorService.ts
+++ b/packages/backend/src/queue/processors/InboxProcessorService.ts
@@ -190,6 +190,8 @@ export class InboxProcessorService implements OnApplicationShutdown {
 			if (signerHost !== activityIdHost) {
 				throw new Bull.UnrecoverableError(`skip: signerHost(${signerHost}) !== activity.id host(${activityIdHost}`);
 			}
+		} else {
+			throw new Bull.UnrecoverableError('skip: activity id is not a string');
 		}
 
 		this.apRequestChart.inbox();
diff --git a/packages/backend/src/server/ActivityPubServerService.ts b/packages/backend/src/server/ActivityPubServerService.ts
index ba2342b630..f34f6583d3 100644
--- a/packages/backend/src/server/ActivityPubServerService.ts
+++ b/packages/backend/src/server/ActivityPubServerService.ts
@@ -105,7 +105,7 @@ export class ActivityPubServerService {
 		let signature;
 
 		try {
-			signature = httpSignature.parseRequest(request.raw, { 'headers': [] });
+			signature = httpSignature.parseRequest(request.raw, { 'headers': ['(request-target)', 'host', 'date'], authorizationHeaderName: 'signature' });
 		} catch (e) {
 			reply.code(401);
 			return;
diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts
index d8c55de7ec..14286bc23e 100644
--- a/packages/backend/src/server/api/endpoints/ap/get.ts
+++ b/packages/backend/src/server/api/endpoints/ap/get.ts
@@ -11,6 +11,7 @@ import { ApResolverService } from '@/core/activitypub/ApResolverService.js';
 export const meta = {
 	tags: ['federation'],
 
+	requireAdmin: true,
 	requireCredential: true,
 	kind: 'read:federation',
 
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index c52608cefb..aca8258c08 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -118,6 +118,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 		]));
 		if (local != null) return local;
 
+		const host = this.utilityService.extractDbHost(uri);
+
+		// local object, not found in db? fail
+		if (this.utilityService.isSelfHost(host)) return null;
+
 		// リモートから一旦オブジェクトフェッチ
 		const resolver = this.apResolverService.createResolver();
 		const object = await resolver.resolve(uri) as any;

From b9cb949eb1f8c57eaa98fc5446d902cf8a5ea85c Mon Sep 17 00:00:00 2001
From: Julia <julia@insertdomain.name>
Date: Wed, 20 Nov 2024 18:24:50 -0500
Subject: [PATCH 095/125] Merge commit from fork

* Fix poll update spoofing

* fix: Disallow negative poll counts

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 .../src/core/activitypub/ApInboxService.ts    |  2 +-
 .../activitypub/models/ApQuestionService.ts   | 29 ++++++++++++++-----
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 8e8ec223cb..72f5eeda14 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -787,7 +787,7 @@ export class ApInboxService {
 			await this.apPersonService.updatePerson(actor.uri, resolver, object);
 			return 'ok: Person updated';
 		} else if (getApType(object) === 'Question') {
-			await this.apQuestionService.updateQuestion(object, resolver).catch(err => console.error(err));
+			await this.apQuestionService.updateQuestion(object, actor, resolver).catch(err => console.error(err));
 			return 'ok: Question updated';
 		} else {
 			return `skip: Unknown type: ${getApType(object)}`;
diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
index 1655a307c4..a2cdaf02ca 100644
--- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts
+++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
@@ -5,17 +5,18 @@
 
 import { Inject, Injectable } from '@nestjs/common';
 import { DI } from '@/di-symbols.js';
-import type { NotesRepository, PollsRepository } from '@/models/_.js';
+import type { UsersRepository, NotesRepository, PollsRepository } from '@/models/_.js';
 import type { Config } from '@/config.js';
 import type { IPoll } from '@/models/Poll.js';
+import type { MiRemoteUser } from '@/models/User.js';
 import type Logger from '@/logger.js';
 import { bindThis } from '@/decorators.js';
+import { getOneApId, isQuestion } from '../type.js';
 import { UtilityService } from '@/core/UtilityService.js';
-import { isQuestion } from '../type.js';
 import { ApLoggerService } from '../ApLoggerService.js';
 import { ApResolverService } from '../ApResolverService.js';
 import type { Resolver } from '../ApResolverService.js';
-import type { IObject, IQuestion } from '../type.js';
+import type { IObject } from '../type.js';
 
 @Injectable()
 export class ApQuestionService {
@@ -25,6 +26,9 @@ export class ApQuestionService {
 		@Inject(DI.config)
 		private config: Config,
 
+		@Inject(DI.usersRepository)
+		private usersRepository: UsersRepository,
+
 		@Inject(DI.notesRepository)
 		private notesRepository: NotesRepository,
 
@@ -67,7 +71,7 @@ export class ApQuestionService {
 	 * @returns true if updated
 	 */
 	@bindThis
-	public async updateQuestion(value: string | IObject, resolver?: Resolver): Promise<boolean> {
+	public async updateQuestion(value: string | IObject, actor?: MiRemoteUser, resolver?: Resolver): Promise<boolean> {
 		const uri = typeof value === 'string' ? value : value.id;
 		if (uri == null) throw new Error('uri is null');
 
@@ -80,15 +84,26 @@ export class ApQuestionService {
 
 		const poll = await this.pollsRepository.findOneBy({ noteId: note.id });
 		if (poll == null) throw new Error('Question is not registered');
+
+		const user = await this.usersRepository.findOneBy({ id: poll.userId });
+		if (user == null) throw new Error('Question is not registered');
 		//#endregion
 
 		// resolve new Question object
 		// eslint-disable-next-line no-param-reassign
 		if (resolver == null) resolver = this.apResolverService.createResolver();
-		const question = await resolver.resolve(value) as IQuestion;
+		const question = await resolver.resolve(value);
 		this.logger.debug(`fetched question: ${JSON.stringify(question, null, 2)}`);
 
-		if (question.type !== 'Question') throw new Error('object is not a Question');
+		if (!isQuestion(question)) throw new Error('object is not a Question');
+
+		const attribution = (question.attributedTo) ? getOneApId(question.attributedTo) : user.uri;
+		const attributionMatchesExisting = attribution === user.uri;
+		const actorMatchesAttribution = (actor) ? attribution === actor.uri : true;
+
+		if (!attributionMatchesExisting || !actorMatchesAttribution) {
+			throw new Error('Refusing to ingest update for poll by different user');
+		}
 
 		const apChoices = question.oneOf ?? question.anyOf;
 		if (apChoices == null) throw new Error('invalid apChoices: ' + apChoices);
@@ -98,7 +113,7 @@ export class ApQuestionService {
 		for (const choice of poll.choices) {
 			const oldCount = poll.votes[poll.choices.indexOf(choice)];
 			const newCount = apChoices.filter(ap => ap.name === choice).at(0)?.replies?.totalItems;
-			if (newCount == null) throw new Error('invalid newCount: ' + newCount);
+			if (newCount == null || !(Number.isInteger(newCount) && newCount >= 0)) throw new Error('invalid newCount: ' + newCount);
 
 			if (oldCount !== newCount) {
 				changed = true;

From 090e9392cdb1f584af94a6fb727fba95de3b8504 Mon Sep 17 00:00:00 2001
From: rectcoordsystem <37621004+rectcoordsystem@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:27:09 +0900
Subject: [PATCH 096/125] Merge commit from fork

* fix(backend): check target IP before sending HTTP request

* fix(backend): allow accessing private IP when testing

* Apply suggestions from code review

Co-authored-by: anatawa12 <anatawa12@icloud.com>

* fix(backend): lint and typecheck

* fix(backend): add isLocalAddressAllowed option to getAgentByUrl and send (HttpRequestService)

* fix(backend): allow fetchSummaryFromProxy, trueMail to access local addresses

---------

Co-authored-by: anatawa12 <anatawa12@icloud.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 packages/backend/src/core/DownloadService.ts  |  22 ---
 packages/backend/src/core/EmailService.ts     |   1 +
 .../backend/src/core/HttpRequestService.ts    | 134 ++++++++++++++++--
 .../src/server/web/UrlPreviewService.ts       |   2 +-
 4 files changed, 123 insertions(+), 36 deletions(-)

diff --git a/packages/backend/src/core/DownloadService.ts b/packages/backend/src/core/DownloadService.ts
index 93f4a38246..2e78e6d877 100644
--- a/packages/backend/src/core/DownloadService.ts
+++ b/packages/backend/src/core/DownloadService.ts
@@ -6,7 +6,6 @@
 import * as fs from 'node:fs';
 import * as stream from 'node:stream/promises';
 import { Inject, Injectable } from '@nestjs/common';
-import ipaddr from 'ipaddr.js';
 import chalk from 'chalk';
 import got, * as Got from 'got';
 import { parse } from 'content-disposition';
@@ -70,13 +69,6 @@ export class DownloadService {
 			},
 			enableUnixSockets: false,
 		}).on('response', (res: Got.Response) => {
-			if ((process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') && !this.config.proxy && res.ip) {
-				if (this.isPrivateIp(res.ip)) {
-					this.logger.warn(`Blocked address: ${res.ip}`);
-					req.destroy();
-				}
-			}
-
 			const contentLength = res.headers['content-length'];
 			if (contentLength != null) {
 				const size = Number(contentLength);
@@ -139,18 +131,4 @@ export class DownloadService {
 			cleanup();
 		}
 	}
-
-	@bindThis
-	private isPrivateIp(ip: string): boolean {
-		const parsedIp = ipaddr.parse(ip);
-
-		for (const net of this.config.allowedPrivateNetworks ?? []) {
-			const cidr = ipaddr.parseCIDR(net);
-			if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
-				return false;
-			}
-		}
-
-		return parsedIp.range() !== 'unicast';
-	}
 }
diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts
index a176474b95..da198d0e42 100644
--- a/packages/backend/src/core/EmailService.ts
+++ b/packages/backend/src/core/EmailService.ts
@@ -312,6 +312,7 @@ export class EmailService {
 					Accept: 'application/json',
 					Authorization: truemailAuthKey,
 				},
+				isLocalAddressAllowed: true,
 			});
 
 			const json = (await res.json()) as {
diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts
index 08e9f46b2d..0ad5667049 100644
--- a/packages/backend/src/core/HttpRequestService.ts
+++ b/packages/backend/src/core/HttpRequestService.ts
@@ -6,6 +6,7 @@
 import * as http from 'node:http';
 import * as https from 'node:https';
 import * as net from 'node:net';
+import ipaddr from 'ipaddr.js';
 import CacheableLookup from 'cacheable-lookup';
 import fetch from 'node-fetch';
 import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
@@ -25,8 +26,102 @@ export type HttpRequestSendOptions = {
 	validators?: ((res: Response) => void)[];
 };
 
+declare module 'node:http' {
+	interface Agent {
+		createConnection(options: net.NetConnectOpts, callback?: (err: unknown, stream: net.Socket) => void): net.Socket;
+	}
+}
+
+class HttpRequestServiceAgent extends http.Agent {
+	constructor(
+		private config: Config,
+		options?: http.AgentOptions,
+	) {
+		super(options);
+	}
+
+	@bindThis
+	public createConnection(options: net.NetConnectOpts, callback?: (err: unknown, stream: net.Socket) => void): net.Socket {
+		const socket = super.createConnection(options, callback)
+			.on('connect', () => {
+				const address = socket.remoteAddress;
+				if (process.env.NODE_ENV === 'production') {
+					if (address && ipaddr.isValid(address)) {
+						if (this.isPrivateIp(address)) {
+							socket.destroy(new Error(`Blocked address: ${address}`));
+						}
+					}
+				}
+			});
+		return socket;
+	};
+
+	@bindThis
+	private isPrivateIp(ip: string): boolean {
+		const parsedIp = ipaddr.parse(ip);
+	
+		for (const net of this.config.allowedPrivateNetworks ?? []) {
+			const cidr = ipaddr.parseCIDR(net);
+			if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
+				return false;
+			}
+		}
+	
+		return parsedIp.range() !== 'unicast';
+	}
+}
+
+class HttpsRequestServiceAgent extends https.Agent {
+	constructor(
+		private config: Config,
+		options?: https.AgentOptions,
+	) {
+		super(options);
+	}
+
+	@bindThis
+	public createConnection(options: net.NetConnectOpts, callback?: (err: unknown, stream: net.Socket) => void): net.Socket {
+		const socket = super.createConnection(options, callback)
+			.on('connect', () => {
+				const address = socket.remoteAddress;
+				if (process.env.NODE_ENV === 'production') {
+					if (address && ipaddr.isValid(address)) {
+						if (this.isPrivateIp(address)) {
+							socket.destroy(new Error(`Blocked address: ${address}`));
+						}
+					}
+				}
+			});
+		return socket;
+	};
+
+	@bindThis
+	private isPrivateIp(ip: string): boolean {
+		const parsedIp = ipaddr.parse(ip);
+	
+		for (const net of this.config.allowedPrivateNetworks ?? []) {
+			const cidr = ipaddr.parseCIDR(net);
+			if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
+				return false;
+			}
+		}
+	
+		return parsedIp.range() !== 'unicast';
+	}
+}
+
 @Injectable()
 export class HttpRequestService {
+	/**
+	 * Get http non-proxy agent (without local address filtering)
+	 */
+	private httpNative: http.Agent;
+
+	/**
+	 * Get https non-proxy agent (without local address filtering)
+	 */
+	private httpsNative: https.Agent;
+
 	/**
 	 * Get http non-proxy agent
 	 */
@@ -57,19 +152,20 @@ export class HttpRequestService {
 			lookup: false,	// nativeのdns.lookupにfallbackしない
 		});
 
-		this.http = new http.Agent({
+		const agentOption = {
 			keepAlive: true,
 			keepAliveMsecs: 30 * 1000,
 			lookup: cache.lookup as unknown as net.LookupFunction,
 			localAddress: config.outgoingAddress,
-		});
+		};
 
-		this.https = new https.Agent({
-			keepAlive: true,
-			keepAliveMsecs: 30 * 1000,
-			lookup: cache.lookup as unknown as net.LookupFunction,
-			localAddress: config.outgoingAddress,
-		});
+		this.httpNative = new http.Agent(agentOption);
+
+		this.httpsNative = new https.Agent(agentOption);
+
+		this.http = new HttpRequestServiceAgent(config, agentOption);
+
+		this.https = new HttpsRequestServiceAgent(config, agentOption);
 
 		const maxSockets = Math.max(256, config.deliverJobConcurrency ?? 128);
 
@@ -104,16 +200,22 @@ export class HttpRequestService {
 	 * @param bypassProxy Allways bypass proxy
 	 */
 	@bindThis
-	public getAgentByUrl(url: URL, bypassProxy = false): http.Agent | https.Agent {
+	public getAgentByUrl(url: URL, bypassProxy = false, isLocalAddressAllowed = false): http.Agent | https.Agent {
 		if (bypassProxy || (this.config.proxyBypassHosts ?? []).includes(url.hostname)) {
+			if (isLocalAddressAllowed) {
+				return url.protocol === 'http:' ? this.httpNative : this.httpsNative;
+			}
 			return url.protocol === 'http:' ? this.http : this.https;
 		} else {
+			if (isLocalAddressAllowed && (!this.config.proxy)) {
+				return url.protocol === 'http:' ? this.httpNative : this.httpsNative;
+			}
 			return url.protocol === 'http:' ? this.httpAgent : this.httpsAgent;
 		}
 	}
 
 	@bindThis
-	public async getActivityJson(url: string): Promise<IObject> {
+	public async getActivityJson(url: string, isLocalAddressAllowed = false): Promise<IObject> {
 		const res = await this.send(url, {
 			method: 'GET',
 			headers: {
@@ -121,6 +223,7 @@ export class HttpRequestService {
 			},
 			timeout: 5000,
 			size: 1024 * 256,
+			isLocalAddressAllowed: isLocalAddressAllowed,
 		}, {
 			throwErrorWhenResponseNotOk: true,
 			validators: [validateContentTypeSetAsActivityPub],
@@ -135,7 +238,7 @@ export class HttpRequestService {
 	}
 
 	@bindThis
-	public async getJson<T = unknown>(url: string, accept = 'application/json, */*', headers?: Record<string, string>): Promise<T> {
+	public async getJson<T = unknown>(url: string, accept = 'application/json, */*', headers?: Record<string, string>, isLocalAddressAllowed = false): Promise<T> {
 		const res = await this.send(url, {
 			method: 'GET',
 			headers: Object.assign({
@@ -143,19 +246,21 @@ export class HttpRequestService {
 			}, headers ?? {}),
 			timeout: 5000,
 			size: 1024 * 256,
+			isLocalAddressAllowed: isLocalAddressAllowed,
 		});
 
 		return await res.json() as T;
 	}
 
 	@bindThis
-	public async getHtml(url: string, accept = 'text/html, */*', headers?: Record<string, string>): Promise<string> {
+	public async getHtml(url: string, accept = 'text/html, */*', headers?: Record<string, string>, isLocalAddressAllowed = false): Promise<string> {
 		const res = await this.send(url, {
 			method: 'GET',
 			headers: Object.assign({
 				Accept: accept,
 			}, headers ?? {}),
 			timeout: 5000,
+			isLocalAddressAllowed: isLocalAddressAllowed,
 		});
 
 		return await res.text();
@@ -170,6 +275,7 @@ export class HttpRequestService {
 			headers?: Record<string, string>,
 			timeout?: number,
 			size?: number,
+			isLocalAddressAllowed?: boolean,
 		} = {},
 		extra: HttpRequestSendOptions = {
 			throwErrorWhenResponseNotOk: true,
@@ -183,6 +289,8 @@ export class HttpRequestService {
 			controller.abort();
 		}, timeout);
 
+		const isLocalAddressAllowed = args.isLocalAddressAllowed ?? false;
+
 		const res = await fetch(url, {
 			method: args.method ?? 'GET',
 			headers: {
@@ -191,7 +299,7 @@ export class HttpRequestService {
 			},
 			body: args.body,
 			size: args.size ?? 10 * 1024 * 1024,
-			agent: (url) => this.getAgentByUrl(url),
+			agent: (url) => this.getAgentByUrl(url, false, isLocalAddressAllowed),
 			signal: controller.signal,
 		});
 
diff --git a/packages/backend/src/server/web/UrlPreviewService.ts b/packages/backend/src/server/web/UrlPreviewService.ts
index 5d493c2c46..9b5f0acd2c 100644
--- a/packages/backend/src/server/web/UrlPreviewService.ts
+++ b/packages/backend/src/server/web/UrlPreviewService.ts
@@ -145,6 +145,6 @@ export class UrlPreviewService {
 			contentLengthRequired: meta.urlPreviewRequireContentLength,
 		});
 
-		return this.httpRequestService.getJson<SummalyResult>(`${proxy}?${queryStr}`);
+		return this.httpRequestService.getJson<SummalyResult>(`${proxy}?${queryStr}`, 'application/json, */*', undefined, true);
 	}
 }

From 9fdabe36665fa3a63c80610ea7e0aba64f10c875 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 21 Nov 2024 09:22:15 +0900
Subject: [PATCH 097/125] fix(backend): use atomic command to improve security

Co-Authored-By: Acid Chicken <root@acid-chicken.com>
---
 packages/backend/src/core/WebAuthnService.ts | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/packages/backend/src/core/WebAuthnService.ts b/packages/backend/src/core/WebAuthnService.ts
index 75ab0a207c..ad53192f18 100644
--- a/packages/backend/src/core/WebAuthnService.ts
+++ b/packages/backend/src/core/WebAuthnService.ts
@@ -246,14 +246,12 @@ export class WebAuthnService {
 
 	@bindThis
 	public async verifyAuthentication(userId: MiUser['id'], response: AuthenticationResponseJSON): Promise<boolean> {
-		const challenge = await this.redisClient.get(`webauthn:challenge:${userId}`);
+		const challenge = await this.redisClient.getdel(`webauthn:challenge:${userId}`);
 
 		if (!challenge) {
 			throw new IdentifiableError('2d16e51c-007b-4edd-afd2-f7dd02c947f6', 'challenge not found');
 		}
 
-		await this.redisClient.del(`webauthn:challenge:${userId}`);
-
 		const key = await this.userSecurityKeysRepository.findOneBy({
 			id: response.id,
 			userId: userId,

From 0f59adc436f80c495b4404807b0bd645da2b1db8 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 21 Nov 2024 09:25:18 +0900
Subject: [PATCH 098/125] fix ap/show

---
 packages/backend/src/server/api/endpoints/ap/show.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index aca8258c08..5c1d8dce9f 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -140,7 +140,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 		return await this.mergePack(
 			me,
 			isActor(object) ? await this.apPersonService.createPerson(getApId(object)) : null,
-			isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, true) : null,
+			isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, resolver) : null,
 		);
 	}
 

From 53e827b18c46f786268278645206404ff2d95f72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Thu, 21 Nov 2024 10:30:30 +0900
Subject: [PATCH 099/125] fix(backend): fix security patches (#15008)

---
 packages/backend/src/core/activitypub/ApInboxService.ts | 2 +-
 packages/backend/src/server/api/endpoints/ap/show.ts    | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 72f5eeda14..9838e3bd30 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -130,7 +130,7 @@ export class ApInboxService {
 		if (actor.uri) {
 			if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
 				setImmediate(() => {
-					this.apPersonService.updatePerson(actor.uri);
+					this.apPersonService.updatePerson(actor.uri, resolver);
 				});
 			}
 		}
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index 5c1d8dce9f..bf99834c17 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -139,8 +139,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 
 		return await this.mergePack(
 			me,
-			isActor(object) ? await this.apPersonService.createPerson(getApId(object)) : null,
-			isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, resolver) : null,
+			isActor(object) ? await this.apPersonService.createPerson(getApId(object), resolver) : null,
+			isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, resolver, true) : null,
 		);
 	}
 

From 3a6c2aa83563515b2ce02cda289b0271d992e84e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Thu, 21 Nov 2024 12:10:02 +0900
Subject: [PATCH 100/125] fix(backend): fix type error(s) in security fixes
 (#15009)

* Fix type error in security fixes

(cherry picked from commit fa3cf6c2996741e642955c5e2fca8ad785e83205)

* Fix error in test function calls

(cherry picked from commit 1758f29364eca3cbd13dbb5c84909c93712b3b3b)

* Fix style error

(cherry picked from commit 23c4aa25714af145098baa7edd74c1d217e51c1a)

* Fix another style error

(cherry picked from commit 36af07abe28bec670aaebf9f5af5694bb582c29a)

* Fix `.punyHost` misuse

(cherry picked from commit 6027b516e1c82324d55d6e54d0e17cbd816feb42)

* attempt to fix test: make yaml valid

---------

Co-authored-by: Julia Johannesen <julia@insertdomain.name>
---
 packages/backend/src/core/HttpRequestService.ts   | 12 ++++++------
 .../backend/src/core/RemoteUserResolveService.ts  |  2 +-
 .../core/activitypub/models/ApPersonService.ts    | 15 +++++++++------
 .../test-federation/.config/example.default.yml   |  7 +++----
 packages/backend/test/unit/activitypub.ts         |  4 ++--
 5 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts
index 0ad5667049..083153940a 100644
--- a/packages/backend/src/core/HttpRequestService.ts
+++ b/packages/backend/src/core/HttpRequestService.ts
@@ -54,19 +54,19 @@ class HttpRequestServiceAgent extends http.Agent {
 				}
 			});
 		return socket;
-	};
+	}
 
 	@bindThis
 	private isPrivateIp(ip: string): boolean {
 		const parsedIp = ipaddr.parse(ip);
-	
+
 		for (const net of this.config.allowedPrivateNetworks ?? []) {
 			const cidr = ipaddr.parseCIDR(net);
 			if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
 				return false;
 			}
 		}
-	
+
 		return parsedIp.range() !== 'unicast';
 	}
 }
@@ -93,19 +93,19 @@ class HttpsRequestServiceAgent extends https.Agent {
 				}
 			});
 		return socket;
-	};
+	}
 
 	@bindThis
 	private isPrivateIp(ip: string): boolean {
 		const parsedIp = ipaddr.parse(ip);
-	
+
 		for (const net of this.config.allowedPrivateNetworks ?? []) {
 			const cidr = ipaddr.parseCIDR(net);
 			if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
 				return false;
 			}
 		}
-	
+
 		return parsedIp.range() !== 'unicast';
 	}
 }
diff --git a/packages/backend/src/core/RemoteUserResolveService.ts b/packages/backend/src/core/RemoteUserResolveService.ts
index 678da0cfa6..098b5e1706 100644
--- a/packages/backend/src/core/RemoteUserResolveService.ts
+++ b/packages/backend/src/core/RemoteUserResolveService.ts
@@ -54,7 +54,7 @@ export class RemoteUserResolveService {
 			}) as MiLocalUser;
 		}
 
-		host = this.utilityService.punyHost(host);
+		host = this.utilityService.toPuny(host);
 
 		if (host === this.utilityService.toPuny(this.config.host)) {
 			this.logger.info(`return local user: ${usernameLower}`);
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index 026ddb6ece..8590861ca0 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -163,13 +163,16 @@ export class ApPersonService implements OnModuleInit {
 		}
 
 		for (const collection of ['outbox', 'followers', 'following'] as (keyof IActor)[]) {
-			const collectionUri = getApId((x as IActor)[collection]);
-			if (typeof collectionUri === 'string' && collectionUri.length > 0) {
-				if (this.utilityService.punyHost(collectionUri) !== expectHost) {
-					throw new Error(`invalid Actor: ${collection} has different host`);
+			const xCollection = (x as IActor)[collection];
+			if (xCollection != null) {
+				const collectionUri = getApId(xCollection);
+				if (typeof collectionUri === 'string' && collectionUri.length > 0) {
+					if (this.utilityService.punyHost(collectionUri) !== expectHost) {
+						throw new Error(`invalid Actor: ${collection} has different host`);
+					}
+				} else if (collectionUri != null) {
+					throw new Error(`invalid Actor: wrong ${collection}`);
 				}
-			} else if (collectionUri != null) {
-				throw new Error(`invalid Actor: wrong ${collection}`);
 			}
 		}
 
diff --git a/packages/backend/test-federation/.config/example.default.yml b/packages/backend/test-federation/.config/example.default.yml
index ff1760a5a6..28d51ac86e 100644
--- a/packages/backend/test-federation/.config/example.default.yml
+++ b/packages/backend/test-federation/.config/example.default.yml
@@ -19,7 +19,6 @@ proxyBypassHosts:
   - challenges.cloudflare.com
 proxyRemoteFiles: true
 signToActivityPubGet: true
-allowedPrivateNetworks: [
-  '127.0.0.1/32',
-  '172.20.0.0/16'
-]
+allowedPrivateNetworks:
+  - 127.0.0.1/32
+  - 172.20.0.0/16
diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts
index 2fc08aec91..9df947982b 100644
--- a/packages/backend/test/unit/activitypub.ts
+++ b/packages/backend/test/unit/activitypub.ts
@@ -176,7 +176,7 @@ describe('ActivityPub', () => {
 			resolver.register(actor.id, actor);
 			resolver.register(post.id, post);
 
-			const note = await noteService.createNote(post.id, resolver, true);
+			const note = await noteService.createNote(post.id, undefined, resolver, true);
 
 			assert.deepStrictEqual(note?.uri, post.id);
 			assert.deepStrictEqual(note.visibility, 'public');
@@ -336,7 +336,7 @@ describe('ActivityPub', () => {
 			resolver.register(actor.featured, featured);
 			resolver.register(firstNote.id, firstNote);
 
-			const note = await noteService.createNote(firstNote.id as string, resolver);
+			const note = await noteService.createNote(firstNote.id as string, undefined, resolver);
 			assert.strictEqual(note?.uri, firstNote.id);
 		});
 	});

From c1f19fad1e7e1717898b37bbb4e863e0f26b306b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Thu, 21 Nov 2024 14:36:24 +0900
Subject: [PATCH 101/125] fix(backend): fix apResolver (#15010)

* fix(backend): fix apResolver

* fix

* add comments

* tweak comment
---
 packages/backend/src/core/activitypub/ApInboxService.ts | 3 ++-
 packages/backend/src/server/api/endpoints/ap/show.ts    | 5 +++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 9838e3bd30..ee3f691c51 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -130,7 +130,8 @@ export class ApInboxService {
 		if (actor.uri) {
 			if (actor.lastFetchedAt == null || Date.now() - actor.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
 				setImmediate(() => {
-					this.apPersonService.updatePerson(actor.uri, resolver);
+					// 同一ユーザーの情報を再度処理するので、使用済みのresolverを再利用してはいけない
+					this.apPersonService.updatePerson(actor.uri);
 				});
 			}
 		}
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index bf99834c17..24d5a7b0f1 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -137,10 +137,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			if (local != null) return local;
 		}
 
+		// 同一ユーザーの情報を再度処理するので、使用済みのresolverを再利用してはいけない
 		return await this.mergePack(
 			me,
-			isActor(object) ? await this.apPersonService.createPerson(getApId(object), resolver) : null,
-			isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, resolver, true) : null,
+			isActor(object) ? await this.apPersonService.createPerson(getApId(object)) : null,
+			isPost(object) ? await this.apNoteService.createNote(getApId(object), undefined, undefined, true) : null,
 		);
 	}
 

From a21a2c52d7c3cf75cf67e001e664cb083188e2b8 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 06:27:16 +0000
Subject: [PATCH 102/125] Bump version to 2024.11.0-alpha.3

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 4dd411c10f..9ee1cac90e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.11.0-alpha.2",
+	"version": "2024.11.0-alpha.3",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index f57656db0b..ac585b5573 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.11.0-alpha.2",
+	"version": "2024.11.0-alpha.3",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 9871035597708815d92ff210ae4d2161d8102d14 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Thu, 21 Nov 2024 15:41:01 +0900
Subject: [PATCH 103/125] Update CHANGELOG.md

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0718150fc4..02566ff87f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -67,6 +67,7 @@
 - Fix: User Webhookテスト機能のMock Payloadを修正  
 - Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)  
 - Fix: リノートミュートが新規投稿通知に対して作用していなかった問題を修正
+- Fix: セキュリティに関する修正
 
 ### Misskey.js
 - Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正

From 7f0ae038d418e65bc39d350ea5eefbda260cb1ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Thu, 21 Nov 2024 17:16:06 +0900
Subject: [PATCH 104/125] Update CHANGELOG.md

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02566ff87f..39ce36d678 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,9 +8,9 @@
 ### General
 - Feat: コンテンツの表示にログインを必須にできるように
 - Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
-- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
 - Enhance: 依存関係の更新
 - Enhance: l10nの更新
+- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
 
 ### Client
 - Enhance: Bull DashboardでRelationship Queueの状態も確認できるように  

From 752606fe887abe4767b9fff194e8694a4ea484ac Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Thu, 21 Nov 2024 08:21:54 +0000
Subject: [PATCH 105/125] Bump version to 2024.11.0-beta.4

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 9ee1cac90e..ccb6170a16 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.11.0-alpha.3",
+	"version": "2024.11.0-beta.4",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index ac585b5573..cda4c183fa 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.11.0-alpha.3",
+	"version": "2024.11.0-beta.4",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 1911972ae2dfd5eb462d34ff3d2e614f733cab10 Mon Sep 17 00:00:00 2001
From: anatawa12 <anatawa12@icloud.com>
Date: Fri, 22 Nov 2024 12:11:45 +0900
Subject: [PATCH 106/125] ci: reset prerelease number on release (#15024)

---
 .github/workflows/release-with-dispatch.yml | 7 ++++---
 .github/workflows/release-with-ready.yml    | 1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/release-with-dispatch.yml b/.github/workflows/release-with-dispatch.yml
index ed2f822269..d750001b71 100644
--- a/.github/workflows/release-with-dispatch.yml
+++ b/.github/workflows/release-with-dispatch.yml
@@ -60,13 +60,13 @@ jobs:
 
         ### General
         -
-        
+
         ### Client
         -
-        
+
         ### Server
         -
-        
+
       use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
       indent: ${{ vars.INDENT }}
     secrets:
@@ -86,6 +86,7 @@ jobs:
       draft_prerelease_channel: alpha
       ready_start_prerelease_channel: beta
       prerelease_channel: ${{ inputs.start-rc && 'rc' || '' }}
+      reset_number_on_channel_change: true
     secrets:
       RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
       RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
diff --git a/.github/workflows/release-with-ready.yml b/.github/workflows/release-with-ready.yml
index e863b5e2e8..585375c20e 100644
--- a/.github/workflows/release-with-ready.yml
+++ b/.github/workflows/release-with-ready.yml
@@ -41,6 +41,7 @@ jobs:
       indent: ${{ vars.INDENT }}
       draft_prerelease_channel: alpha
       ready_start_prerelease_channel: beta
+      reset_number_on_channel_change: true
     secrets:
       RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
       RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

From f25fc5215bd03b9405b257fc8b8b1d7df7ea33b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 22 Nov 2024 12:14:41 +0900
Subject: [PATCH 107/125] =?UTF-8?q?fix(backend):=20Inbox=E3=81=AE=E3=82=A8?=
 =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=82=92throw=E3=81=9B=E3=81=9Areturn?=
 =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=84=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#15022)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix exception handling for Like activities

(cherry picked from commit 8f42e8434eaebe3aba5d1980c57f49dd8ad0de91)

* fix exception handling for Announce activities

(cherry picked from commit cfc3ab4b045af0674122fa49176431860176358b)

* fix exception handling for Undo activities

* Update Changelog

---------

Co-authored-by: Hazelnoot <acomputerdog@gmail.com>
---
 CHANGELOG.md                                       |  2 ++
 .../backend/src/core/activitypub/ApInboxService.ts | 14 +++++++++-----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 39ce36d678..5fa756c0f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -67,6 +67,8 @@
 - Fix: User Webhookテスト機能のMock Payloadを修正  
 - Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)  
 - Fix: リノートミュートが新規投稿通知に対して作用していなかった問題を修正
+- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/730)
 - Fix: セキュリティに関する修正
 
 ### Misskey.js
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index ee3f691c51..21c7adf7b2 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -28,6 +28,7 @@ import { bindThis } from '@/decorators.js';
 import type { MiRemoteUser } from '@/models/User.js';
 import { GlobalEventService } from '@/core/GlobalEventService.js';
 import { AbuseReportService } from '@/core/AbuseReportService.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
 import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
 import { ApNoteService } from './models/ApNoteService.js';
 import { ApLoggerService } from './ApLoggerService.js';
@@ -201,13 +202,16 @@ export class ApInboxService {
 
 		await this.apNoteService.extractEmojis(activity.tag ?? [], actor.host).catch(() => null);
 
-		return await this.reactionService.create(actor, note, activity._misskey_reaction ?? activity.content ?? activity.name).catch(err => {
-			if (err.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') {
+		try {
+			await this.reactionService.create(actor, note, activity._misskey_reaction ?? activity.content ?? activity.name);
+			return 'ok';
+		} catch (err) {
+			if (err instanceof IdentifiableError && err.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') {
 				return 'skip: already reacted';
 			} else {
 				throw err;
 			}
-		}).then(() => 'ok');
+		}
 	}
 
 	@bindThis
@@ -288,7 +292,7 @@ export class ApInboxService {
 
 		const target = await resolver.resolve(activity.object).catch(e => {
 			this.logger.error(`Resolution failed: ${e}`);
-			return e;
+			throw e;
 		});
 
 		if (isPost(target)) return await this.announceNote(actor, activity, target);
@@ -649,7 +653,7 @@ export class ApInboxService {
 
 		const object = await resolver.resolve(activity.object).catch(e => {
 			this.logger.error(`Resolution failed: ${e}`);
-			return e;
+			throw e;
 		});
 
 		// don't queue because the sender may attempt again when timeout

From 71bfa859862d716e5284ab1988df08561d4de60b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Fri, 22 Nov 2024 18:01:56 +0900
Subject: [PATCH 108/125] New Crowdin updates (#15027)

* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Chinese Simplified)
---
 locales/zh-CN.yml | 48 +++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 08e007df7f..e6232070d7 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -143,8 +143,8 @@ unmarkAsSensitive: "取消标记为敏感内容"
 enterFileName: "输入文件名"
 mute: "屏蔽"
 unmute: "解除静音"
-renoteMute: "屏蔽转帖"
-renoteUnmute: "解除屏蔽转帖"
+renoteMute: "隐藏转帖"
+renoteUnmute: "解除隐藏转帖"
 block: "拉黑"
 unblock: "取消拉黑"
 suspend: "冻结"
@@ -213,7 +213,7 @@ charts: "图表"
 perHour: "每小时"
 perDay: "每天"
 stopActivityDelivery: "停止发送活动"
-blockThisInstance: "封锁此服务器"
+blockThisInstance: "屏蔽此服务器"
 silenceThisInstance: "静音此服务器"
 mediaSilenceThisInstance: "隐藏此服务器的媒体文件"
 operations: "操作"
@@ -233,17 +233,17 @@ clearQueueConfirmTitle: "确定清除队列?"
 clearQueueConfirmText: "未送达的帖子将不会被投递。 通常无需执行此操作。"
 clearCachedFiles: "清除缓存"
 clearCachedFilesConfirm: "确定要清除所有缓存的远程文件?"
-blockedInstances: "被封锁的服务器"
-blockedInstancesDescription: "设定要封锁的服务器,以换行分隔。被封锁的服务器将无法与本服务器进行交换通讯。子域名也同样会被封锁。"
+blockedInstances: "被屏蔽的服务器"
+blockedInstancesDescription: "设定要屏蔽的服务器,以换行分隔。被屏蔽的服务器将无法与本服务器进行交换通讯。子域名也同样会被屏蔽。"
 silencedInstances: "被静音的服务器"
 silencedInstancesDescription: "设置要静音的服务器,以换行分隔。被静音的服务器内所有的账户将默认处于「静音」状态,仅能发送关注请求,并且在未关注状态下无法提及本地账户。被阻止的实例不受影响。"
 mediaSilencedInstances: "已隐藏媒体文件的服务器"
 mediaSilencedInstancesDescription: "设置要隐藏媒体文件的服务器,以换行分隔。被设置为隐藏媒体文件服务器内所有账号的文件均按照「敏感内容」处理,且将无法使用自定义表情符号。被阻止的实例不受影响。"
 federationAllowedHosts: "允许联合的服务器"
 federationAllowedHostsDescription: "设定允许联合的服务器,以换行分隔。"
-muteAndBlock: "静音/拉黑"
-mutedUsers: "已静音用户"
-blockedUsers: "已拉黑的用户"
+muteAndBlock: "隐藏和屏蔽"
+mutedUsers: "已隐藏用户"
+blockedUsers: "已屏蔽的用户"
 noUsers: "无用户"
 editProfile: "编辑资料"
 noteDeleteConfirm: "要删除该帖子吗?"
@@ -683,11 +683,11 @@ emptyToDisableSmtpAuth: "用户名和密码留空可以禁用 SMTP 验证"
 smtpSecure: "在 SMTP 连接中使用隐式 SSL / TLS"
 smtpSecureInfo: "使用 STARTTLS 时关闭。"
 testEmail: "邮件发送测试"
-wordMute: "文字屏蔽"
+wordMute: "隐藏文字"
 hardWordMute: "屏蔽关键词"
 regexpError: "正则表达式错误"
 regexpErrorDescription: "{tab} 屏蔽文字的第 {line} 行的正则表达式有错误:"
-instanceMute: "被屏蔽的服务器"
+instanceMute: "已隐藏的服务器"
 userSaysSomething: "{name} 说了什么,但是被屏蔽词过滤了"
 makeActive: "启用"
 display: "显示"
@@ -915,8 +915,8 @@ manageAccounts: "管理账户"
 makeReactionsPublic: "将回应设置为公开"
 makeReactionsPublicDescription: "将您发表过的回应设置成公开可见。"
 classic: "经典"
-muteThread: "屏蔽帖子列表"
-unmuteThread: "取消屏蔽帖子列表"
+muteThread: "隐藏帖子列表"
+unmuteThread: "取消隐藏帖子列表"
 followingVisibility: "关注的人的公开范围"
 followersVisibility: "关注者的公开范围"
 continueThread: "查看更多帖子"
@@ -939,7 +939,7 @@ searchByGoogle: "Google"
 instanceDefaultLightTheme: "服务器默认浅色主题"
 instanceDefaultDarkTheme: "服务器默认深色主题"
 instanceDefaultThemeDescription: "以对象格式输入主题代码"
-mutePeriod: "屏蔽期限"
+mutePeriod: "隐藏期限"
 period: "截止时间"
 indefinitely: "永久"
 tenMinutes: "10 分钟"
@@ -1779,7 +1779,7 @@ _role:
     canUpdateBioMedia: "可以更新头像和横幅"
     pinMax: "帖子置顶数量限制"
     antennaMax: "可创建的最大天线数量"
-    wordMuteMax: "屏蔽词的字数限制"
+    wordMuteMax: "隐藏词的字数限制"
     webhookMax: "Webhook 创建数量限制"
     clipMax: "便签创建数量限制"
     noteEachClipsMax: "单个便签内的贴文数量限制"
@@ -1792,7 +1792,7 @@ _role:
     canUseTranslator: "使用翻译功能"
     avatarDecorationLimit: "可添加头像挂件的最大个数"
     canImportAntennas: "允许导入天线"
-    canImportBlocking: "允许导入拉黑列表"
+    canImportBlocking: "允许导入屏蔽列表"
     canImportFollowing: "允许导入关注列表"
     canImportMuting: "允许导入屏蔽列表"
     canImportUserLists: "允许导入用户列表"
@@ -1942,14 +1942,14 @@ _menuDisplay:
   top: "顶部"
   hide: "隐藏"
 _wordMute:
-  muteWords: "禁用词"
+  muteWords: "要隐藏的词"
   muteWordsDescription: "AND 条件用空格分隔,OR 条件用换行符分隔。"
   muteWordsDescription2: "正则表达式用斜线包裹"
 _instanceMute:
-  instanceMuteDescription: "屏蔽服务器中的所有帖子和转帖,包括这些服务器上的用户回复。"
+  instanceMuteDescription: "隐藏服务器中的所有帖子和转帖,包括这些服务器上的用户回复。"
   instanceMuteDescription2: "一行一个"
   title: "隐藏服务器已设置的帖子。"
-  heading: "屏蔽服务器"
+  heading: "已隐藏的服务器"
 _theme:
   explore: "寻找主题"
   install: "安装主题"
@@ -2089,8 +2089,8 @@ _2fa:
 _permissions:
   "read:account": "查看账户信息"
   "write:account": "更改帐户信息"
-  "read:blocks": "查看黑名单"
-  "write:blocks": "编辑黑名单"
+  "read:blocks": "查看屏蔽列表"
+  "write:blocks": "编辑屏蔽列表"
   "read:drive": "查看网盘"
   "write:drive": "管理网盘文件"
   "read:favorites": "查看收藏夹"
@@ -2099,8 +2099,8 @@ _permissions:
   "write:following": "关注/取消关注"
   "read:messaging": "查看消息"
   "write:messaging": "撰写或删除消息"
-  "read:mutes": "查看屏蔽列表"
-  "write:mutes": "编辑屏蔽列表"
+  "read:mutes": "查看隐藏列表"
+  "write:mutes": "编辑隐藏列表"
   "write:notes": "撰写或删除帖子"
   "read:notifications": "查看通知"
   "write:notifications": "管理通知"
@@ -2300,8 +2300,8 @@ _exportOrImport:
   favoritedNotes: "收藏的帖子"
   clips: "便签"
   followingList: "关注中"
-  muteList: "屏蔽"
-  blockingList: "拉黑"
+  muteList: "隐藏"
+  blockingList: "屏蔽"
   userLists: "列表"
   excludeMutingUsers: "排除屏蔽用户"
   excludeInactiveUsers: "排除不活跃用户"

From 551040ed0ff4bfabeb4c54df2fd1860d58bedd21 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 09:15:09 +0000
Subject: [PATCH 109/125] Release: 2024.11.0

---
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index ccb6170a16..60de6f4e15 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.11.0-beta.4",
+	"version": "2024.11.0",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index cda4c183fa..7994dac1e4 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.11.0-beta.4",
+	"version": "2024.11.0",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From 872cefcfb80eb8f0185f5b28e9aed0a2a49fc544 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Fri, 22 Nov 2024 09:15:37 +0000
Subject: [PATCH 110/125] [skip ci] Update CHANGELOG.md (prepend template)

---
 CHANGELOG.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5fa756c0f0..8f097d16fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+## Unreleased
+
+### General
+-
+
+### Client
+-
+
+### Server
+-
+
+
 ## 2024.11.0
 
 ### Note

From 0e90589290de7948683131b356f91265c521d280 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 22 Nov 2024 21:19:12 +0900
Subject: [PATCH 111/125] Update CHANGELOG.md (typo)

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f097d16fd..a0ea1127c3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -49,7 +49,7 @@
 - Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
 - Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
 - Fix: リンク切れを修正
-= Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正  
+- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正  
   (Cherry-picked from https://github.com/taiyme/misskey/pull/305)
 - Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
 - Fix: 画面幅が狭い環境でデザインが崩れる問題を修正  

From 04b221409cac8e54e9f392b1a50094799c866441 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 23 Nov 2024 04:44:33 +0900
Subject: [PATCH 112/125] fix(backend): use atomic command to improve security

---
 packages/backend/src/core/WebAuthnService.ts | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/packages/backend/src/core/WebAuthnService.ts b/packages/backend/src/core/WebAuthnService.ts
index ad53192f18..ed75e4f467 100644
--- a/packages/backend/src/core/WebAuthnService.ts
+++ b/packages/backend/src/core/WebAuthnService.ts
@@ -189,14 +189,12 @@ export class WebAuthnService {
 	 */
 	@bindThis
 	public async verifySignInWithPasskeyAuthentication(context: string, response: AuthenticationResponseJSON): Promise<MiUser['id'] | null> {
-		const challenge = await this.redisClient.get(`webauthn:challenge:${context}`);
+		const challenge = await this.redisClient.getdel(`webauthn:challenge:${context}`);
 
 		if (!challenge) {
 			throw new IdentifiableError('2d16e51c-007b-4edd-afd2-f7dd02c947f6', `challenge '${context}' not found`);
 		}
 
-		await this.redisClient.del(`webauthn:challenge:${context}`);
-
 		const key = await this.userSecurityKeysRepository.findOneBy({
 			id: response.id,
 		});

From d91a1be56201cba91d61265bc928f70ac21a2fad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 23 Nov 2024 15:35:06 +0900
Subject: [PATCH 113/125] =?UTF-8?q?fix(frontend):=20=E7=94=BB=E9=9D=A2?=
 =?UTF-8?q?=E3=82=B5=E3=82=A4=E3=82=BA=E3=81=8C=E5=A4=89=E3=82=8F=E3=81=A3?=
 =?UTF-8?q?=E3=81=9F=E9=9A=9B=E3=81=ABnavbar=E3=81=8C=E8=87=AA=E5=8B=95?=
 =?UTF-8?q?=E3=81=A7=E6=8A=98=E3=82=8A=E3=81=9F=E3=81=9F=E3=81=BE=E3=82=8C?=
 =?UTF-8?q?=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?=
 =?UTF-8?q?=20(#15042)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): 画面サイズが変わった際にnavbarが自動で折りたたまれない問題を修正

* Update Changelog

* fix
---
 CHANGELOG.md                                 |  2 +-
 packages/frontend/src/ui/_common_/navbar.vue | 22 +++++++++++---------
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0ea1127c3..3ce54e4d1d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
 -
 
 ### Client
--
+- 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
 
 ### Server
 -
diff --git a/packages/frontend/src/ui/_common_/navbar.vue b/packages/frontend/src/ui/_common_/navbar.vue
index 8fc76741e3..9724905e02 100644
--- a/packages/frontend/src/ui/_common_/navbar.vue
+++ b/packages/frontend/src/ui/_common_/navbar.vue
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 				</component>
 			</template>
 			<div :class="$style.divider"></div>
-			<MkA v-if="$i.isAdmin || $i.isModerator" v-tooltip.noDelay.right="i18n.ts.controlPanel" :class="$style.item" :activeClass="$style.active" to="/admin">
+			<MkA v-if="$i != null && ($i.isAdmin || $i.isModerator)" v-tooltip.noDelay.right="i18n.ts.controlPanel" :class="$style.item" :activeClass="$style.active" to="/admin">
 				<i :class="$style.itemIcon" class="ti ti-dashboard ti-fw"></i><span :class="$style.itemText">{{ i18n.ts.controlPanel }}</span>
 			</MkA>
 			<button class="_button" :class="$style.item" @click="more">
@@ -48,10 +48,10 @@ SPDX-License-Identifier: AGPL-3.0-only
 			</MkA>
 		</div>
 		<div :class="$style.bottom">
-			<button v-tooltip.noDelay.right="i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="os.post">
+			<button v-tooltip.noDelay.right="i18n.ts.note" class="_button" :class="[$style.post]" data-cy-open-post-form @click="() => { os.post(); }">
 				<i class="ti ti-pencil ti-fw" :class="$style.postIcon"></i><span :class="$style.postText">{{ i18n.ts.note }}</span>
 			</button>
-			<button v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="_button" :class="[$style.account]" @click="openAccountMenu">
+			<button v-if="$i != null" v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="_button" :class="[$style.account]" @click="openAccountMenu">
 				<MkAvatar :user="$i" :class="$style.avatar"/><MkAcct class="_nowrap" :class="$style.acct" :user="$i"/>
 			</button>
 		</div>
@@ -83,8 +83,12 @@ import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
 import { defaultStore } from '@/store.js';
 import { i18n } from '@/i18n.js';
 import { instance } from '@/instance.js';
+import { getHTMLElementOrNull } from '@/scripts/get-dom-node-or-null.js';
 
-const iconOnly = ref(false);
+const forceIconOnly = ref(window.innerWidth <= 1279);
+const iconOnly = computed(() => {
+	return forceIconOnly.value || (defaultStore.reactiveState.menuDisplay.value === 'sideIcon');
+});
 
 const menu = computed(() => defaultStore.state.menu);
 const otherMenuItemIndicated = computed(() => {
@@ -95,14 +99,10 @@ const otherMenuItemIndicated = computed(() => {
 	return false;
 });
 
-const forceIconOnly = window.innerWidth <= 1279;
-
 function calcViewState() {
-	iconOnly.value = forceIconOnly || (defaultStore.state.menuDisplay === 'sideIcon');
+	forceIconOnly.value = window.innerWidth <= 1279;
 }
 
-calcViewState();
-
 window.addEventListener('resize', calcViewState);
 
 watch(defaultStore.reactiveState.menuDisplay, () => {
@@ -120,8 +120,10 @@ function openAccountMenu(ev: MouseEvent) {
 }
 
 function more(ev: MouseEvent) {
+	const target = getHTMLElementOrNull(ev.currentTarget ?? ev.target);
+	if (!target) return;
 	const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkLaunchPad.vue')), {
-		src: ev.currentTarget ?? ev.target,
+		src: target,
 	}, {
 		closed: () => dispose(),
 	});

From 00301ed04f144c57e2ed54b5103292ef573e8c02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sat, 23 Nov 2024 16:05:10 +0900
Subject: [PATCH 114/125] =?UTF-8?q?Update=20CHANGELOG.md=20(=E6=9B=B8?=
 =?UTF-8?q?=E3=81=8D=E6=96=B9=E3=82=92=E6=8F=83=E3=81=88=E3=82=8B)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ce54e4d1d..762ecafbdb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
 -
 
 ### Client
-- 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
+- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
 
 ### Server
 -

From a77ad7a16ba3f5c4845fe0716a72c7f01c285e9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?=
 <46447427+samunohito@users.noreply.github.com>
Date: Sat, 23 Nov 2024 16:45:05 +0900
Subject: [PATCH 115/125] =?UTF-8?q?fix(backend):=20=E3=82=A2=E3=83=89?=
 =?UTF-8?q?=E3=83=AC=E3=82=B9=E5=85=A5=E5=8A=9B=E3=81=A7=E7=9B=B4=E6=8E=A5?=
 =?UTF-8?q?=E3=83=A6=E3=83=BC=E3=82=B6=E3=81=AE=E3=83=97=E3=83=AD=E3=83=95?=
 =?UTF-8?q?=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=9A=E3=83=BC=E3=82=B8=E3=82=92?=
 =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=97=E3=81=9F=E9=9A=9B=E3=80=81=E5=89=8D?=
 =?UTF-8?q?=E6=8F=90=E3=83=87=E3=83=BC=E3=82=BF=E3=81=8C=E8=B6=B3=E3=82=8A?=
 =?UTF-8?q?=E3=81=9A=E6=8F=8F=E7=94=BB=E3=81=AB=E5=A4=B1=E6=95=97=E3=81=99?=
 =?UTF-8?q?=E3=82=8B=20(#15033)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(backend): アドレス入力で直接ユーザのプロフィールページを表示した際、前提データが足りず描画に失敗する

* fix CHANGELOG.md
---
 CHANGELOG.md                                           | 2 +-
 packages/backend/src/server/web/ClientServerService.ts | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 762ecafbdb..7896a42883 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@
 - Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
 
 ### Server
--
+- Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
 
 
 ## 2024.11.0
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index 1b8873214b..e356e0d76c 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -585,7 +585,10 @@ export class ClientServerService {
 					reply.header('X-Robots-Tag', 'noai');
 				}
 
-				const _user = await this.userEntityService.pack(user);
+				const _user = await this.userEntityService.pack(user, null, {
+					schema: 'UserDetailed',
+					userProfile: profile,
+				});
 
 				return await reply.view('user', {
 					user, profile, me,

From ae1d0b08eb7d95a79d23d1f2c1d9d69cc0650e0a Mon Sep 17 00:00:00 2001
From: anatawa12 <anatawa12@icloud.com>
Date: Sat, 23 Nov 2024 17:42:55 +0900
Subject: [PATCH 116/125] ci: do not run chromatic on fork repositories
 (#15041)

---
 .github/workflows/storybook.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml
index c02f38ee0b..efcf0291d8 100644
--- a/.github/workflows/storybook.yml
+++ b/.github/workflows/storybook.yml
@@ -15,6 +15,8 @@ on:
 
 jobs:
   build:
+    # chromatic is not likely to be available for fork repositories, so we disable for fork repositories.
+    if: github.repository == 'misskey-dev/misskey'
     runs-on: ubuntu-latest
 
     env:

From d176db517fd11b63e83daa7c1f45ecd25bd0750e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sun, 24 Nov 2024 15:23:07 +0900
Subject: [PATCH 117/125] =?UTF-8?q?fix(backend/misskey-js):=20=E3=82=BF?=
 =?UTF-8?q?=E3=82=A4=E3=83=9D=E4=BF=AE=E6=AD=A3=20(#15046)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/server/api/openapi/gen-spec.ts        |   2 +-
 packages/misskey-js/src/autogen/types.ts      | 110 +++++++++---------
 2 files changed, 56 insertions(+), 56 deletions(-)

diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts
index efa47a6986..3b20ec1321 100644
--- a/packages/backend/src/server/api/openapi/gen-spec.ts
+++ b/packages/backend/src/server/api/openapi/gen-spec.ts
@@ -183,7 +183,7 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) {
 				},
 				...(endpoint.meta.limit ? {
 					'429': {
-						description: 'To many requests',
+						description: 'Too many requests',
 						content: {
 							'application/json': {
 								schema: {
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 280abba727..42ca05e057 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -10593,7 +10593,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -11112,7 +11112,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -11179,7 +11179,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -11573,7 +11573,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -11633,7 +11633,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -11756,7 +11756,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -13351,7 +13351,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -14184,7 +14184,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -14531,7 +14531,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -14656,7 +14656,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -15151,7 +15151,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -15624,7 +15624,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -15684,7 +15684,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -15747,7 +15747,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -15806,7 +15806,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -15866,7 +15866,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -16373,7 +16373,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -16648,7 +16648,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -17908,7 +17908,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -17969,7 +17969,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18020,7 +18020,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18071,7 +18071,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18122,7 +18122,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18173,7 +18173,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18224,7 +18224,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18275,7 +18275,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18512,7 +18512,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18572,7 +18572,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18631,7 +18631,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18690,7 +18690,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18749,7 +18749,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18817,7 +18817,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -18885,7 +18885,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -19877,7 +19877,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -20114,7 +20114,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -20174,7 +20174,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -20544,7 +20544,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -21023,7 +21023,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -21191,7 +21191,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -21688,7 +21688,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -21746,7 +21746,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -21804,7 +21804,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -22464,7 +22464,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -22898,7 +22898,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -23142,7 +23142,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -23278,7 +23278,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -23416,7 +23416,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -23550,7 +23550,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -23882,7 +23882,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -23949,7 +23949,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -24279,7 +24279,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -24829,7 +24829,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -26108,7 +26108,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -27398,7 +27398,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];
@@ -27512,7 +27512,7 @@ export type operations = {
           'application/json': components['schemas']['Error'];
         };
       };
-      /** @description To many requests */
+      /** @description Too many requests */
       429: {
         content: {
           'application/json': components['schemas']['Error'];

From eddf6a23197e1a14b20423c7da08206034d198aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sun, 24 Nov 2024 15:23:21 +0900
Subject: [PATCH 118/125] =?UTF-8?q?fix(frontend):=20=E3=82=B5=E3=83=BC?=
 =?UTF-8?q?=E3=83=90=E3=83=BC=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3?=
 =?UTF-8?q?=E3=83=88=E3=81=A8Misskey=E9=96=A2=E9=80=A3=E3=83=AA=E3=82=BD?=
 =?UTF-8?q?=E3=83=BC=E3=82=B9=E3=81=A8=E3=81=AE=E9=96=93=E3=81=ABdivider?=
 =?UTF-8?q?=E3=81=8C=E5=85=A5=E3=82=89=E3=81=AA=E3=81=84=E3=81=93=E3=81=A8?=
 =?UTF-8?q?=E3=81=8C=E3=81=82=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?=
 =?UTF-8?q?=E6=AD=A3=20(#15044)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): サーバードキュメントとMisskey関連リソースとの間にdividerが入らないことがある問題を修正

* Update Changelog
---
 CHANGELOG.md                                | 1 +
 packages/frontend/src/ui/_common_/common.ts | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7896a42883..b8eca4c355 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 
 ### Client
 - Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
+- Fix: サーバー情報メニューに区切り線が不足していたのを修正
 
 ### Server
 - Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts
index f908803f01..b31254196a 100644
--- a/packages/frontend/src/ui/_common_/common.ts
+++ b/packages/frontend/src/ui/_common_/common.ts
@@ -124,7 +124,7 @@ export function openInstanceMenu(ev: MouseEvent) {
 		});
 	}
 
-	if (!instance.impressumUrl && !instance.tosUrl && !instance.privacyPolicyUrl) {
+	if (instance.impressumUrl != null || instance.tosUrl != null || instance.privacyPolicyUrl != null) {
 		menuItems.push({ type: 'divider' });
 	}
 

From a0e91b5882379b31b379ec366ed09e7253c788bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Sun, 24 Nov 2024 20:43:47 +0900
Subject: [PATCH 119/125] =?UTF-8?q?fix(backend):=20=E8=B5=B7=E5=8B=95?=
 =?UTF-8?q?=E5=89=8D=E3=81=AE=E7=96=8E=E9=80=9A=E3=83=81=E3=82=A7=E3=83=83?=
 =?UTF-8?q?=E3=82=AF=E3=81=8C=E6=A9=9F=E8=83=BD=E3=81=97=E3=81=AA=E3=81=8F?=
 =?UTF-8?q?=E3=81=AA=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E5=95=8F=E9=A1=8C?=
 =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=20(#15043)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* check harder for connectibility

`allSettled` does not throw if a promise is rejected, so
`check_connect` never actually failed

* Update Changelog

---------

Co-authored-by: dakkar <dakkar@thenautilus.net>
---
 CHANGELOG.md                              | 2 ++
 packages/backend/scripts/check_connect.js | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8eca4c355..badcf1cebb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@
 
 ### Server
 - Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
+- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
 
 
 ## 2024.11.0
diff --git a/packages/backend/scripts/check_connect.js b/packages/backend/scripts/check_connect.js
index bb149444b5..96c4549ccb 100644
--- a/packages/backend/scripts/check_connect.js
+++ b/packages/backend/scripts/check_connect.js
@@ -53,4 +53,4 @@ const promises = Array
 		connectToPostgres()
 	]);
 
-await Promise.allSettled(promises);
+await Promise.all(promises);

From dd56623cded7cc7a355d1dc59e46e2d8f1ed3660 Mon Sep 17 00:00:00 2001
From: anatawa12 <anatawa12@icloud.com>
Date: Sun, 24 Nov 2024 20:44:59 +0900
Subject: [PATCH 120/125] fix: unable to upload to local object storage
 (#15040)

---
 packages/backend/src/core/S3Service.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/backend/src/core/S3Service.ts b/packages/backend/src/core/S3Service.ts
index bb2a463354..37721d2bf1 100644
--- a/packages/backend/src/core/S3Service.ts
+++ b/packages/backend/src/core/S3Service.ts
@@ -28,7 +28,7 @@ export class S3Service {
 			? `${meta.objectStorageUseSSL ? 'https' : 'http'}://${meta.objectStorageEndpoint}`
 			: `${meta.objectStorageUseSSL ? 'https' : 'http'}://example.net`; // dummy url to select http(s) agent
 
-		const agent = this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy);
+		const agent = this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy, true);
 		const handlerOption: NodeHttpHandlerOptions = {};
 		if (meta.objectStorageUseSSL) {
 			handlerOption.httpsAgent = agent as https.Agent;

From 8076f78d06786dd60db121b588289be54731b13e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Mon, 25 Nov 2024 22:18:00 +0000
Subject: [PATCH 121/125] Bump version to 2024.11.1-alpha.0

---
 CHANGELOG.md                     | 2 +-
 package.json                     | 2 +-
 packages/misskey-js/package.json | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index badcf1cebb..8f2c36ffc3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## Unreleased
+## 2024.11.1
 
 ### General
 -
diff --git a/package.json b/package.json
index 60de6f4e15..b91f044ff7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "misskey",
-	"version": "2024.11.0",
+	"version": "2024.11.1-alpha.0",
 	"codename": "nasubi",
 	"repository": {
 		"type": "git",
diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json
index 7994dac1e4..6a2b45150d 100644
--- a/packages/misskey-js/package.json
+++ b/packages/misskey-js/package.json
@@ -1,7 +1,7 @@
 {
 	"type": "module",
 	"name": "misskey-js",
-	"version": "2024.11.0",
+	"version": "2024.11.1-alpha.0",
 	"description": "Misskey SDK for JavaScript",
 	"license": "MIT",
 	"main": "./built/index.js",

From fa271cf84e7797358703d4cda0e8f48b26bdbd87 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Sat, 30 Nov 2024 13:20:49 +0900
Subject: [PATCH 122/125] Update about-misskey.vue

---
 packages/frontend/src/pages/about-misskey.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index f2becfd8f5..1a86e34969 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -384,6 +384,7 @@ const patrons = [
 	'こまつぶり',
 	'まゆつな空高',
 	'asata',
+	'ruru',
 ];
 
 const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));

From 020c191e2c7457c8eaa6b7bbbd7892de32b9de24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Tue, 10 Dec 2024 10:29:40 +0900
Subject: [PATCH 123/125] =?UTF-8?q?fix(frontend):=20MiAuth=E8=AA=8D?=
 =?UTF-8?q?=E5=8F=AF=E7=94=BB=E9=9D=A2=E3=81=AE=E3=83=87=E3=82=B6=E3=82=A4?=
 =?UTF-8?q?=E3=83=B3=E4=BF=AE=E6=AD=A3=20(#15106)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/frontend/src/pages/miauth.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue
index e85d2c29c1..7fb6653c13 100644
--- a/packages/frontend/src/pages/miauth.vue
+++ b/packages/frontend/src/pages/miauth.vue
@@ -117,5 +117,6 @@ definePageMetadata(() => ({
 	border-radius: var(--MI-radius);
 	background-color: var(--MI_THEME-panel);
 	overflow-x: scroll;
+	white-space: nowrap;
 }
 </style>

From 074b7b0bee82ea692ba675bf4b35734b540b7752 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Tue, 10 Dec 2024 10:36:03 +0900
Subject: [PATCH 124/125] =?UTF-8?q?fix(frontend):=20=E5=85=AC=E9=96=8B?=
 =?UTF-8?q?=E7=AF=84=E5=9B=B2=E3=81=8C=E3=83=9B=E3=83=BC=E3=83=A0=E3=81=AE?=
 =?UTF-8?q?=E3=83=8E=E3=83=BC=E3=83=88=E3=81=AE=E5=9F=8B=E3=82=81=E8=BE=BC?=
 =?UTF-8?q?=E3=81=BF=E3=82=A6=E3=82=A3=E3=82=B8=E3=82=A7=E3=83=83=E3=83=88?=
 =?UTF-8?q?=E3=81=8C=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BE=E3=82=8C=E3=81=AA?=
 =?UTF-8?q?=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#1510?=
 =?UTF-8?q?2)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Resolve frontend/backend contradiction for home visibility embeds

This now uses the same check from `packages/frontend/src/scripts/get-note-menu.ts`

* Update Changelog

---------

Co-authored-by: CenTdemeern1 <timo.herngreen@gmail.com>
---
 CHANGELOG.md                                           | 2 ++
 packages/backend/src/server/web/ClientServerService.ts | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f2c36ffc3..595252d3e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@
 ### Client
 - Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
 - Fix: サーバー情報メニューに区切り線が不足していたのを修正
+- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正  
+  (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
 
 ### Server
 - Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts
index e356e0d76c..1a75096c4e 100644
--- a/packages/backend/src/server/web/ClientServerService.ts
+++ b/packages/backend/src/server/web/ClientServerService.ts
@@ -871,7 +871,7 @@ export class ClientServerService {
 			});
 
 			if (note == null) return;
-			if (note.visibility !== 'public') return;
+			if (['specified', 'followers'].includes(note.visibility)) return;
 			if (note.userHost != null) return;
 
 			const _note = await this.noteEntityService.pack(note, null, { detail: true });

From e8bf6285cb023bd2031e85de3a3eb495bf4afb2e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?=
 <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Tue, 10 Dec 2024 10:42:12 +0900
Subject: [PATCH 125/125] =?UTF-8?q?fix(frontend):=20=E3=83=8E=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E3=81=8C=E3=83=AD=E3=82=B0=E3=82=A4=E3=83=B3=E3=81=97?=
 =?UTF-8?q?=E3=81=A6=E3=81=84=E3=82=8B=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC?=
 =?UTF-8?q?=E3=81=97=E3=81=8B=E8=A6=8B=E3=82=8C=E3=81=AA=E3=81=84=E5=A0=B4?=
 =?UTF-8?q?=E5=90=88=E3=81=AB=E3=83=AD=E3=82=B0=E3=82=A4=E3=83=B3=E3=82=92?=
 =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=B3=E3=82=BB=E3=83=AB=E3=81=97=E3=81=9F?=
 =?UTF-8?q?=E5=A0=B4=E5=90=88=E3=81=9D=E3=81=AE=E5=BE=8C=E3=81=AE=E5=8B=95?=
 =?UTF-8?q?=E7=B7=9A=E3=81=8C=E3=81=AA=E3=81=8F=E3=81=AA=E3=82=8B=E5=95=8F?=
 =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#15101)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix(frontend): ノートがログインしているユーザーしか見れない場合にログインをキャンセルすると一切の処理が停止する問題を修正

* Update Changelog

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 CHANGELOG.md                         | 1 +
 packages/frontend/src/pages/note.vue | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 595252d3e4..6b9ae480af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
 ### Client
 - Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
 - Fix: サーバー情報メニューに区切り線が不足していたのを修正
+- Fix: ノートがログインしているユーザーしか見れない場合にログインダイアログを閉じるとその後の動線がなくなる問題を修正
 - Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正  
   (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
 
diff --git a/packages/frontend/src/pages/note.vue b/packages/frontend/src/pages/note.vue
index 3e1d04bd6d..5cf8f56776 100644
--- a/packages/frontend/src/pages/note.vue
+++ b/packages/frontend/src/pages/note.vue
@@ -50,6 +50,7 @@ SPDX-License-Identifier: AGPL-3.0-only
 <script lang="ts" setup>
 import { computed, watch, ref } from 'vue';
 import * as Misskey from 'misskey-js';
+import { host } from '@@/js/config.js';
 import type { Paging } from '@/components/MkPagination.vue';
 import MkNoteDetailed from '@/components/MkNoteDetailed.vue';
 import MkNotes from '@/components/MkNotes.vue';
@@ -140,7 +141,12 @@ function fetchNote() {
 	}).catch(err => {
 		if (err.id === '8e75455b-738c-471d-9f80-62693f33372e') {
 			pleaseLogin({
+				path: '/',
 				message: i18n.ts.thisContentsAreMarkedAsSigninRequiredByAuthor,
+				openOnRemote: {
+					type: 'lookup',
+					url: `https://${host}/notes/${props.noteId}`,
+				},
 			});
 		}
 		error.value = err;