diff --git a/src/backend/clients/database/SqliteDatabaseClient.ts b/src/backend/clients/database/SqliteDatabaseClient.ts
index 9bbeec8da..c88eed10a 100644
--- a/src/backend/clients/database/SqliteDatabaseClient.ts
+++ b/src/backend/clients/database/SqliteDatabaseClient.ts
@@ -91,6 +91,7 @@ const AVAILABLE_MIGRATIONS: [number, string[]][] = [
[55, ['0060_add_card_fingerprint.sql']],
[56, ['0061_add_suspended_at.sql']],
[57, ['0062_blocked-app-origins.sql']],
+ [58, ['0063_add_suspended_reason.sql']],
];
export class SqliteDatabaseClient extends AbstractDatabaseClient {
diff --git a/src/backend/clients/database/migrations/mysql/mysql_mig_18.sql b/src/backend/clients/database/migrations/mysql/mysql_mig_18.sql
new file mode 100644
index 000000000..7d0428323
--- /dev/null
+++ b/src/backend/clients/database/migrations/mysql/mysql_mig_18.sql
@@ -0,0 +1,26 @@
+-- Copyright (C) 2024-present Puter Technologies Inc.
+--
+-- This file is part of Puter.
+--
+-- Puter is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU Affero General Public License as published
+-- by the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Affero General Public License for more details.
+--
+-- You should have received a copy of the GNU Affero General Public License
+-- along with this program. If not, see .
+
+-- Suspension reason column. Mirrors SQLite migration 0063. Why an account was
+-- suspended (NULL while not suspended) — companion to the boolean `suspended`
+-- flag and `suspended_at` timestamp. Constrained at the application layer to a
+-- fixed set of reasons (see extensions/admin suspension_reasons.js).
+--
+-- Idempotent: the column add uses _puter_add_col (defined in mig_1, which
+-- leaves it resident for later migrations).
+
+CALL _puter_add_col('user', 'suspended_reason', '`suspended_reason` VARCHAR(64) DEFAULT NULL');
diff --git a/src/backend/clients/database/migrations/postgres/postgres_mig_6.sql b/src/backend/clients/database/migrations/postgres/postgres_mig_6.sql
new file mode 100644
index 000000000..a6304510a
--- /dev/null
+++ b/src/backend/clients/database/migrations/postgres/postgres_mig_6.sql
@@ -0,0 +1,36 @@
+-- Copyright (C) 2024-present Puter Technologies Inc.
+--
+-- This file is part of Puter.
+--
+-- Puter is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU Affero General Public License as published
+-- by the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Affero General Public License for more details.
+--
+-- You should have received a copy of the GNU Affero General Public License
+-- along with this program. If not, see .
+
+-- Admin-managed blocklist of app origins. Mirrors SQLite migration 0062 /
+-- MySQL mysql_mig_17 (which Postgres was originally missed for). An app whose
+-- `index_url` host (or a request origin) matches an entry is denied access to
+-- Puter resources. `include_subdomains = 1` also blocks every subdomain of
+-- `domain`. Enforced in AuthService via AppOriginBlocklistService.
+--
+-- Idempotent via IF NOT EXISTS.
+
+CREATE TABLE IF NOT EXISTS blocked_app_origins (
+ id SERIAL PRIMARY KEY,
+ domain VARCHAR(255) NOT NULL,
+ include_subdomains SMALLINT NOT NULL DEFAULT 0,
+ reason TEXT DEFAULT NULL,
+ created_by VARCHAR(255) DEFAULT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE UNIQUE INDEX IF NOT EXISTS idx_blocked_app_origins_domain
+ ON blocked_app_origins (domain);
diff --git a/src/backend/clients/database/migrations/postgres/postgres_mig_7.sql b/src/backend/clients/database/migrations/postgres/postgres_mig_7.sql
new file mode 100644
index 000000000..12cf4a946
--- /dev/null
+++ b/src/backend/clients/database/migrations/postgres/postgres_mig_7.sql
@@ -0,0 +1,24 @@
+-- Copyright (C) 2024-present Puter Technologies Inc.
+--
+-- This file is part of Puter.
+--
+-- Puter is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU Affero General Public License as published
+-- by the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Affero General Public License for more details.
+--
+-- You should have received a copy of the GNU Affero General Public License
+-- along with this program. If not, see .
+
+-- Suspension reason column. Mirrors SQLite migration 0063. Why an account was
+-- suspended (NULL while not suspended) — companion to the boolean `suspended`
+-- flag and `suspended_at` timestamp. Constrained at the application layer to a
+-- fixed set of reasons (see extensions/admin suspension_reasons.js).
+-- Idempotent via IF NOT EXISTS.
+
+ALTER TABLE "user" ADD COLUMN IF NOT EXISTS suspended_reason text;
diff --git a/src/backend/clients/database/migrations/sqlite/0063_add_suspended_reason.sql b/src/backend/clients/database/migrations/sqlite/0063_add_suspended_reason.sql
new file mode 100644
index 000000000..01eba687d
--- /dev/null
+++ b/src/backend/clients/database/migrations/sqlite/0063_add_suspended_reason.sql
@@ -0,0 +1,23 @@
+-- Copyright (C) 2024-present Puter Technologies Inc.
+--
+-- This file is part of Puter.
+--
+-- Puter is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU Affero General Public License as published
+-- by the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Affero General Public License for more details.
+--
+-- You should have received a copy of the GNU Affero General Public License
+-- along with this program. If not, see .
+
+-- Why an account was suspended, NULL while not suspended. Companion to the
+-- boolean `suspended` flag and `suspended_at` timestamp. Constrained at the
+-- application layer to a fixed set of reasons (see extensions/admin
+-- suspension_reasons.js) — kept as free TEXT here so adding a reason later
+-- needs no migration.
+ALTER TABLE `user` ADD COLUMN `suspended_reason` TEXT DEFAULT NULL;