From 8188327fcfd11107d079f1313fef0eee7205eed9 Mon Sep 17 00:00:00 2001 From: aXenDeveloper Date: Tue, 13 Oct 2026 10:37:17 +0200 Subject: [PATCH] =?UTF-8?q?feat(moderation):=20=E2=9C=A8=20moderation=20MV?= =?UTF-8?q?P=20with=20ModCP,=20reports=20and=20scoped=20moderators?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Scoped moderator permissions, moderation registry and report API - ModCP with reports board, report sidebar and snapshot peek - Report button with blog and example plugin reporting, plus migration - ModCP labels, snapshot rendering and docs screenshots - Moderation guides, reference pages and cross-links - Regression tests for scopes, reports and snapshots - Parallel database queries with Promise.all Co-Authored-By: Claude Opus 5.5 --- .../migration.sql | 46 + .../snapshot.json | 17707 ++++++++++++++++ .../content-engine/content-visibility.mdx | 5 +- .../content/docs/content-engine/reference.mdx | 10 + .../docs/dev/events/built-in-events.mdx | 26 + apps/web/content/docs/dev/meta.json | 1 + .../dev/moderation/configure-moderators.mdx | 86 + .../docs/dev/moderation/enable-reports.mdx | 120 + .../web/content/docs/dev/moderation/index.mdx | 38 + .../web/content/docs/dev/moderation/meta.json | 13 + .../moderation/moderation-modcp-queue.webp | Bin 0 -> 102394 bytes .../moderation/moderation-modcp-report.webp | Bin 0 -> 175204 bytes .../moderation/moderation-report-dialog.webp | Bin 0 -> 50704 bytes .../moderation/moderation-scope-dialog.webp | Bin 0 -> 46786 bytes .../moderation/moderation-scope-editor.webp | Bin 0 -> 77274 bytes .../docs/dev/moderation/process-reports.mdx | 118 + .../content/docs/dev/moderation/reference.mdx | 164 + .../dev/moderation/scoped-permissions.mdx | 155 + .../working-with-users/staff-permissions.mdx | 21 + apps/web/content/docs/ui/user.mdx | 51 +- apps/web/src/docs/examples/user-format.tsx | 30 + apps/web/src/docs/examples/user-roles.tsx | 65 + .../api/lib/check-staff-permission.test.ts | 119 +- .../src/api/lib/check-staff-permission.ts | 34 +- .../vitnode/src/api/lib/moderation/access.ts | 258 + .../src/api/lib/moderation/registry.test.ts | 202 + .../src/api/lib/moderation/registry.ts | 156 + .../vitnode/src/api/lib/moderation/scopes.ts | 61 + .../src/api/lib/moderation/snapshot.test.ts | 90 + .../src/api/lib/moderation/snapshot.ts | 77 + .../vitnode/src/api/lib/moderation/targets.ts | 86 + .../vitnode/src/api/lib/permission-staff.ts | 23 +- packages/vitnode/src/api/lib/plugin.ts | 21 +- .../src/api/lib/staff-permission-cache.ts | 2 +- .../src/api/lib/staff-permission.test.ts | 262 + .../vitnode/src/api/lib/staff-permission.ts | 209 +- .../src/api/middlewares/global.middleware.ts | 20 + packages/vitnode/src/api/models/events.ts | 34 + packages/vitnode/src/api/moderation.ts | 19 + .../src/api/modules/admin/staff/lib/schema.ts | 26 + .../modules/admin/staff/lib/scoped-grants.ts | 202 + .../admin/staff/lib/staff-entry-guards.ts | 11 +- .../staff/routes/permission-catalog.route.ts | 27 +- .../staff/routes/scope-resources.route.ts | 98 + .../staff/routes/scoped-permissions.test.ts | 239 + .../staff/routes/update-permissions.route.ts | 73 +- .../modules/admin/staff/staff.admin.module.ts | 2 + .../api/modules/moderation/lib/candidates.ts | 60 + .../src/api/modules/moderation/lib/notes.ts | 66 + .../src/api/modules/moderation/lib/people.ts | 57 + .../src/api/modules/moderation/lib/reports.ts | 271 + .../src/api/modules/moderation/lib/schema.ts | 82 + .../modules/moderation/moderation.module.ts | 38 + .../api/modules/moderation/reports.test.ts | 586 + .../modules/moderation/routes/create.route.ts | 192 + .../modules/moderation/routes/list.route.ts | 188 + .../modules/moderation/routes/notes.routes.ts | 134 + .../modules/moderation/routes/show.route.ts | 241 + .../moderation/routes/workflow.routes.ts | 518 + .../modules/users/routes/permissions.route.ts | 10 + packages/vitnode/src/api/plugin.ts | 2 + .../components/form/fields/input-users.tsx | 28 +- packages/vitnode/src/components/side-nav.tsx | 58 + .../vitnode/src/components/table/content.tsx | 2 +- .../vitnode/src/components/user-format.tsx | 52 +- .../src/content/define-reports.test.ts | 100 + .../vitnode/src/content/define-reports.ts | 143 + packages/vitnode/src/content/define-shared.ts | 1 + packages/vitnode/src/content/define.ts | 12 + packages/vitnode/src/content/index.ts | 3 + .../src/content/server/hidden-access.test.ts | 103 + .../src/content/server/hidden-access.ts | 63 +- packages/vitnode/src/content/server/model.ts | 12 +- .../src/content/server/report-target.ts | 491 + packages/vitnode/src/content/types.ts | 18 + packages/vitnode/src/database/moderation.ts | 96 + packages/vitnode/src/database/relations.ts | 2 + .../src/editor/block-shell/block-shell.tsx | 2 +- .../src/editor/dnd/container-sortable.tsx | 25 +- packages/vitnode/src/editor/dnd/context.ts | 8 + packages/vitnode/src/editor/dnd/drop-slot.ts | 31 + packages/vitnode/src/editor/dnd/provider.tsx | 235 +- .../vitnode/src/editor/zones/area-frame.tsx | 4 +- .../vitnode/src/editor/zones/block-body.tsx | 51 + .../vitnode/src/editor/zones/drop-slot.tsx | 52 + .../src/editor/zones/editable-zone.tsx | 137 +- packages/vitnode/src/lib/dnd/drag-lift.tsx | 52 + packages/vitnode/src/lib/dnd/drag-motion.ts | 92 +- packages/vitnode/src/lib/dnd/layout-flip.ts | 77 + .../vitnode/src/lib/dnd/use-stable-ids.ts | 17 + packages/vitnode/src/lib/moderation/const.ts | 74 + .../vitnode/src/lib/moderation/snapshot.ts | 45 + packages/vitnode/src/locales/en.json | 307 +- packages/vitnode/src/pages/modcp/index.tsx | 16 + packages/vitnode/src/pages/modcp/layout.tsx | 23 + packages/vitnode/src/pages/modcp/report.tsx | 24 + packages/vitnode/src/pages/modcp/reports.tsx | 34 + packages/vitnode/src/routes.tsx | 27 + .../src/tanstack/admin/staff/edit-route.tsx | 29 +- .../src/tanstack/admin/staff/edit-screen.tsx | 8 + .../src/tanstack/moderation/breadcrumb.tsx | 23 + .../vitnode/src/tanstack/moderation/index.ts | 2 + .../src/tanstack/moderation/layout.tsx | 23 + .../src/tanstack/moderation/namespaces.ts | 1 + .../src/tanstack/moderation/report-button.tsx | 127 + .../src/tanstack/moderation/report-screen.tsx | 16 + .../tanstack/moderation/reports-screen.tsx | 57 + .../src/tanstack/moderation/route-search.ts | 55 + .../vitnode/src/tanstack/moderation/route.ts | 117 + .../core/dashboard/grid/board-provider.tsx | 38 +- .../core/dashboard/grid/dashboard-grid.tsx | 6 +- .../views/core/dashboard/grid/layout-flip.ts | 75 +- .../views/core/dashboard/grid/widget-card.tsx | 2 +- .../staff/edit/edit-staff-form-content.tsx | 348 +- .../core/staff/edit/scope/scope-dialog.tsx | 293 + .../core/staff/edit/scope/scope-query.ts | 90 + .../views/core/staff/staff-model.test.ts | 113 + .../admin/views/core/staff/staff-model.ts | 161 +- .../views/core/users/list/users-query.ts | 5 +- .../src/views/auth/settings/nav-content.tsx | 92 +- .../theme/header/user/user-header-model.ts | 45 +- .../moderation/modcp/board/board-card.tsx | 213 + .../moderation/modcp/board/board-moves.ts | 104 + .../moderation/modcp/board/reports-board.tsx | 606 + .../src/views/moderation/modcp/modcp-nav.tsx | 112 + .../src/views/moderation/modcp/modcp-query.ts | 128 + .../moderation/modcp/plugin-messages.tsx | 27 + .../moderation/modcp/report-activity.tsx | 686 + .../views/moderation/modcp/report-content.tsx | 285 + .../views/moderation/modcp/report-forms.tsx | 178 + .../views/moderation/modcp/report-sidebar.tsx | 629 + .../moderation/modcp/report-snapshot-peek.tsx | 104 + .../views/moderation/modcp/report-tone.tsx | 129 + .../moderation/modcp/reports-content.tsx | 59 + .../views/moderation/modcp/snapshot-view.tsx | 173 + .../views/moderation/modcp/status-badge.tsx | 34 + .../views/moderation/moderation-mutations.ts | 279 + .../report/report-dialog-content.tsx | 146 + plugins/blog/src/content/post.ts | 2 + plugins/blog/src/locales/en.json | 8 +- plugins/blog/src/pages/post-page.tsx | 34 +- plugins/example/src/api/lib/moderation.ts | 43 + plugins/example/src/config.api.ts | 2 + plugins/example/src/content/article.ts | 2 + plugins/example/src/database/articles.ts | 1 + plugins/example/src/locales/en.json | 6 + 146 files changed, 31190 insertions(+), 495 deletions(-) create mode 100644 apps/api/migrations/20261011193321_add_moderation_reports/migration.sql create mode 100644 apps/api/migrations/20261011193321_add_moderation_reports/snapshot.json create mode 100644 apps/web/content/docs/dev/moderation/configure-moderators.mdx create mode 100644 apps/web/content/docs/dev/moderation/enable-reports.mdx create mode 100644 apps/web/content/docs/dev/moderation/index.mdx create mode 100644 apps/web/content/docs/dev/moderation/meta.json create mode 100644 apps/web/content/docs/dev/moderation/moderation-modcp-queue.webp create mode 100644 apps/web/content/docs/dev/moderation/moderation-modcp-report.webp create mode 100644 apps/web/content/docs/dev/moderation/moderation-report-dialog.webp create mode 100644 apps/web/content/docs/dev/moderation/moderation-scope-dialog.webp create mode 100644 apps/web/content/docs/dev/moderation/moderation-scope-editor.webp create mode 100644 apps/web/content/docs/dev/moderation/process-reports.mdx create mode 100644 apps/web/content/docs/dev/moderation/reference.mdx create mode 100644 apps/web/content/docs/dev/moderation/scoped-permissions.mdx create mode 100644 apps/web/src/docs/examples/user-format.tsx create mode 100644 apps/web/src/docs/examples/user-roles.tsx create mode 100644 packages/vitnode/src/api/lib/moderation/access.ts create mode 100644 packages/vitnode/src/api/lib/moderation/registry.test.ts create mode 100644 packages/vitnode/src/api/lib/moderation/registry.ts create mode 100644 packages/vitnode/src/api/lib/moderation/scopes.ts create mode 100644 packages/vitnode/src/api/lib/moderation/snapshot.test.ts create mode 100644 packages/vitnode/src/api/lib/moderation/snapshot.ts create mode 100644 packages/vitnode/src/api/lib/moderation/targets.ts create mode 100644 packages/vitnode/src/api/lib/staff-permission.test.ts create mode 100644 packages/vitnode/src/api/moderation.ts create mode 100644 packages/vitnode/src/api/modules/admin/staff/lib/scoped-grants.ts create mode 100644 packages/vitnode/src/api/modules/admin/staff/routes/scope-resources.route.ts create mode 100644 packages/vitnode/src/api/modules/admin/staff/routes/scoped-permissions.test.ts create mode 100644 packages/vitnode/src/api/modules/moderation/lib/candidates.ts create mode 100644 packages/vitnode/src/api/modules/moderation/lib/notes.ts create mode 100644 packages/vitnode/src/api/modules/moderation/lib/people.ts create mode 100644 packages/vitnode/src/api/modules/moderation/lib/reports.ts create mode 100644 packages/vitnode/src/api/modules/moderation/lib/schema.ts create mode 100644 packages/vitnode/src/api/modules/moderation/moderation.module.ts create mode 100644 packages/vitnode/src/api/modules/moderation/reports.test.ts create mode 100644 packages/vitnode/src/api/modules/moderation/routes/create.route.ts create mode 100644 packages/vitnode/src/api/modules/moderation/routes/list.route.ts create mode 100644 packages/vitnode/src/api/modules/moderation/routes/notes.routes.ts create mode 100644 packages/vitnode/src/api/modules/moderation/routes/show.route.ts create mode 100644 packages/vitnode/src/api/modules/moderation/routes/workflow.routes.ts create mode 100644 packages/vitnode/src/components/side-nav.tsx create mode 100644 packages/vitnode/src/content/define-reports.test.ts create mode 100644 packages/vitnode/src/content/define-reports.ts create mode 100644 packages/vitnode/src/content/server/hidden-access.test.ts create mode 100644 packages/vitnode/src/content/server/report-target.ts create mode 100644 packages/vitnode/src/database/moderation.ts create mode 100644 packages/vitnode/src/editor/dnd/drop-slot.ts create mode 100644 packages/vitnode/src/editor/zones/block-body.tsx create mode 100644 packages/vitnode/src/editor/zones/drop-slot.tsx create mode 100644 packages/vitnode/src/lib/dnd/drag-lift.tsx create mode 100644 packages/vitnode/src/lib/dnd/layout-flip.ts create mode 100644 packages/vitnode/src/lib/dnd/use-stable-ids.ts create mode 100644 packages/vitnode/src/lib/moderation/const.ts create mode 100644 packages/vitnode/src/lib/moderation/snapshot.ts create mode 100644 packages/vitnode/src/pages/modcp/index.tsx create mode 100644 packages/vitnode/src/pages/modcp/layout.tsx create mode 100644 packages/vitnode/src/pages/modcp/report.tsx create mode 100644 packages/vitnode/src/pages/modcp/reports.tsx create mode 100644 packages/vitnode/src/tanstack/moderation/breadcrumb.tsx create mode 100644 packages/vitnode/src/tanstack/moderation/index.ts create mode 100644 packages/vitnode/src/tanstack/moderation/layout.tsx create mode 100644 packages/vitnode/src/tanstack/moderation/namespaces.ts create mode 100644 packages/vitnode/src/tanstack/moderation/report-button.tsx create mode 100644 packages/vitnode/src/tanstack/moderation/report-screen.tsx create mode 100644 packages/vitnode/src/tanstack/moderation/reports-screen.tsx create mode 100644 packages/vitnode/src/tanstack/moderation/route-search.ts create mode 100644 packages/vitnode/src/tanstack/moderation/route.ts create mode 100644 packages/vitnode/src/views/admin/views/core/staff/edit/scope/scope-dialog.tsx create mode 100644 packages/vitnode/src/views/admin/views/core/staff/edit/scope/scope-query.ts create mode 100644 packages/vitnode/src/views/moderation/modcp/board/board-card.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/board/board-moves.ts create mode 100644 packages/vitnode/src/views/moderation/modcp/board/reports-board.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/modcp-nav.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/modcp-query.ts create mode 100644 packages/vitnode/src/views/moderation/modcp/plugin-messages.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/report-activity.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/report-content.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/report-forms.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/report-sidebar.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/report-snapshot-peek.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/report-tone.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/reports-content.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/snapshot-view.tsx create mode 100644 packages/vitnode/src/views/moderation/modcp/status-badge.tsx create mode 100644 packages/vitnode/src/views/moderation/moderation-mutations.ts create mode 100644 packages/vitnode/src/views/moderation/report/report-dialog-content.tsx create mode 100644 plugins/example/src/api/lib/moderation.ts diff --git a/apps/api/migrations/20261011193321_add_moderation_reports/migration.sql b/apps/api/migrations/20261011193321_add_moderation_reports/migration.sql new file mode 100644 index 0000000000..25f5e9d796 --- /dev/null +++ b/apps/api/migrations/20261011193321_add_moderation_reports/migration.sql @@ -0,0 +1,46 @@ +CREATE TABLE "core_moderation_report_events" ( + "id" serial PRIMARY KEY, + "reportId" integer NOT NULL, + "type" varchar(32) NOT NULL, + "actorId" integer, + "data" jsonb DEFAULT '{}' NOT NULL, + "createdAt" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "core_moderation_report_events" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +CREATE TABLE "core_moderation_reports" ( + "id" serial PRIMARY KEY, + "pluginId" varchar(100) NOT NULL, + "targetType" varchar(100) NOT NULL, + "targetId" varchar(64) NOT NULL, + "reporterId" integer, + "reason" varchar(32) NOT NULL, + "description" text, + "snapshot" jsonb NOT NULL, + "targetTitle" varchar(500), + "status" varchar(20) DEFAULT 'new' NOT NULL, + "assigneeId" integer, + "resolution" varchar(32), + "resolutionNote" text, + "resolvedAt" timestamp, + "resolvedById" integer, + "scopeFamily" varchar(100), + "scopeId" varchar(64), + "openKey" varchar(255) UNIQUE, + "version" integer DEFAULT 1 NOT NULL, + "createdAt" timestamp DEFAULT now() NOT NULL, + "updatedAt" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "core_moderation_reports" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint +CREATE INDEX "core_moderation_report_events_report_idx" ON "core_moderation_report_events" ("reportId","id");--> statement-breakpoint +CREATE INDEX "core_moderation_reports_target_idx" ON "core_moderation_reports" ("pluginId","targetType","targetId");--> statement-breakpoint +CREATE INDEX "core_moderation_reports_status_idx" ON "core_moderation_reports" ("status","createdAt");--> statement-breakpoint +CREATE INDEX "core_moderation_reports_assignee_idx" ON "core_moderation_reports" ("assigneeId");--> statement-breakpoint +CREATE INDEX "core_moderation_reports_reporter_idx" ON "core_moderation_reports" ("reporterId","createdAt");--> statement-breakpoint +CREATE INDEX "core_moderation_reports_scope_idx" ON "core_moderation_reports" ("scopeFamily","scopeId");--> statement-breakpoint +ALTER TABLE "core_moderation_report_events" ADD CONSTRAINT "core_moderation_report_events_4CqHOxfheaUm_fkey" FOREIGN KEY ("reportId") REFERENCES "core_moderation_reports"("id") ON DELETE CASCADE;--> statement-breakpoint +ALTER TABLE "core_moderation_report_events" ADD CONSTRAINT "core_moderation_report_events_actorId_core_users_id_fkey" FOREIGN KEY ("actorId") REFERENCES "core_users"("id") ON DELETE SET NULL;--> statement-breakpoint +ALTER TABLE "core_moderation_reports" ADD CONSTRAINT "core_moderation_reports_reporterId_core_users_id_fkey" FOREIGN KEY ("reporterId") REFERENCES "core_users"("id") ON DELETE SET NULL;--> statement-breakpoint +ALTER TABLE "core_moderation_reports" ADD CONSTRAINT "core_moderation_reports_assigneeId_core_users_id_fkey" FOREIGN KEY ("assigneeId") REFERENCES "core_users"("id") ON DELETE SET NULL;--> statement-breakpoint +ALTER TABLE "core_moderation_reports" ADD CONSTRAINT "core_moderation_reports_resolvedById_core_users_id_fkey" FOREIGN KEY ("resolvedById") REFERENCES "core_users"("id") ON DELETE SET NULL; \ No newline at end of file diff --git a/apps/api/migrations/20261011193321_add_moderation_reports/snapshot.json b/apps/api/migrations/20261011193321_add_moderation_reports/snapshot.json new file mode 100644 index 0000000000..060b6fcab9 --- /dev/null +++ b/apps/api/migrations/20261011193321_add_moderation_reports/snapshot.json @@ -0,0 +1,17707 @@ +{ + "version": "8", + "dialect": "postgres", + "id": "3ad3093b-71a8-4478-b2ce-1bbcaa1ff602", + "prevIds": [ + "27a31513-4f49-4cab-aa26-2538019a87d9" + ], + "ddl": [ + { + "isRlsEnabled": true, + "name": "core_admin_permissions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_admin_sessions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_action_settings", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_budget_periods", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_calls", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_cost_adjustments", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_reservations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_role_permissions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_role_policies", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_runs", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_settings", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_translation_sources", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_ai_user_overrides", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_documents", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_drafts", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_field_locks", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_file_refs", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_revisions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_schedules", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_content_slug_history", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_cron", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_admin_dashboard", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_files", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_files_alt", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_files_alt_analysis", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_files_alt_state", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_languages", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_languages_words", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_logs", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_moderation_report_events", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_moderation_reports", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_moderators_permissions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_navigation", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_notification_deliveries", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_notification_events", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_notification_receipts", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_notification_settings", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_notification_user_state", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_notifications", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_page_layouts", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_passkey_challenges", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_passkeys", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_queue", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_roles", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_search_index", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_secrets", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_sessions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_sessions_known_devices", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_confirm_emails", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_forgot_password", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_secondary_roles", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_sso", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_sso_operations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "core_users_sso_profile_sources", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "blog_categories", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "blog_categories_translations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "blog_posts", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "blog_posts_author_id", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "blog_posts_category_id", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "blog_posts_translations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_advanced_articles", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_advanced_articles_categories", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_advanced_articles_faq", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_advanced_articles_related_articles", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_advanced_articles_tags", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_advanced_articles_translations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_articles", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_articles_gallery", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_categories", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_events", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_events_gallery", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_events_related_events", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_events_sessions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_events_tags", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_events_translations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_localized_articles", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_localized_articles_translations", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_pages", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_tags", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_tags_related_tags", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": true, + "name": "example_tags_translations", + "entityType": "tables", + "schema": "public" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roleId", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "protected", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "unrestricted", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "permissions", + "entityType": "columns", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "lastSeen", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deviceId", + "entityType": "columns", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actionKey", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "enabled", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "modelId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fallbackModelId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "maxInputCharacters", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "maxOutputTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "timeoutMs", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "maxRetries", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "maxSteps", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "dailyLimit", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "instructions", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_action_settings" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scopeKey", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "unit", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "periodStart", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "periodEnd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "limitAmount", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'0'", + "generated": null, + "identity": null, + "name": "spentAmount", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'0'", + "generated": null, + "identity": null, + "name": "reservedAmount", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "unknownCount", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "runId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "attempt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "modelId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerModelId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerRequestId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "errorCode", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "inputTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "outputTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cacheReadTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cacheWriteTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reasoningTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "images", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "costUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "costSource", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "costReason", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pricingVersion", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pricingSnapshot", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "startedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "finishedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reconciledAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_calls" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "callId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "runId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "previousCostUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "previousSource", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "newCostUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "newSource", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deltaUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reason", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "runId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "budgetPeriodId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "amount", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'active'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "settledAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roleId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_permissions" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "permission", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_permissions" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "granted", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_permissions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "dailyLimit", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_permissions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roleId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_policies" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "monthlyPoints", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_policies" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "unlimited", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_policies" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_role_policies" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actionKey", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actorType", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "idempotencyKey", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resourceType", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resourceId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "errorCode", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "promptVersion", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pointsConversionVersion", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "modelId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerModelId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "inputTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "outputTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cacheReadTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cacheWriteTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reasoningTokens", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "costUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "costSource", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "chargedUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "chargedPoints", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'0'", + "generated": null, + "identity": null, + "name": "reservedUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'0'", + "generated": null, + "identity": null, + "name": "reservedPoints", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'pending'", + "generated": null, + "identity": null, + "name": "settlement", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "leaseExpiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "accepted", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "acceptedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "sourceFingerprint", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "startedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "finishedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "settledAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_runs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "enabled", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "monthlyBudgetUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "systemMonthlyBudgetUsd", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'0'", + "generated": null, + "identity": null, + "name": "defaultMonthlyPoints", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "pointsConversionVersion", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "10", + "generated": null, + "identity": null, + "name": "userRequestsPerMinute", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "2", + "generated": null, + "identity": null, + "name": "userConcurrency", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "2", + "generated": null, + "identity": null, + "name": "systemConcurrency", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "365", + "generated": null, + "identity": null, + "name": "historyRetentionDays", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "altEnabled", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "10", + "generated": null, + "identity": null, + "name": "altBatchSize", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "altScanCursor", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "altScanStartedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_settings" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "locale", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "field", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "sourceLocale", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "sourceFingerprint", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "targetFingerprint", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "origin", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updatedById", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_ai_user_overrides" + }, + { + "type": "numeric(24,12)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "monthlyPoints", + "entityType": "columns", + "schema": "public", + "table": "core_ai_user_overrides" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "unlimited", + "entityType": "columns", + "schema": "public", + "table": "core_ai_user_overrides" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "blocked", + "entityType": "columns", + "schema": "public", + "table": "core_ai_user_overrides" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_ai_user_overrides" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "field", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "varchar(35)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "language", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "bytea", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "baseVersion", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updatedBy", + "entityType": "columns", + "schema": "public", + "table": "core_content_documents" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "language", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "values", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "baseVersion", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updatedBy", + "entityType": "columns", + "schema": "public", + "table": "core_content_drafts" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "field", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "language", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "acquiredAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "revisionId", + "entityType": "columns", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fileId", + "entityType": "columns", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "operation", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "snapshot", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "changedFields", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'system'", + "generated": null, + "identity": null, + "name": "actorType", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actorUserId", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "restoredFromRevisionId", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_revisions" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "action", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scheduledFor", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "generation", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'pending'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "createdBy", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "completedAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastError", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "effectsError", + "entityType": "columns", + "schema": "public", + "table": "core_content_schedules" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contentTypeId", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "varchar(512)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "path", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "retiredAt", + "entityType": "columns", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastRun", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "module", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "nextRun", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "schedule", + "entityType": "columns", + "schema": "public", + "table": "core_cron" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "widgets", + "entityType": "columns", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(512)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "key", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "folder", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "mimeType", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "size", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fingerprint", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'automatic'", + "generated": null, + "identity": null, + "name": "altPolicy", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_files" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fileId", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageCode", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "text", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "origin", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fileFingerprint", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "runId", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updatedById", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fileId", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fileFingerprint", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "runId", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "fileId", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_state" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_state" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastError", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_state" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_files_alt_state" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "code", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'UTC'", + "generated": null, + "identity": null, + "name": "timezone", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "protected", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "default", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "time24", + "entityType": "columns", + "schema": "public", + "table": "core_languages" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "varchar", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageCode", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "varchar(50)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginCode", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "tableName", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "variable", + "entityType": "columns", + "schema": "public", + "table": "core_languages_words" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "varchar(45)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ipAddress", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "varchar(10)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'GET'", + "generated": null, + "identity": null, + "name": "method", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'localhost'", + "generated": null, + "identity": null, + "name": "path", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userAgent", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "500", + "generated": null, + "identity": null, + "name": "statusCode", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_logs" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reportId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actorId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "data", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "targetType", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "targetId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reporterId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reason", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "snapshot", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(500)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "targetTitle", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'new'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "assigneeId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resolution", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resolutionNote", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resolvedAt", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resolvedById", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scopeFamily", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scopeId", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "openKey", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roleId", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "protected", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "unrestricted", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "permissions", + "entityType": "columns", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "parentId", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'header'", + "generated": null, + "identity": null, + "name": "location", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "varchar(50)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "varchar(120)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "presetId", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "href", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "icon", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "isOpenInNewTab", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_navigation" + }, + { + "type": "bigserial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "channel", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "mode", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "eventId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "idempotencyKey", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'pending'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "attempts", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "5", + "generated": null, + "identity": null, + "name": "maxAttempts", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "availableAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "periodStart", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "periodEnd", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "itemCount", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerMessageId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(500)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastError", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "varchar(50)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "skipReason", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "sentAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "type": "bigserial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "schemaVersion", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "idempotencyKey", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actorId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "subjectType", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "subjectId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "groupKey", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "data", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "recipientIds", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "allowSelf", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'pending'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "recipientCursor", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "deliveredCount", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastError", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "completedAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_events" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "eventId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "notificationId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "seq", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "emailPending", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "emailDeliveryId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "key", + "entityType": "columns", + "schema": "public", + "table": "core_notification_settings" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "value", + "entityType": "columns", + "schema": "public", + "table": "core_notification_settings" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_settings" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "unreadCount", + "entityType": "columns", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "revision", + "entityType": "columns", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "preferences", + "entityType": "columns", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "type": "bigserial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(50)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "category", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "groupKey", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "groupBucket", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "subjectType", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "subjectId", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "latestEventId", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "eventCount", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "activitySeq", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "readSeq", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "readAt", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "archivedAt", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "lastActivityAt", + "entityType": "columns", + "schema": "public", + "table": "core_notifications" + }, + { + "type": "varchar(120)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pageId", + "entityType": "columns", + "schema": "public", + "table": "core_page_layouts" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "zones", + "entityType": "columns", + "schema": "public", + "table": "core_page_layouts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_page_layouts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_page_layouts" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "tokenHash", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ceremony", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "varchar(128)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "challenge", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "varchar(128)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "webauthnUserId", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "varchar(1024)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "credentialId", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publicKey", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "counter", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "varchar(128)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "webauthnUserId", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "transports", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deviceType", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "backedUp", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "varchar(36)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "aaguid", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastUsedAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'default'", + "generated": null, + "identity": null, + "name": "queue", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "varchar(20)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'pending'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "payload", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "priority", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "attempts", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "3", + "generated": null, + "identity": null, + "name": "maxAttempts", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "availableAt", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reservedAt", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastError", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "completedAt", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "dedupeKey", + "entityType": "columns", + "schema": "public", + "table": "core_queue" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "protected", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "default", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "root", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "guest", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "varchar(50)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "color", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "prefix", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "allowUploadFiles", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "totalMaxStorage", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "maxStorageForSubmit", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "allowUploadAvatar", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "2048", + "generated": null, + "identity": null, + "name": "maxAvatarSize", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "allowUploadCover", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "5120", + "generated": null, + "identity": null, + "name": "maxCoverSize", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "allowEditPersonalInfo", + "entityType": "columns", + "schema": "public", + "table": "core_roles" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "pluginId", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemType", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "languageCode", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "authorIds", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "tsvector", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": { + "as": "setweight(to_tsvector(CASE lower(split_part(\"core_search_index\".\"languageCode\", '-', 1)) WHEN 'da' THEN 'danish'::regconfig WHEN 'de' THEN 'german'::regconfig WHEN 'en' THEN 'english'::regconfig WHEN 'es' THEN 'spanish'::regconfig WHEN 'fi' THEN 'finnish'::regconfig WHEN 'fr' THEN 'french'::regconfig WHEN 'hu' THEN 'hungarian'::regconfig WHEN 'it' THEN 'italian'::regconfig WHEN 'nl' THEN 'dutch'::regconfig WHEN 'no' THEN 'norwegian'::regconfig WHEN 'pl' THEN 'polish'::regconfig WHEN 'pt' THEN 'portuguese'::regconfig WHEN 'ro' THEN 'romanian'::regconfig WHEN 'ru' THEN 'russian'::regconfig WHEN 'sv' THEN 'swedish'::regconfig WHEN 'tr' THEN 'turkish'::regconfig ELSE 'simple'::regconfig END, coalesce(\"core_search_index\".\"title\", '')), 'A') || setweight(to_tsvector(CASE lower(split_part(\"core_search_index\".\"languageCode\", '-', 1)) WHEN 'da' THEN 'danish'::regconfig WHEN 'de' THEN 'german'::regconfig WHEN 'en' THEN 'english'::regconfig WHEN 'es' THEN 'spanish'::regconfig WHEN 'fi' THEN 'finnish'::regconfig WHEN 'fr' THEN 'french'::regconfig WHEN 'hu' THEN 'hungarian'::regconfig WHEN 'it' THEN 'italian'::regconfig WHEN 'nl' THEN 'dutch'::regconfig WHEN 'no' THEN 'norwegian'::regconfig WHEN 'pl' THEN 'polish'::regconfig WHEN 'pt' THEN 'portuguese'::regconfig WHEN 'ro' THEN 'romanian'::regconfig WHEN 'ru' THEN 'russian'::regconfig WHEN 'sv' THEN 'swedish'::regconfig WHEN 'tr' THEN 'turkish'::regconfig ELSE 'simple'::regconfig END, coalesce(\"core_search_index\".\"content\", '')), 'B')", + "type": "stored" + }, + "identity": null, + "name": "search_vector", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "containerType", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "containerId", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "url", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "isPublic", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "isHidden", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "imageId", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "indexedAt", + "entityType": "columns", + "schema": "public", + "table": "core_search_index" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_secrets" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value", + "entityType": "columns", + "schema": "public", + "table": "core_secrets" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_secrets" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_sessions" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "core_sessions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_sessions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deviceId", + "entityType": "columns", + "schema": "public", + "table": "core_sessions" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_sessions_known_devices" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publicId", + "entityType": "columns", + "schema": "public", + "table": "core_sessions_known_devices" + }, + { + "type": "varchar(40)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ipAddress", + "entityType": "columns", + "schema": "public", + "table": "core_sessions_known_devices" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userAgent", + "entityType": "columns", + "schema": "public", + "table": "core_sessions_known_devices" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "lastSeen", + "entityType": "columns", + "schema": "public", + "table": "core_sessions_known_devices" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "nameCode", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(128)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "firstName", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(128)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lastName", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "phone", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "headline", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "showRealName", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "password", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "newsletter", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(6)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatarColor", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "emailVerified", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roleId", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "birthday", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "timeZone", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(40)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ipAddress", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'en'", + "generated": null, + "identity": null, + "name": "language", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatarId", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "coverId", + "entityType": "columns", + "schema": "public", + "table": "core_users" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "type": "varchar(40)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ipAddress", + "entityType": "columns", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "type": "varchar(40)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ipAddress", + "entityType": "columns", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roleId", + "entityType": "columns", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerAccountId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerEmail", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerUsername", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "syncOnSignIn", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "varchar(2048)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatarSourceUrl", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatarSha256", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatarFileId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "varchar(64)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "tokenHash", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "varchar(16)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "intent", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "fields", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerAccountId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "preview", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expiresAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "userId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "field", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "providerId", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "blog_categories" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "blog_categories" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "blog_categories" + }, + { + "type": "varchar(50)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "color", + "entityType": "columns", + "schema": "public", + "table": "blog_categories" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "hiddenAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "hiddenBy", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "coverImage", + "entityType": "columns", + "schema": "public", + "table": "blog_posts" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "friendlyUrl", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "excerpt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "varchar(255)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "coverImageAlt", + "entityType": "columns", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "syndicationIndexable", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "syndicationNoIndex", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "5", + "generated": null, + "identity": null, + "name": "syndicationPriority", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "question", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "answer", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "seoTitle", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "seoDescription", + "entityType": "columns", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "code", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "excerpt", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "views", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "featured", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "noIndex", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "author", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "animation", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "category", + "entityType": "columns", + "schema": "public", + "table": "example_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_categories" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_categories" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_categories" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "example_categories" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": { + "type": "byDefault", + "name": "example_events_id_seq", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "9223372036854775807", + "cache": 1, + "cycle": false + }, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "hiddenAt", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "hiddenBy", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "primaryTag", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "category", + "entityType": "columns", + "schema": "public", + "table": "example_events" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_gallery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_gallery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_events_gallery" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_gallery" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_related_events" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_related_events" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_events_related_events" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_related_events" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "startsAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_sessions" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_tags" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_events_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_tags" + }, + { + "type": "bigint", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "body", + "entityType": "columns", + "schema": "public", + "table": "example_events_translations" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "featured", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "body", + "entityType": "columns", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "type": "serial", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "varchar(200)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "example_pages" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "gen_random_uuid()", + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "hiddenAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "hiddenBy", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "category", + "entityType": "columns", + "schema": "public", + "table": "example_tags" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "relatedItemId", + "entityType": "columns", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "type": "uuid", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "itemId", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "languageId", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "createdAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updatedAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "timestamp", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "publishedAt", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "varchar(32)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "varchar(100)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "type": "varchar(160)", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "example_tags_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "roleId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_admin_permissions_role_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_admin_permissions_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_admin_permissions_updated_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_admin_sessions_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "deviceId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_admin_sessions_device_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "scopeKey", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "periodStart", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_budget_periods_scope_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_budget_periods" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "runId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_calls_run_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_calls" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "costSource", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "reconciledAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_calls_reconcile_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_calls" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "callId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_cost_adjustments_call_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "runId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "budgetPeriodId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_reservations_run_period_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_reservations_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_runs_user_created_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_runs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_runs_created_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_runs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "actionKey", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_runs_action_created_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_runs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "leaseExpiresAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_runs_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_runs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "actorType", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "idempotencyKey", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"idempotencyKey\" IS NOT NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_runs_idempotency_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_runs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "locale", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "field", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_ai_translation_sources_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "field", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "language", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_documents_doc_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_documents" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_documents_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_documents" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedBy", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_documents_updated_by_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_documents" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "language", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_drafts_key_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_drafts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_drafts_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_drafts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedBy", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_drafts_updated_by_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_drafts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "field", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "language", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_field_locks_key_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "expiresAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_field_locks_expires_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_field_locks_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "revisionId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "fileId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_file_refs_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "fileId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_file_refs_file_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "version", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"languageId\" IS NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_revisions_item_version_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_revisions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "version", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"languageId\" IS NOT NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_revisions_translation_version_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_revisions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "version", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_revisions_language_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_revisions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_revisions_plugin_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_revisions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "actorUserId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_revisions_actor_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_revisions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "action", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "status = 'pending'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_schedules_active_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_schedules" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "scheduledFor", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_schedules_due_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_schedules" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_schedules_item_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_schedules" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_schedules_plugin_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_schedules" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdBy", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_schedules_created_by_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_schedules" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"languageId\" IS NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_slug_history_shared_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"languageId\" IS NOT NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_slug_history_locale_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contentTypeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_slug_history_item_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_content_slug_history_plugin_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_content_slug_history" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "lastRun", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_cron_last_run_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_cron" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_admin_dashboard_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_files_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_files" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_files_created_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_files" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "fileId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "languageCode", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_files_alt_file_language_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_files_alt" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "fileId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "fileFingerprint", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_files_alt_analysis_file_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": "status <> 'completed'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_files_alt_state_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_files_alt_state" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "name", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_languages_name_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_languages" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageCode", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_languages_words_lang_code_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_languages_words" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "tableName", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "pluginCode", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "variable", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_languages_words_lookup_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_languages_words" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_logs_created_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_logs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_logs_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_logs" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "reportId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderation_report_events_report_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "targetType", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "targetId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderation_reports_target_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderation_reports_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "assigneeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderation_reports_assignee_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "reporterId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderation_reports_reporter_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "scopeFamily", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "scopeId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderation_reports_scope_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "roleId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderators_permissions_role_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderators_permissions_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_moderators_permissions_updated_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_navigation_position_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_navigation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "location", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_navigation_location_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_navigation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "parentId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_navigation_parent_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_navigation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "availableAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": "status = 'pending'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_deliveries_claim_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_deliveries_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_deliveries_user_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "type", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "idempotencyKey", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_events_idempotency_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_events_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_events_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "notificationId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "seq", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_receipts_notification_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_receipts_user_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": "\"emailPending\" = true AND \"emailDeliveryId\" IS NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_receipts_email_pending_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "unreadCount", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notification_user_state_unread_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "type", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "groupKey", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "groupBucket", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notifications_group_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "lastActivityAt", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": "\"archivedAt\" IS NULL", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notifications_inbox_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "lastActivityAt", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": "\"archivedAt\" IS NULL AND \"readSeq\" < \"activitySeq\"", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notifications_unread_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "subjectType", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "subjectId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notifications_subject_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "lastActivityAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notifications_last_activity_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "latestEventId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_notifications_latest_event_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "expiresAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_passkey_challenges_expires_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_passkey_challenges_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_passkeys_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "webauthnUserId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_passkeys_webauthn_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "availableAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_queue_status_available_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_queue" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_queue_created_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_queue" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "pluginId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "dedupeKey", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"dedupeKey\" IS NOT NULL AND status IN ('pending', 'processing')", + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_queue_dedupe_active_unique", + "entityType": "indexes", + "schema": "public", + "table": "core_queue" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_roles_updated_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_roles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "search_vector", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "gin", + "concurrently": false, + "name": "core_search_index_search_vector_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_search_index_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "authorIds", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "gin", + "concurrently": false, + "name": "core_search_index_author_ids_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemType", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_search_index_item_type_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageCode", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_search_index_language_code_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "isPublic", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_search_index_is_public_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "imageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_search_index_image_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_sessions_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_sessions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "deviceId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_sessions_device_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_sessions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "ipAddress", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_sessions_known_devices_ip_address_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_sessions_known_devices" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "avatarId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_avatar_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "coverId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_cover_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_created_at_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "roleId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_secondary_roles_role_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_sso_user_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_sso" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "userId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "providerId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_sso_operations_user_provider_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "expiresAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "core_users_sso_operations_expires_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_categories_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_categories" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_categories_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_categories" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_categories_translations_language_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_status_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "coverImage", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_cover_image_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "hiddenBy", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_hidden_by_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_author_id_position_key", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_author_id_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_category_id_position_key", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_category_id_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_translations_language_id_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "friendlyUrl", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "blog_posts_translations_language_id_friendly_url_key", + "entityType": "indexes", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "syndicationPriority", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_syndication_priority_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_categories_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_categories_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_faq_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_related_articles_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_related_articles_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_tags_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_tags_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_translations_language_id_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_advanced_articles_translations_language_id_slug_key", + "entityType": "indexes", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_status_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_slug_key", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "code", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_code_key", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "author", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_author_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "animation", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_animation_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "category", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_category_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_gallery_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_articles_gallery_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_categories_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_categories" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_categories_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_categories" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "primaryTag", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_primary_tag_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "category", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_category_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "hiddenBy", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_hidden_by_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_gallery_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_events_gallery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_gallery_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events_gallery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_related_events_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_events_related_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_related_events_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events_related_events" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_sessions_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_events_sessions" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_tags_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_events_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_tags_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_translations_language_id_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_events_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_events_translations_language_id_slug_key", + "entityType": "indexes", + "schema": "public", + "table": "example_events_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_localized_articles_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_localized_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_localized_articles_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_localized_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_localized_articles_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_localized_articles" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_localized_articles_translations_language_id_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_localized_articles_translations_language_id_slug_key", + "entityType": "indexes", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_pages_slug_key", + "entityType": "indexes", + "schema": "public", + "table": "example_pages" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_pages_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_pages" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_pages_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_pages" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_pages_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_pages" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "category", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_category_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "createdAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_created_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "updatedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_updated_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "publishedAt", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_status_published_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "hiddenBy", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_hidden_by_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "itemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_related_tags_position_key", + "entityType": "indexes", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "relatedItemId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_related_tags_related_item_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_translations_language_id_status_idx", + "entityType": "indexes", + "schema": "public", + "table": "example_tags_translations" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "languageId", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "example_tags_translations_language_id_slug_key", + "entityType": "indexes", + "schema": "public", + "table": "example_tags_translations" + }, + { + "nameExplicit": false, + "columns": [ + "roleId" + ], + "schemaTo": "public", + "tableTo": "core_roles", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_admin_permissions_roleId_core_roles_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_admin_permissions_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_admin_permissions" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_admin_sessions_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "nameExplicit": false, + "columns": [ + "deviceId" + ], + "schemaTo": "public", + "tableTo": "core_sessions_known_devices", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_admin_sessions_deviceId_core_sessions_known_devices_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_admin_sessions" + }, + { + "nameExplicit": false, + "columns": [ + "runId" + ], + "schemaTo": "public", + "tableTo": "core_ai_runs", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_calls_runId_core_ai_runs_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_calls" + }, + { + "nameExplicit": false, + "columns": [ + "callId" + ], + "schemaTo": "public", + "tableTo": "core_ai_calls", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_cost_adjustments_callId_core_ai_calls_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "nameExplicit": false, + "columns": [ + "runId" + ], + "schemaTo": "public", + "tableTo": "core_ai_runs", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_cost_adjustments_runId_core_ai_runs_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_cost_adjustments" + }, + { + "nameExplicit": false, + "columns": [ + "runId" + ], + "schemaTo": "public", + "tableTo": "core_ai_runs", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_reservations_runId_core_ai_runs_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "nameExplicit": false, + "columns": [ + "budgetPeriodId" + ], + "schemaTo": "public", + "tableTo": "core_ai_budget_periods", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_reservations_FClYpPXZwvsm_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_reservations" + }, + { + "nameExplicit": false, + "columns": [ + "roleId" + ], + "schemaTo": "public", + "tableTo": "core_roles", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_role_permissions_roleId_core_roles_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_role_permissions" + }, + { + "nameExplicit": false, + "columns": [ + "roleId" + ], + "schemaTo": "public", + "tableTo": "core_roles", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_role_policies_roleId_core_roles_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_role_policies" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_ai_runs_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_runs" + }, + { + "nameExplicit": false, + "columns": [ + "updatedById" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_ai_translation_sources_updatedById_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_translation_sources" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_ai_user_overrides_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_ai_user_overrides" + }, + { + "nameExplicit": false, + "columns": [ + "updatedBy" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "core_content_documents_updatedBy_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_content_documents" + }, + { + "nameExplicit": false, + "columns": [ + "updatedBy" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "core_content_drafts_updatedBy_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_content_drafts" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "core_content_field_locks_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_content_field_locks" + }, + { + "nameExplicit": false, + "columns": [ + "revisionId" + ], + "schemaTo": "public", + "tableTo": "core_content_revisions", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "core_content_file_refs_5get6SfhBPHr_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "nameExplicit": false, + "columns": [ + "fileId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "core_content_file_refs_fileId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_content_file_refs" + }, + { + "nameExplicit": false, + "columns": [ + "actorUserId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "core_content_revisions_actorUserId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_content_revisions" + }, + { + "nameExplicit": false, + "columns": [ + "createdBy" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "core_content_schedules_createdBy_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_content_schedules" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_admin_dashboard_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_admin_dashboard" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_files_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_files" + }, + { + "nameExplicit": false, + "columns": [ + "fileId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_files_alt_fileId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt" + }, + { + "nameExplicit": false, + "columns": [ + "languageCode" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "code" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_files_alt_languageCode_core_languages_code_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt" + }, + { + "nameExplicit": false, + "columns": [ + "runId" + ], + "schemaTo": "public", + "tableTo": "core_ai_runs", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_files_alt_runId_core_ai_runs_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt" + }, + { + "nameExplicit": false, + "columns": [ + "updatedById" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_files_alt_updatedById_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt" + }, + { + "nameExplicit": false, + "columns": [ + "fileId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_files_alt_analysis_fileId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "nameExplicit": false, + "columns": [ + "runId" + ], + "schemaTo": "public", + "tableTo": "core_ai_runs", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_files_alt_analysis_runId_core_ai_runs_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt_analysis" + }, + { + "nameExplicit": false, + "columns": [ + "fileId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_files_alt_state_fileId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_files_alt_state" + }, + { + "nameExplicit": false, + "columns": [ + "languageCode" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "code" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_languages_words_languageCode_core_languages_code_fk", + "entityType": "fks", + "schema": "public", + "table": "core_languages_words" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "core_logs_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_logs" + }, + { + "nameExplicit": false, + "columns": [ + "reportId" + ], + "schemaTo": "public", + "tableTo": "core_moderation_reports", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_moderation_report_events_4CqHOxfheaUm_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "nameExplicit": false, + "columns": [ + "actorId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_moderation_report_events_actorId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_moderation_report_events" + }, + { + "nameExplicit": false, + "columns": [ + "reporterId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_moderation_reports_reporterId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": false, + "columns": [ + "assigneeId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_moderation_reports_assigneeId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": false, + "columns": [ + "resolvedById" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_moderation_reports_resolvedById_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_moderation_reports" + }, + { + "nameExplicit": false, + "columns": [ + "roleId" + ], + "schemaTo": "public", + "tableTo": "core_roles", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_moderators_permissions_roleId_core_roles_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_moderators_permissions_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_moderators_permissions" + }, + { + "nameExplicit": false, + "columns": [ + "parentId" + ], + "schemaTo": "public", + "tableTo": "core_navigation", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_navigation_parentId_core_navigation_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_navigation" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_notification_deliveries_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "nameExplicit": false, + "columns": [ + "eventId" + ], + "schemaTo": "public", + "tableTo": "core_notification_events", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_notification_deliveries_vcf37BytIa0M_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_deliveries" + }, + { + "nameExplicit": false, + "columns": [ + "actorId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_notification_events_actorId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_events" + }, + { + "nameExplicit": false, + "columns": [ + "eventId" + ], + "schemaTo": "public", + "tableTo": "core_notification_events", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_notification_receipts_UQ7ZEs0I6ijx_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_notification_receipts_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "nameExplicit": false, + "columns": [ + "notificationId" + ], + "schemaTo": "public", + "tableTo": "core_notifications", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_notification_receipts_Vxye2Cs6MgcL_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_notification_user_state_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notification_user_state" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_notifications_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": false, + "columns": [ + "latestEventId" + ], + "schemaTo": "public", + "tableTo": "core_notification_events", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "RESTRICT", + "name": "core_notifications_I8QoGbTal5Wt_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_notifications" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_passkey_challenges_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users_passkey_challenges" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_passkeys_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users_passkeys" + }, + { + "nameExplicit": false, + "columns": [ + "imageId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_search_index_imageId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_sessions_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_sessions" + }, + { + "nameExplicit": false, + "columns": [ + "deviceId" + ], + "schemaTo": "public", + "tableTo": "core_sessions_known_devices", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_sessions_deviceId_core_sessions_known_devices_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_sessions" + }, + { + "nameExplicit": false, + "columns": [ + "roleId" + ], + "schemaTo": "public", + "tableTo": "core_roles", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "NO ACTION", + "name": "core_users_roleId_core_roles_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": false, + "columns": [ + "language" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "code" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET DEFAULT", + "name": "core_users_language_core_languages_code_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": false, + "columns": [ + "avatarId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_users_avatarId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": false, + "columns": [ + "coverId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_users_coverId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_confirm_emails_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users_confirm_emails" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_forgot_password_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users_forgot_password" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_secondary_roles_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "nameExplicit": false, + "columns": [ + "roleId" + ], + "schemaTo": "public", + "tableTo": "core_roles", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_secondary_roles_roleId_core_roles_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_sso_userId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "core_users_sso" + }, + { + "nameExplicit": false, + "columns": [ + "avatarFileId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "core_users_sso_avatarFileId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users_sso" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_sso_operations_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_sso_profile_sources_userId_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "nameExplicit": true, + "columns": [ + "userId", + "providerId" + ], + "schemaTo": "public", + "tableTo": "core_users_sso", + "columnsTo": [ + "userId", + "providerId" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "core_users_sso_profile_sources_connection_fkey", + "entityType": "fks", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "blog_categories", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "blog_categories_translations_itemId_blog_categories_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "nameExplicit": false, + "columns": [ + "languageId" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "blog_categories_translations_languageId_core_languages_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "nameExplicit": false, + "columns": [ + "hiddenBy" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "blog_posts_hiddenBy_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": false, + "columns": [ + "coverImage" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "blog_posts_coverImage_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "blog_posts" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "blog_posts", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "blog_posts_author_id_itemId_blog_posts_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "blog_posts_author_id_relatedItemId_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "blog_posts", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "blog_posts_category_id_itemId_blog_posts_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "blog_categories", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "blog_posts_category_id_relatedItemId_blog_categories_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "blog_posts", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "blog_posts_translations_itemId_blog_posts_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "nameExplicit": false, + "columns": [ + "languageId" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "blog_posts_translations_languageId_core_languages_id_fk", + "entityType": "fks", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_advanced_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_advanced_articles_categories_itemId_example_advanced_ar", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "example_categories", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_advanced_articles_categories_relatedItemId_example_cate", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_advanced_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_advanced_articles_faq_itemId_example_advanced_articles_", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_faq" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_advanced_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_advanced_articles_related_articles_itemId_example_advan", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "example_advanced_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_advanced_articles_related_articles_relatedItemId_exampl", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_advanced_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_advanced_articles_tags_ATchHLRtvoCM_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "example_tags", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_advanced_articles_tags_dEsWdkDmu7nW_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_advanced_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_advanced_articles_translations_itemId_example_advanced_", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "nameExplicit": false, + "columns": [ + "languageId" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_advanced_articles_translations_languageId_core_language", + "entityType": "fks", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "nameExplicit": false, + "columns": [ + "author" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "example_articles_author_core_users_id_fk", + "entityType": "fks", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": false, + "columns": [ + "animation" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_articles_animation_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": false, + "columns": [ + "category" + ], + "schemaTo": "public", + "tableTo": "example_categories", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_articles_category_example_categories_id_fk", + "entityType": "fks", + "schema": "public", + "table": "example_articles" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_articles_gallery_itemId_example_articles_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_articles_gallery_relatedItemId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "nameExplicit": false, + "columns": [ + "hiddenBy" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "example_events_hiddenBy_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": false, + "columns": [ + "primaryTag" + ], + "schemaTo": "public", + "tableTo": "example_tags", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "example_events_primaryTag_example_tags_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": false, + "columns": [ + "category" + ], + "schemaTo": "public", + "tableTo": "example_categories", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "example_events_category_example_categories_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_events", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_events_gallery_itemId_example_events_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_gallery" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "core_files", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_events_gallery_relatedItemId_core_files_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_gallery" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_events", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_events_related_events_itemId_example_events_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_related_events" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "example_events", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_events_related_events_oaRvqnKyAS7L_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_related_events" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_events", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_events_sessions_itemId_example_events_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_sessions" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_events", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_events_tags_itemId_example_events_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_tags" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "example_tags", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_events_tags_relatedItemId_example_tags_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_tags" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_events", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_events_translations_itemId_example_events_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_translations" + }, + { + "nameExplicit": false, + "columns": [ + "languageId" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_events_translations_languageId_core_languages_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_events_translations" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_localized_articles", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_localized_articles_translations_itemId_example_localize", + "entityType": "fks", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "nameExplicit": false, + "columns": [ + "languageId" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_localized_articles_translations_languageId_core_languag", + "entityType": "fks", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "nameExplicit": false, + "columns": [ + "hiddenBy" + ], + "schemaTo": "public", + "tableTo": "core_users", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "example_tags_hiddenBy_core_users_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": false, + "columns": [ + "category" + ], + "schemaTo": "public", + "tableTo": "example_categories", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "SET NULL", + "name": "example_tags_category_example_categories_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_tags" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_tags", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_tags_related_tags_itemId_example_tags_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "nameExplicit": false, + "columns": [ + "relatedItemId" + ], + "schemaTo": "public", + "tableTo": "example_tags", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_tags_related_tags_relatedItemId_example_tags_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "nameExplicit": false, + "columns": [ + "itemId" + ], + "schemaTo": "public", + "tableTo": "example_tags", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "CASCADE", + "name": "example_tags_translations_itemId_example_tags_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_tags_translations" + }, + { + "nameExplicit": false, + "columns": [ + "languageId" + ], + "schemaTo": "public", + "tableTo": "core_languages", + "columnsTo": [ + "id" + ], + "onUpdate": "CASCADE", + "onDelete": "RESTRICT", + "name": "example_tags_translations_languageId_core_languages_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "example_tags_translations" + }, + { + "columns": [ + "roleId", + "permission" + ], + "nameExplicit": false, + "name": "core_ai_role_permissions_pkey", + "entityType": "pks", + "schema": "public", + "table": "core_ai_role_permissions" + }, + { + "columns": [ + "eventId", + "userId" + ], + "nameExplicit": false, + "name": "core_notification_receipts_pkey", + "entityType": "pks", + "schema": "public", + "table": "core_notification_receipts" + }, + { + "columns": [ + "userId", + "roleId" + ], + "nameExplicit": false, + "name": "core_users_secondary_roles_userId_roleId_pk", + "entityType": "pks", + "schema": "public", + "table": "core_users_secondary_roles" + }, + { + "columns": [ + "userId", + "field" + ], + "nameExplicit": false, + "name": "core_users_sso_profile_sources_pkey", + "entityType": "pks", + "schema": "public", + "table": "core_users_sso_profile_sources" + }, + { + "columns": [ + "itemId", + "languageId" + ], + "nameExplicit": true, + "name": "blog_categories_translations_item_id_language_id_pk", + "entityType": "pks", + "schema": "public", + "table": "blog_categories_translations" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "blog_posts_author_id_pk", + "entityType": "pks", + "schema": "public", + "table": "blog_posts_author_id" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "blog_posts_category_id_pk", + "entityType": "pks", + "schema": "public", + "table": "blog_posts_category_id" + }, + { + "columns": [ + "itemId", + "languageId" + ], + "nameExplicit": true, + "name": "blog_posts_translations_item_id_language_id_pk", + "entityType": "pks", + "schema": "public", + "table": "blog_posts_translations" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_advanced_articles_categories_pk", + "entityType": "pks", + "schema": "public", + "table": "example_advanced_articles_categories" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_advanced_articles_related_articles_pk", + "entityType": "pks", + "schema": "public", + "table": "example_advanced_articles_related_articles" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_advanced_articles_tags_pk", + "entityType": "pks", + "schema": "public", + "table": "example_advanced_articles_tags" + }, + { + "columns": [ + "itemId", + "languageId" + ], + "nameExplicit": true, + "name": "example_advanced_articles_translations_item_id_language_id_pk", + "entityType": "pks", + "schema": "public", + "table": "example_advanced_articles_translations" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_articles_gallery_pk", + "entityType": "pks", + "schema": "public", + "table": "example_articles_gallery" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_events_gallery_pk", + "entityType": "pks", + "schema": "public", + "table": "example_events_gallery" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_events_related_events_pk", + "entityType": "pks", + "schema": "public", + "table": "example_events_related_events" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_events_tags_pk", + "entityType": "pks", + "schema": "public", + "table": "example_events_tags" + }, + { + "columns": [ + "itemId", + "languageId" + ], + "nameExplicit": true, + "name": "example_events_translations_item_id_language_id_pk", + "entityType": "pks", + "schema": "public", + "table": "example_events_translations" + }, + { + "columns": [ + "itemId", + "languageId" + ], + "nameExplicit": true, + "name": "example_localized_articles_translations_item_id_language_id_pk", + "entityType": "pks", + "schema": "public", + "table": "example_localized_articles_translations" + }, + { + "columns": [ + "itemId", + "relatedItemId" + ], + "nameExplicit": true, + "name": "example_tags_related_tags_pk", + "entityType": "pks", + "schema": "public", + "table": "example_tags_related_tags" + }, + { + "columns": [ + "itemId", + "languageId" + ], + "nameExplicit": true, + "name": "example_tags_translations_item_id_language_id_pk", + "entityType": "pks", + "schema": "public", + "table": "example_tags_translations" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_admin_permissions_pkey", + "schema": "public", + "table": "core_admin_permissions", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_admin_sessions_pkey", + "schema": "public", + "table": "core_admin_sessions", + "entityType": "pks" + }, + { + "columns": [ + "actionKey" + ], + "nameExplicit": false, + "name": "core_ai_action_settings_pkey", + "schema": "public", + "table": "core_ai_action_settings", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_budget_periods_pkey", + "schema": "public", + "table": "core_ai_budget_periods", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_calls_pkey", + "schema": "public", + "table": "core_ai_calls", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_cost_adjustments_pkey", + "schema": "public", + "table": "core_ai_cost_adjustments", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_reservations_pkey", + "schema": "public", + "table": "core_ai_reservations", + "entityType": "pks" + }, + { + "columns": [ + "roleId" + ], + "nameExplicit": false, + "name": "core_ai_role_policies_pkey", + "schema": "public", + "table": "core_ai_role_policies", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_runs_pkey", + "schema": "public", + "table": "core_ai_runs", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_settings_pkey", + "schema": "public", + "table": "core_ai_settings", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_ai_translation_sources_pkey", + "schema": "public", + "table": "core_ai_translation_sources", + "entityType": "pks" + }, + { + "columns": [ + "userId" + ], + "nameExplicit": false, + "name": "core_ai_user_overrides_pkey", + "schema": "public", + "table": "core_ai_user_overrides", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_documents_pkey", + "schema": "public", + "table": "core_content_documents", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_drafts_pkey", + "schema": "public", + "table": "core_content_drafts", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_field_locks_pkey", + "schema": "public", + "table": "core_content_field_locks", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_file_refs_pkey", + "schema": "public", + "table": "core_content_file_refs", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_revisions_pkey", + "schema": "public", + "table": "core_content_revisions", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_schedules_pkey", + "schema": "public", + "table": "core_content_schedules", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_content_slug_history_pkey", + "schema": "public", + "table": "core_content_slug_history", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_cron_pkey", + "schema": "public", + "table": "core_cron", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_admin_dashboard_pkey", + "schema": "public", + "table": "core_admin_dashboard", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_files_pkey", + "schema": "public", + "table": "core_files", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_files_alt_pkey", + "schema": "public", + "table": "core_files_alt", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_files_alt_analysis_pkey", + "schema": "public", + "table": "core_files_alt_analysis", + "entityType": "pks" + }, + { + "columns": [ + "fileId" + ], + "nameExplicit": false, + "name": "core_files_alt_state_pkey", + "schema": "public", + "table": "core_files_alt_state", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_languages_pkey", + "schema": "public", + "table": "core_languages", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_languages_words_pkey", + "schema": "public", + "table": "core_languages_words", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_logs_pkey", + "schema": "public", + "table": "core_logs", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_moderation_report_events_pkey", + "schema": "public", + "table": "core_moderation_report_events", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_moderation_reports_pkey", + "schema": "public", + "table": "core_moderation_reports", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_moderators_permissions_pkey", + "schema": "public", + "table": "core_moderators_permissions", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_navigation_pkey", + "schema": "public", + "table": "core_navigation", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_notification_deliveries_pkey", + "schema": "public", + "table": "core_notification_deliveries", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_notification_events_pkey", + "schema": "public", + "table": "core_notification_events", + "entityType": "pks" + }, + { + "columns": [ + "key" + ], + "nameExplicit": false, + "name": "core_notification_settings_pkey", + "schema": "public", + "table": "core_notification_settings", + "entityType": "pks" + }, + { + "columns": [ + "userId" + ], + "nameExplicit": false, + "name": "core_notification_user_state_pkey", + "schema": "public", + "table": "core_notification_user_state", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_notifications_pkey", + "schema": "public", + "table": "core_notifications", + "entityType": "pks" + }, + { + "columns": [ + "pageId" + ], + "nameExplicit": false, + "name": "core_page_layouts_pkey", + "schema": "public", + "table": "core_page_layouts", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_users_passkey_challenges_pkey", + "schema": "public", + "table": "core_users_passkey_challenges", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_users_passkeys_pkey", + "schema": "public", + "table": "core_users_passkeys", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_queue_pkey", + "schema": "public", + "table": "core_queue", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_roles_pkey", + "schema": "public", + "table": "core_roles", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_search_index_pkey", + "schema": "public", + "table": "core_search_index", + "entityType": "pks" + }, + { + "columns": [ + "name" + ], + "nameExplicit": false, + "name": "core_secrets_pkey", + "schema": "public", + "table": "core_secrets", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_sessions_pkey", + "schema": "public", + "table": "core_sessions", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_sessions_known_devices_pkey", + "schema": "public", + "table": "core_sessions_known_devices", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_users_pkey", + "schema": "public", + "table": "core_users", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_users_confirm_emails_pkey", + "schema": "public", + "table": "core_users_confirm_emails", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_users_forgot_password_pkey", + "schema": "public", + "table": "core_users_forgot_password", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "core_users_sso_operations_pkey", + "schema": "public", + "table": "core_users_sso_operations", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "blog_categories_pkey", + "schema": "public", + "table": "blog_categories", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "blog_posts_pkey", + "schema": "public", + "table": "blog_posts", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_advanced_articles_pkey", + "schema": "public", + "table": "example_advanced_articles", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_advanced_articles_faq_pkey", + "schema": "public", + "table": "example_advanced_articles_faq", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_articles_pkey", + "schema": "public", + "table": "example_articles", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_categories_pkey", + "schema": "public", + "table": "example_categories", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_events_pkey", + "schema": "public", + "table": "example_events", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_events_sessions_pkey", + "schema": "public", + "table": "example_events_sessions", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_localized_articles_pkey", + "schema": "public", + "table": "example_localized_articles", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_pages_pkey", + "schema": "public", + "table": "example_pages", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "example_tags_pkey", + "schema": "public", + "table": "example_tags", + "entityType": "pks" + }, + { + "nameExplicit": true, + "columns": [ + "itemType", + "itemId", + "languageCode" + ], + "nullsNotDistinct": false, + "name": "core_search_index_item_unique", + "entityType": "uniques", + "schema": "public", + "table": "core_search_index" + }, + { + "nameExplicit": true, + "columns": [ + "providerId", + "providerAccountId" + ], + "nullsNotDistinct": false, + "name": "core_users_sso_provider_account_key", + "entityType": "uniques", + "schema": "public", + "table": "core_users_sso" + }, + { + "nameExplicit": true, + "columns": [ + "userId", + "providerId" + ], + "nullsNotDistinct": false, + "name": "core_users_sso_user_provider_key", + "entityType": "uniques", + "schema": "public", + "table": "core_users_sso" + }, + { + "nameExplicit": false, + "columns": [ + "token" + ], + "nullsNotDistinct": false, + "name": "core_admin_sessions_token_unique", + "schema": "public", + "table": "core_admin_sessions", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "nullsNotDistinct": false, + "name": "core_admin_dashboard_userId_unique", + "schema": "public", + "table": "core_admin_dashboard", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "key" + ], + "nullsNotDistinct": false, + "name": "core_files_key_unique", + "schema": "public", + "table": "core_files", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "code" + ], + "nullsNotDistinct": false, + "name": "core_languages_code_unique", + "schema": "public", + "table": "core_languages", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "openKey" + ], + "nullsNotDistinct": false, + "name": "core_moderation_reports_openKey_key", + "schema": "public", + "table": "core_moderation_reports", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "idempotencyKey" + ], + "nullsNotDistinct": false, + "name": "core_notification_deliveries_idempotencyKey_key", + "schema": "public", + "table": "core_notification_deliveries", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "tokenHash" + ], + "nullsNotDistinct": false, + "name": "core_users_passkey_challenges_tokenHash_key", + "schema": "public", + "table": "core_users_passkey_challenges", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "credentialId" + ], + "nullsNotDistinct": false, + "name": "core_users_passkeys_credentialId_key", + "schema": "public", + "table": "core_users_passkeys", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "token" + ], + "nullsNotDistinct": false, + "name": "core_sessions_token_unique", + "schema": "public", + "table": "core_sessions", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "publicId" + ], + "nullsNotDistinct": false, + "name": "core_sessions_known_devices_publicId_unique", + "schema": "public", + "table": "core_sessions_known_devices", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "nameCode" + ], + "nullsNotDistinct": false, + "name": "core_users_nameCode_unique", + "schema": "public", + "table": "core_users", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "name" + ], + "nullsNotDistinct": false, + "name": "core_users_name_unique", + "schema": "public", + "table": "core_users", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "email" + ], + "nullsNotDistinct": false, + "name": "core_users_email_unique", + "schema": "public", + "table": "core_users", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "token" + ], + "nullsNotDistinct": false, + "name": "core_users_confirm_emails_token_unique", + "schema": "public", + "table": "core_users_confirm_emails", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "userId" + ], + "nullsNotDistinct": false, + "name": "core_users_forgot_password_userId_unique", + "schema": "public", + "table": "core_users_forgot_password", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "token" + ], + "nullsNotDistinct": false, + "name": "core_users_forgot_password_token_unique", + "schema": "public", + "table": "core_users_forgot_password", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "tokenHash" + ], + "nullsNotDistinct": false, + "name": "core_users_sso_operations_tokenHash_key", + "schema": "public", + "table": "core_users_sso_operations", + "entityType": "uniques" + }, + { + "value": "\"intent\" IN ('link', 'import', 'sync', 'preview')", + "name": "core_users_sso_operations_intent_check", + "entityType": "checks", + "schema": "public", + "table": "core_users_sso_operations" + }, + { + "value": "\"field\" IN ('avatar', 'firstName', 'lastName')", + "name": "core_users_sso_profile_sources_field_check", + "entityType": "checks", + "schema": "public", + "table": "core_users_sso_profile_sources" + } + ], + "renames": [] +} \ No newline at end of file diff --git a/apps/web/content/docs/content-engine/content-visibility.mdx b/apps/web/content/docs/content-engine/content-visibility.mdx index aeabf6bda4..06abc5dded 100644 --- a/apps/web/content/docs/content-engine/content-visibility.mdx +++ b/apps/web/content/docs/content-engine/content-visibility.mdx @@ -126,12 +126,13 @@ A record is public only when it is published, its `publishedAt` is not in the fu ## Who can still see it -Hidden doesn't mean gone for the people working on it. Signed in, a record's **authors** and its **editors** still reach it: +Hidden doesn't mean gone for the people working on it. Signed in, a record's **authors**, its **editors** and its **moderators** still reach it: - **Authors** are the users in the content type's [`search.authorField`](/docs/content-engine/search), such as the blog's **Author** field. - **Editors** are staff with `can_edit` on the content type, such as `posts:can_edit` for the blog. +- **Moderators** with the moderator permission `can_view_hidden` on a [reportable](/docs/dev/moderation/enable-reports) content type, in the record's scope when it has one. They need no AdminCP permission. -The route tells whose record it is by its `id`, so `id` must be in `publicApi.fields`. For authors and editors: +The route tells whose record it is by its `id`, so `id` must be in `publicApi.fields`. For them: - The page opens with an eye-off icon before the title and a **This article is hidden** note, so nobody mistakes it for a live page. The response sends `noindex` and `Cache-Control: private, no-store`, so search engines and caches never keep it. - The detail route answers `200`, and `GET .../delivery/resolve/{slug}` returns `hidden: true`. diff --git a/apps/web/content/docs/content-engine/reference.mdx b/apps/web/content/docs/content-engine/reference.mdx index 2d1490eae4..9db162300e 100644 --- a/apps/web/content/docs/content-engine/reference.mdx +++ b/apps/web/content/docs/content-engine/reference.mdx @@ -66,6 +66,7 @@ Many of these rules are type errors too, so your editor often complains before t | `search` | [`search`](#search) | No | off | Site search indexing | | `visibility` | `boolean` | No | off | [Hide and unhide](#visibility) records. Needs `publication` | | `duplication` | `true` \| [`duplication`](#duplication) | No | off | A [Duplicate](#duplication) action that copies a record into a new draft | +| `reports` | `true` \| [`reports`](#reports) | No | off | Readers can [report](#reports) published records to moderators. Needs `publicApi` | | `indexes` | [`indexes`](#indexes) | No | `[]` | Extra database indexes | A feature block is on when it is present. `publicApi`, `localization` and `search` take an options object. `publication`, `liveEditing` and `visibility` are `true`, and `editorial`, `delivery` and `duplication` take `true` or an options object. Leave a block out, or set it to `false`, to keep it off. Write `true` or the object directly rather than a `boolean` variable, because the generated types read the literal to decide which columns and routes exist. @@ -277,6 +278,15 @@ publication: true, visibility: true, ``` +## `reports` + +`reports: true` lets signed-in readers report a published record. It registers a report target, adds `can_view_reports` and `can_manage_reports` to the moderator catalog, plus `can_view_hidden` and `can_hide` with `visibility`, and needs no migration. Pass `{ titleField, snapshotFields }` to choose what the report's snapshot keeps. Guide: [Enable reports](/docs/dev/moderation/enable-reports). Options: [Moderation reference](/docs/dev/moderation/reference#reports-on-a-content-type). + +```ts title="plugins/blog/src/content/post.ts" +publicApi: { path: "blog", fields: ["id", "title", "friendlyUrl", "content"] }, +reports: true, +``` + ## `duplication` Adds a **Duplicate** action and the `POST /{id}/duplicate` staff route, which copy a record and its translations into a new draft. Pass `true`, or an object to change the title suffix. Guide: [Duplicate content](/docs/content-engine/duplicate-content). diff --git a/apps/web/content/docs/dev/events/built-in-events.mdx b/apps/web/content/docs/dev/events/built-in-events.mdx index c18b93c20c..98a8e258d5 100644 --- a/apps/web/content/docs/dev/events/built-in-events.mdx +++ b/apps/web/content/docs/dev/events/built-in-events.mdx @@ -536,6 +536,32 @@ own preferences are saved, by them or by staff on their AdminCP user page. pauses, deletes or resets everything, or note when staff changed how a single member is notified. +## Moderation events + +Seven names, declared in `VitNodeEvents` in +`packages/vitnode/src/api/models/events.ts` and emitted by core with +`pluginId: "@vitnode/core"`. Each fires **after** its database transaction +commits. The envelope's `actor` is the reporter for `created` and the +moderator for the rest. Adding an internal note emits nothing. See +[Moderation](/docs/dev/moderation). + +| Event | Payload | Fires when | +| ---------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------- | +| `moderation.report.created` | `{ reportId, pluginId, targetType, targetId, reason }` | A signed-in user files a report | +| `moderation.report.assigned` | `{ reportId, assigneeId, previousAssigneeId }` | A moderator takes, reassigns or unassigns a report. `assigneeId` may be `null` | +| `moderation.report.action` | `{ reportId, action, pluginId, targetType, targetId }` | A content action from the ModCP changed the content. `action` is `hide` or `unhide` | +| `moderation.report.resolved` | `{ reportId, resolution }` | A report is closed with an outcome | +| `moderation.report.reopened` | `{ reportId }` | A closed report is reopened | +| `moderation.report.note_updated` | `{ reportId, noteId }` | A moderator edits an internal note | +| `moderation.report.note_deleted` | `{ reportId, noteId }` | A moderator deletes an internal note | + +A hide or restore from the ModCP also emits the content type's own +`content.{id}.hidden` or `unhidden` event, because it goes through the same +visibility service as the AdminCP. + +**A listener would** notify a staff channel when a report arrives, or keep a +per-moderator count of resolved reports. + ## AI events Declared in `VitNodeEvents` in `packages/vitnode/src/api/models/events.ts`. diff --git a/apps/web/content/docs/dev/meta.json b/apps/web/content/docs/dev/meta.json index 91ff1b562c..2e90a52dce 100644 --- a/apps/web/content/docs/dev/meta.json +++ b/apps/web/content/docs/dev/meta.json @@ -24,6 +24,7 @@ "---Extend VitNode---", "widgets", "working-with-users", + "moderation", "events", "notifications", "---Services---", diff --git a/apps/web/content/docs/dev/moderation/configure-moderators.mdx b/apps/web/content/docs/dev/moderation/configure-moderators.mdx new file mode 100644 index 0000000000..5f6bbc8c41 --- /dev/null +++ b/apps/web/content/docs/dev/moderation/configure-moderators.mdx @@ -0,0 +1,86 @@ +--- +title: Configure moderators +description: Give a VitNode user or role moderator permissions in the AdminCP, and limit report permissions to selected resources such as categories. +icon: UserCog +--- + +import { ImgDocs } from "@/components/fumadocs/img"; +import scopeEditor from "./moderation-scope-editor.webp"; +import scopeDialog from "./moderation-scope-dialog.webp"; + +You set up moderators on the same AdminCP screen as every other staff permission. This guide makes a user a moderator who handles blog reports everywhere and example article reports only in some categories. + +## Before you begin + +You need the `staff_moderators` admin permissions **Create moderators** and **Edit moderator permissions**, or a root role. The content types you want moderated must have [reports enabled](/docs/dev/moderation/enable-reports). + + + + + +### Add the moderator + +Open **AdminCP → Staff → Moderators** and choose **Add Moderator**. Pick a role or a single user and save. The new entry grants nothing yet, and the AdminCP opens its permissions. + + + + + +### Grant report permissions + +Keep **Restricted** selected. Pick a plugin on the left, open a module, and tick the permissions. For the blog, open **Articles** and tick **View article reports**, **Claim, assign and resolve article reports**, **Open hidden articles** and **Hide and unhide articles**. + +A permission that depends on another one stays locked until its dependency is ticked. **Hide and unhide articles** needs **Open hidden articles**, so a moderator can always see what they hid. + + + + + +### Choose where a scoped permission applies + +A scoped permission shows its scope under the checkbox: **All resources**, or the number of selected resources. Here the example plugin's **View reports** covers two categories and the management permission covers one: + + + +Choose **Change** to open the picker. **All resources** includes resources created later. **Selected resources** lists the family's resources with a search box, loading more on demand: + + + +Tick **Apply to every scoped permission in this module** to copy the same scope to the module's other scoped permissions. Each permission still saves its own scope, so you can narrow one afterwards. + + + + + +### Save + +Choose **Save changes**. The moderator's permissions apply on their next request. If a resource no longer exists, the picker marks it **Removed**. Take it out before saving. + + + + + +## Check the result + +Sign in as the moderator. The user menu now has a **Moderator CP** link to `/modcp/reports`, and the reports board shows blog reports plus example article reports from the two selected categories only. See [Process reports](/docs/dev/moderation/process-reports). + +## When saving is refused + +The form checks scopes before it sends them, and the API checks them again. Each problem is shown under the permission it belongs to: + +| Message | What to change | +| ---------------------------------------------------------- | -------------------------------------------------------------- | +| Choose where *permission* applies | Open **Change** and pick **All resources** or some resources | +| Pick at least one resource for *permission* | A selection cannot be empty | +| *Permission* reaches further than *dependency* | Narrow the permission, or widen its dependency first | +| *Permission* names resources that no longer exist | Remove the resources marked **Removed** | + +You can only grant what you hold yourself. An administrator whose own moderator permissions cover two categories cannot give a third one, or **All resources**, to somebody else. Only a root administrator can grant **Unrestricted**. Changing a role's permissions or a user's roles takes effect immediately. VitNode clears the cached permissions of every affected user. diff --git a/apps/web/content/docs/dev/moderation/enable-reports.mdx b/apps/web/content/docs/dev/moderation/enable-reports.mdx new file mode 100644 index 0000000000..7050c41292 --- /dev/null +++ b/apps/web/content/docs/dev/moderation/enable-reports.mdx @@ -0,0 +1,120 @@ +--- +title: Enable reports +description: Let signed-in readers report a VitNode Content Engine content type, such as blog articles, with one option and a Report button. +icon: Flag +--- + +import { ImgDocs } from "@/components/fumadocs/img"; +import reportDialog from "./moderation-report-dialog.webp"; + +Turn on reports for a content type so signed-in readers can flag a published record to your moderators. This guide follows the blog plugin, whose articles are reportable. + +## Before you begin + +The content type needs a [public API](/docs/content-engine/public-api). A reader can only report what the public API lets them read, so a draft, a hidden record or an unpublished translation can never be reported. + + + + + +### Turn on reports + +Add `reports: true` to the content type definition: + +```ts title="plugins/blog/src/content/post.ts" +export const blogPostContentType = defineContentType({ + id: "blog.post", + tableName: "blog_posts", + publication: true, + visibility: true, + reports: true, // [!code ++] + // ... +}); +``` + +`reports` needs no migration. Reports live in core tables, and the content type's own tables do not change. + + + + + +### Choose what the snapshot keeps (optional) + +By default, a report's snapshot keeps the record's title and its public `text`, `textarea`, `richText`, `enum` and `file` fields. The title comes from `admin.titleField` when that field is public. Pass an object to pick the fields yourself: + +```ts title="plugins/blog/src/content/post.ts" +reports: { + titleField: "title", + snapshotFields: ["content", "excerpt"], +}, +``` + +An unknown field, or a field of a kind a snapshot cannot hold, such as a relation, throws when the content type is defined. Fields you list explicitly may be private, because only moderators read snapshots. + + + + + +### Label the generated permissions + +`reports: true` adds moderator permissions to the content type's permission module: `can_view_reports`, `can_manage_reports`, `can_edit_notes` and `can_delete_notes`, plus `can_view_hidden` and `can_hide` when the content type has [`visibility`](/docs/content-engine/content-visibility). Core ships generic labels, such as **View reports**. Override them in your plugin when you want your own wording: + +```json title="plugins/blog/src/locales/en.json" +{ + "@vitnode/blog:posts:can_view_reports": "View article reports", + "@vitnode/blog:posts:can_manage_reports": "Claim, assign and resolve article reports", + "@vitnode/blog:posts:can_view_hidden": "Open hidden articles" +} +``` + +Enabling reports grants nothing. An administrator still has to give these permissions to a moderator. See [Configure moderators](/docs/dev/moderation/configure-moderators). + + + + + +### Place the Report button + +A plugin's own pages place the button themselves. Pass the record's stable id and the language the reader was served: + +```tsx title="plugins/blog/src/pages/post-page.tsx" +import { ReportButton } from "@vitnode/core/tanstack/moderation"; + +{!metadata.hidden && metadata.itemId !== null ? ( + +) : null} +``` + +The blog reads `itemId`, `locale` and `requestedLocale` from the [delivery resolution](/docs/content-engine/public-pages), so the button reports the article in the language the reader actually saw, even after a fallback. The form loads only when the dialog opens. A signed-out reader gets a **Sign in** link instead of the form. + + + + + +## Check the result + +Rebuild with `pnpm build:plugins`, restart `pnpm dev`, sign in as a regular user and open a published article. Click **Report**, pick a reason and send it: + + + +A toast says **Report sent**. Try sending it again and the toast tells you, politely, that you already did. A moderator with `can_view_reports` on the blog now sees the report in [the ModCP](/docs/dev/moderation/process-reports). + +## What the server checks + +- The reporter must be signed in. A guest gets `401`. +- The target must be readable by the reporter through the public API. Anything else is `404`, the same answer as a typo. +- **Other** needs at least 10 characters of details. Details are at most 2000 characters. +- One reporter can hold one open report per target. Other reporters get their own reports. +- A user can file at most 20 reports per hour, on top of the per-IP [rate limiter](/docs/dev/advanced/rate-limiter) every API route has. + +Reports work for targets outside the Content Engine too. A plugin registers its own target with `defineReportTarget`. See the [reference](/docs/dev/moderation/reference#custom-report-targets). diff --git a/apps/web/content/docs/dev/moderation/index.mdx b/apps/web/content/docs/dev/moderation/index.mdx new file mode 100644 index 0000000000..f701b79810 --- /dev/null +++ b/apps/web/content/docs/dev/moderation/index.mdx @@ -0,0 +1,38 @@ +--- +title: Moderation +description: How VitNode moderation works. Users report content, the server keeps a snapshot, and moderators handle reports in the public Moderator CP with permissions you can limit to some resources. +icon: ShieldAlert +--- + +VitNode moderation lets signed-in users report content, and lets moderators review those reports and act on the content from the public site. It is built from three parts that core provides and any plugin can use: reports, the **Moderator CP** (ModCP) and scoped moderator permissions. + +| Part | What it does | +| -------------------- | -------------------------------------------------------------------------------------------------------------- | +| Reports | A report stores the reason, the reporter's details and a server-side snapshot of what the reporter saw | +| Moderator CP | `/modcp/reports` on the public site: a reports board, the snapshot, assignment, notes, resolution and content actions | +| Scoped permissions | A moderator permission can cover every resource of a family, such as every forum section, or only some of them | + +A moderator signs in with their normal user session. The ModCP never asks for an AdminCP session, and the server authorizes every ModCP request. + +## Choose a guide + +| You want to | Read | +| --------------------------------------------------------------- | ------------------------------------------------------------------- | +| Let readers report a Content Engine content type, like the blog | [Enable reports](/docs/dev/moderation/enable-reports) | +| Limit moderators to some categories or sections | [Scoped permissions](/docs/dev/moderation/scoped-permissions) | +| Give a user or role moderator permissions in the AdminCP | [Configure moderators](/docs/dev/moderation/configure-moderators) | +| Review, assign, resolve and act on reports | [Process reports](/docs/dev/moderation/process-reports) | +| Look up routes, options, events and limits | [Moderation reference](/docs/dev/moderation/reference) | + +## How the parts fit together + +1. A content type opts in with `reports: true`. This registers a **report target** and adds report permissions to the moderator catalog. Nobody holds them until an administrator grants them. +2. A reader clicks **Report** on the article page. The browser sends only the article id, the language, the reason and the details. The server checks that the reader can read the article, then stores a snapshot of it. +3. A moderator opens the ModCP. The reports board shows only reports the moderator may view, filtered before anything is counted. +4. The moderator takes the report, writes internal notes, hides the article if needed and closes the report with an outcome. Every step lands in the report's timeline. + +Reports belong to core, not to the plugin. They keep their snapshot after the article is edited, after its revisions are pruned, after it is deleted and even after its plugin is uninstalled. + +## What is not included yet + +This first version covers reports plus hiding and restoring content. It has no warnings, bans, approval queues, automatic moderation, anonymous reports, report notifications or permanent deletion from the ModCP. Moderators still have to read things themselves, sorry. diff --git a/apps/web/content/docs/dev/moderation/meta.json b/apps/web/content/docs/dev/moderation/meta.json new file mode 100644 index 0000000000..a591b75a1a --- /dev/null +++ b/apps/web/content/docs/dev/moderation/meta.json @@ -0,0 +1,13 @@ +{ + "title": "Moderation", + "description": "Reports, the Moderator CP and scoped moderator permissions", + "icon": "ShieldAlert", + "pages": [ + "index", + "enable-reports", + "scoped-permissions", + "configure-moderators", + "process-reports", + "reference" + ] +} diff --git a/apps/web/content/docs/dev/moderation/moderation-modcp-queue.webp b/apps/web/content/docs/dev/moderation/moderation-modcp-queue.webp new file mode 100644 index 0000000000000000000000000000000000000000..6391ba8b06d46fa8eb72f4a19eb2ab34d4b4a6eb GIT binary patch literal 102394 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 z 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 literal 0 HcmV?d00001 diff --git a/apps/web/content/docs/dev/moderation/moderation-scope-dialog.webp b/apps/web/content/docs/dev/moderation/moderation-scope-dialog.webp new file mode 100644 index 0000000000000000000000000000000000000000..586b90efaa639e9a2cdc6219f52234b8566f5a20 GIT binary patch literal 46786 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 z zb_?RoLX{RB)8YES!KeksM&*FK^?X0-4oW}Sht~}rDZU+AY}G_)t(kqWZ`2aye7l(9bsS<96O#W{#@qbb_dsIzAb|zXmd!b z3t-W0X+)SUJ{&pRJN$iQOx%ftGzSS9%k3Cm*2)%LTnQ#r;f7Zq+3$+U*kLvqc64SA zfO|lSSnj9Mj7WlwFmj&~tCi3!ea8^WasVRYaVoTmapV8KpM^#yLx)>(n)1zY=mGkH zQcBa>gAAoOj_RPe?zSetY5eA_W?fd`NcABgp+lFkO^q8Kk5}h#Q?l(!JT(yFE|Woy~+);t_xsD1~?Sq*3}}=oR7_nmJ7Bc`zUXl z0F_8T3AZpol+7G<*;#sa56Y-8>-LeP!_KJr3Y7i1E7bO1&g^np=MpF1H>4mj4~ha* zQmGyzH8;#3+Cl|Uhr)RwizuT0`knJy3ZK6)B(+>ApnQHj&BW}L z*4&>z3&fQNVHcX*N232Cu0kbX21nh)>L+Hx6O2DyY_9=-F$3N~UYYFsgTK80() zGt*gS8U6rnb-6H~8k~Mu;7Ul1?YUa< z^m~E=@!zZniA|ROi@}m*GPj_>cNtnRjdr$0`^SXm>{^)}eT|-~nrAV93%tU2Wm$|k zIny`%g=XqFNdB-MinE}DCw;r^`YD~Dvnv3{RL6|NP${!RkdCVuTg5tIJAD3XOxv1D z`Jy*4qH_P!$~4r{R|3$gc$65EjtfdTv9&eG&}?p33c2xd%~KfKku6y1%iMIhf}ft- z&<-tre|Vj!TT=IduN)W!VEGT;@?nV;qQp6pA{m?P`r+Dbg&LY5i0F(=fj3qkt!7%# zqQmuiKU!aDA3Td>-Z(WwS`<%mq%H6iVFAb3q7120;WCjPAfM>br6U$;qzIC-a~2Fh z+F!;iyiNKYSitr#SiMTHN@5zmj)mR1ow>akYcY;T+y9>-`5JM)4qPDz_}7ovP#l^7 zc_jUR9#Kp9f~r7&R_fW7=L`H(PKZ9DzWmS^#p};@ShRSbpSfDF20LgVCNF!@-m#OW zU$48}jEzuPM3|Wia1jSCeBN9oTuWNPdyKmiu}Po9wQ$5d>Kf}kG%@k71;0SoiX%zv zyf_YC(-k_8A7SW$jbmLlErfvu9`%bg!Q4Y9iQysu==%_(jW{hW#Rd^<=*Z|xHho-Q zS*)$f^5r?Szl#JXLbhyTRlEm8zL@IDhYUtE-6XBm0bs`w_Q9;y3{rmcpXV%LmHqh; zyY5TwwVg>rg=sSTA`sf@ixW6fq#W^IMgv$8Bg+nUaYC+yS<)(xtRQhxAJ|uP1&XHY zFn)X$vT$j#5JgMXfIy^%XQ4C!vnu14JGy~{e9%u4@@Ps+ZepPzZXJ0027Eul^h2D>AyTho%^ zft*#$5jXocYF9XzJ6-m$)Vht7#wm?M=*=@>vf0mpKc~r>f9G0LJ?>@TsI6;nSSvqC zYhJy>OY!|@$JuX_LWf=ZzF)JV@R`!xMDY?3M##N#*X<62FHej!D$DM#hidW}hpCB0 zH2JSD1P#<|&Zr9l3 zjQNGb5c$3m)ph$ry*I0%;niIW~HGK@R~gnVclMRD+Jqv=TF_ zPL|C1`(WiN9gZVS4CGDNwqKROQ&!o;05)XEbl=HRi5_gOL`|uDfTy|C&M-CqN!~HQ zX2;CIY%?)cuQRl=o~We`iKlgViNyx(fL8w(*EBPCx7S@-5Jc+bqLA2X7iBc^gUn)I zJ}r|GI#(s{vJslbG)oV+Ad|f9Qq*|sULAvk*kW*U-d5`VMm-siN!?V3QhMcScHq4R zhq(T304jptmpxu2=4VercJq~B0Ddtq01E18{+0fe z%2gyti@`V4nq*#XTtGEHIlkZR%<17m0J1L>Qr1TB$ZtgFsb7g? zSZBuj@b4-x54+!4YzJ|-k2dgn!hj=)1Grs8aPo3H0_}Peu`K10I4_xxX&E0ET1Z2MGvdLHpok@OF_@VU ztYN4u{dxZx<-E*#LfI66yd3f7vHU346whzi=eXjaVxL9IxcIQB@0nDRBNEXO_^Fif{65-f(I8B#&w`He~PILy{Uyvsb7U9{J$8mP2x7XRfFz9?-( zN)4b07h64FUXfW3H%#OQDELxlH}_w7cTU@=l7Atf2@7DC0zgr^11hEB^3Cqeez9CH z^$y?hN)UuAbuzfR8+-ZSv1Ii$9Ths7GxaI_7mQG8ITI^cd2uRNNe513m0|dtV3%e= z-`s*vZ5lH>UB?fRzWC?Vq>wh-OIY&z>gPY-l_}0JVL|%@QhlUt#Rwf9EulNp${MtW zvR9jG_J!1*ZO_c;UTpP|$9PWk;WaGSYE#C;A-wX*MVuT?UZq`v$azd-spB^tkJMTD zEqqkaNz;(|T-dK_;?d;KPP%8v4C1%{3Z%A;(xu4E#zWxwCf4nP2wRiPlMs*10_uz8 z6slcuX^od`I;fGrHjSU9z%jJRqg~PgTCUO{FFYDSh##Ml!AkoW9X){Fvl#4ME z)*!s_k2l#1$>iT7yqZ+G-@^mYpgHhJa(o+KncB+kfEqB#2dyqot{xa`zXjDP?1@?3 z{igZHLFjzg1pcjvW6{>R1mh^l_O1gL_P50kHk@$oCi&_Y&-nRbpTWfDW5p0Ro^FZkEb^9Wd(R zi{C+H6{ODO@9^Z0d;a}8@0S%UNfKla_T7ltdaRPzoOTbtQU^|Im$0}|TLtTW;m*~M zN9FfNR|3E|F~X=Td9ktJ1IUi0zV@k`0|_INc_u`h4dtURcb&-C&?|VCenkEp#XTZX zhqo==RsU*DmpUJ;erss$IU4EIO~O(vU=J1zU0c;4&cZ`V3atbhqj69x%DFXqOtFdE z>}@7?dTl4v^2Z-iXEnCd4Y^rV8ytR$0m#$LnEQKuD_y~7NLRBuYh8?3e*Nj3CLHs$ zCwr)rn~VS^OKy=u&|qDA-FVveBmJB$tE;gE;7AbXng*)R<@B9}JV1j5GfhYRtwDwI zT13g{fwc1}Sc}^R7AcAaxUSnHauw=#r` zDQI5Qu0ipHdXcOZP?grmxak+o4NQ3zY$m)4Mvmd(Uv_28iTM2l(hb;7X#hSI;aat? zswKO%F~|nG(9I^1?JGXuG4&(TZHzj6e|=)q$9^`9_c;^lq zz+m?LKtAQvvvI%#u2CqeFz&;E5K&cXc@}*-ag3(ZJXvEG)BYVrn%6trM;qPsSUp2k zrpRe`qB4tg^ouA9&!gRiaT~|pB%q+_bHq5qF;_3ujTW=hoiwH^PSolTvw4YUeW4nT zRc=FiSK;0MUdwUf&`G&YLH8BaxEdhu5u4HWSp~nnw9un#>JO9C%ED6?Tu6+>Fdx9_ z&k^i+#^o5UD*vuHOc3r5y1F2UmH}#hvZ(lH4agNs3A{D}G_rqeqhTS@WFa%FLmXR$ zW|3^DBLSt~6y0qh_9H94i9|q1rR~PfnI*SlgO3vRkDl`0LKnso63WM)?O_>Cm9KNE zP-pVK!)ws0e_w}T_^e-zw~#Eudz#8c_O%@GVs=Omn;Bf)g%RrU4G~*caFzipN{7iL#l~2(yDo%cPjuxgm?*J> z#h14sF1Xg4X+8d2tgm4azD&^jhjnAe%{_|~swta89*C7HsvowzZp-iEh;ltd6w%h- zA+n$ihkHfChT#7DO}$-KBo#`MFE+Y%B3)kvBu7=1eN_AP5r^o@3(s5fHn{Qh zdRojkRJh^3-aY8=Fch9RfTtH;(?0WVuGU=t95*Ru+u3c=Z>VUxC3Anp={B0|ez++H zH$fqzC@n@C^&P`kTN#UBTR0%OAfOt3X$ZaGV5Sz_){20(N88SR*^!NwqgnuW9V5Jt zwsdbAHAjo(rGBE!N<}CNd;`OTP)Q`y60W^!6E<6vPXekBv^c;=DCD$LCZN~nnjjFp z8OJ|tkTV6PG_f7qcl-{GsqKVbRar2nYPTM6r@eW@wQLrJi;AqbWF3-NAQq6&p-Mx6 znU;-0-ASi5q`(XPkCulbx#~_q)v&n}s0|mCG;m1NrnsH&BfJ~%9mmp9~odZ&q z8zp0ob_VRxi6r6MAvs4aCJ*6U3<83Ok#)?BmSkN3jXQkNQPQhD1?P;+T8|2f&!#Nx z{yR&x9ypj)!AnnybWbvUXYXejbt~l@tGr3cBEp5v6#GhM5c!}K{T^?rRA4Lb0bmDI zyo}9$LIuzQKf4x`wr}3)@JhlfZP$97gqr5x&h)6L296Xw? zM?@^PL!=Q4#AvAbV+C!D4;uPKrC1YJbnnxMb?mO#SZm22e87S_59(FO5-&%GZG8v5c2Xmzh8rP6Td?Kr8MDP$HPf|7Q2l+A zS*P<3b14Zjzaans5EGA!g+SFi)R&V@1COZkpjb3Du})|-geN`TuB)&+jP#t8a7V86 zD4}@ljdw)m7<5#}xy%k zX2DG6d*6UUYMtX+62Kv{8-KHXrJPMGo_2LpX1ICPPPY+H=~m@vAoGvF#~ik2ls6T% zIA+yWLgi#2-Tl{RM|dy=VtN|EOayzef@_?koeus;y6iSL?{^`NwxOtEqx8J1uf3Sm z0yU5`?yE0svH%Zwd5xOy+`8ZgD4=80lDcY;B*>tQBMJ%fs3)*??PknPt@pL#B7Rz^ zY-)T*kWkS>Q?l>`RMbv+H6y~{kwyLDG#N1Q&Ci*7@^HIl+`1FD0tkZRPtuer#h}?# zGZbw2w!7{#TgCJd(Q5LAswis0|FI)$k;Ys}wFQ*rURM8+1|)l1sDpsz+HlcK)P3@B z1Q&d0>BX&+0a5qYOW{lazCUfQe`338xWZP;&19a2r8z{J6Q$R2Yb-;<6BqXqZ@zmA z@F3LL3s*kI47_?-_0|s2EKic++dcG17Z?QZzSpk_p|8IynMAvaShM6~hD^yL} zd-muVb{3+;x^alt{+R&8OEa zlqJmdp=}x_#LYzS`N4YTvCr%HtRt~}WBAg>6NVA~K{~h!rgz(4MxP!g-Uj3L#~TfA zKgfdS>aUQAtcaBkO{HCxv3ZQEa2c7wz=ynkKj{uQrOW~TF<=cWLm+othMS7hG*-3N zGABU{><4a|9)Z!Mrwwrb?|+vVtgOtej?A=-AQ)P>my3rwht0DA3qXoZ;4k&6dJ5kq z#)X!|XT9x4Vt>>;X=KscqDC&!kh_u*41y5j`*P5{?!Tu_C4(cX%y=1x?C<=t*J?q5 z(X$?hJMN7$C!gqWo!J3Z`|Aq2jOxhugTdag1I9CcEY`OwYI=sB-k|;?JWPZPSrYG0 z1fSp=9L(I2H3QDs9e8)sNHYnV?{(S^>BFn$PGyVMDy(gqt?Sm{V1CnY!#pg{_;3VJ zfzT+khKk+vz+tWn$fNpgvOM%-~~JTz*j1M$*t%FSY+E8 zdd{{cnk=SxBx%o#w_~~_7B~~x1Bi$RmgaUV(-LijS;`UJd4G0X=dI@X?79t-t6hI3 z-!?-)Tpjba*+m4zZ~E?8=BNkGDZczj#d|3=g#;J$W8t>JBC0!$=Jy|Q(D)LIE&lZq z6OU>D?RjPL5Gz*g*w?siTY5mw>_wd^-fb~2pW`w2Hy`%~LLeGZcjqwW*_y2jLFyWs z4K(&e7G&*7HDP4d?pN612?EGDDEV_hs_ay$zmvdUE_X`ABMq{1vwKf8b|=^KXAhjO z0C+SLOk+9yvRe}2rQexOrL!4Jr&HZxdEAK=#gBA`Lt$(AekT^{=Q<1&eRZAm-V zKZiA^_hvg`rM;?-jFRp*zD3pbv%!V@ru$A3ZV%yjyBvTspZ4aPxx}6MWKR!vYx|vpIIxY{!`O}=1 z+XQ8DG@xKoK1Ka%Z@(B9>EgM7J9qD^BT0Q?{*eB;KCCa(V`Q>Yp&2k+b#i7)RXw!& z?WH$;)3PoLX*gJxHjvEUky)NJ{Wg{Ety5wkWb=GLjzdxI+wu(r5Ee)L?(~RSnmXYD zbZG`|9vX^Vlbc$OJ=rDiWGE%Y7OVm{NZ6#`koVH@(5{-(jaf`_&H=Q#xX)@GD5MWz z)hKw}(FJe96KPP#sk)c2WhNv=OHLE<^Z`UsMc%7e$kKthJ%x%NF6TCC+gJn?7cq>0 zQr`=b$;`HT-H#fsVxc&=5AN)hnXp4x84mJ_fLiW3#4w^wrZ72J&tRTHJyOb*SiG(T zu|~>gAXpfJ`$Vd9!kq{I3{%4Y*q8337TZsUUxo!eqMR*5`{BG%w;f#FJo!@(8OIeg z4!MJRHvJdeeo!k37JVArZmH?(eDRt9JAyMbNzdJC(8u zB=FX|P}K&5N#zS%NoWZ-{*4X@g9&SoT!IwZkf*!y_Ia#Mya*D0`c8{rjDl|n^7`$K zu|F1w*I*{Sch*psy&b?SyCv-MyapjW@-izm$=W*;GF$s4-8JAV4n=FzVzV`1^M-!N zdwdKWI;wP*u~5)K3-ia}k1Xu5_@Kdckb=5LcL@nvl9Tv}855dZNd-8NDPQ)ZDMj7d zeh*4|)IdrXfEuccqDj@dHmj6UEIz!uE{m7Suj@EpD>z5gAf=ZW;F#Ax)0@hlNp17n z6O?koa4ftO@U+hHAWi1plZd)NfB4U=fqceg0i3%-=xMglneF&$ZP?t?WKuzoNqGtg z)=j4-@9*hI|2<8L=VbN;2)a@VXoiccS033j5peiZg$)4cPGjq+jx8^qgzWmW!b)yY zgO9j;9RL8#fmZimax|ZufP~5{+gTVIKiMS*x^0%(K-Q?7aVN|TJJBq>Mo0yWlhN@x z!~mfsL}(QeT0?}^@c&r~Zf3oWCWg3!FbtLhlcDEd=9A_9$20yknv_fKT0fS)%YC39 z$sL%G1MHb5#oV))>yb3eswurfZ#kmXyt;wlt-wWBxE&jV{&WXcT zB%f(O6gB2X&LL+z2ljv}y(6FaiKmVmVc&?dJ=%@i9Ds&zrW23L2B$XC`3@Et|0KT` z{vwsHfcV*7d{pF$$k?}^+V=eI({eefVJlJPtk;1H{i~w6jr%3?ddzj>+C18^jmAYI?p@fwD z1`;y+fyc_g`$n^ncR;Z}b-pLLkW9)4p!kTxYw;RiR60Yr7YCrg0p_wtd(mkmycSBm z_w8UMVuNIoJbMgxF0L#qVS*wa`ID4SoCiu{9+Spxp-`F@$`~cK`e58WiLAi73tbw} zdLMsr;;>J{@2T?M`Vrn`taKkB?GY6eMKb_^vgTZCYcQ=#FIR zZGAu=A5n24oE36?xQ=P`nLSVT_|R~6yFou3aMTKA%4*$_UlG-%AcBml9Qnh(76SQb zwCu_y%>U2B7uBBG{|Lai-)_UdL*fv$D7EVB$a(wEb~*i|`|M&$99U~0f5Rm$X1 z8nyf*6J~B_jeiB^a+)?!#keqC9GA0b3Yg(bGq4!xFvo|nKe|^Ki5*WmQ-iB(lb+iI zc3viY=UgXM-1S>J58kn;m5;?jYZjzIDiF1^#+vjxV0+7p@hs zSH3y~0fa@ybG9lVoFv_!{K3e8|Dec>=bZXHh>pzEQ$CRN*O{Q_T1bI&^hR>zaDZf! zh3L0L(T<^UQ?ngLMgudLbe+o>%jBM%Ko`zxDsn(`v@%hO*p$YFL)ufx#}2R{R7|P? z6DsdLr4|Ucqv!gl#$c~*!Vpv_-svW{q|}$Xoj{3df6E3o%T53Q0O&@XRj@6U{cFO^ z0G=Q08-)!o6GO!B><=nb%bP(Is`*vdQp`~$jX_->%4L40`3FPo-oB?tHiIZs%S!`* zZm&T*G?s=^k6&+j8=-DWsZ|rQP7Y|uOz8~((}47+Axqe^Uq}U?G8Bq08IC)ji8isE z|K{JNAzj$d1caAeHTdDPr0EfU^_vn<8Q^rH&Nlx;1IuI@8$I`~x2ph=-!EFj++-v& zpo5T?cmnhZ5zW}$AI__2M#v$D!u=RW7UhYi+SOq5o9k2?jq2j_iqI$ie}hCcqPMu# zHiYVXZHb}218*C3qd2ph@>Ym5^XFexaRF~ zIzjtn!S|@bghH>ozqh;*e_l+^O8$my5isZpz9Ay5I3^A&(21hDeU?ba=jj|2zw|BE z{Mt|Afdkr(D(f2RxbeMI<7%j)?8rigMbHo8u36p)83=uOcVhM<1!A2o1MvsNsYft+v6(C7H^ z_ZaOI1(Mx?&Bo#bmY-6Zw(;ELvMIr;*4|$F!K%W%ROk$VMINg|JBSWXeQkA9pFKlszvaGXoVNpa-QnMGU zt+eSvqrgn>NTe-cb(6+|iFnNHTQ#%_kX+AIFuS5W%c&YYvBTD72x>3RMDmqC?>@v3 z2h_P)S4VISfH)fV!dVs!nkoE2V2xj8{n#_UUW;baMd>#Z>$X%(>12`)1Zl(d!^6?Z zrZl(*N=Ld+h$z2NRa5%kwoVdOFm$U*ChhrDj6HjojVT@SbirPt0HL}C;o~|1fV9iW zvE=5G7}}GytbF`FZvsCxU&toi=D>-l_z@CD^3Fg~IPt2iC)83BMFUiyqv*JU{l1x8 zNf1ce-rDmXTCYRbc%WHx#Oe1}Hfqt11x!FhZ04Y=N7OPfe}>7@TLJ-H-z-%1SxQQ# zZjafSG|yDLDA(+yHDoGX<>WLTWgXn`Fm~9I%*}iYJZ{yZ=EifsA{nLi&@Foeal>?o zCewWI65$u4#nJCF+ck~c@Gx@J-q%H{u&2e_rND6p6Clh`T)z?{(G#>mRTJ&p(eWYg zlQV#qeW`3EuPpYT-*L^^_G?eU>-2O&lAAIiY$Uu5^KNLEqDM3gt??sS6y|Z*yrkz` zGD#0EoxDVb#C&=dAKdrEorXthG0@g7ZdIlZRCB$4R__sntTiVBFcEp}(sbQPPZotD zZj=Ev{n;pMZh=FlrEq9a{$xc2rIlP6g>`H9QI;qXmO0I?zoEy#Up8u_1>Qe`cd!`9 zTpr?cHD9L#%}um@iO=QYnopX|NOsF5q#Z~v>^|m*J>DUsG>Ccz01yHFphgkRLjEag zHRTtp$H>`5a>qBJVXQV&x00x->&LlD`9C<{xhwhg(lT5-$Mn8CR}a1LeEbdHGYz7Q zZ(3q=nnpf<9SA4MOgVXlI=`DK@rpzpbwi2pz;`<6VsApVgQ_&*s`HprNe&A$%U~y@6{3$bJvhvVwnIE-=@(Ys= zUY$QhZmD)wvmB4^pIzQ~=&feUSThv2K8tE$L;)FKO(2@DHidNto^W~>DR<7E4Nc2p z9sKbzyny7TPoUEnl`KWa5A^Y|7}kFqzxRBsuM!4jCK8}uP@#zmD$XV~H%4aUWI6Cf zId*5BeApfU5twsf>l7UBDbS3SY@(hRGHElmcoDU-m5HYDFr3HPb{%)1_U*J9MMAUU z6B(3C@x`2_@2Nv+Vf8xFtjgDicoE7~=ni}h(jSys!xC(azP*0C^?Kh?>JCvf6o;~; z{L%;37t1etgEVvk3hH0qmzH4erVNe)7FNU5XC$R{)H`?kHgT}gnk1UNxN*7cP?z$W z{}JU+$V?=IfB|k*Fw9T?!WFx9h>LJFSrQBkGZlT?04`nBa(5h=Vu7PKHH9<#9h7KmfO zOng)3+IN&v)}`glW=Y=4tM4h$71}5-kAGmCohH8!(dzkjck#nEWJ#{XT|i=uM2fDo zXG}{`MsAWURP;KN<7|JWkRf%PD#RUYg}53dU(+U!l98Rmyuj+BkS}o=cf=~m~ggBig*FOOs%Ei zOpCm-M{p(U=U}A~)60lD<2>53Bxl7E)P(CQJa_NL+@PYHy&100ny5M;+|2g9OB-D$ zAWv`F3j(ZIW*WTYSco_(J67SqITjXLUQ^F~J5;s^O@^TL$4-)SLphxb8J*rUggK^u zZXTy#Q0_itM0k>Et@08V#6GgVhf7?xvG}M!ANW3GO%(6;BsX*l5fmq_j;vUiG2#gY zWO5@G67HU#e1I`Q#-T{Ut|;~l^*uQ&nN2$Xnt3QD-WN2O?4lxW!P=XbuXMDheBoQ!cF`!j{!4%**jmCZt|!q6snu^8+`g1510bAk0W9cVVFlNi@+ zfl%eRF;%a(*SflKLgHg;n;J#5O*BF+%sTcC(sC+Xpe8D5{}Q3$GbuAC_1UWes*y=+ zUNwlbS`^ew`=sD}F0KxPqtN7vE8$|4=$TqDDm2!Xq2g6~4*t@SMH?Mdf7Ua^OuQeA zG_YiCtHWq=eu%*JBIgqo?pR&Osd@lv^9A$@_921*lQE&{vImIX{DC5Ege?@89L>cL zN32U_`!(3qr{;mK`u~GlB483z`LZYzKGR$5;v`pAa*rGfzN4vX!#DLMT93Pvrz-I0 z;IQGtNhN4NLlES4-~XQp^gsQerTH%gAJ2l5+u{+D@+XysiTX6S?91^^nHn)DZX&d6 zW6c(7f_9bst5-9WvD@1p(vAvMgQF32CHOO-!gRyPQpUf*qXcMvAIww?c)ob*Fft{Zg!Gr&@R;`@X{&N$5bRm3BK-$uZl7VO= zZS{dUQVN@eZ{_fkd2bWo@L?lazCM2I3;reC1G5~~O-61Iy%J|oSX^(}n z;(hF&Nzz&ku?-^4(ywQZFgW@Zu^`Kaa!|32;wE<+C~-^%%&Kp8CzNu_VA>q&F%ogn zlKE8mgmlg{a@IU!?E=bkW;q|2*m%`dcM*Nhf=F@i!B6Y#KrNi51VwH~!tSzi4R=RC zWC8lm4)@MYZl46ZDL#{B=-NJ!J*%N&CxhS*e3p@*%&ulj39cl;M^Rm(ZH&bqvLXlYW@-eE(ziHer!EE)tX7B zS^DAKJG=Z)0;IiYLOuIOeeQB0rsS%oEf2V~ZM{Toctu|b3Z2zc}SaiRUZRH17P z`(oDw4S#9PJDvf#ZA4Kht|`PZOFV&dy&1FW$RZlL?P^?NTV?Kr)5rXki0}*+_JQBo zG(?Fju+z8&qa3?XA4D31fEe3Gi+t$Mkp7~XQ714kHVfw^J-ISxq|uXB3PMh?kqd5wGP zXPIB&XB`$?Tly26y%Oy~+>ODC_i$z(j1+^^TUIpZ?HjMLC0x5ez}0j|hpC}GcYFYV zNRL>3!HwczsdI%G<&;U4>Fkh!29?jj)cbCId_vY$*+Vx~BDXJ6ePLqW7g_C=`14n~ zo*$hZ^XGx~Mr3?++PY(1!%NNA+^yOYPTdYu3>F|L1JwJOgp+KuTwu25%1l0w+&sW- zi%}zlmk5Qd-1h@pP?<7bh{rt(Y(Stup8y5_w53Y^l3jbzu=d}%V>dTvhEav$+{#90 zDj->YB3&DqRTVwnLB%< zH6wJA3YlkI*b_yM5&X*(hN`kHK<#=eo%Tj2wIsk0)>FD??DUR`8s6gH|5z#CeB7W^ zTbPlt7dSAYDSs*SZq`D{ep{pj(?_mU)_Qy?4cOyflz87>PKd zp$*u6HRG4DMRcrV#fPA-N$Ed%tDFWDiTZH|_T#;T&t8Zo0a(TZTLLB6gA9kCZ;Kmj z*bdynZWf}wA`{F~s~WOW&6}ucbk`A-fChbq#>=``+!uJpm0KrFn5p}AFx1CW41La$ zOc8}bWBfhj5@2km-u+NR zI3zkE+~!zF)OLRx+p8`$40(<%wgmL2^(as{K7;nY?L1Sz%(ZKO7CZ>XIl%Z-WgOE1 ziV;7o1TTN0zeCCsy1;N@yHbB~-OS`{?hwc0mNha$9zy2jBM>8tq8e-_NWbsfGUk1Wza}d91aU?bs zDiwHT6BC7ScA9%WmnXpZmmc5|mf; zIwIW`Fl8AOgPzMu7ei0hTi5v!h`0uiw}CwXu!;guK)?3#KO84W2J)Syn&zSt8BZ;5 z+<_p=obr03JEHZzsqf)Py{hf{KAfn~4P45nF;>Y@*0D@eC&<(14<3#6+etW1=LqOR0p3V3o`_mm&e#-D!I?4rd+`4v-cfzM->;jYB4EH%x zO$Zxxn;Wq0*a`{yC7Hk~h0+wc4RQ@a@c>)1sWXWlZ!vU&|;FnQ@Brx{d?>v*^)3M(B(L`0)- z#$J{VZGgPfKohps{tYM<0aaW*6huHSm*3z}{?RVc$-RCF;7TQHf3prkmnD#xpfvNM z1nYn!Eao2wzd)*kDwO-e$ivZu4QT28vtKJ<(G zNmV!S4}lSvE8cThJJrM~(!hFsb`Y*%Z{8&$-^3m?GtC6p)tTwkV^lTm6X5#@gYa(E z5QM>3GveoxP;51%ny<&yT8E({Mt$hJqxZD; z+>G4WOJm(+tQir(p{$C}7=#~1a-Y@guh&lKAIFh9~*R1%qE;15>rYqD8FlW-;ygGCq22!`$h{I7)wHy=T0 zsZgNdOxq7sr8pZ0+3Jxw+h|u#LHuD`Ae-?WN?B9K z9;VE%wNf{ssujLFxn656$;Kt1Jethu8<+M4H^{;AF8jfGb;p9wM>q025F)OL^y%5b zNCQ?%2=<>0e`5Hz8aq!+W`Zucg5%C?7gX%=W25~oRK(GdrW&MEw^9W^GxrKptAsI9U>KwLz^Hf#F34yU?wUB7#RtE)Tbt`xP(k-T0m@mkK9^=bS)k9gLD;ZxW#ym z8uX*OKAaPIvIOYOf7WGR>pQ>$C7E}N$7D!8SYbfy90ag~CNMK>OQ)Hl!cs~>z7Py% zIv7`9J3%4}eJIpJ{2VKovgzlHpY2cPGOq|haH4W-XmS1MWTwGO%f)2l>t+phb5}j?ut^It4bPG4iN2GI&3lzX zNJ5bGX?T{#L@b>F0IAqu)B17kKHlw0!nxo&8O6-zPHwA~TbgCIX1OgHVWhFn?m(F3 zyZ2nVtlcJ)&G@p+fU*dXK2NJ6>=-(gy{fpJLop(p!q5ZrMV?brJTdsf*ZC-RJ5Ucx z-dW7@v~s@&_seTowOMZP)d@byNjXC!s9!fds76lix~dg$PXZcc^;mcu2|tq!Dp0|r zm9JVjv~s}An(rL!l@(idkV3A}$qEfVI*$g%EqXDAPfeuJ(i0iD8Wh;UjSZr{iG=AY z4ur*ED&_E@zucp#j%;_9a5!Xfr-fpzx}&f?x45`#v@&}xgM>(z3BCB}kCC zsMqIxvGD>+_gG&)EQ`l;EA5vr-8u&Q)D&-Gci6=IfP19_?I6M?%mFH%FzBd;P7Sw4 z3BV(&FltYwVS0C%BuWh6WtE4q6f&{Z_eJ3kD^6e~y17lc=!q``JMgdP>ZJzgt_=fI zbiS$agC)4FB6CXW9i#mMOqKE!KgYF|lfn1206l19+p2A=yq!6P{`ZHTEl)674@RSz z*(v|s6(nL7N{vObvNV*KZ1KJPkW{yqAxu@YU_r%Evo>O4vM=IqmhGcVw*G}RV99JI zoedT!gyTS(&var}R$|zS;P6_&=|&I8xD@}z4C}DwQKT$T4ud&cCTyxDfUeamdfP+q z?b7Eq1mI@^0*weu!SCmeX3{OL?*vsmqPjrKT$0$CS5EKMTS0OLQLc*|kC!m?4r=xD zsbQEotEvnOWm5bqApLhSk%C!?edp&Ts;UDHnxj0`N*#2`T`dg`qZ_i$TwazuvKqGD z-}CHrf8#p$1qSFh`N{#J!dO5KV4cK166XO-qR|jFQ49oo`C#zF?8_QX)}O@^g5PTN zr)+Axm>uTn3isH=51XOXd&x|Hgz&;c@SqeAzc~?<|B+J2y-iipiqv{9nI@I zqTvIeEGjkb^pd??54l77ha@b{{FW7k*;y2%MEs|OF>8GS3#)=zYH>nC)9o_6jgOY6U>;j;IN8@_IjUOW}98_?}LjvTQy1LL9e zmEL(La_me4{Hrtc0-k0zPM@z!mn}!<)K?uie{zq0&Ro3j78CJFJDzXSN`)W$+AGL{ zImKiW5=sgcikt60J~hV-im?@2!Y`FA?FXnWU4Vv@OiT7NDhnp1SZhIY|>M=WdZ6750$uqIuk#|z*WJR-%Jn#pca zWVPb4qhU3Z=*#YL31f(mjdFLQQUiB#XrF-(@{U}0DDiisa&rul1elHe8-Tlm#RC1dKuwXCaGwWjC(i2yxOVHPtw@H8P(hRF{f|OAkPF zZp&@YgJ%7zLN0U0y)>)GGm%QJ+OJ()M`BiB%a;T6JW4pf9eDk1ppJ^&N&F7W2GlG9_Q(caK)l_S- z4qx~=WRUh`S9zh9a<(SNoB&*^$tTgb+~fanHZUihOF)4B3)^!RuUF1c~qsov5M#hutL7xL?k?M0_E9GFr@vrwhCDe1u9 zLsFf*bZ}mbUt=s7x}f$y0;n)o&!MX3zn-Wjx!RlCY=dKvCLs21caUh%c|B~B4N4#K zdgzQ6AOQ_E{DapH*SG)x0x~;SP~=LWxHJ*uS%d@t00fCLGeq2U zy1*(2-T(jusThU+i3mAN9*L3NiWYJQu?7A(-H6M1*jTka8h00xzM48B`X;gmpqtS0 zZaVPE+LXyP;ll(WMyKatRf~Od)WSqSS@4q!Aa6gsQ=w4Fuk}|_^IKfGkVs(8{42le~RiwIOufy9=hW*m3LN<@%$Jtt6tMMh~x_+BW z%-YQ$W$+wwiIKshJEevDLvojoXnQ{WV1SRVV}W|~^qrKAbI6jJ<|+dB$*CeS%caTH zL*ZG5-{w~A=T}hw|F_|+Vq3~(W(`W%n(8zxmM>8(>pYz*tbkcF$KMo>Hp!$% zml|f9MNv8?O!`F;4{rGjo%s=b91hkZ9(_>-&$K+tM0yrwURsKAdhsyzM|gTiJA}0w z&+9D+=6S+Zfye64djJ3Ad&|+CS*4Vo8Ynr{{4orqJ&)zU4GA)kg8~d?C~-8j;6_7T zB;p!Il1&|pBJ#Y`-QAK0d9b@{$}EnBiUwQeXTb#HOb1+q&4mIjvwX*72gvmE9}2;c zabl_5l4*@r&w=4p&uNBp;*huZC?zRtbsekvdT;Q`qNa>@a*+do1_rKFzK9YghC;1M@7HWP@JtxC}CLh?7P(8}LM*9A& z*?`i0@i+-f%`+?IsX6bJ{#M7S)C=l1y*DQ~KOQOm9oS-12j8fBWH?8eq!_sMci9u|2Lm!Z?zgswbz ztiUsYyr0oDmihPq0E~{R`)OxRQb39*c9s$dS0yr@TLTsied}0u)4ZvF^w zm$I*tN%XYko)g~uV9pvt_Z1temv$S}%1%ug5R5uY8y3xg+qeGe zo@Aq2+(5nH44U;jwE<$iXCJZaTz(xXFNZ_=^qP~`0OOmYK=CCYw@ zzvhcGq^*ib3W{^jnwa94VkO}XQ;ioAEDQr3h7I-6XETf|vcrz=CMg0Kw2_BN*(OhN z^4l3LWHXC?Z<@~U5R44@Owl1tQn|4J{Fp~QC(-zkSDrjpDlncj@Wot|aO5qWgJQ%~ z(zEL*`4l4h9;j3pk7FYR%Fk}B?|xXIEx@lpU>*tVU&EFZUgM17-K*&aUX05qL76W9 zX&?@-PaFtv%j-|4MPMYmJ0*JrL_AqV|ID?$K9iwW7DMs~t};x0Y@J@o3QjTY))$B| zo{l>pCOjZdt-t*159#*54-fXG<_E68FYhhNmvk)lm23`lJ5P~CYzdygUdmF}uDTpw6ZqFY)C4S% zHz58b8j7XqUZ{QrGJz(|V!B#J$0_Exo_#a=v=@e$dSrZP>^XrO`GR%;WSq)eK6<3% zfK%?K7i<@*(v6(zV8_artN%=-Riz_fPGP1_H!B!2A{hPORQ9B4bhJqiL042pUeYq@ zfA6uJrrK(uSJ~N6NM}^VW1wL+MNb zmwdr7b;A@^RTY@0>n|zVPtz3~mDk9>idI2*Q;;4aey=uO%EHsnsaENmGL;P3Qu`K+ zrHV{$a%ag21>Uh3 z;&f_|LwOLlbQD7Okqh2LFL@BXzirgbrYYe^>eTAX_55)x zW+EO1v%IsBwo!>@sIEYb17o)|i`qW-cBn*+f{DBt%&Y-viMvt^^KV|T zRVg={Ii1sSRp5Vp@I7BO%5_+Wj|rHn{?~*1_|yfOTIev~D>G*(zs}Id#$l<@wQR$Q zaj>@Fe_sxZLQ9z=uA9h~o|Lg{dOw2;L?$mu__Hx_Al9I8~k-U=P4K2k~yA1Eq-;l^F=3R(i(X)`ZImK-?KA z2Q+jgKFU$%eO6Dx%?^bc7NqXfcd*P@Y^ZbbmZgH6MX*@KG1q27B<7G)?+S_;A0O=Q zpH_xJ{`IenoTL0a0_=xzH~rZpH(JrB)5%(&olA3sK&uqs@4yt=>(Ylbp8`RQBqyp1 z)1qcE&{hI=$IsS7Q8{?uWtM|DJaww;3=_GkRQm|AfAsKLJQX%Td+tned{13$kv9pK z_Qh4z%fZGtfSeYAtej0y4tEo9Z-RN^M|1Kd=0Qi~=1MiH7W6_gCfg8d(~#08q` zxqY|6-polk$|r#r5`@ZrBYp&4hp`j}h)aob~S>+-{rY zK^jrU4i>&-sgM|kq-LtBXlCk)q81fk$y--PyfyJ*=Bdqw-~$=Jii}~xa>5T4BkZ0L zau(`mv$Ipp*kJw&DygBjwPA(&I300DQbt%TxR2S3}M51DbW|H0A4@S^c47pQ5) z5qtU5xlKX29JCJV>Po~;mEai zH{EEnZN)9Jf65&iz!La?5jg&U^8afXqBh#L#u&`nhQ+8ewY>D1Rzk>#XUFQf=rhOZ ztNrv{;fVu?TF-L6z#Mwgd;$B6rZ5VC`6um(^9)UWt*^v*BfRW9;FXvlAG|N07h+O0 zC1f>yuaf7dcybgGh}9+|K9VBaCOrzrCM0tgItXT?7G!jt4sO#5%r0f8$P+cDRgnvt z%;}X;`9blM%fmgL)g1_1#=&mu`IU^F9gnfV03su<;>9H)2=71u0A~W%4vmC_N;8A* zDjom;1XxgE#Ms4kYkjL4fUhaQx9pvOIR$chkmCar+WS=UB`Rf-#sc<_f2w4SNO z2Dp=VZ9||T5{RLe7`y-XW?*@Ne6>Iv_I>$l4t5RxUJSF1qI8XWPQ*(kj|8&LIjVLX zjpdQ?bS5wT{0anKe;i~so|1rVGr%KarRJ@aVoupnDru<2gx!n_kBm&bo$6SD2J4@y z4~&HZEh>c1Me_cq4zrE=$yJ=iO`a9jylxAdLG3B;PITQg#QwcDyJ41j`XeM4g>!Gm zU@%eml%7rXWjg#FlBmlV+AOO!BxnP3j7+4{Lu~5Ki#osVKyuffd<+XG8jm&&G7~Q} z=w4`iDh)Guf{{gapiokzmkF>qoswMIUygY*UbDnrI4P4Tf}ngRNC07PU5P>r)Ao4R zZmj|is53oqt0pHmoHH;uAHJ*^W<|!*G`|Rgph-4oD3YJ%+>XEVfh*v2vQJV8ktD~^ zBK*3pdgLa601?Du7@nsPTp^VL*sPha5e5elMg9&_cPIFe4!&)m*v;m*n%&Ur`qwD!5$~;(kdZjIK+raJ9bgufZpStWz-JHR_0b>2 zAw=SJ@hUAfk}0OypJXvygm_vXhHjw94!%h);zHD#6ZMRi0p~=z{p)ekTRqy~Xc5(D zS}jPB`O<6JsA2zzCPZh5&{QF`)o6aP*vP_s(w=nUNh^e7P)YZ&3Z+2msOTEYHrjgQ z3ZS>W*F?>Q?G*r}1Y~c}tTz)AVi~aj}o#}!4Q=Jl)$YBz*Rb#u!R>OAk6hum38rgUr6uYoR zdq@}~+7=Cnb)JNKdLjauqq=aM(E=T_>fIR3;}{-`V!*r=LZ<+#FmLX7h_ zN=>bi?Xxc0T3N&05@s-o7Rhk`-<_|y9>)@S-$?O0w&=Y!v{6uE!_eCc*pkDsv`icO zr87XjT*MJ=BNg)s&zw%2asO}Q$nHOvwD$qKgqosX=q18#w|)^5A1F6HM@?Ewne$8w zUyWqZPlPFZJ|qrrltSmmGC|{TZ|Vums7|w23x!n*J~WeYVN;upF}X%` z;=v>Vbj-Fag?B5O{$@7PMfhhbakt;fL~E2ah7s^!Wx(;lR*kS4vFv@%L%pm&sk;UQ zEdM~fo^I{g&Xwkv8Ih~^Hp9*a8#=w94uMbfs=m`9a@7%D*!zvCX35WN=Jlue%>^g4 zjqx6kGOl2UGi-u0zxa;T2mq`f4JsK@@VTC*uQMVxay+^tC2C>_r+=6X&GsZ41^`tb z*-oO^`vTn%*d(1_Fkvcj5xa*`eE$$hAbi#~sL44uOVxtTR*zKR6$8 z8lCKYH~;_wS&~Rr&F1%2B@JhoG2YujJ|s0HxHyYWT63Lgn`-|pO$`E`Df*ymVR0JXXT%kep&glYl*h*ZH>`6RnnjnNp#FcGyp4aC(6R! z1pB}M00I25Msf}wMyn<>GUhSa5BKl@01*=#>9~rqi|X75m8rEoy8+uU6e?kK)@-SW zY9w6#_M%Eb`n^Hxo;L~}H+;Qn&L)k zbe97Hoo}F4qmRu_HK)oyYB8GU%J^fcN?bI91K)wLXZN)WSILavFRP zLkcE!(U1V_Gq15<3;p|&x1V?M+{6zS4vW}>kDEM0YUvdVXVkqXWy4qeo&B}Y3?E(E zs;x84Xw~_k(tE*`KJ9{{6nB~;(70ek&MO$4u?&uZi{Jo6%==WcR^^E3dn*h} zq%8FXsGnLzbkTIQ79|0u{#|I6do%of1@x~KDRiOsa_~~E`0wg{%?;wvF0-o8;f~_4 z(c{Jn3n&C%EBCPU!gLLMWOnL?ld`=bU8&j#PXsS`&s zP{m&Ztm2>F3E`5v2M3lH7DM19rl7&A?B=aM{d%hHeRNk2lj2;#{ObLEiYAeTZ;H@z zUNnq{`qK&f{f$n5pgmCs`DH(3%Ydt$O~WBEOZ>4+D)%uz?)tlMVF`Rrt!GiN{Z==x zk4u4cf%})^`aCN|j2yU6oM0gQ2H)+m-6kST#t;KS^SkwOt)(3dY@QdWEfv*8j-fnT z$9nGZW2T+%k`jA&b%g;%P4EAazVx|NTNKQU2L`{RVLJg{f-2MDYlS{9rKhyH_RCnf zB$tYG8qeD=+z-a)K~G`T1SDYB;2?SLUDhgl;-lBH8=P~#<2gC= z7}kn^q|n7>z~RP*6~brAvoq!6^oARdJ)--!w#ddo-8OH2P>}n5taK7;nPHy9yyYtn z4~4tUac4q*biH-R)2x=bSxc}GF5oO^*Se2-m78+n_;MiOxqb|@Nh~sY_(g$J;Z;KB z_j4Os*s2-gUXCLLOr@vHgC+%qT}!c|EUwZarHQd+;tcs2&6GVsBfhU;6zG-b^9LAub3i1&)Db`qF&use?s zQY2UQ2h11&nd?hr9Jcir%9vnj7)3csqNO9T+DPolrrt<_{Cxc@?WEo)%5@={0LO#F ztk?|}#z2-7^3P08dU%hRxaITM?H7~O1rT`Zs;%~^m~ZG-BNv|=*{laOYR&+X68iFv zbv2dbZxIlhSk+qHl_KuvhheWbon3%L!DXjXO=unu{^ie-)%Mx35$tw0sN2TtHwW!m zFI39JHU+BX6wczLn3exF>p>1DgDd|U$rLjnal~%I5tr}*64l`%m%>93`{eHKj%VK23z+ExN^L$kXD~eFZL*))Z5l zc*k+vv1&2t%$gDQI1~5xvRk9M+w&Y-5pp8?w!f@Tkd8k6Qy}0kS#o1i5xg5KDAyer z{tI=D{ECD?g^RqR-@;7m;M;c)H$?jueITAi{DSez2D`lH*ddqFn}QT&FUp*Dy#qEe z5|>|AeP_&QAfzl+0Mzwbq{uCE8=4Oa;s3Lwi`?_HVnz0*DF!tQ4x+W(1*RUA1O&#w zSty`yxfUkj*%!})M~VKv2LV6uCaY6og;){7+Ye0%KYz9}PXO8uNS(nZ&wq_&5!X;G zcIRo)^^1Mfl*_cvpjTKP3?5!aUdb+_qRfr9B+g6lvl9iONLj96O$ z-;nNytk%9g;caWB>2#o+ytyXKZmt&PJ%O0;O+58U9OLSbR4-Rhfbu$QV)qu>^J|$e5W0$ZK2QGYUS>Gf~4z^TN@zT$sx}r z22Ii-Fyq}AduQD((lC%bebMlyFITbMdg}jWfQ(2_^!G%6>H*@R^x{P#ot=!$v>8=L{1+?zLvJe(l@%W4)?%b z_$;H5<-YF&)5CAKmmp{xCKQ@Vcqdp{zA->0>xe%9X!jMxfzP51k#HzHPihrCkJ{Y} zF9hn)3#}^_(i$;R@-w(uh^5%aIFhBGUzc2EEbXSmn-;FHz!rYZJ@lF|KQ~hc6H8vg z2eJYjKwj6glRnRJob0)XuxWizJjv$@1U$1iB96APTlulKK%1_5nsveJB_dL6q|Do2*!cPX=HW@50Qdwys{Y63^-y>oG8%2?nj-k1ahcO*bep{v{noGDy)c@ z@Rl_s!eY%-!lv-NuoMZeTcwd!l5M9i&n~U%O>v}>2S8vr>;73VZO{fCoa`5at||XQ zlN8`9fKWGq#3^Vx!=Z_&>#itPd;H5CkOLP7XF7E92dmPjXow;8=d8mq?)Tf!3+IajCmaDGii8$>pJ?1y}Bon5|rG+CV(f7yUC0*T6hE-*t z&{UuH+SVhg&l!0c&{*eIvvo^xhIPBn$u(rEkCOl*+qQI*lTv}deG1s*r&lwQ_lX1j zv}=fq!MEiBlaqU@nVg!?6<6*As^74y;So$eFig;3Y?g{;kEBYxj51j9@Cl2zTA&zi z8m(>5#sNywMYanefK`rPNIBVZts{leOapm}>r7Fevzwm*swtEn^|`h-QGx9Sej&&K z9?Z?M#)(L}_B+z>g=5FD-+SucMXiqD3C5$`6ZbkeGJM`|6uXUIu_)$lj)SW8ElU5f z&f;w+&Dw+NO>3U8aqkgPVdhyeywNN)i)jN?GL&L>8s^LuR&0Q3 znxSbbKDq)Ql=#bH5m`jgr{OjDs_i+6Y3p)b!j9G@O!Wr-US zE+k3Y!s`kz0#<@JIj{9V%5TKga7*k!MAy7a*XEWYyfFF(d9dE)M$NLpj6jGY^D`UX zx5>6sxPdyh{V2rUDLBiMYvg>0*8R9$MYNnbM6Tt%Esos)CCX#h`@U3ge=j6we(x$o zIOnms1|F=axGdS~ihID39Fz4%A7PMXPFKlmTygN*a#vQ+RV(##0s{+<3rxt@S$j9J zQjz9`_IBi57aR;G*IoU+4iI`h(|&dH#^ zjZt?rm{UShmJg_q7;jIk)cDIxmOmj%5!@T5@9fQmH&MR_W7S3No+dcfgUk{UGw}sr z;1S0aN{G&19>v3qdC0zg8949?{2RsF=P_R_q)Ngrpx|NLbJXb(!PS6zE`=t}({H(u zn}d(v&+&dE%4_=X8?^vXU?5h579MvCELuK9*#Lmg!4FshLhEz_o!fHev*q6UE}Jgd zPK1cCk^!K8ber2q*vRs89Vw{594WxR_g)4)U3cvN07V`EsWZvz&c6XOzxC=QL0@Ia zfYp{6f_^3xJFJs?Cy3bG<&Ro}Cg!E@0(0+P&hf{N6{rVvc^T@v{y5U}r@}02QZrEp z0>UoE?rssTn!nxP9v2_bx;fWl`?)F61i=XPT&K5{gDgT1RVK zjVjfxP$v1W8E&|GDb+unqE6I4QpsKA_y^)euXSd4Gz5?(OB%(d+_T#ObivXynQ%6IMF1pXy&5Ci z4_6^5sq;}-ae1ix*f@~pJsR#ZV@n#rirJvfh^`m4GFWY@?j(a@JslL|T@0;J@3zlO z581gf!0n-T6r%E^WZRZ}@YjJ^*>2Ne9q^3F%e#+u--w+?;wUe76iFX$E`?A7rT;cH{hopLzcGtWc$GkyKF)4 zYdjrgph`f%VqH2s7>&;G^xS>xYkp2&e3WlBuB`q%`q0hCYWXOoUB&`<_oSR-5hIXc z2k=H;C4QbXz>imcf#SK;;jkG;q{T7qK+ z(d2yopdtqDao|gPJMH0)1THVMsbPWUyaPu9&98eV0&_;QrQ7%a4m;G) zvGU-eTiPhqX{5j98&ZE!v*m|&2ExS?l2|*qmvJ~}2waduY!R#1fbMN%s1}3_?B25N zx|ejCb$AGd%}t~t0aolKBw$Q^D*hfZJE7D>Z**Vw;`7k~fHV|isGFbSgF!r)&s3A^ zEZ0^K2$erUODj1=6Pz18UnzPKD!Fed{yD+v%z3RTH)7*xFrHYNL#YJ4PM8jKo9FN; zDysb;=C$pcs6fZ%;HgT;I%>}yYI-Gr>GBUQzS1S-iL^cMm|PndQFoc_DM8>t2lw6e zOSNfVqkhP+NxNQM-EbA)>Mw4@6L2cow$c~*+K3WdoYlb${cTcz1I1qsT5Ebk(J~{e zZ44ZC@3>`bw~s?#`&%d8(Rfa^kKY5eaMN;H_icV8Gz+zNB(1L`mL|=jyV2!dVd-CB zXNBVJJ_%Onu7wQUHQxOATU`b3I#bW%e5W`Q0J(~V-lGqj$GOhw!b(}?3ia!ufl9bL z$|UCW$h$Cz0XcwJ$KwYkD1`otWJYMNw8p91eB01=Wl!U)S$z3!UA=3~xlT!Egcq0s zeVpg8rID}gWCW^(gZrZ3aYY88i0qXB)pu@O!@|5f!f%IFfTL-`Ff_XxH`IKcIw}7e z0WMD8BujqLL3opDw;TPI($+>%h9G$d&U(7bEbb|SmXti(MWx$P7#yfrEFb7il>c4#!VJz_Y& z_YQAufsES!R(|RCB*IGPfYhgQHkY-)NO&!Vk_1hC1_uG;3|QB3&v6`w-S;(j(qZ>> zu2Q+b+v%bU79+9uAe0aqE77&I_<=Ym4+}%+-diYG@EXbG`k0eL^+<(5g}2(HE4UE0 z(;tzG3E_r(!$|+^o~vW6yu-wn6E(PvQ~EQ)Q{H_b4N6`j{IoC+@_7Jw<4#$~X6;?{ zoQkxsJc~UHd+3C+)UnePTT$qO2mxAFZmgGIk3IfGt9os0Ls^G8mxu%RdmHF2fXw0zB)mMo`Z=I()la8p>j^91J$!U~Y zpJ?YCd$04Fsssdt%qHpjtGQk75Un<9%W___W6BsbJPF8o7PMo{YCeFw`x`@hVcjS} z)VZjGA7AYr&VOU(FQ;Zb;c8PDakML!(v_mCP(<}W6!uhUnBVvkrlZ=8?R=Uz=&l=! zKQpW6?fA!)Bd5;fJ$4GC#jAo7U9-&VW~TtKWUka;Wl9uQfRK9zY#EQW=z#hQFT&~f4Gk(nvo&@27Y^j+ zNT#W}hq>XO3rWn$dy#QbruS_J!@iZc)KSdhYWcq0MERp#B;#`q=I$WHSr>?Y)F{?A zBy5vON>fYP^?)5OXq4=pT#ef4%B=xOP6)*A@_lk25rmZd9~gjbX2C{$cDH-rss{f=+D z>#gqAe2oi)`cnu%KfLB4G?u#5geNscIS8m+Bk^u6M6{=L2STWZZuxp zq(HxON9ZS>gc9c;3puAu_TD|(#Q7iTU#e8JBAMCn8Z1kYGumvCzo{^%yDMuGGAULH zJ|$FaA;YMl#sKco#!T7PFnLKaQ3BPyYu7DPN0AHB`SOAXNfK4+;)w0{87B)hEXRVO1g%+f$ z11;e0{%g8KRk*kPbMH~b3k+3Sye3!KEdt;-`C;90$m9~j0~Me0+zE5|R8@ybM%3e> zjbKv@zo_x&BvyvHt7)FnH#v`>smFi-eG!4Pp}!@~X+JsuyTR7k`@wmc*Nus~4-!|3 zUUSCB+YIlME82f9kdor{kkF?Qb>uC=t7_+&Z3|7^3C|#a4p=1ke9N$cTShpjq&qe8 z0(wc3#fG6J__a5G@bXwrbk5XFw(fhq1+oGJVJkB}mw2Vuj)Jm`Q)k*EyShZLgnSg@ zc<9KO&`&RN;?DPvJr%`!xnl;+f+c)14r7VU({U$ zP#k5E0#tFu10g!j)X{Mu#QREERG?w<05_X8rN?zQ$kY5<$jDQJk==BTXeB&zPYO;* zL!GEECLGZGz5HUIqho774nE<#R@O=$QW|!QCW8JrC){kJqfS$(v_Q`&f8pN1ZZ*2! z40~dp^$@lTU}vrDS!n*NWyBdVPNV^y-FEWN@nykQ z6W~IS_r>Ntv0=at5v#3LoXMkt;+sWY&GGPHqD`W6UJIo}-Q50l{1A)p006waOstID zVz~SaJ8ib8_CNk<(^ZxPEnE6|6=#xG(tF!&ASO+m2z!|i?bIY3D=97(RJz!g!G_{Y z3ck_>0$3F{V_gFK{Qf zC*FcCR1;pk{ZNpq$dpwxuvze~Leq3~R5biRRSmbA3Kj>5qrG}}oe((nzy6S@#{xaj zR_iavB2gmQvot;-1O07fzG2bp9KgQr19q-|@e?umjL~PxCW-wZhao&{ha9%mD^Z{w zQU)J_>|Ysx5V1iHF?Wd61(f1v{_!}}Y~?#FBhH*&rg zE@CGTYr4M|PxUri^r17ipYFNkRDy&sX+O_(!b+f7A3d}hfQswg_+ z(C@7=t43y(F#!u9C()mEv7E`IS@{4%^$_v~q+tI{Lz?-?i~3bJwB>5TY$aiKz*FAD zNiXCtH1Ka0;%7Gf8hn>FfqNfPK}FWSaWrwu4> zkVpN8Yki&`{O5V9SxrcnTU=A?zyu5xQ#vC!HGVK5^^JWOFD6_xEDuTh(H}w_Hqx}T zU%n>kP8u6?ii<$;cGZYR{_55S)_J{t;mzx*PMDpfS(NH>Q(!*How>oUKZ48H0`J2U zRPB&Ck#**Ql-)W9{g(=7dft7jQ3)a~VB!urfmfDruI(O9^9+(DLiuX|)MC|Wja28< zxhXr!Eeb}%TIO*hw$>Q|Mw^h61Zr8j$?17s2Gbnv|D-*fP9f3Sg{d>sxp3V1{b4WB z9FHU7nRlA%+D7d{SnaptXRMYFc(ggiBt`s8M0$Vvhi-g{=ORJb&^xei=b%I$h^^?IJgWb^$=^Uig z{VzFG@VCOak`O#mB98Pkwb~Om5|3{;pQNoC30beDT4C3Mv`7^fhT0vlgV6YIU^R4A z%ZhX;gW;)L;LE|}-8@d=Rr42(DwV`HSl*`jxln<6VEp|F9JS+EK0QZb;GUkfDS*0f z8&(>=b)!8A5l|wc;;KNE2IvqwrG&>1;)N)eAI%}0K zClv8E>;Hq5_?W6Du0RA#NCHC z(Z$W;CLW+YNunjdO>ZD(Z4g3mEA6Gg;6x8jF%=*$tc`{|VKQ9;yHyF=Z`NC$E=jfnxolO_9Ye?~H7myE}Ue z4qK{r*1{X2B=soM*g33;{F+2DBoeMtxQcz?)et4uMtBVwjc;zBY^!2w)zB9h!QvAn8Ldd9U*$R+omba7&%E|xo~2hL$ZzU|c%j@1t`XTHyXSmtyrf~B!< z!&}!uY+3}WH=m65BRv2CA#FOyoNN-Ncnb04QvA66`4RC%iw6uz)cOCnyV|=3_dd;( zh)(9)ECY;%B7aRgYH!yxZG8{KEfDh2yi(pQt$RarAk`MVY57*)Y$en2uNBvbb=}|> z=ea6P0Kk%Qsj5k1C-+{+Jfr80ufgr3_=Q*k+a%I(V~q(4-&_sGgMxRoUd>q_>UW>? zq9l*@?-+Z!T9BYCY=>IFSV%%{twVs=_vJQQg%7cb0YxogRfacuP8Y;BS3kZKsXs=e z<8V|sAz8;%{38m!9>x%#1rG;?SpprOv95`PpMbt zI%m9ktQ`3np(4(g%8}S&EvWklh5jXfFYpLQ!HCuIXo}b*Z$EhEvZzT(E;l4}wa9T8 zN2deN_@WcAr12?b9pdwDTR+kL0000O zD`N9a29pal@NSTyL%&XtN;sq?f3kxTdB72dLVON&ZRgY5(f|Me2gI1fz~&Iz)+UkK zP%=%wpdyKkjS-C8Rlfa0k22e5JJiW(| zPD!kygz--=M?+=^p;n&E5kjp!m?DK*doV=`wDw?%6>03j6e`o%f+$s|vjkA9Pi6?3 zye>8pG*zaiY|w|FglUw_D_`@$PXo0Y9iQekt}9tyL)=9>%>oqy!w#Lo={SG@0M-fc AfB*mh literal 0 HcmV?d00001 diff --git a/apps/web/content/docs/dev/moderation/moderation-scope-editor.webp b/apps/web/content/docs/dev/moderation/moderation-scope-editor.webp new file mode 100644 index 0000000000000000000000000000000000000000..e3a0aaf48f04a5eb7016758ff4a2a7082a27ce35 GIT binary patch literal 77274 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 literal 0 HcmV?d00001 diff --git a/apps/web/content/docs/dev/moderation/process-reports.mdx b/apps/web/content/docs/dev/moderation/process-reports.mdx new file mode 100644 index 0000000000..100af5ec6c --- /dev/null +++ b/apps/web/content/docs/dev/moderation/process-reports.mdx @@ -0,0 +1,118 @@ +--- +title: Process reports +description: Review VitNode reports in the Moderator CP. Work the reports board, compare the snapshot with the live content, take a report, hide content and close it with an outcome. +icon: Inbox +--- + +import { ImgDocs } from "@/components/fumadocs/img"; +import queue from "./moderation-modcp-queue.webp"; +import detail from "./moderation-modcp-report.webp"; + +The **Moderator CP** at `/modcp/reports` is where moderators work through reports, signed in with their normal account. This guide takes a spam report about a blog article from new to closed. + +## Before you begin + +You need a moderator entry with `can_view_reports` for the content type, and `can_manage_reports` to change anything. Hiding needs `can_hide`. See [Configure moderators](/docs/dev/moderation/configure-moderators). + + + + + +### Open the board + +Choose **Moderator CP** in the user menu. **Reports** is a board with three columns, **New**, **In progress** and **Done**. It holds the reports you may view, newest first in each column: + + + +Search by title or report number above the board. Type at least three characters, like `#12` or `gift`. **Assigned** narrows the board to your reports or the unassigned ones. + +Search and the filter live in the address, so you can send a filtered board to another moderator as a link. Each column loads 20 cards at a time, and **Show more** loads the next 20. + +The pill next to the reason, like **+1**, means other people reported the same content. It only counts reports you may view. Reports outside your scopes never appear, not even in the column counts. + +Drag a card to another column to move it, and the column tells you what will happen before you let go: + +| Move | What happens | +| --- | --- | +| **New** → **In progress** | The report is assigned to you. | +| **In progress** → **New** | The assignee is removed. | +| Any column → **Done** | The close dialog opens, so you pick an outcome first. | +| **Done** → **New** or **In progress** | The reopen dialog asks for a reason. | + +The card moves right away. If another moderator changed the report first, you get a message and the card slides back to where the server says it belongs. Cards always sit in date order, so a moved card lands where its date puts it, not where you dropped it. + +On a touch screen, press and hold a card to pick it up. With a keyboard, focus the grip next to a card's **…** menu, press `Space`, use the arrow keys to pick a column and press `Space` again. The **…** menu has the same moves under **Move to**. + + + + + +### Read the report + +Open a report. The heading names the content type and its author. The main card starts with the **Description**, the reporter's own words, followed by the **Snapshot**, which is what the reporter saw at the moment they filed it. Choose **View full snapshot** to read it in a side panel. It never changes, even if the article was edited, its revisions were pruned or it was deleted. + +On the right, **Details** opens with the reported content: its type, its title linked to the live page and the plugin it belongs to. Below are the assignee, the reporter and the author with their role colors, the reason and the **Visibility** of the content right now. **Linked reports** lists other reports about the same content, each with its reporter and the start of their text. + + + +The snapshot names the language it was captured in. When the reader asked for another language and was served a fallback, it shows both. Files appear as names and sizes only. The report never copies the file itself. + + + + + +### Take the report + +Drag the card from **New** to **In progress**, or open the report and choose **Start progress** in the status button (**New**), or **Assign to me** under the assignee. The report is assigned to you and moves to **In progress**. To hand it over, open the assignee and pick another moderator; the list shows only moderators who may manage this report. **Stop progress** unassigns you and moves it back to **New**. + +When two moderators take the same report at once, one wins and the other sees **Another moderator took this report first**. Every change carries the version you loaded, so acting on a stale page refreshes it instead of overwriting someone else's work. + + + + + +### Note and act + +Under **Activity**, choose **Add an internal note** or press `M`. Notes use the rich-text editor, and `Cmd+Enter` (`Ctrl+Enter` on Windows) saves them. They are visible to moderators only, never to the reporter or the author. **Notes** is the tab that opens first; **All** and **History** show the rest of the activity. + +To change a note, open its **…** menu and choose **Edit** or **Delete**. You can always edit and delete your own notes. Editing or deleting another moderator's notes needs `can_edit_notes` or `can_delete_notes`. An edited note shows **(edited)**, and **History** records every edit with the text before and after, and every deletion with the removed text. + +Open **Actions** next to the status button, choose **Hide content** and confirm. The article leaves the public site, search and the sitemap at once, exactly like [hiding it from the AdminCP](/docs/content-engine/content-visibility). It gets a revision, the `hidden` event fires and VitNode revalidates the caches. The activity records the action only when it succeeds. **Restore content** brings it back. + + + + + +### Close the report + +Drag the card to **Done**, or open the status button on the report and choose **Close report**. Pick an outcome, **No violation**, **Action taken** or **Duplicate**, and add an explanation for the other moderators if you like. When you already hid the content, **Action taken** is picked for you. **Close report** moves it to **Done**. Other reports about the same content stay open, because each reporter's report closes on its own. + +On a closed report, the status button offers **Reopen**, which needs a reason that goes into the activity. Dragging the card out of **Done** asks for the same reason. + + + + + +## Check the result + +The report sits in the **Done** column, and its activity lists the report, the assignment, your note, the hide and the resolution with names and times. Open the article signed out: it answers `404` while hidden. Open it as the moderator: it loads with the hidden notice, because `can_view_hidden` lets moderators inspect hidden content without any AdminCP edit permission. + +## Who sees what + +- **Reporters** see only their own toast. Nothing about the report is public. +- **Moderators** with `can_view_reports` see the report, the reporter's name, the snapshot and the activity, for content in their scopes. Without it, a direct URL answers like a report that does not exist. +- **Moderators** with `can_manage_reports` can also take, reassign, note, resolve and reopen, and edit or delete their own notes. +- **Moderators** with `can_edit_notes` or `can_delete_notes` can edit or delete any moderator's notes. +- **Authors** of the reported content never learn who reported it. + +When content moves to a resource outside a moderator's scope, the report moves with it. The moderator loses access, and if the report was assigned to them, VitNode unassigns it and logs that in the activity. When the content is deleted, the report keeps its last known scope. diff --git a/apps/web/content/docs/dev/moderation/reference.mdx b/apps/web/content/docs/dev/moderation/reference.mdx new file mode 100644 index 0000000000..f22cb421fc --- /dev/null +++ b/apps/web/content/docs/dev/moderation/reference.mdx @@ -0,0 +1,164 @@ +--- +title: Moderation reference +description: Reference for VitNode moderation, covering the reports option, scope families, report targets, permissions, ModCP API routes, statuses, events, snapshot format and limits. +icon: BookOpen +--- + +Exact names, types and behavior of the moderation APIs. For step-by-step guides, start at [Moderation](/docs/dev/moderation). + +## `reports` on a content type + +`defineContentType({ reports })` from `@vitnode/core/content`. Omitted or `false` registers nothing. + +| Name | Type | Required | Default | Description | +| ---------------- | ------------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------- | +| `titleField` | field name | No | `admin.titleField` when it is in `publicApi.fields`, else none | A `text`, `textarea` or `slug` field | +| `snapshotFields` | field names | No | Public `text`, `textarea`, `richText`, `enum` and `file` fields, without the title | Fields of kind `text`, `textarea`, `richText`, `slug`, `number`, `boolean`, `enum`, `dateTime` or `file` | + +`reports: true` uses both defaults. It throws without `publicApi`, for an unknown option, for `reports.enabled`, and for a field that does not exist or cannot be snapshotted. + +The server-side model can scope reports with `createContentModel(definition, { moderationScope: { column, family } })`, where `column` is a base-table column holding the resource id. + +## Generated moderator permissions + +Added to the content type's `permissionModule` in the **moderator** catalog, unless the plugin declares that moderator module itself. All of them carry the target's scope family when it has one. + +| Permission | Depends on | Added when | Allows | +| -------------------- | ------------------ | ---------------------------- | --------------------------------------------------- | +| `can_view_reports` | | Always | The reports board, report details and related reports | +| `can_manage_reports` | `can_view_reports` | Always | Take, reassign, notes, resolve, reopen; edit and delete your own notes | +| `can_edit_notes` | `can_manage_reports` | Always | Edit any moderator's notes | +| `can_delete_notes` | `can_manage_reports` | Always | Delete any moderator's notes | +| `can_view_hidden` | | The target can be hidden | Opening hidden content on the public site | +| `can_hide` | `can_view_hidden` | The target can be hidden | **Hide content** and **Restore content** in the ModCP | + +Content actions also need `can_manage_reports`, because they are recorded in the report. + +## Scoped grants + +A stored grant is `{ plugin, module, permission, scope? }`. `scope` is one of: + +```ts +{ family: "example.category", mode: "all" } +{ family: "example.category", mode: "selected", ids: ["1", "2"] } +``` + +Declare a scoped permission with `{ permission, dependsOn?, scope: "family.id" }` in `permissionStaff.moderator`. Admin permissions cannot be scoped. Resource ids match `/^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/`. + +`PATCH /api/@vitnode/core/admin/staff/entry/moderator/{id}` answers `400` with `{ error: "invalid_permissions", issues }`. Each issue has a `key` and a `type`: `missing_scope`, `empty_selection`, `invalid_resource`, `unknown_resource`, `unexpected_scope`, `wrong_family` or `dependency_scope`. A grant wider than the caller's own permissions is `403`. + +`GET /api/@vitnode/core/users/permissions` returns the signed-in user's moderator grants, each with its `scope`. + +## `defineModerationScope` + +From `@vitnode/core/api/moderation`. Register with `buildApiPlugin({ moderation: { scopes } })`. + +| Name | Type | Required | Description | +| ------------- | --------------------------------------------------------------------------------- | -------- | ------------------------------------------------- | +| `id` | `string` | Yes | Lowercase and dot separated, unique across plugins | +| `label` | `string` | Yes | i18n key | +| `description` | `string` | No | i18n key shown in the picker | +| `list` | `(c, { cursor, limit, search }) => Promise<{ items, nextCursor }>` | Yes | One page of resources for the AdminCP picker | +| `find` | `(c, ids) => Promise` | Yes | The resources with these ids that exist | + +An item is `{ id: string; label: string; context?: string[] }`. The AdminCP reads them through `GET /api/@vitnode/core/admin/staff/scope-resources/{family}?search=&cursor=`, or `?ids=1,2` to label a saved selection, which also returns `missing` ids. + +## Custom report targets + +Content Engine types register their target automatically. Anything else registers one with `defineReportTarget` and `buildApiPlugin({ moderation: { reportTargets } })`. + +| Name | Type | Required | Description | +| ------------------ | ------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------- | +| `type` | `string` | Yes | Stable id stored in reports, such as `forum.topic` | +| `label` | `string` | Yes | i18n key for the kind of thing, an ICU plural called with `count: 1` | +| `permissionModule` | `string` | Yes | Moderator module the report permissions are added to | +| `parseId` | `(value) => string \| null` | Yes | Validates a client id before anything reads it | +| `capture` | `(c, { targetId, locale }) => Promise` | Yes | The snapshot body, or `null` when the reporter cannot read the target | +| `current` | `(c, { targetId, locale }) => Promise<{ hidden, url } \| null>` | Yes | The target now, or `null` once deleted | +| `scope` | `string` | No | Scope family id | +| `resolveScope` | `(c, targetId) => Promise` | With `scope` | The resource id now, `""` for none, `undefined` once deleted | +| `actions` | `{ hide?, unhide? }` | No | `{ permission, available(state), run(c, { actorUserId, targetId, tx }) }` | + +`run` executes inside the report's transaction and returns `{ changed, effects }`. `effects` runs after the commit. When `run` throws, the transaction rolls back and no timeline entry is written. + +## Report lifecycle + +| Status | Reached by | +| ------------- | -------------------------------------------------- | +| `new` | Filing a report, unassigning, or reopening an unassigned report | +| `in_progress` | Taking or assigning a report, or reopening an assigned one | +| `done` | Resolving with `no_violation`, `action_taken` or `duplicate` | + +Reasons are `spam`, `abusive`, `rule_violation` and `other`; `other` needs details. Every change except a note needs `expectedVersion`. A stale version answers `409` with `{ error: "conflict", current }`, and taking a report someone else holds answers `409 already_claimed`. + +## ModCP API routes + +All under `/api/@vitnode/core/moderation`, using the user session. A guest gets `401`, a user without a moderator entry `403`, and a report outside the moderator's scopes `404`. + +| Method and path | Permission | Body | +| ------------------------------------ | -------------------- | -------------------------------------------- | +| `POST /reports` | Signed in | `{ pluginId, targetType, targetId, locale?, requestedLocale?, reason, description? }` | +| `GET /reports` | `can_view_reports` | Query `status`, `assigned`, `search`, `page`, `pageSize` | +| `GET /reports/{id}` | `can_view_reports` | | +| `POST /reports/{id}/claim` | `can_manage_reports` | `{ expectedVersion }` | +| `POST /reports/{id}/assign` | `can_manage_reports` | `{ expectedVersion, assigneeId }` | +| `POST /reports/{id}/notes` | `can_manage_reports` | `{ body }`: plain text or a rich-text document | +| `POST /reports/{id}/notes/{noteId}/edit` | `can_manage_reports` and the note's author, or `can_edit_notes` | `{ body }` | +| `POST /reports/{id}/notes/{noteId}/delete` | `can_manage_reports` and the note's author, or `can_delete_notes` | | +| `POST /reports/{id}/resolve` | `can_manage_reports` | `{ expectedVersion, resolution, explanation? }` | +| `POST /reports/{id}/reopen` | `can_manage_reports` | `{ expectedVersion, reason }` | +| `POST /reports/{id}/actions/{action}` | `can_manage_reports` and the action's permission | `{ expectedVersion }` | +| `GET /reports/{id}/assignees` | `can_manage_reports` | | + +## Events + +| Event | Payload | +| ----------------------------- | ------------------------------------------------------------- | +| `moderation.report.created` | `{ reportId, pluginId, targetType, targetId, reason }` | +| `moderation.report.assigned` | `{ reportId, assigneeId, previousAssigneeId }` | +| `moderation.report.action` | `{ reportId, action, pluginId, targetType, targetId }` | +| `moderation.report.resolved` | `{ reportId, resolution }` | +| `moderation.report.reopened` | `{ reportId }` | +| `moderation.report.note_updated` | `{ reportId, noteId }` | +| `moderation.report.note_deleted` | `{ reportId, noteId }` | + +Adding a note emits no event. Hiding through a report also emits the content type's own `hidden` or `unhidden` event. See [Built-in events](/docs/dev/events/built-in-events#moderation-events). + +## Snapshot format + +Stored in `core_moderation_reports.snapshot` as JSON, `version: 1`: + +| Field | Description | +| ----------- | ---------------------------------------------------------------------- | +| `capturedAt` | When the server captured it | +| `target` | `{ pluginId, type, id }` | +| `title` | The display title | +| `fields` | `{ name, label, kind, value }` with `kind` `text`, `richText`, `file` or `value` | +| `locale` | `{ requested, served, fallback }` | +| `source` | `{ version, updatedAt, publishedAt }` of the captured state | +| `authors` | `{ id, name }` of the record's authors | +| `scope` | The scope resource at capture time, as evidence | +| `url` | The public address at capture time | +| `truncated` | `true` when text was cut to fit | + +The snapshot is read in one read-only transaction, so its fields and `source` describe the same state. The ModCP renders every snapshot with a generic viewer that needs no plugin code, and rich text goes through the same element allowlist as the public site. + +## Limits + +| Limit | Value | +| -------------------------------- | ---------- | +| Report details | 2000 characters, at least 10 for `other` | +| Plain-text notes, reopen reasons | 3 to 2000 characters | +| Resolution explanations | Optional, up to 2000 characters | +| Rich-text notes | 64 KB, not empty | +| One text value in a snapshot | 20,000 characters | +| Whole snapshot | 256 KB; rich text falls back to plain text, then fields are dropped | +| Reports per user | 20 per hour | +| Open reports per reporter and target | 1 | +| Queue page size | 25 by default, up to 100 | + +File fields keep `{ id, name, mimeType, size, url }` only. The file's bytes are never copied, so a file deleted later cannot be opened from the report. + +## Database + +The migration `20261011193321_add_moderation_reports` adds `core_moderation_reports` and `core_moderation_report_events`. Neither references the reported content, so deleting content keeps its reports. Reporter, assignee and resolver are `ON DELETE SET NULL`, so deleting an account keeps the evidence. The unique `openKey` column enforces one open report per reporter and target, even under concurrent submissions. diff --git a/apps/web/content/docs/dev/moderation/scoped-permissions.mdx b/apps/web/content/docs/dev/moderation/scoped-permissions.mdx new file mode 100644 index 0000000000..a046dfdcc1 --- /dev/null +++ b/apps/web/content/docs/dev/moderation/scoped-permissions.mdx @@ -0,0 +1,155 @@ +--- +title: Scoped moderator permissions +description: Limit VitNode moderator permissions to selected resources, such as some forum sections or categories, with defineModerationScope and a content model's moderationScope. +icon: ListChecks +--- + +A scoped moderator permission applies to every resource of a **scope family**, or only to the resources an administrator picks. "View reports in every section" and "hide topics only in section B" are two grants of scoped permissions. This guide uses the example plugin, whose article reports are scoped by category. + +## Before you begin + +Scopes build on [staff permissions](/docs/dev/working-with-users/staff-permissions) and on reports. If your content type does not report yet, start with [Enable reports](/docs/dev/moderation/enable-reports). + + + + + +### Register a scope family + +A scope family tells the AdminCP which resources exist. Create it on the server with `defineModerationScope`: + +```ts title="plugins/example/src/api/lib/moderation.ts" +import { defineModerationScope } from "@vitnode/core/api/moderation"; +import { and, asc, gt, ilike, inArray } from "drizzle-orm"; + +import { example_categories } from "@/database/categories"; + +export const exampleCategoryScope = defineModerationScope({ + id: "example.category", + label: "@vitnode/example.moderation.category.label", + description: "@vitnode/example.moderation.category.desc", + list: async (c, { cursor, limit, search }) => { + const rows = await c + .get("db") + .select({ id: example_categories.id, name: example_categories.name }) + .from(example_categories) + .where( + and( + cursor ? gt(example_categories.id, Number(cursor)) : undefined, + search ? ilike(example_categories.name, `%${search}%`) : undefined, + ), + ) + .orderBy(asc(example_categories.id)) + .limit(limit + 1); + const page = rows.slice(0, limit); + + return { + items: page.map(row => ({ id: String(row.id), label: row.name })), + nextCursor: rows.length > limit ? String(page.at(-1)?.id) : null, + }; + }, + find: async (c, ids) => { + const numeric = ids.map(Number).filter(id => Number.isSafeInteger(id)); + if (numeric.length === 0) return []; + + const rows = await c + .get("db") + .select({ id: example_categories.id, name: example_categories.name }) + .from(example_categories) + .where(inArray(example_categories.id, numeric)); + + return rows.map(row => ({ id: String(row.id), label: row.name })); + }, +}); +``` + +`list` feeds the picker one page at a time. `find` labels a saved selection and lets the API refuse an id that does not exist. Return `context`, such as `["Games"]`, on each resource to show where a nested resource sits. Both callbacks read the database, so the family never reaches the browser. + + + + + +### Add it to the plugin + +Pass the family to `buildApiPlugin`, and translate its label: + +```ts title="plugins/example/src/config.api.ts" +buildApiPlugin({ + pluginId: CONFIG_PLUGIN.pluginId, + moderation: { scopes: [exampleCategoryScope] }, // [!code ++] + modules: [/* ... */], +}); +``` + +```json title="plugins/example/src/locales/en.json" +{ + "@vitnode/example": { + "moderation": { + "category": { + "label": "Categories", + "desc": "Limit this permission to articles in some categories." + } + } + } +} +``` + +Family ids are global. Two plugins registering the same id, or a permission naming a family nobody registers, stops the API at boot with a `ModerationRegistryError`. + + + + + +### Tell the content model where a record sits + +On the server-side model, name the base-table column that holds the resource id: + +```ts title="plugins/example/src/database/articles.ts" +export const articleContent = createContentModel(articleContentType, { + references: { category: () => example_categories.id }, + moderationScope: { column: "category", family: "example.category" }, // [!code ++] +}); +``` + +The report permissions of `example.article` are now scoped by `example.category`. The server reads the column itself, so a client can never claim a record is in another category. The definition in `content/article.ts` stays browser-safe, without callbacks. + + + + + +## Check the result + +Rebuild with `pnpm build:plugins` and restart `pnpm dev`. Open **AdminCP → Staff → Moderators**, edit a moderator and select the example plugin. **View reports** and **Claim, assign, annotate and resolve reports** now show a scope under the checkbox, and **Change** opens the category picker. See [Configure moderators](/docs/dev/moderation/configure-moderators). + +## How grants combine + +A user's effective moderator permissions come from their own staff entry and the entries of every role they hold: + +- **Grants of one permission merge.** "View reports in A" from a role and "view reports in B" from the user give "view reports in A and B". "All resources" wins over a selection. +- **Permissions never combine across each other.** A role with "hide in A" and a user entry with "view in B" never allow hiding in B. Each permission keeps its own scope. +- **Dependencies are checked per resource.** Managing reports depends on viewing reports, so "manage in A" needs "view in A". Saving "manage in B" with only "view in A" is refused, and if broken data ever gets through, the effective scope of "manage" is cut down to where "view" is held. +- **Root roles and unrestricted entries** still allow everything, in every scope. + +`isModerator` in the session means "has a moderator entry". It grants no permission by itself, and the ModCP shows only what the grants allow. + +## Compatibility with unscoped grants + +Unscoped permissions work as before. A grant without a `scope` allows the permission everywhere. + +When a plugin later makes an existing permission scoped, grants saved before that change have no scope. They keep meaning **all resources**, and the editor shows them as **All resources**. A new save always needs an explicit scope. The API answers `400` with `missing_scope` instead of guessing that a missing scope means "everything". + +## Check a scope in your own code + +Pass the resource when you check a scoped permission: + +```ts +const allowed = await checkStaffPermission(c, { + type: "moderator", + plugin: "@vitnode/example", + module: "article", + permission: "can_view_reports", + resource: { family: "example.category", id: "2" }, +}); +``` + +A check without `resource` only passes for an unscoped or an **All resources** grant, so older code can never be widened by a selection. When a record moves to another resource, call `syncModerationReportScope(c, { pluginId, targetType, targetId })` from `@vitnode/core/api/moderation` after the move, so its reports follow it. The ModCP also re-reads the scope every time it opens a report. diff --git a/apps/web/content/docs/dev/working-with-users/staff-permissions.mdx b/apps/web/content/docs/dev/working-with-users/staff-permissions.mdx index 3d66e3ebd8..faa931901b 100644 --- a/apps/web/content/docs/dev/working-with-users/staff-permissions.mdx +++ b/apps/web/content/docs/dev/working-with-users/staff-permissions.mdx @@ -159,6 +159,27 @@ permissionStaff: { The AdminCP permission editor automatically disables child toggles until prerequisites are checked. +## Moderator permissions with scopes + +A moderator permission can be limited to some resources of a scope family, such as some forum sections. Declare the family with `scope` on the entry: + +```ts title="config.api.ts" +permissionStaff: { + moderator: { + topics: [ + { permission: "can_view_reports", scope: "forum.section" }, + { + permission: "can_manage_reports", + dependsOn: ["can_view_reports"], + scope: "forum.section", + }, + ], + }, +}, +``` + +Each grant then carries a scope, and dependencies are checked per resource: managing in a section needs viewing in that section. The scope families and the AdminCP picker are covered in [Scoped moderator permissions](/docs/dev/moderation/scoped-permissions). + ## Learn More diff --git a/apps/web/content/docs/ui/user.mdx b/apps/web/content/docs/ui/user.mdx index 20c95fadf4..937606c34e 100644 --- a/apps/web/content/docs/ui/user.mdx +++ b/apps/web/content/docs/ui/user.mdx @@ -1,6 +1,6 @@ --- title: User -description: Pick a person by name, with their avatar, in an Auto Form field that stores the user id. +description: Pick a person in an Auto Form field that stores the user id, or show a member's name with their role color and a link to their profile. icon: CircleUser --- @@ -63,6 +63,50 @@ that sets the value to `null`, so pair it with `z.number().nullable()`. `selected` can be partial: just `id` and `name`. Without `avatarColor`, the field draws a neutral placeholder avatar instead of guessing a color. +## Role colors + + + +Add a `role` to each option and the picker draws the name the way the rest of +the site does: in the role's color, with its prefix icon or emoji in front. +Options without a `role` keep a plain name, so you can add it gradually. + +```tsx +const moderators: UserOption[] = [ + { + avatarColor: '2563eb', + id: 1, + name: 'Ada Lovelace', + nameCode: 'ada', + role: { color: '#dc2626', prefix: 'icon:shield' }, + }, +] +``` + +`prefix` takes the same `icon:` or `emoji:` value as a +role's prefix in the AdminCP. In the AdminCP, `searchAdminUsersInBrowser` +already returns each person's primary role, so its pickers show colored names +without extra work. + +## Show a member's name + + + +`UserFormat` prints a name the way the rest of the site does. `format` adds the +role color and prefix, and `link` turns the name into a link to the member's +profile at `/users/`. + +```tsx +import { UserFormat } from '@vitnode/core/components/user-format' + + +``` + +`user` is `{ name, nameCode?, role: { color, prefix? } }`. `link` needs a +`nameCode`; without one, the name renders as plain text. Leave `link` off when +the name sits inside another link or a button, such as a table row that +already opens something. + ## Custom search `search` can call any endpoint: a plugin's own members, fixtures in a test. @@ -90,8 +134,9 @@ types. Results are never cached, so deleted users don't linger. | `clearable` | `boolean` | `false` | Adds a button that sets `null` | | `disabled` | `boolean` | `false` | Blocks opening the picker and clearing | -`UserOption` is `{ id, name, nameCode, avatarColor }`. `PartialUserOption` -makes `nameCode` and `avatarColor` optional. +`UserOption` is `{ id, name, nameCode, avatarColor, role? }`, where `role` is +`{ color: string | null, prefix?: string | null }`. `PartialUserOption` makes +`nameCode` and `avatarColor` optional. ## In the Content Engine diff --git a/apps/web/src/docs/examples/user-format.tsx b/apps/web/src/docs/examples/user-format.tsx new file mode 100644 index 0000000000..e8baad3c29 --- /dev/null +++ b/apps/web/src/docs/examples/user-format.tsx @@ -0,0 +1,30 @@ +import { UserFormat } from '@vitnode/core/components/user-format' + +const MEMBERS = [ + { + name: 'Ada Lovelace', + nameCode: 'ada', + role: { color: '#dc2626', prefix: 'icon:crown' }, + }, + { + name: 'Grace Hopper', + nameCode: 'grace', + role: { color: '#16a34a', prefix: 'icon:shield' }, + }, + { name: 'Alan Turing', nameCode: 'alan', role: { color: null } }, +] + +export default function UserFormatExample() { + return ( +

+ ) +} diff --git a/apps/web/src/docs/examples/user-roles.tsx b/apps/web/src/docs/examples/user-roles.tsx new file mode 100644 index 0000000000..08e2297c08 --- /dev/null +++ b/apps/web/src/docs/examples/user-roles.tsx @@ -0,0 +1,65 @@ +import { AutoForm } from '@vitnode/core/components/form/auto-form' +import { + AutoFormUser, + type UserOption, +} from '@vitnode/core/components/form/fields/input-users' +import { z } from 'zod' + +const formSchema = z.object({ + assigneeId: z.number().nullable().default(1), +}) + +const MODERATORS: UserOption[] = [ + { + avatarColor: '2563eb', + id: 1, + name: 'Ada Lovelace', + nameCode: 'ada', + role: { color: '#dc2626', prefix: 'icon:shield' }, + }, + { + avatarColor: 'db2777', + id: 2, + name: 'Grace Hopper', + nameCode: 'grace', + role: { color: '#16a34a' }, + }, + { + avatarColor: '0891b2', + id: 3, + name: 'Alan Turing', + nameCode: 'alan', + role: { color: null }, + }, +] + +export default function UserRolesExample() { + return ( + ( + + Promise.resolve( + MODERATORS.filter((person) => + person.name.toLowerCase().includes(value.toLowerCase()), + ), + ) + } + selected={MODERATORS[0]} + /> + ), + }, + ]} + formSchema={formSchema} + /> + ) +} diff --git a/packages/vitnode/src/api/lib/check-staff-permission.test.ts b/packages/vitnode/src/api/lib/check-staff-permission.test.ts index 89f4b04901..8121c7692f 100644 --- a/packages/vitnode/src/api/lib/check-staff-permission.test.ts +++ b/packages/vitnode/src/api/lib/check-staff-permission.test.ts @@ -10,11 +10,17 @@ import { createTestCache } from "@/tests/cache"; import { createMemoryDb } from "@/tests/memory-db"; import { grantStaffPermissions } from "@/tests/staff-permissions"; +import type { + PermissionsStaffArgs, + PermissionStaffCatalogEntry, +} from "./permission-staff"; + import { getStaffFlags, isStaff, resolveStaffPermissions, } from "./check-staff-permission"; +import { normalizePermissionStaffModules } from "./permission-staff"; import { invalidateAllStaffPermissions, invalidateStaffEntry, @@ -33,7 +39,7 @@ const DELETE_POSTS = { }; const staffEntry = (entry: { - permissions?: (typeof DELETE_POSTS)[]; + permissions?: PermissionsStaffArgs[]; roleId?: number; unrestricted?: boolean; userId?: number; @@ -48,11 +54,13 @@ const staffEntry = (entry: { const contextWith = ({ admin = [], cache = createTestCache(), + catalog, moderator = [], secondaryRoleIds = [], }: { admin?: ReturnType[]; cache?: ReturnType; + catalog?: PermissionStaffCatalogEntry[]; moderator?: ReturnType[]; secondaryRoleIds?: number[]; }) => { @@ -73,7 +81,11 @@ const contextWith = ({ [core_admin_permissions, admin], [core_moderators_permissions, moderator], ]); - const values: Record = { cache, db }; + const values: Record = { + cache, + core: catalog ? { permissionStaff: catalog } : undefined, + db, + }; return Object.assign( { get: (key: string) => values[key] } as unknown as Context, @@ -251,3 +263,106 @@ describe("getStaffFlags", () => { expect((await getStaffFlags(c, USER)).isAdmin).toBe(false); }); }); + +describe("resolveStaffPermissions with scoped grants", () => { + const FAMILY = "forum.section"; + const reports = ( + permission: string, + ids: string[], + ): PermissionsStaffArgs => ({ + module: "topics", + permission, + plugin: "@vitnode/forum", + scope: { family: FAMILY, ids, mode: "selected" }, + }); + const CATALOG: PermissionStaffCatalogEntry[] = [ + { + admin: {}, + moderator: normalizePermissionStaffModules({ + topics: [ + { permission: "can_view_reports", scope: FAMILY }, + { + dependsOn: ["can_view_reports"], + permission: "can_manage_reports", + scope: FAMILY, + }, + ], + }), + pluginId: "@vitnode/forum", + }, + ]; + + it("keeps the distinct scopes a user entry and a role entry grant", async () => { + const c = contextWith({ + moderator: [ + staffEntry({ + permissions: [reports("can_view_reports", ["a"])], + userId: USER.id, + }), + staffEntry({ + permissions: [reports("can_view_reports", ["b"])], + roleId: STAFF_ROLE, + }), + ], + secondaryRoleIds: [STAFF_ROLE], + }); + + expect( + await resolveStaffPermissions(c, { type: "moderator", user: USER }), + ).toEqual({ + permissions: [reports("can_view_reports", ["a", "b"])], + root: false, + staff: true, + }); + }); + + it("narrows a grant to where its dependency is held, across entries", async () => { + const c = contextWith({ + catalog: CATALOG, + moderator: [ + staffEntry({ + permissions: [reports("can_view_reports", ["a"])], + userId: USER.id, + }), + staffEntry({ + permissions: [reports("can_manage_reports", ["a", "b"])], + roleId: STAFF_ROLE, + }), + ], + secondaryRoleIds: [STAFF_ROLE], + }); + + const { permissions } = await resolveStaffPermissions(c, { + type: "moderator", + user: USER, + }); + + expect(permissions).toEqual([ + reports("can_view_reports", ["a"]), + reports("can_manage_reports", ["a"]), + ]); + }); + + it("reflects a changed scope once the entry is invalidated", async () => { + const c = contextWith({ + moderator: [ + staffEntry({ + permissions: [reports("can_view_reports", ["a"])], + userId: USER.id, + }), + ], + }); + const resolve = async () => + (await resolveStaffPermissions(c, { type: "moderator", user: USER })) + .permissions; + expect(await resolve()).toEqual([reports("can_view_reports", ["a"])]); + + await c.db + .update(core_moderators_permissions) + .set({ permissions: [reports("can_view_reports", ["b"])] }); + expect(await resolve()).toEqual([reports("can_view_reports", ["a"])]); + + await invalidateStaffEntry(c, { userId: USER.id }); + expect(await resolve()).toEqual([reports("can_view_reports", ["b"])]); + }); +}); diff --git a/packages/vitnode/src/api/lib/check-staff-permission.ts b/packages/vitnode/src/api/lib/check-staff-permission.ts index be5a2095fa..feec43f155 100644 --- a/packages/vitnode/src/api/lib/check-staff-permission.ts +++ b/packages/vitnode/src/api/lib/check-staff-permission.ts @@ -13,8 +13,13 @@ import type { PermissionStaffType, ResolvedStaffPermissionSet, } from "./permission-staff"; +import type { StaffPermissionCheck } from "./staff-permission"; -import { hasStaffPermission, staffPermissionKey } from "./staff-permission"; +import { + applyScopedStaffDependencies, + hasStaffPermission, + mergeStaffPermissionGrants, +} from "./staff-permission"; import { readStaffPermissions, readStaffPermissionsOfUser, @@ -83,22 +88,20 @@ const findStaffEntries = async ( }; const toStaffPermissionSet = ( + c: Context, entries: Awaited>, ): ResolvedStaffPermissionSet => { if (entries.some(entry => entry.unrestricted)) { return rootStaffPermissions(); } - const seen = new Set(); - const permissions: PermissionsStaffArgs[] = []; - for (const entry of entries) { - for (const permission of entry.permissions ?? []) { - const key = staffPermissionKey(permission); - if (seen.has(key)) continue; - seen.add(key); - permissions.push(permission); - } - } + const merged: PermissionsStaffArgs[] = mergeStaffPermissionGrants( + entries.flatMap(entry => entry.permissions ?? []), + ); + const catalog = c.get("core")?.permissionStaff; + const permissions = catalog + ? applyScopedStaffDependencies(merged, catalog) + : merged; return { root: false, permissions, staff: entries.length > 0 }; }; @@ -112,6 +115,7 @@ const loadStaffPermissions = async ( if (await hasRootRole(c, roleIds)) return rootStaffPermissions(); return toStaffPermissionSet( + c, await findStaffEntries(c, { roleIds, type, userId: user.id }), ); }; @@ -197,7 +201,7 @@ const loadMissingStaffPermissions = async ( return entriesByType.map(([type, entries]) => [ type, - root ? rootStaffPermissions() : toStaffPermissionSet(entries), + root ? rootStaffPermissions() : toStaffPermissionSet(c, entries), ]); }; @@ -229,7 +233,7 @@ export const getStaffFlags = async ( export const checkStaffPermissionOfUser = async ( c: Context, user: StaffUser, - { type, ...args }: PermissionsStaffArgs & { type: PermissionStaffType }, + { type, ...args }: StaffPermissionCheck & { type: PermissionStaffType }, ): Promise => { const set = await resolveStaffPermissions(c, { type, user }); @@ -238,7 +242,7 @@ export const checkStaffPermissionOfUser = async ( export const checkStaffPermission = async ( c: Context, - args: PermissionsStaffArgs & { type: PermissionStaffType }, + args: StaffPermissionCheck & { type: PermissionStaffType }, ): Promise => { const user = args.type === "admin" ? c.get("admin")?.user : c.get("user"); if (!user) return false; @@ -248,7 +252,7 @@ export const checkStaffPermission = async ( export const assertStaffPermission = async ( c: Context, - args: PermissionsStaffArgs & { type: PermissionStaffType }, + args: StaffPermissionCheck & { type: PermissionStaffType }, ): Promise => { const allowed = await checkStaffPermission(c, args); if (!allowed) { diff --git a/packages/vitnode/src/api/lib/moderation/access.ts b/packages/vitnode/src/api/lib/moderation/access.ts new file mode 100644 index 0000000000..e7d08cf392 --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/access.ts @@ -0,0 +1,258 @@ +import type { SQL } from "drizzle-orm"; +import type { Context } from "hono"; + +import { and, eq, inArray, or } from "drizzle-orm"; +import { HTTPException } from "hono/http-exception"; + +import { + core_moderation_report_events, + core_moderation_reports, +} from "@/database/moderation"; +import { core_users } from "@/database/users"; +import { MODERATION_PERMISSIONS } from "@/lib/moderation/const"; + +import type { ResolvedStaffPermissionSet } from "../permission-staff"; +import type { RegisteredReportTarget } from "./targets"; + +import { resolveStaffPermissions } from "../check-staff-permission"; +import { + hasStaffPermission, + staffPermissionResources, +} from "../staff-permission"; +import { findReportTarget } from "./registry"; + +export interface ModeratorContext { + set: ResolvedStaffPermissionSet; + user: { id: number; roleId: number }; +} + +export const requireModerator = async ( + c: Context, +): Promise => { + const user = c.get("user"); + if (!user) throw new HTTPException(401, { message: "Sign in first." }); + + const set = await resolveStaffPermissions(c, { type: "moderator", user }); + if (!set.staff) throw new HTTPException(403, { message: "Forbidden" }); + + return { set, user }; +}; + +export interface ReportScopeRef { + pluginId: string; + scopeId: null | string; + targetType: string; +} + +export const canOnReport = ( + c: Context, + set: ResolvedStaffPermissionSet, + report: ReportScopeRef, + permission: string, +): boolean => { + if (set.root) return true; + + const target = findReportTarget(c.get("core").moderation, { + pluginId: report.pluginId, + type: report.targetType, + }); + if (!target) return false; + + return hasStaffPermission(set, { + module: target.definition.permissionModule, + permission, + plugin: target.pluginId, + ...(target.definition.scope + ? { + resource: { + family: target.definition.scope, + id: report.scopeId ?? "", + }, + } + : {}), + }); +}; + +export const viewableReportsCondition = ( + c: Context, + set: ResolvedStaffPermissionSet, +): SQL | undefined => { + if (set.root) return undefined; + + const table = core_moderation_reports; + const conditions: (SQL | undefined)[] = []; + for (const target of c.get("core").moderation?.targets ?? []) { + const family = target.definition.scope; + const resources = staffPermissionResources( + set, + { + module: target.definition.permissionModule, + permission: MODERATION_PERMISSIONS.viewReports, + plugin: target.pluginId, + }, + family ?? "", + ); + if (resources === null) continue; + + const ofTarget = and( + eq(table.pluginId, target.pluginId), + eq(table.targetType, target.definition.type), + ); + conditions.push( + resources === "all" || !family + ? ofTarget + : and( + ofTarget, + eq(table.scopeFamily, family), + inArray(table.scopeId, resources), + ), + ); + } + + return ( + (conditions.length > 0 ? or(...conditions) : undefined) ?? eq(table.id, 0) + ); +}; + +export const syncReportTargetScope = async ( + c: Context, + { target, targetId }: { target: RegisteredReportTarget; targetId: string }, +): Promise => { + const { definition, pluginId } = target; + if (!definition.scope || !definition.resolveScope) return null; + + const current = await definition.resolveScope(c, targetId); + if (current === undefined) return undefined; + + const table = core_moderation_reports; + const ofTarget = and( + eq(table.pluginId, pluginId), + eq(table.targetType, definition.type), + eq(table.targetId, targetId), + ); + const stale = await c + .get("db") + .select({ + assigneeId: table.assigneeId, + id: table.id, + scopeId: table.scopeId, + status: table.status, + version: table.version, + }) + .from(table) + .where(ofTarget); + + const moved = stale.filter(report => report.scopeId !== current); + if (moved.length === 0) return current; + + for (const report of moved) { + await c + .get("db") + .update(table) + .set({ + scopeFamily: definition.scope, + scopeId: current, + version: report.version + 1, + }) + .where(and(eq(table.id, report.id), eq(table.version, report.version))); + report.version += 1; + } + + await revalidateAssignees(c, { + reports: moved.filter( + report => report.assigneeId !== null && report.status !== "done", + ), + scopeId: current, + target, + }); + + return current; +}; + +const revalidateAssignees = async ( + c: Context, + { + reports, + scopeId, + target, + }: { + reports: { assigneeId: null | number; id: number; version: number }[]; + scopeId: string; + target: RegisteredReportTarget; + }, +): Promise => { + const assigneeIds = [ + ...new Set( + reports + .map(report => report.assigneeId) + .filter((id): id is number => id !== null), + ), + ]; + if (assigneeIds.length === 0) return; + + const users = await c + .get("db") + .select({ id: core_users.id, roleId: core_users.roleId }) + .from(core_users) + .where(inArray(core_users.id, assigneeIds)); + + for (const assigneeId of assigneeIds) { + const user = users.find(row => row.id === assigneeId); + const set = user + ? await resolveStaffPermissions(c, { type: "moderator", user }) + : null; + const keeps = + set !== null && + canOnReport( + c, + set, + { + pluginId: target.pluginId, + scopeId, + targetType: target.definition.type, + }, + MODERATION_PERMISSIONS.manageReports, + ); + if (keeps) continue; + + const lost = reports.filter(report => report.assigneeId === assigneeId); + await c.get("db").transaction(async tx => { + for (const report of lost) { + const [updated] = await tx + .update(core_moderation_reports) + .set({ assigneeId: null, status: "new", version: report.version + 1 }) + .where( + and( + eq(core_moderation_reports.id, report.id), + eq(core_moderation_reports.version, report.version), + ), + ) + .returning({ id: core_moderation_reports.id }); + if (!updated) continue; + await tx.insert(core_moderation_report_events).values({ + actorId: null, + data: { previousAssigneeId: assigneeId, reason: "lost_access" }, + reportId: report.id, + type: "unassigned", + }); + } + }); + } +}; + +export const syncModerationReportScope = async ( + c: Context, + { + pluginId, + targetId, + targetType, + }: { pluginId: string; targetId: string; targetType: string }, +): Promise => { + const target = findReportTarget(c.get("core").moderation, { + pluginId, + type: targetType, + }); + if (!target) return; + + await syncReportTargetScope(c, { target, targetId }); +}; diff --git a/packages/vitnode/src/api/lib/moderation/registry.test.ts b/packages/vitnode/src/api/lib/moderation/registry.test.ts new file mode 100644 index 0000000000..35d45fcb8d --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/registry.test.ts @@ -0,0 +1,202 @@ +import { describe, expect, it } from "vitest"; + +import type { PermissionStaffCatalogEntry } from "../permission-staff"; +import type { ModerationReportTargetDefinition } from "./targets"; + +import { normalizePermissionStaffModules } from "../permission-staff"; +import { + validateModerationRegistry, + withModerationPermissions, +} from "./registry"; +import { defineModerationScope, ModerationRegistryError } from "./scopes"; +import { defineReportTarget } from "./targets"; + +const FORUM = "@vitnode/forum"; +const FAMILY = "forum.section"; + +const action = { + available: () => true, + permission: "can_hide", + run: async () => Promise.resolve(null), +}; + +const target = ( + overrides: Partial = {}, +): ModerationReportTargetDefinition => + defineReportTarget({ + capture: async () => Promise.resolve(null), + current: async () => Promise.resolve(null), + label: "Topic", + parseId: value => value, + permissionModule: "topics", + resolveScope: async () => Promise.resolve(""), + scope: FAMILY, + type: "forum.topic", + ...overrides, + }); + +const scope = defineModerationScope({ + find: async () => Promise.resolve([]), + id: FAMILY, + label: "Section", + list: async () => Promise.resolve({ items: [], nextCursor: null }), +}); + +describe("withModerationPermissions", () => { + it("generates view, manage and note permissions, scoped like the target, without hiding", () => { + expect(withModerationPermissions(undefined, [target()])).toEqual({ + moderator: { + topics: [ + { permission: "can_view_reports", scope: FAMILY }, + { + dependsOn: ["can_view_reports"], + permission: "can_manage_reports", + scope: FAMILY, + }, + { + dependsOn: ["can_manage_reports"], + permission: "can_edit_notes", + scope: FAMILY, + }, + { + dependsOn: ["can_manage_reports"], + permission: "can_delete_notes", + scope: FAMILY, + }, + ], + }, + }); + }); + + it.each(["hide", "unhide"] as const)( + "adds view hidden and hide when the target can %s", + name => { + const generated = withModerationPermissions(undefined, [ + target({ actions: { [name]: action } }), + ]); + + expect(generated?.moderator?.topics).toEqual( + expect.arrayContaining([ + { permission: "can_view_hidden", scope: FAMILY }, + { + dependsOn: ["can_view_hidden"], + permission: "can_hide", + scope: FAMILY, + }, + ]), + ); + }, + ); + + it("leaves an unscoped target's permissions unscoped", () => { + const generated = withModerationPermissions(undefined, [ + target({ resolveScope: undefined, scope: undefined }), + ]); + + expect(generated?.moderator?.topics).toEqual([ + { permission: "can_view_reports" }, + { dependsOn: ["can_view_reports"], permission: "can_manage_reports" }, + { dependsOn: ["can_manage_reports"], permission: "can_edit_notes" }, + { dependsOn: ["can_manage_reports"], permission: "can_delete_notes" }, + ]); + }); + + it("keeps a module the plugin declared itself", () => { + const declared = { moderator: { topics: ["can_view_reports"] } }; + + expect(withModerationPermissions(declared, [target()])).toEqual(declared); + }); +}); + +describe("validateModerationRegistry", () => { + const catalog = ( + entry: Partial = {}, + ): PermissionStaffCatalogEntry[] => [ + { admin: {}, moderator: {}, pluginId: FORUM, ...entry }, + ]; + + it("accepts scopes, targets and scoped moderator permissions that line up", () => { + const registry = validateModerationRegistry({ + catalog: catalog({ + moderator: normalizePermissionStaffModules({ + topics: [{ permission: "can_view_reports", scope: FAMILY }], + }), + }), + scopes: [{ definition: scope, pluginId: FORUM }], + targets: [{ definition: target(), pluginId: FORUM }], + }); + + expect(registry.targets.map(entry => entry.definition.type)).toEqual([ + "forum.topic", + ]); + }); + + it.each<[string, Parameters[0]]>([ + [ + "a scoped admin permission", + { + catalog: catalog({ + admin: normalizePermissionStaffModules({ + topics: [{ permission: "can_edit", scope: FAMILY }], + }), + }), + scopes: [{ definition: scope, pluginId: FORUM }], + targets: [], + }, + ], + [ + "a moderator permission scoped by an unknown family", + { + catalog: catalog({ + moderator: normalizePermissionStaffModules({ + topics: [{ permission: "can_view_reports", scope: "forum.nope" }], + }), + }), + scopes: [{ definition: scope, pluginId: FORUM }], + targets: [], + }, + ], + [ + "a target scoped by an unknown family", + { + catalog: catalog(), + scopes: [], + targets: [{ definition: target(), pluginId: FORUM }], + }, + ], + [ + "a family registered twice", + { + catalog: catalog(), + scopes: [ + { definition: scope, pluginId: FORUM }, + { definition: scope, pluginId: "@vitnode/other" }, + ], + targets: [], + }, + ], + [ + "a target type registered twice", + { + catalog: catalog(), + scopes: [{ definition: scope, pluginId: FORUM }], + targets: [ + { definition: target(), pluginId: FORUM }, + { definition: target(), pluginId: "@vitnode/other" }, + ], + }, + ], + ])("rejects %s", (_label, input) => { + expect(() => validateModerationRegistry(input)).toThrow( + ModerationRegistryError, + ); + }); +}); + +describe("defineReportTarget", () => { + it("requires resolveScope on a scoped target", () => { + expect(() => target({ resolveScope: undefined })).toThrow( + ModerationRegistryError, + ); + }); +}); diff --git a/packages/vitnode/src/api/lib/moderation/registry.ts b/packages/vitnode/src/api/lib/moderation/registry.ts new file mode 100644 index 0000000000..5ae22f4060 --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/registry.ts @@ -0,0 +1,156 @@ +import { MODERATION_PERMISSIONS } from "@/lib/moderation/const"; + +import type { + PermissionStaffCatalogEntry, + PermissionStaffConfig, + PermissionStaffEntryInput, +} from "../permission-staff"; +import type { + ModerationScopeDefinition, + RegisteredModerationScope, +} from "./scopes"; +import type { + ModerationReportTargetDefinition, + RegisteredReportTarget, +} from "./targets"; + +import { ModerationRegistryError } from "./scopes"; + +export interface ModerationPluginConfig { + reportTargets?: ModerationReportTargetDefinition[]; + scopes?: ModerationScopeDefinition[]; +} + +export interface ModerationRegistry { + scopes: RegisteredModerationScope[]; + targets: RegisteredReportTarget[]; +} + +export const moderationPermissionEntries = ( + target: Pick, +): PermissionStaffEntryInput[] => { + const scope = target.scope ? { scope: target.scope } : {}; + const hideable = Boolean(target.actions?.hide ?? target.actions?.unhide); + + return [ + { permission: MODERATION_PERMISSIONS.viewReports, ...scope }, + { + dependsOn: [MODERATION_PERMISSIONS.viewReports], + permission: MODERATION_PERMISSIONS.manageReports, + ...scope, + }, + { + dependsOn: [MODERATION_PERMISSIONS.manageReports], + permission: MODERATION_PERMISSIONS.editNotes, + ...scope, + }, + { + dependsOn: [MODERATION_PERMISSIONS.manageReports], + permission: MODERATION_PERMISSIONS.deleteNotes, + ...scope, + }, + ...(hideable + ? [ + { permission: MODERATION_PERMISSIONS.viewHidden, ...scope }, + { + dependsOn: [MODERATION_PERMISSIONS.viewHidden], + permission: MODERATION_PERMISSIONS.hide, + ...scope, + }, + ] + : []), + ]; +}; + +export const withModerationPermissions = ( + permissionStaff: PermissionStaffConfig | undefined, + targets: readonly ModerationReportTargetDefinition[], +): PermissionStaffConfig | undefined => { + if (targets.length === 0) return permissionStaff; + + const moderator = { ...permissionStaff?.moderator }; + for (const target of targets) { + if (moderator[target.permissionModule]) continue; + moderator[target.permissionModule] = moderationPermissionEntries(target); + } + + return { ...permissionStaff, moderator }; +}; + +export const validateModerationRegistry = ({ + catalog, + scopes, + targets, +}: { + catalog: readonly PermissionStaffCatalogEntry[]; + scopes: readonly RegisteredModerationScope[]; + targets: readonly RegisteredReportTarget[]; +}): ModerationRegistry => { + const families = new Map(); + for (const entry of scopes) { + const existing = families.get(entry.definition.id); + if (existing) { + throw new ModerationRegistryError( + `Scope family "${entry.definition.id}" is registered by both ${existing.pluginId} and ${entry.pluginId}.`, + ); + } + families.set(entry.definition.id, entry); + } + + for (const plugin of catalog) { + for (const [module, entries] of Object.entries(plugin.admin)) { + const scoped = entries.find(entry => entry.scope); + if (scoped) { + throw new ModerationRegistryError( + `${plugin.pluginId}:${module}:${scoped.permission} is an admin permission with a scope. Only moderator permissions can be scoped.`, + ); + } + } + for (const [module, entries] of Object.entries(plugin.moderator)) { + for (const entry of entries) { + if (entry.scope && !families.has(entry.scope)) { + throw new ModerationRegistryError( + `${plugin.pluginId}:${module}:${entry.permission} is scoped by "${entry.scope}", which no plugin registers with \`moderation.scopes\`.`, + ); + } + } + } + } + + const types = new Map(); + for (const entry of targets) { + const existing = types.get(entry.definition.type); + if (existing) { + throw new ModerationRegistryError( + `Report target "${entry.definition.type}" is registered by both ${existing.pluginId} and ${entry.pluginId}.`, + ); + } + if (entry.definition.scope && !families.has(entry.definition.scope)) { + throw new ModerationRegistryError( + `Report target "${entry.definition.type}" is scoped by "${entry.definition.scope}", which no plugin registers.`, + ); + } + types.set(entry.definition.type, entry); + } + + return { + scopes: [...families.values()], + targets: [...types.values()].sort((a, b) => + a.definition.type.localeCompare(b.definition.type), + ), + }; +}; + +export const findReportTarget = ( + registry: ModerationRegistry | undefined, + { pluginId, type }: { pluginId: string; type: string }, +): RegisteredReportTarget | undefined => + registry?.targets.find( + entry => entry.pluginId === pluginId && entry.definition.type === type, + ); + +export const findModerationScope = ( + registry: ModerationRegistry | undefined, + family: string, +): RegisteredModerationScope | undefined => + registry?.scopes.find(entry => entry.definition.id === family); diff --git a/packages/vitnode/src/api/lib/moderation/scopes.ts b/packages/vitnode/src/api/lib/moderation/scopes.ts new file mode 100644 index 0000000000..89f01d1b77 --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/scopes.ts @@ -0,0 +1,61 @@ +import type { Context } from "hono"; + +import { + MODERATION_IDENTIFIER_PATTERN, + MODERATION_RESOURCE_ID_PATTERN, +} from "@/lib/moderation/const"; + +export interface ModerationScopeResource { + context?: string[]; + id: string; + label: string; +} + +export interface ModerationScopeListArgs { + cursor: null | string; + limit: number; + search?: string; +} + +export interface ModerationScopeListResult { + items: ModerationScopeResource[]; + nextCursor: null | string; +} + +export interface ModerationScopeDefinition { + description?: string; + find: (c: Context, ids: string[]) => Promise; + id: string; + label: string; + list: ( + c: Context, + args: ModerationScopeListArgs, + ) => Promise; +} + +export interface RegisteredModerationScope { + definition: ModerationScopeDefinition; + pluginId: string; +} + +export class ModerationRegistryError extends Error { + constructor(message: string) { + super(`[moderation] ${message}`); + this.name = "ModerationRegistryError"; + } +} + +export const defineModerationScope = ( + definition: ModerationScopeDefinition, +): ModerationScopeDefinition => { + if (!MODERATION_IDENTIFIER_PATTERN.test(definition.id)) { + throw new ModerationRegistryError( + `Scope family id "${definition.id}" must be lowercase and dot separated, like "forum.section".`, + ); + } + + return definition; +}; + +export const isModerationResourceId = (value: string): boolean => + MODERATION_RESOURCE_ID_PATTERN.test(value); diff --git a/packages/vitnode/src/api/lib/moderation/snapshot.test.ts b/packages/vitnode/src/api/lib/moderation/snapshot.test.ts new file mode 100644 index 0000000000..e6fcd3c4f7 --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/snapshot.test.ts @@ -0,0 +1,90 @@ +import { describe, expect, it } from "vitest"; + +import { + MODERATION_LIMITS, + MODERATION_SNAPSHOT_VERSION, +} from "@/lib/moderation/const"; + +import type { ModerationCaptureResult } from "./targets"; + +import { sealReportSnapshot } from "./snapshot"; + +const TARGET = { id: "7", pluginId: "@vitnode/forum", type: "forum.topic" }; +const CAPTURED_AT = new Date("2026-01-02T03:04:05.000Z"); + +const capture = ( + overrides: Partial = {}, +): ModerationCaptureResult => ({ + authors: [{ id: 1, name: "Ada" }], + fields: [{ kind: "text", label: null, name: "body", value: "Hello" }], + locale: { fallback: false, requested: "en", served: "en" }, + scope: null, + source: { publishedAt: null, updatedAt: null, version: null }, + title: "A topic", + url: "/topics/7", + ...overrides, +}); + +const seal = (overrides: Partial = {}) => + sealReportSnapshot({ + capture: capture(overrides), + capturedAt: CAPTURED_AT, + target: TARGET, + }); + +describe("sealReportSnapshot", () => { + it("stamps, versions and keeps a small capture whole", () => { + expect(seal()).toEqual({ + ...capture(), + capturedAt: CAPTURED_AT.toISOString(), + target: TARGET, + truncated: false, + version: MODERATION_SNAPSHOT_VERSION, + }); + }); + + it("cuts a long text value and the title, and says so", () => { + const snapshot = seal({ + fields: [ + { + kind: "text", + label: null, + name: "body", + value: "x".repeat(MODERATION_LIMITS.snapshotTextMaxLength + 10), + }, + ], + title: "t".repeat(600), + }); + + expect(snapshot.truncated).toBe(true); + expect(snapshot.title).toHaveLength(500); + expect(snapshot.fields[0]?.value).toHaveLength( + MODERATION_LIMITS.snapshotTextMaxLength, + ); + }); + + it("drops fields from the end until the document fits", () => { + const big = (name: string) => ({ + kind: "text" as const, + label: null, + name, + value: "y".repeat(MODERATION_LIMITS.snapshotTextMaxLength), + }); + const count = + Math.ceil( + MODERATION_LIMITS.snapshotMaxBytes / + MODERATION_LIMITS.snapshotTextMaxLength, + ) + 2; + + const snapshot = seal({ + fields: Array.from({ length: count }, (_, index) => big(`f${index}`)), + }); + + expect(snapshot.truncated).toBe(true); + expect(snapshot.fields.length).toBeLessThan(count); + expect(snapshot.fields[0]?.name).toBe("f0"); + expect( + Buffer.byteLength(JSON.stringify(snapshot), "utf8"), + ).toBeLessThanOrEqual(MODERATION_LIMITS.snapshotMaxBytes); + }); +}); diff --git a/packages/vitnode/src/api/lib/moderation/snapshot.ts b/packages/vitnode/src/api/lib/moderation/snapshot.ts new file mode 100644 index 0000000000..8c363b1873 --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/snapshot.ts @@ -0,0 +1,77 @@ +import type { + ModerationReportSnapshot, + ModerationSnapshotField, +} from "@/lib/moderation/snapshot"; + +import { richTextToPlainText } from "@/content/rich-text/plain-text"; +import { + MODERATION_LIMITS, + MODERATION_SNAPSHOT_VERSION, +} from "@/lib/moderation/const"; + +import type { ModerationCaptureResult } from "./targets"; + +const byteLength = (value: unknown): number => + Buffer.byteLength(JSON.stringify(value), "utf8"); + +const clip = (value: string, max: number): [string, boolean] => + value.length > max ? [value.slice(0, max), true] : [value, false]; + +export const sealReportSnapshot = ({ + capture, + capturedAt = new Date(), + target, +}: { + capture: ModerationCaptureResult; + capturedAt?: Date; + target: ModerationReportSnapshot["target"]; +}): ModerationReportSnapshot => { + let truncated = false; + const maxText = MODERATION_LIMITS.snapshotTextMaxLength; + + const fields: ModerationSnapshotField[] = capture.fields.map(field => { + if (field.kind === "text" && field.value !== null) { + const [value, cut] = clip(field.value, maxText); + truncated ||= cut; + + return { ...field, value }; + } + + return field; + }); + + const [title, titleCut] = + capture.title === null ? [null, false] : clip(capture.title, 500); + truncated ||= titleCut; + + const snapshot: ModerationReportSnapshot = { + ...capture, + capturedAt: capturedAt.toISOString(), + fields, + target, + title, + truncated, + version: MODERATION_SNAPSHOT_VERSION, + }; + + if (byteLength(snapshot) <= MODERATION_LIMITS.snapshotMaxBytes) { + return snapshot; + } + + snapshot.truncated = true; + snapshot.fields = snapshot.fields.map(field => { + if (field.kind !== "richText" || field.value === null) return field; + const [value] = clip(richTextToPlainText(field.value), maxText); + + return { kind: "text", label: field.label, name: field.name, value }; + }); + + while ( + snapshot.fields.length > 0 && + byteLength(snapshot) > MODERATION_LIMITS.snapshotMaxBytes + ) { + snapshot.fields = snapshot.fields.slice(0, -1); + } + + return snapshot; +}; diff --git a/packages/vitnode/src/api/lib/moderation/targets.ts b/packages/vitnode/src/api/lib/moderation/targets.ts new file mode 100644 index 0000000000..4b524de540 --- /dev/null +++ b/packages/vitnode/src/api/lib/moderation/targets.ts @@ -0,0 +1,86 @@ +import type { Context } from "hono"; + +import type { ContentDatabase } from "@/content/server/service"; +import type { ModerationTargetAction } from "@/lib/moderation/const"; +import type { ModerationReportSnapshot } from "@/lib/moderation/snapshot"; + +import { MODERATION_IDENTIFIER_PATTERN } from "@/lib/moderation/const"; + +import { ModerationRegistryError } from "./scopes"; + +export interface ModerationTargetState { + hidden: boolean; + url: null | string; +} + +export interface ModerationCaptureArgs { + locale: null | string; + targetId: string; +} + +export type ModerationCaptureResult = Omit< + ModerationReportSnapshot, + "capturedAt" | "target" | "truncated" | "version" +>; + +export interface ModerationActionArgs { + actorUserId: number; + targetId: string; + tx: ContentDatabase; +} + +export interface ModerationActionOutcome { + changed: boolean; + effects: () => Promise; +} + +export interface ModerationTargetActionDefinition { + available: (state: ModerationTargetState) => boolean; + permission: string; + run: ( + c: Context, + args: ModerationActionArgs, + ) => Promise; +} + +export interface ModerationReportTargetDefinition { + actions?: Partial< + Record + >; + capture: ( + c: Context, + args: ModerationCaptureArgs, + ) => Promise; + current: ( + c: Context, + args: { locale: null | string; targetId: string }, + ) => Promise; + label: string; + parseId: (value: string) => null | string; + permissionModule: string; + resolveScope?: (c: Context, targetId: string) => Promise; + scope?: string; + type: string; +} + +export interface RegisteredReportTarget { + definition: ModerationReportTargetDefinition; + pluginId: string; +} + +export const defineReportTarget = ( + definition: ModerationReportTargetDefinition, +): ModerationReportTargetDefinition => { + if (!MODERATION_IDENTIFIER_PATTERN.test(definition.type)) { + throw new ModerationRegistryError( + `Report target type "${definition.type}" must be lowercase and dot separated, like "forum.topic".`, + ); + } + if (definition.scope && !definition.resolveScope) { + throw new ModerationRegistryError( + `Report target "${definition.type}" is limited by the "${definition.scope}" scope, so it needs \`resolveScope\`.`, + ); + } + + return definition; +}; diff --git a/packages/vitnode/src/api/lib/permission-staff.ts b/packages/vitnode/src/api/lib/permission-staff.ts index 5b9d686b97..11b638a1d5 100644 --- a/packages/vitnode/src/api/lib/permission-staff.ts +++ b/packages/vitnode/src/api/lib/permission-staff.ts @@ -1,6 +1,10 @@ export type PermissionStaffEntryInput = | string - | { dependsOn?: string[]; permission: string }; + | { + dependsOn?: string[]; + permission: string; + scope?: string; + }; /** * Author-facing module map - what a plugin declares in its API config. @@ -13,6 +17,7 @@ export type PermissionStaffModulesInput = Record< export interface PermissionStaffEntry { dependsOn: string[]; permission: string; + scope?: string; } export type PermissionStaffModules = Record; @@ -33,15 +38,29 @@ export const normalizePermissionStaffModules = ( entries.map(entry => typeof entry === "string" ? { permission: entry, dependsOn: [] } - : { permission: entry.permission, dependsOn: entry.dependsOn ?? [] }, + : { + permission: entry.permission, + dependsOn: entry.dependsOn ?? [], + ...(entry.scope ? { scope: entry.scope } : {}), + }, ), ]), ); +export type PermissionStaffScope = + | { family: string; ids: string[]; mode: "selected" } + | { family: string; mode: "all" }; + export interface PermissionsStaffArgs { module: string; permission: string; plugin: string; + scope?: PermissionStaffScope; +} + +export interface PermissionStaffResource { + family: string; + id: string; } /** diff --git a/packages/vitnode/src/api/lib/plugin.ts b/packages/vitnode/src/api/lib/plugin.ts index f5d4deecbb..40f9c6b09f 100644 --- a/packages/vitnode/src/api/lib/plugin.ts +++ b/packages/vitnode/src/api/lib/plugin.ts @@ -15,12 +15,16 @@ import { validateContentTypes, withContentPermissions, } from "@/content/registry"; +import { contentDefinitionOf } from "@/content/server/model"; +import { contentReportTarget } from "@/content/server/report-target"; import type { SearchIndexer } from "../models/search"; import type { AnyAiActionDefinition } from "./ai/action"; import type { CronJobConfig } from "./cron"; import type { RegisteredEditablePage } from "./editable-pages"; import type { EventListenerConfig } from "./events"; +import type { ModerationPluginConfig } from "./moderation/registry"; +import type { ModerationReportTargetDefinition } from "./moderation/targets"; import type { BaseBuildModuleReturn, BuildModuleReturn } from "./module"; import type { AnyNotificationTypeDefinition } from "./notifications/registry"; import type { PermissionStaffConfig } from "./permission-staff"; @@ -31,6 +35,7 @@ import { validateSearchIndexers } from "../models/search"; import { collectAiActions } from "./ai/registry"; import { checkPluginId } from "./check-plugin-id"; import { registerEditablePage, validateEditablePages } from "./editable-pages"; +import { withModerationPermissions } from "./moderation/registry"; import { collectNavigationPresets } from "./navigation-presets"; import { validateNotificationTypes } from "./notifications/registry"; import { applyModuleTags } from "./openapi-tags"; @@ -51,6 +56,7 @@ export interface BuildPluginApiReturn< events?: Omit[]; hono: OpenAPIHono; messages?: LocaleMessagesMap; + moderation?: Required; modules: Modules; navigation?: NavigationPresetDeclaration[]; notificationTypes?: AnyNotificationTypeDefinition[]; @@ -77,6 +83,7 @@ export function buildApiPlugin< editablePages, pluginId, messages, + moderation, modules = [] as unknown as Modules, navigation, notificationTypes, @@ -87,6 +94,7 @@ export function buildApiPlugin< blocks?: BlockPluginSource; editablePages?: AnyEditablePageDefinition[]; messages?: LocaleMessagesMap; + moderation?: ModerationPluginConfig; modules?: Modules; navigation?: NavigationPresetDeclaration[]; notificationTypes?: AnyNotificationTypeDefinition[]; @@ -177,6 +185,13 @@ export function buildApiPlugin< } } + const reportTargets: ModerationReportTargetDefinition[] = [ + ...(moderation?.reportTargets ?? []), + ...contentModels + .filter(model => contentDefinitionOf(model).reports.enabled) + .map(model => contentReportTarget(model, pluginId)), + ]; + return { pluginId, aiActions, @@ -198,7 +213,11 @@ export function buildApiPlugin< webSockets, // Every content type contributes can_view/can_create/can_edit/can_delete // unless the plugin declared that module itself. - permissionStaff: withContentPermissions(permissionStaff, registered), + permissionStaff: withModerationPermissions( + withContentPermissions(permissionStaff, registered), + reportTargets, + ), + moderation: { reportTargets, scopes: moderation?.scopes ?? [] }, }; } diff --git a/packages/vitnode/src/api/lib/staff-permission-cache.ts b/packages/vitnode/src/api/lib/staff-permission-cache.ts index 074a43c894..eb350fae16 100644 --- a/packages/vitnode/src/api/lib/staff-permission-cache.ts +++ b/packages/vitnode/src/api/lib/staff-permission-cache.ts @@ -19,7 +19,7 @@ const readEpoch = async (c: Context): Promise => const permissionsKey = ( epoch: string, { type, userId }: { type: PermissionStaffType; userId: number }, -): string => `staff-permissions:v2:${epoch}:${type}:${userId}`; +): string => `staff-permissions:v3:${epoch}:${type}:${userId}`; /** The cached resolution, or `null` on a miss, without Redis, or on error. */ export const readStaffPermissions = async ( diff --git a/packages/vitnode/src/api/lib/staff-permission.test.ts b/packages/vitnode/src/api/lib/staff-permission.test.ts new file mode 100644 index 0000000000..d44fdcacde --- /dev/null +++ b/packages/vitnode/src/api/lib/staff-permission.test.ts @@ -0,0 +1,262 @@ +import { describe, expect, it } from "vitest"; + +import type { + PermissionsStaffArgs, + PermissionStaffScope, + StaffPermissionSet, +} from "./permission-staff"; + +import { normalizePermissionStaffModules } from "./permission-staff"; +import { + applyScopedStaffDependencies, + hasStaffPermission, + holdsStaffPermission, + mergeStaffPermissionGrants, + staffPermissionResources, + staffScopeCovers, +} from "./staff-permission"; + +const PLUGIN = "@vitnode/forum"; +const MODULE = "topics"; +const FAMILY = "forum.section"; + +const VIEW = "can_view_reports"; +const MANAGE = "can_manage_reports"; +const VIEW_HIDDEN = "can_view_hidden"; +const HIDE = "can_hide"; + +const all = (family = FAMILY): PermissionStaffScope => ({ + family, + mode: "all", +}); +const only = (...ids: string[]): PermissionStaffScope => ({ + family: FAMILY, + ids, + mode: "selected", +}); + +const grant = ( + permission: string, + scope?: PermissionStaffScope, +): PermissionsStaffArgs => ({ + module: MODULE, + permission, + plugin: PLUGIN, + ...(scope ? { scope } : {}), +}); + +const set = (...permissions: PermissionsStaffArgs[]): StaffPermissionSet => ({ + permissions, + root: false, +}); + +const check = (permission: string, id?: string) => ({ + module: MODULE, + permission, + plugin: PLUGIN, + ...(id === undefined ? {} : { resource: { family: FAMILY, id } }), +}); + +const CATALOG = [ + { + moderator: normalizePermissionStaffModules({ + [MODULE]: [ + { permission: VIEW, scope: FAMILY }, + { dependsOn: [VIEW], permission: MANAGE, scope: FAMILY }, + { permission: VIEW_HIDDEN, scope: FAMILY }, + { dependsOn: [VIEW_HIDDEN], permission: HIDE, scope: FAMILY }, + ], + }), + pluginId: PLUGIN, + }, +]; + +describe("hasStaffPermission with a resource", () => { + it.each<[string, PermissionsStaffArgs, string | undefined, boolean]>([ + ["a selected grant, inside", grant(VIEW, only("a", "b")), "a", true], + ["a selected grant, outside", grant(VIEW, only("a")), "b", false], + [ + "a selected grant, no resource named", + grant(VIEW, only("a")), + undefined, + false, + ], + ["an all-resources grant, any resource", grant(VIEW, all()), "z", true], + [ + "an all-resources grant, no resource named", + grant(VIEW, all()), + undefined, + true, + ], + ["a legacy unscoped grant, any resource", grant(VIEW), "z", true], + [ + "a legacy unscoped grant, no resource named", + grant(VIEW), + undefined, + true, + ], + ])("%s", (_label, held, id, expected) => { + expect(hasStaffPermission(set(held), check(VIEW, id))).toBe(expected); + }); + + it("does not let a grant in one family answer for another family", () => { + expect( + hasStaffPermission( + set(grant(VIEW, all("blog.category"))), + check(VIEW, "a"), + ), + ).toBe(false); + }); + + it("answers yes to everything for root", () => { + expect( + hasStaffPermission({ permissions: [], root: true }, check(HIDE, "a")), + ).toBe(true); + }); +}); + +describe("holdsStaffPermission", () => { + it("is true for a permission held in any scope, without naming one", () => { + const held = set(grant(VIEW, only("a"))); + + expect(holdsStaffPermission(held, check(VIEW))).toBe(true); + expect(holdsStaffPermission(held, check(MANAGE))).toBe(false); + }); +}); + +describe("staffPermissionResources", () => { + it.each<[string, StaffPermissionSet, "all" | null | string[]]>([ + ["root", { permissions: [], root: true }, "all"], + ["a legacy unscoped grant", set(grant(VIEW)), "all"], + ["an all-resources grant", set(grant(VIEW, all())), "all"], + [ + "selected grants, merged and sorted", + set(grant(VIEW, only("c", "a")), grant(VIEW, only("b", "a"))), + ["a", "b", "c"], + ], + ["another permission only", set(grant(MANAGE, all())), null], + ["another family only", set(grant(VIEW, all("blog.category"))), null], + ["nothing", set(), null], + ])("answers %s", (_label, held, expected) => { + expect(staffPermissionResources(held, check(VIEW), FAMILY)).toEqual( + expected, + ); + }); +}); + +describe("staffScopeCovers", () => { + it.each< + [ + string, + PermissionStaffScope | undefined, + PermissionStaffScope | undefined, + boolean, + ] + >([ + ["unscoped covers anything", undefined, only("a"), true], + ["a scope never covers unscoped", all(), undefined, false], + ["all covers a selection", all(), only("a", "b"), true], + ["a selection never covers all", only("a", "b"), all(), false], + ["a superset covers a subset", only("a", "b"), only("b"), true], + ["a subset does not cover a superset", only("a"), only("a", "b"), false], + ["another family covers nothing", all("blog.category"), only("a"), false], + ])("%s", (_label, outer, inner, expected) => { + expect(staffScopeCovers(outer, inner)).toBe(expected); + }); +}); + +describe("mergeStaffPermissionGrants", () => { + it("unions the scopes of one permission granted by a user and a role", () => { + const merged = mergeStaffPermissionGrants([ + grant(VIEW, only("b")), + grant(VIEW, only("a", "b")), + ]); + + expect(merged).toEqual([grant(VIEW, only("a", "b"))]); + }); + + it.each<[string, PermissionsStaffArgs[], PermissionsStaffArgs[]]>([ + [ + "all absorbs a selection", + [grant(VIEW, only("a")), grant(VIEW, all())], + [grant(VIEW, all())], + ], + [ + "an unscoped grant absorbs a scoped one before it", + [grant(VIEW, only("a")), grant(VIEW)], + [grant(VIEW)], + ], + [ + "an unscoped grant absorbs a scoped one after it", + [grant(VIEW), grant(VIEW, only("a"))], + [grant(VIEW)], + ], + [ + "grants in different families stay apart", + [grant(VIEW, only("a")), grant(VIEW, all("blog.category"))], + [grant(VIEW, only("a")), grant(VIEW, all("blog.category"))], + ], + ])("%s", (_label, grants, expected) => { + expect(mergeStaffPermissionGrants(grants)).toEqual(expected); + }); + + it("never combines scopes across permissions", () => { + const merged = set( + ...mergeStaffPermissionGrants([ + grant(HIDE, only("a")), + grant(VIEW, only("b")), + ]), + ); + + expect(hasStaffPermission(merged, check(HIDE, "a"))).toBe(true); + expect(hasStaffPermission(merged, check(HIDE, "b"))).toBe(false); + expect(hasStaffPermission(merged, check(VIEW, "a"))).toBe(false); + expect(hasStaffPermission(merged, check(VIEW, "b"))).toBe(true); + }); +}); + +describe("applyScopedStaffDependencies", () => { + it.each<[string, PermissionsStaffArgs[], PermissionsStaffArgs[]]>([ + [ + "narrows a grant to where its dependency is held", + [grant(VIEW, only("a")), grant(MANAGE, only("a", "b"))], + [grant(VIEW, only("a")), grant(MANAGE, only("a"))], + ], + [ + "narrows an all-resources grant to the dependency's selection", + [grant(VIEW, only("a")), grant(MANAGE, all())], + [grant(VIEW, only("a")), grant(MANAGE, only("a"))], + ], + [ + "drops a grant whose dependency is held nowhere it applies", + [grant(VIEW, only("b")), grant(MANAGE, only("a"))], + [grant(VIEW, only("b"))], + ], + [ + "drops a grant whose dependency is missing", + [grant(MANAGE, only("a", "b"))], + [], + ], + [ + "keeps a grant whose dependency is unscoped", + [grant(VIEW), grant(MANAGE, only("a"))], + [grant(VIEW), grant(MANAGE, only("a"))], + ], + ["leaves an unscoped grant alone", [grant(MANAGE)], [grant(MANAGE)]], + ])("%s", (_label, grants, expected) => { + expect(applyScopedStaffDependencies(grants, CATALOG)).toEqual(expected); + }); + + it("follows each permission's own dependency, not another's", () => { + const narrowed = applyScopedStaffDependencies( + [ + grant(VIEW, all()), + grant(VIEW_HIDDEN, only("a")), + grant(HIDE, only("a", "b")), + ], + CATALOG, + ); + + expect(narrowed).toContainEqual(grant(HIDE, only("a"))); + }); +}); diff --git a/packages/vitnode/src/api/lib/staff-permission.ts b/packages/vitnode/src/api/lib/staff-permission.ts index 30cf9d884c..1aa882f0a4 100644 --- a/packages/vitnode/src/api/lib/staff-permission.ts +++ b/packages/vitnode/src/api/lib/staff-permission.ts @@ -1,27 +1,224 @@ import type { PermissionsStaffArgs, + PermissionStaffModules, + PermissionStaffResource, + PermissionStaffScope, StaffPermissionSet, } from "./permission-staff"; +export type StaffPermissionCheck = Omit & { + resource?: PermissionStaffResource; +}; + +const sameKey = ( + grant: Omit, + args: Omit, +): boolean => + grant.plugin === args.plugin && + grant.module === args.module && + grant.permission === args.permission; + +const grantAllows = ( + grant: PermissionsStaffArgs, + resource: PermissionStaffResource | undefined, +): boolean => { + if (!grant.scope) return true; + if (resource && resource.family !== grant.scope.family) return false; + if (grant.scope.mode === "all") return true; + + return resource !== undefined && grant.scope.ids.includes(resource.id); +}; + export const hasStaffPermission = ( set: StaffPermissionSet, - args: PermissionsStaffArgs, + { resource, ...args }: StaffPermissionCheck, ): boolean => { if (set.root) return true; return set.permissions.some( - permission => - permission.plugin === args.plugin && - permission.module === args.module && - permission.permission === args.permission, + grant => sameKey(grant, args) && grantAllows(grant, resource), ); }; +export const holdsStaffPermission = ( + set: StaffPermissionSet, + args: Omit, +): boolean => set.root || set.permissions.some(grant => sameKey(grant, args)); + +export const staffPermissionResources = ( + set: StaffPermissionSet, + args: Omit, + family: string, +): "all" | null | string[] => { + if (set.root) return "all"; + + const ids = new Set(); + for (const grant of set.permissions) { + if (!sameKey(grant, args)) continue; + if (!grant.scope) return "all"; + if (grant.scope.family !== family) continue; + if (grant.scope.mode === "all") return "all"; + for (const id of grant.scope.ids) ids.add(id); + } + + return ids.size > 0 ? [...ids].sort() : null; +}; + export const staffPermissionKey = ({ plugin, module, permission, -}: PermissionsStaffArgs): string => `${plugin}:${module}:${permission}`; +}: Omit): string => + `${plugin}:${module}:${permission}`; + +export const staffScopeCovers = ( + outer: PermissionStaffScope | undefined, + inner: PermissionStaffScope | undefined, +): boolean => { + if (!outer) return true; + if (!inner) return false; + if (outer.family !== inner.family) return false; + if (outer.mode === "all") return true; + if (inner.mode === "all") return false; + + const allowed = new Set(outer.ids); + + return inner.ids.every(id => allowed.has(id)); +}; + +const unionScopes = ( + a: PermissionStaffScope, + b: PermissionStaffScope, +): PermissionStaffScope => { + if (a.mode === "all") return a; + if (b.mode === "all") return b; + + return { + family: a.family, + ids: [...new Set([...a.ids, ...b.ids])].sort(), + mode: "selected", + }; +}; + +export const mergeStaffPermissionGrants = ( + grants: readonly PermissionsStaffArgs[], +): PermissionsStaffArgs[] => { + const merged = new Map(); + + for (const grant of grants) { + const key = staffPermissionKey(grant); + const base = { + module: grant.module, + permission: grant.permission, + plugin: grant.plugin, + }; + const unscoped = merged.get(key); + if (unscoped && !unscoped.scope) continue; + + if (!grant.scope) { + for (const existing of merged.keys()) { + if (existing.startsWith(`${key}|`)) merged.delete(existing); + } + merged.set(key, base); + continue; + } + + const familyKey = `${key}|${grant.scope.family}`; + const existing = merged.get(familyKey); + merged.set(familyKey, { + ...base, + scope: existing?.scope + ? unionScopes(existing.scope, grant.scope) + : grant.scope, + }); + } + + return [...merged.values()]; +}; + +const intersectScopes = ( + a: PermissionStaffScope, + b: PermissionStaffScope | undefined, +): null | PermissionStaffScope => { + if (!b) return a; + if (a.family !== b.family) return b.mode === "all" ? a : null; + if (b.mode === "all") return a; + if (a.mode === "all") return b; + + const allowed = new Set(b.ids); + const ids = a.ids.filter(id => allowed.has(id)).sort(); + + return ids.length > 0 ? { family: a.family, ids, mode: "selected" } : null; +}; + +export const applyScopedStaffDependencies = ( + grants: readonly PermissionsStaffArgs[], + catalog: readonly { moderator: PermissionStaffModules; pluginId: string }[], +): PermissionsStaffArgs[] => { + const dependencies = new Map(); + for (const plugin of catalog) { + for (const [module, entries] of Object.entries(plugin.moderator)) { + for (const entry of entries) { + dependencies.set( + staffPermissionKey({ + module, + permission: entry.permission, + plugin: plugin.pluginId, + }), + entry.dependsOn, + ); + } + } + } + + let current = [...grants]; + let changed = true; + while (changed) { + changed = false; + const next: PermissionsStaffArgs[] = []; + for (const grant of current) { + if (!grant.scope) { + next.push(grant); + continue; + } + + let scope: null | PermissionStaffScope = grant.scope; + for (const dependency of dependencies.get(staffPermissionKey(grant)) ?? + []) { + if (!scope) break; + const held = current.filter( + other => + other.plugin === grant.plugin && + other.module === grant.module && + other.permission === dependency, + ); + if (held.length === 0) { + scope = null; + break; + } + if (held.some(other => !other.scope)) continue; + const narrowing: PermissionStaffScope = scope; + let widest: null | PermissionStaffScope = null; + for (const other of held) { + const overlap = intersectScopes(narrowing, other.scope); + if (!overlap) continue; + widest = widest ? unionScopes(widest, overlap) : overlap; + } + scope = widest; + } + + if (!scope) { + changed = true; + continue; + } + if (JSON.stringify(scope) !== JSON.stringify(grant.scope)) changed = true; + next.push({ ...grant, scope }); + } + current = next; + } + + return current; +}; /** * Nobody's permissions - the answer when there is no admin session to read one diff --git a/packages/vitnode/src/api/middlewares/global.middleware.ts b/packages/vitnode/src/api/middlewares/global.middleware.ts index eb2c8805fc..13e1ce0591 100644 --- a/packages/vitnode/src/api/middlewares/global.middleware.ts +++ b/packages/vitnode/src/api/middlewares/global.middleware.ts @@ -44,6 +44,7 @@ import type { AiActionRegistry } from "../lib/ai/registry"; import type { BuildCronReturn } from "../lib/cron"; import type { RegisteredEditablePage } from "../lib/editable-pages"; import type { EventListenerConfig } from "../lib/events"; +import type { ModerationRegistry } from "../lib/moderation/registry"; import type { NotificationWorkerSettings } from "../lib/notifications/preferences"; import type { NotificationRegistry } from "../lib/notifications/registry"; import type { ResolvedPasskeysConfig } from "../lib/passkey-config"; @@ -70,6 +71,7 @@ import { loggerMiddleware, type LoggerMiddlewareType, } from "../lib/logger-middleware"; +import { validateModerationRegistry } from "../lib/moderation/registry"; import { collectNavigationPresets } from "../lib/navigation-presets"; import { resolveNotificationWorkerSettings } from "../lib/notifications/preferences"; import { createNotificationRegistry } from "../lib/notifications/registry"; @@ -157,6 +159,7 @@ export interface EnvVariablesVitNode { shortTitle?: string; title: string; }; + moderation: ModerationRegistry; /** Every prebuilt main-menu item the installed plugins offer. */ navigation: NavigationPreset[]; notifications?: NotificationRegistry; @@ -420,6 +423,22 @@ export const globalMiddleware = ({ permissionStaff: permissionStaffMetadata, }); + const moderationMetadata: ModerationRegistry = validateModerationRegistry({ + catalog: permissionStaffMetadata, + scopes: plugins.flatMap(plugin => + (plugin.moderation?.scopes ?? []).map(definition => ({ + definition, + pluginId: plugin.pluginId, + })), + ), + targets: plugins.flatMap(plugin => + (plugin.moderation?.reportTargets ?? []).map(definition => ({ + definition, + pluginId: plugin.pluginId, + })), + ), + }); + return async (c: Context, next: Next) => { if (!c.get("ipAddress")) { c.set("ipAddress", resolveClientIp(c)); @@ -486,6 +505,7 @@ export const globalMiddleware = ({ queue: queueMetadata, webSockets: webSocketsMetadata, permissionStaff: permissionStaffMetadata, + moderation: moderationMetadata, navigation: navigationMetadata, notifications: notificationsMetadata, notificationWorkers, diff --git a/packages/vitnode/src/api/models/events.ts b/packages/vitnode/src/api/models/events.ts index 6c75ebb158..4a78722a43 100644 --- a/packages/vitnode/src/api/models/events.ts +++ b/packages/vitnode/src/api/models/events.ts @@ -30,6 +30,40 @@ export interface VitNodeEvents { languageCodes: string[]; origin: "ai" | "human"; }; + "moderation.report.action": { + action: "hide" | "unhide"; + pluginId: string; + reportId: number; + targetId: string; + targetType: string; + }; + "moderation.report.assigned": { + assigneeId: null | number; + previousAssigneeId: null | number; + reportId: number; + }; + "moderation.report.created": { + pluginId: string; + reason: string; + reportId: number; + targetId: string; + targetType: string; + }; + "moderation.report.note_deleted": { + noteId: number; + reportId: number; + }; + "moderation.report.note_updated": { + noteId: number; + reportId: number; + }; + "moderation.report.reopened": { + reportId: number; + }; + "moderation.report.resolved": { + reportId: number; + resolution: string; + }; "navigation.created": { navigationId: number; }; diff --git a/packages/vitnode/src/api/moderation.ts b/packages/vitnode/src/api/moderation.ts new file mode 100644 index 0000000000..797d8ff71e --- /dev/null +++ b/packages/vitnode/src/api/moderation.ts @@ -0,0 +1,19 @@ +export { syncModerationReportScope } from "./lib/moderation/access"; +export type { ModerationPluginConfig } from "./lib/moderation/registry"; +export { + defineModerationScope, + type ModerationScopeDefinition, + type ModerationScopeListArgs, + type ModerationScopeListResult, + type ModerationScopeResource, +} from "./lib/moderation/scopes"; +export { + defineReportTarget, + type ModerationActionArgs, + type ModerationActionOutcome, + type ModerationCaptureArgs, + type ModerationCaptureResult, + type ModerationReportTargetDefinition, + type ModerationTargetActionDefinition, + type ModerationTargetState, +} from "./lib/moderation/targets"; diff --git a/packages/vitnode/src/api/modules/admin/staff/lib/schema.ts b/packages/vitnode/src/api/modules/admin/staff/lib/schema.ts index bda31629de..9e50fc4358 100644 --- a/packages/vitnode/src/api/modules/admin/staff/lib/schema.ts +++ b/packages/vitnode/src/api/modules/admin/staff/lib/schema.ts @@ -51,10 +51,36 @@ export const staffListAdminSchema = z.object({ pageInfo: zodPaginationPageInfo, }); +export const permissionStaffScopeSchema = z.discriminatedUnion("mode", [ + z.object({ family: z.string().max(100), mode: z.literal("all") }), + z.object({ + family: z.string().max(100), + mode: z.literal("selected"), + ids: z.array(z.string().max(64)).max(500), + }), +]); + export const permissionsStaffArgsSchema = z.object({ plugin: z.string(), module: z.string(), permission: z.string(), + scope: permissionStaffScopeSchema.optional(), +}); + +export const staffGrantIssueSchema = z.object({ + key: z.string(), + type: z.enum([ + "dependency_scope", + "empty_selection", + "invalid_resource", + "missing_scope", + "unexpected_scope", + "unknown_resource", + "wrong_family", + ]), + dependency: z.string().optional(), + expected: z.string().optional(), + ids: z.array(z.string()).optional(), }); export const staffTypeSchema = z.enum(["admin", "moderator"]); diff --git a/packages/vitnode/src/api/modules/admin/staff/lib/scoped-grants.ts b/packages/vitnode/src/api/modules/admin/staff/lib/scoped-grants.ts new file mode 100644 index 0000000000..47546a9cba --- /dev/null +++ b/packages/vitnode/src/api/modules/admin/staff/lib/scoped-grants.ts @@ -0,0 +1,202 @@ +import type { Context } from "hono"; + +import { HTTPException } from "hono/http-exception"; + +import type { + PermissionsStaffArgs, + PermissionStaffCatalogEntry, + PermissionStaffType, +} from "@/api/lib/permission-staff"; + +import { findModerationScope } from "@/api/lib/moderation/registry"; +import { isModerationResourceId } from "@/api/lib/moderation/scopes"; +import { + staffPermissionKey, + staffScopeCovers, +} from "@/api/lib/staff-permission"; + +export type StaffGrantIssue = + | { dependency: string; key: string; type: "dependency_scope" } + | { expected: string; key: string; type: "wrong_family" } + | { ids: string[]; key: string; type: "invalid_resource" } + | { ids: string[]; key: string; type: "unknown_resource" } + | { key: string; type: "empty_selection" } + | { key: string; type: "missing_scope" } + | { key: string; type: "unexpected_scope" }; + +export class StaffGrantValidationError extends HTTPException { + constructor(issues: StaffGrantIssue[]) { + super(400, { + message: "The submitted permissions are not valid.", + res: Response.json( + { error: "invalid_permissions", issues }, + { status: 400 }, + ), + }); + this.issues = issues; + } + + readonly issues: StaffGrantIssue[]; +} + +interface CatalogEntry { + dependsOn: string[]; + scope?: string; +} + +const catalogIndex = ( + catalog: readonly PermissionStaffCatalogEntry[], + type: PermissionStaffType, +) => { + const index = new Map(); + for (const plugin of catalog) { + for (const [module, entries] of Object.entries(plugin[type])) { + for (const entry of entries) { + index.set( + staffPermissionKey({ + module, + permission: entry.permission, + plugin: plugin.pluginId, + }), + { + dependsOn: entry.dependsOn.map(dependency => + staffPermissionKey({ + module, + permission: dependency, + plugin: plugin.pluginId, + }), + ), + scope: entry.scope, + }, + ); + } + } + } + + return index; +}; + +export const sanitizeStaffGrants = async ( + c: Context, + { + permissions, + type, + }: { permissions: PermissionsStaffArgs[]; type: PermissionStaffType }, +): Promise => { + const index = catalogIndex(c.get("core").permissionStaff, type); + const registry = c.get("core").moderation; + const issues: StaffGrantIssue[] = []; + + const granted = new Map(); + for (const permission of permissions) { + const key = staffPermissionKey(permission); + const entry = index.get(key); + if (!entry || granted.has(key)) continue; + + const base = { + module: permission.module, + permission: permission.permission, + plugin: permission.plugin, + }; + + if (!entry.scope) { + if (permission.scope) issues.push({ key, type: "unexpected_scope" }); + granted.set(key, base); + continue; + } + + const scope = permission.scope; + if (!scope) { + issues.push({ key, type: "missing_scope" }); + continue; + } + if (scope.family !== entry.scope) { + issues.push({ expected: entry.scope, key, type: "wrong_family" }); + continue; + } + if (scope.mode === "all") { + granted.set(key, { + ...base, + scope: { family: scope.family, mode: "all" }, + }); + continue; + } + + const ids = [...new Set(scope.ids)]; + if (ids.length === 0) { + issues.push({ key, type: "empty_selection" }); + continue; + } + const malformed = ids.filter(id => !isModerationResourceId(id)); + if (malformed.length > 0) { + issues.push({ ids: malformed, key, type: "invalid_resource" }); + continue; + } + granted.set(key, { + ...base, + scope: { family: scope.family, ids: ids.sort(), mode: "selected" }, + }); + } + + const selectedByFamily = new Map>(); + for (const grant of granted.values()) { + if (grant.scope?.mode !== "selected") continue; + const ids = selectedByFamily.get(grant.scope.family) ?? new Set(); + for (const id of grant.scope.ids) ids.add(id); + selectedByFamily.set(grant.scope.family, ids); + } + for (const [family, ids] of selectedByFamily) { + const scope = findModerationScope(registry, family); + const found = new Set( + scope + ? (await scope.definition.find(c, [...ids])).map(item => item.id) + : [], + ); + for (const [key, grant] of granted) { + if (grant.scope?.mode !== "selected" || grant.scope.family !== family) { + continue; + } + const missing = grant.scope.ids.filter(id => !found.has(id)); + if (missing.length > 0) { + issues.push({ ids: missing, key, type: "unknown_resource" }); + } + } + } + + let changed = true; + while (changed) { + changed = false; + for (const key of [...granted.keys()]) { + const dependencies = index.get(key)?.dependsOn ?? []; + if (dependencies.some(dependency => !granted.has(dependency))) { + granted.delete(key); + changed = true; + } + } + } + + for (const [key, grant] of granted) { + for (const dependency of index.get(key)?.dependsOn ?? []) { + const held = granted.get(dependency); + if (held && !staffScopeCovers(held.scope, grant.scope)) { + issues.push({ dependency, key, type: "dependency_scope" }); + } + } + } + + if (issues.length > 0) throw new StaffGrantValidationError(issues); + + return [...granted.values()]; +}; + +export const staffGrantsWithinCeiling = ( + requested: readonly PermissionsStaffArgs[], + ceiling: readonly PermissionsStaffArgs[], +): boolean => + requested.every(grant => + ceiling.some( + held => + staffPermissionKey(held) === staffPermissionKey(grant) && + staffScopeCovers(held.scope, grant.scope), + ), + ); diff --git a/packages/vitnode/src/api/modules/admin/staff/lib/staff-entry-guards.ts b/packages/vitnode/src/api/modules/admin/staff/lib/staff-entry-guards.ts index 56e2f76380..55d7cc0087 100644 --- a/packages/vitnode/src/api/modules/admin/staff/lib/staff-entry-guards.ts +++ b/packages/vitnode/src/api/modules/admin/staff/lib/staff-entry-guards.ts @@ -13,9 +13,10 @@ import { getUserRoleIds, resolveStaffPermissions, } from "@/api/lib/check-staff-permission"; -import { staffPermissionKey } from "@/api/lib/staff-permission"; import { core_roles } from "@/database/roles"; +import { staffGrantsWithinCeiling } from "./scoped-grants"; + interface StaffEntryTarget { roleId?: null | number; userId?: null | number; @@ -77,13 +78,7 @@ interface StaffEntryGrant { const exceedsCeiling = ( permissions: PermissionsStaffArgs[], ceiling: PermissionsStaffArgs[], -): boolean => { - const allowed = new Set(ceiling.map(staffPermissionKey)); - - return permissions.some( - permission => !allowed.has(staffPermissionKey(permission)), - ); -}; +): boolean => !staffGrantsWithinCeiling(permissions, ceiling); export const assertCanManageStaffEntry = async ( c: Context, diff --git a/packages/vitnode/src/api/modules/admin/staff/routes/permission-catalog.route.ts b/packages/vitnode/src/api/modules/admin/staff/routes/permission-catalog.route.ts index 98e84721fe..f48c8ba389 100644 --- a/packages/vitnode/src/api/modules/admin/staff/routes/permission-catalog.route.ts +++ b/packages/vitnode/src/api/modules/admin/staff/routes/permission-catalog.route.ts @@ -9,10 +9,17 @@ const permissionStaffModulesSchema = z.record( z.object({ permission: z.string(), dependsOn: z.array(z.string()), + scope: z.string().optional(), }), ), ); +const scopeFamilySchema = z.object({ + id: z.string(), + label: z.string(), + description: z.string().nullable(), +}); + export const permissionCatalogStaffAdminRoute = buildRoute({ pluginId: CONFIG_PLUGIN.pluginId, route: { @@ -29,11 +36,13 @@ export const permissionCatalogStaffAdminRoute = buildRoute({ pluginId: z.string(), admin: permissionStaffModulesSchema, moderator: permissionStaffModulesSchema, + scopes: z.array(scopeFamilySchema), }), ), }, }, - description: "Staff permission catalog", + description: + "Staff permission catalog, with the moderation scope families each plugin registers", }, 403: { description: "Access Denied", @@ -41,6 +50,20 @@ export const permissionCatalogStaffAdminRoute = buildRoute({ }, }, handler: c => { - return c.json(c.get("core").permissionStaff, 200); + const { moderation, permissionStaff } = c.get("core"); + + return c.json( + permissionStaff.map(plugin => ({ + ...plugin, + scopes: (moderation?.scopes ?? []) + .filter(scope => scope.pluginId === plugin.pluginId) + .map(({ definition }) => ({ + id: definition.id, + label: definition.label, + description: definition.description ?? null, + })), + })), + 200, + ); }, }); diff --git a/packages/vitnode/src/api/modules/admin/staff/routes/scope-resources.route.ts b/packages/vitnode/src/api/modules/admin/staff/routes/scope-resources.route.ts new file mode 100644 index 0000000000..c23fa2e6d0 --- /dev/null +++ b/packages/vitnode/src/api/modules/admin/staff/routes/scope-resources.route.ts @@ -0,0 +1,98 @@ +import { z } from "@hono/zod-openapi"; + +import { findModerationScope } from "@/api/lib/moderation/registry"; +import { isModerationResourceId } from "@/api/lib/moderation/scopes"; +import { buildRoute } from "@/api/lib/route"; +import { CONFIG_PLUGIN } from "@/config"; + +import { staffPermissionModuleByType } from "../lib/schema"; + +const resourceSchema = z.object({ + id: z.string(), + label: z.string(), + context: z.array(z.string()), +}); + +const PAGE_SIZE = 20; + +export const scopeResourcesStaffAdminRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + adminStaffPermission: { + module: staffPermissionModuleByType.moderator, + permission: "can_edit", + }, + route: { + method: "get", + description: + "List the resources of one moderation scope family for the moderator editor (Admin only)", + path: "/scope-resources/{family}", + request: { + params: z.object({ family: z.string().max(100) }), + query: z.object({ + search: z.string().max(100).optional(), + cursor: z.string().max(200).optional(), + ids: z.string().max(4000).optional(), + }), + }, + responses: { + 200: { + content: { + "application/json": { + schema: z.object({ + items: z.array(resourceSchema), + missing: z.array(z.string()), + nextCursor: z.string().nullable(), + }), + }, + }, + description: "One page of resources, or the requested ones", + }, + 403: { description: "Access Denied" }, + 404: { description: "Unknown scope family" }, + }, + }, + handler: async c => { + const { family } = c.req.valid("param"); + const scope = findModerationScope(c.get("core").moderation, family); + if (!scope) return c.json({ error: "Unknown scope family" }, 404); + + const { cursor, ids, search } = c.req.valid("query"); + const normalize = (item: { + context?: string[]; + id: string; + label: string; + }) => ({ id: item.id, label: item.label, context: item.context ?? [] }); + + if (ids !== undefined) { + const wanted = [ + ...new Set(ids.split(",").filter(id => isModerationResourceId(id))), + ].slice(0, 200); + const found = wanted.length ? await scope.definition.find(c, wanted) : []; + const foundIds = new Set(found.map(item => item.id)); + + return c.json( + { + items: found.map(normalize), + missing: wanted.filter(id => !foundIds.has(id)), + nextCursor: null, + }, + 200, + ); + } + + const page = await scope.definition.list(c, { + cursor: cursor ?? null, + limit: PAGE_SIZE, + search: search?.trim() === "" ? undefined : search?.trim(), + }); + + return c.json( + { + items: page.items.slice(0, PAGE_SIZE).map(normalize), + missing: [], + nextCursor: page.nextCursor, + }, + 200, + ); + }, +}); diff --git a/packages/vitnode/src/api/modules/admin/staff/routes/scoped-permissions.test.ts b/packages/vitnode/src/api/modules/admin/staff/routes/scoped-permissions.test.ts new file mode 100644 index 0000000000..deb45691b4 --- /dev/null +++ b/packages/vitnode/src/api/modules/admin/staff/routes/scoped-permissions.test.ts @@ -0,0 +1,239 @@ +import type { Context } from "hono"; + +import { OpenAPIHono } from "@hono/zod-openapi"; +import { describe, expect, it } from "vitest"; + +import type { + PermissionsStaffArgs, + PermissionStaffScope, + StaffPermissionSet, +} from "@/api/lib/permission-staff"; + +import { defineModerationScope } from "@/api/lib/moderation/scopes"; +import { normalizePermissionStaffModules } from "@/api/lib/permission-staff"; +import { core_moderators_permissions } from "@/database/moderators"; +import { core_roles } from "@/database/roles"; +import { core_users_secondary_roles } from "@/database/users"; +import { createTestCache } from "@/tests/cache"; +import { createMemoryDb } from "@/tests/memory-db"; +import { + grantStaffPermissions, + ROOT_STAFF_PERMISSIONS, +} from "@/tests/staff-permissions"; + +import { updatePermissionsStaffAdminRoute } from "./update-permissions.route"; + +const FORUM = "@vitnode/forum"; +const FAMILY = "forum.section"; +const SECTION_A = "10"; +const SECTION_B = "20"; +const SECTION_C = "30"; +const SECTIONS = [ + { id: SECTION_A, label: "General" }, + { id: SECTION_B, label: "Off-topic" }, + { id: SECTION_C, label: "Support" }, +]; + +const CATALOG = [ + { + admin: {}, + moderator: normalizePermissionStaffModules({ + topics: [ + { permission: "can_view_reports", scope: FAMILY }, + { + dependsOn: ["can_view_reports"], + permission: "can_manage_reports", + scope: FAMILY, + }, + "can_pin", + ], + }), + pluginId: FORUM, + }, +]; + +const SECTION_SCOPE = defineModerationScope({ + find: async (_c, ids) => + Promise.resolve(SECTIONS.filter(section => ids.includes(section.id))), + id: FAMILY, + label: "@vitnode/forum.scopes.section", + list: async () => Promise.resolve({ items: SECTIONS, nextCursor: null }), +}); + +const selected = (...ids: string[]): PermissionStaffScope => ({ + family: FAMILY, + ids, + mode: "selected", +}); +const everywhere: PermissionStaffScope = { family: FAMILY, mode: "all" }; + +const topics = ( + permission: string, + scope?: PermissionStaffScope, +): PermissionsStaffArgs => ({ + module: "topics", + permission, + plugin: FORUM, + ...(scope ? { scope } : {}), +}); + +const CALLER = { id: 1, roleId: 10 }; +const TARGET_ROLE_ID = 20; +const ENTRY = { + id: 5, + permissions: [], + protected: false, + roleId: TARGET_ROLE_ID, + unrestricted: false, + userId: null, +}; +const EDIT_MODERATORS: PermissionsStaffArgs = { + module: "staff_moderators", + permission: "can_edit", + plugin: "@vitnode/core", +}; + +const appFor = async ( + moderator: + | PermissionsStaffArgs[] + | StaffPermissionSet = ROOT_STAFF_PERMISSIONS, +) => { + const cache = createTestCache(); + await grantStaffPermissions(cache, { + permissions: [EDIT_MODERATORS], + userId: CALLER.id, + }); + await grantStaffPermissions(cache, { + permissions: moderator, + type: "moderator", + userId: CALLER.id, + }); + const memory = createMemoryDb([ + [ + core_roles, + [ + { default: false, guest: false, id: CALLER.roleId, root: false }, + { default: false, guest: false, id: TARGET_ROLE_ID, root: false }, + ], + ], + [core_users_secondary_roles, []], + [core_moderators_permissions, [ENTRY]], + ]); + const app = new OpenAPIHono(); + app.use("*", async (c, next) => { + c.set("admin", { user: CALLER } as unknown as Context["var"]["admin"]); + c.set("cache", cache); + c.set("db", memory.db as unknown as Context["var"]["db"]); + c.set("core", { + moderation: { + scopes: [{ definition: SECTION_SCOPE, pluginId: FORUM }], + targets: [], + }, + permissionStaff: CATALOG, + } as unknown as Context["var"]["core"]); + await next(); + }); + app.openapi( + updatePermissionsStaffAdminRoute.route, + updatePermissionsStaffAdminRoute.handler, + ); + + const save = async (permissions: PermissionsStaffArgs[]) => + await app.request(`/entry/moderator/${ENTRY.id}`, { + body: JSON.stringify({ permissions, unrestricted: false }), + headers: { "Content-Type": "application/json" }, + method: "PATCH", + }); + const stored = () => memory.rows(core_moderators_permissions)[0]?.permissions; + + return { save, stored }; +}; + +const VIEW_KEY = `${FORUM}:topics:can_view_reports`; +const MANAGE_KEY = `${FORUM}:topics:can_manage_reports`; + +describe("saving scoped moderator permissions", () => { + it.each<[string, PermissionsStaffArgs[], Record]>([ + [ + "a scoped permission without a scope", + [topics("can_view_reports")], + { key: VIEW_KEY, type: "missing_scope" }, + ], + [ + "a section id that does not exist", + [topics("can_view_reports", selected(SECTION_A, "999"))], + { ids: ["999"], key: VIEW_KEY, type: "unknown_resource" }, + ], + [ + "an empty selection", + [topics("can_view_reports", selected())], + { key: VIEW_KEY, type: "empty_selection" }, + ], + [ + "managing where the moderator cannot view", + [ + topics("can_view_reports", selected(SECTION_A)), + topics("can_manage_reports", selected(SECTION_B)), + ], + { dependency: VIEW_KEY, key: MANAGE_KEY, type: "dependency_scope" }, + ], + [ + "a scope on an unscoped permission", + [topics("can_pin", everywhere)], + { key: `${FORUM}:topics:can_pin`, type: "unexpected_scope" }, + ], + ])("refuses %s", async (_label, permissions, issue) => { + const { save, stored } = await appFor(); + + const res = await save(permissions); + + expect(res.status).toBe(400); + expect(await res.json()).toEqual({ + error: "invalid_permissions", + issues: [issue], + }); + expect(stored()).toEqual([]); + }); + + it("stores a valid selection with its ids sorted and de-duplicated", async () => { + const { save, stored } = await appFor(); + + const res = await save([ + topics("can_view_reports", selected(SECTION_C, SECTION_A, SECTION_C)), + topics("can_manage_reports", selected(SECTION_A)), + ]); + + expect(res.status).toBe(200); + expect(stored()).toEqual([ + topics("can_view_reports", selected(SECTION_A, SECTION_C)), + topics("can_manage_reports", selected(SECTION_A)), + ]); + }); + + it("measures delegation against the resources the caller holds", async () => { + const callerViewsA = [topics("can_view_reports", selected(SECTION_A))]; + + const wider = await appFor(callerViewsA); + expect( + ( + await wider.save([ + topics("can_view_reports", selected(SECTION_A, SECTION_B)), + ]) + ).status, + ).toBe(403); + expect(wider.stored()).toEqual([]); + + const everywhereRequest = await appFor(callerViewsA); + expect( + (await everywhereRequest.save([topics("can_view_reports", everywhere)])) + .status, + ).toBe(403); + + const within = await appFor(callerViewsA); + expect( + (await within.save([topics("can_view_reports", selected(SECTION_A))])) + .status, + ).toBe(200); + expect(within.stored()).toEqual(callerViewsA); + }); +}); diff --git a/packages/vitnode/src/api/modules/admin/staff/routes/update-permissions.route.ts b/packages/vitnode/src/api/modules/admin/staff/routes/update-permissions.route.ts index 84df835ff0..1baaaccce0 100644 --- a/packages/vitnode/src/api/modules/admin/staff/routes/update-permissions.route.ts +++ b/packages/vitnode/src/api/modules/admin/staff/routes/update-permissions.route.ts @@ -6,7 +6,6 @@ import type { PermissionsStaffArgs } from "@/api/lib/permission-staff"; import { assertStaffPermission } from "@/api/lib/check-staff-permission"; import { buildRoute } from "@/api/lib/route"; -import { staffPermissionKey } from "@/api/lib/staff-permission"; import { invalidateStaffEntry } from "@/api/lib/staff-permission-cache"; import { CONFIG_PLUGIN } from "@/config"; import { core_admin_permissions } from "@/database/admins"; @@ -14,9 +13,11 @@ import { core_moderators_permissions } from "@/database/moderators"; import { permissionsStaffArgsSchema, + staffGrantIssueSchema, staffPermissionModuleByType, staffTypeSchema, } from "../lib/schema"; +import { sanitizeStaffGrants } from "../lib/scoped-grants"; import { assertNotOwnStaffEntry, assertStaffAssignableRole, @@ -63,7 +64,16 @@ export const updatePermissionsStaffAdminRoute = buildRoute({ description: "Updated permissions", }, 400: { - description: "The default and guest roles cannot be given staff access", + content: { + "application/json": { + schema: z.object({ + error: z.string(), + issues: z.array(staffGrantIssueSchema), + }), + }, + }, + description: + "A scope is missing, malformed, names unknown resources, or is wider than its dependency's. The default and guest roles cannot be given staff access either", }, 403: { description: "Access Denied", @@ -136,62 +146,9 @@ export const updatePermissionsStaffAdminRoute = buildRoute({ requested: { unrestricted, permissions }, }); - // Only persist permissions that actually exist in the catalog for this - // staff type - silently drops anything unknown/forged. Also record each - // permission's dependencies (the keys of the permissions it `dependsOn` - // within the same module) so we can drop grants whose gate is missing. - const allowed = new Set(); - const dependencies = new Map(); - for (const plugin of c.get("core").permissionStaff) { - for (const [module, modulePermissions] of Object.entries(plugin[type])) { - for (const entry of modulePermissions) { - const key = staffPermissionKey({ - plugin: plugin.pluginId, - module, - permission: entry.permission, - }); - allowed.add(key); - dependencies.set( - key, - entry.dependsOn.map(dependency => - staffPermissionKey({ - plugin: plugin.pluginId, - module, - permission: dependency, - }), - ), - ); - } - } - } - - const seen = new Set(); - const granted = new Map(); - // When unrestricted, the explicit list is irrelevant - store none. - if (!unrestricted) { - for (const permission of permissions) { - const key = staffPermissionKey(permission); - if (!allowed.has(key) || seen.has(key)) continue; - seen.add(key); - granted.set(key, permission); - } - - // Drop any granted permission whose dependencies aren't all granted too, - // repeating until stable so a broken chain (a → b → c) collapses fully. - let changed = true; - while (changed) { - changed = false; - for (const key of granted.keys()) { - const deps = dependencies.get(key) ?? []; - if (deps.some(dependency => !granted.has(dependency))) { - granted.delete(key); - changed = true; - } - } - } - } - - const sanitized: PermissionsStaffArgs[] = [...granted.values()]; + const sanitized: PermissionsStaffArgs[] = unrestricted + ? [] + : await sanitizeStaffGrants(c, { permissions, type }); const [updated] = await c .get("db") diff --git a/packages/vitnode/src/api/modules/admin/staff/staff.admin.module.ts b/packages/vitnode/src/api/modules/admin/staff/staff.admin.module.ts index 7b66659c25..e1320d356e 100644 --- a/packages/vitnode/src/api/modules/admin/staff/staff.admin.module.ts +++ b/packages/vitnode/src/api/modules/admin/staff/staff.admin.module.ts @@ -6,6 +6,7 @@ import { createStaffAdminRoute } from "./routes/create.route"; import { deleteStaffAdminRoute } from "./routes/delete.route"; import { listModeratorsStaffAdminRoute } from "./routes/moderators.route"; import { permissionCatalogStaffAdminRoute } from "./routes/permission-catalog.route"; +import { scopeResourcesStaffAdminRoute } from "./routes/scope-resources.route"; import { showPermissionsStaffAdminRoute } from "./routes/show-permissions.route"; import { updatePermissionsStaffAdminRoute } from "./routes/update-permissions.route"; @@ -16,6 +17,7 @@ export const staffAdminModule = buildModule({ listModeratorsStaffAdminRoute, listAdminsStaffAdminRoute, permissionCatalogStaffAdminRoute, + scopeResourcesStaffAdminRoute, showPermissionsStaffAdminRoute, updatePermissionsStaffAdminRoute, createStaffAdminRoute, diff --git a/packages/vitnode/src/api/modules/moderation/lib/candidates.ts b/packages/vitnode/src/api/modules/moderation/lib/candidates.ts new file mode 100644 index 0000000000..c676f88988 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/lib/candidates.ts @@ -0,0 +1,60 @@ +import type { Context } from "hono"; + +import { eq, inArray, or } from "drizzle-orm"; + +import { core_moderators_permissions } from "@/database/moderators"; +import { core_roles } from "@/database/roles"; +import { core_users, core_users_secondary_roles } from "@/database/users"; + +const LIMIT = 100; + +export const listModeratorCandidates = async (c: Context) => { + const db = c.get("db"); + const [entries, rootRoles] = await Promise.all([ + db + .select({ + roleId: core_moderators_permissions.roleId, + userId: core_moderators_permissions.userId, + }) + .from(core_moderators_permissions), + db + .select({ id: core_roles.id }) + .from(core_roles) + .where(eq(core_roles.root, true)), + ]); + + const roleIds = [ + ...new Set([ + ...entries.map(entry => entry.roleId), + ...rootRoles.map(role => role.id), + ]), + ].filter((id): id is number => id !== null); + const userIds = entries + .map(entry => entry.userId) + .filter((id): id is number => id !== null); + + const secondary = roleIds.length + ? await db + .select({ userId: core_users_secondary_roles.userId }) + .from(core_users_secondary_roles) + .where(inArray(core_users_secondary_roles.roleId, roleIds)) + : []; + const ids = [...new Set([...userIds, ...secondary.map(row => row.userId)])]; + + const conditions = [ + ...(ids.length ? [inArray(core_users.id, ids)] : []), + ...(roleIds.length ? [inArray(core_users.roleId, roleIds)] : []), + ]; + if (conditions.length === 0) return []; + + return await db + .select({ + id: core_users.id, + name: core_users.name, + nameCode: core_users.nameCode, + roleId: core_users.roleId, + }) + .from(core_users) + .where(or(...conditions)) + .limit(LIMIT); +}; diff --git a/packages/vitnode/src/api/modules/moderation/lib/notes.ts b/packages/vitnode/src/api/modules/moderation/lib/notes.ts new file mode 100644 index 0000000000..1b5d353926 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/lib/notes.ts @@ -0,0 +1,66 @@ +import type { Context } from "hono"; + +import { and, eq } from "drizzle-orm"; + +import type { ModeratorContext } from "@/api/lib/moderation/access"; + +import { canOnReport } from "@/api/lib/moderation/access"; +import { core_moderation_report_events } from "@/database/moderation"; +import { MODERATION_PERMISSIONS } from "@/lib/moderation/const"; + +import type { ReportRow } from "./reports"; + +import { reportError } from "./reports"; + +type NoteAction = "delete" | "edit"; + +const ANY_NOTE_PERMISSION: Record = { + delete: MODERATION_PERMISSIONS.deleteNotes, + edit: MODERATION_PERMISSIONS.editNotes, +}; + +export const canChangeNote = ( + c: Context, + moderator: ModeratorContext, + report: Pick, + note: { actorId: null | number }, + action: NoteAction, +): boolean => { + const ref = { + pluginId: report.pluginId, + scopeId: report.scopeId, + targetType: report.targetType, + }; + if ( + !canOnReport(c, moderator.set, ref, MODERATION_PERMISSIONS.manageReports) + ) { + return false; + } + + return ( + note.actorId === moderator.user.id || + canOnReport(c, moderator.set, ref, ANY_NOTE_PERMISSION[action]) + ); +}; + +export const loadReportNote = async ( + c: Context, + reportId: number, + noteId: number, +) => { + const [note] = await c + .get("db") + .select() + .from(core_moderation_report_events) + .where( + and( + eq(core_moderation_report_events.id, noteId), + eq(core_moderation_report_events.reportId, reportId), + eq(core_moderation_report_events.type, "note"), + ), + ) + .limit(1); + if (!note) throw reportError(404, { error: "note_not_found" }); + + return note; +}; diff --git a/packages/vitnode/src/api/modules/moderation/lib/people.ts b/packages/vitnode/src/api/modules/moderation/lib/people.ts new file mode 100644 index 0000000000..340ab682ca --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/lib/people.ts @@ -0,0 +1,57 @@ +import type { Context } from "hono"; + +import { eq, inArray } from "drizzle-orm"; + +import { storageUrlOf } from "@/api/lib/storage-url"; +import { core_files } from "@/database/files"; +import { core_roles } from "@/database/roles"; +import { core_users } from "@/database/users"; + +export interface ReportPerson { + avatarColor: string; + avatarUrl: null | string; + id: number; + name: string; + nameCode: string; + role: { color: null | string; prefix: null | string }; +} + +export const loadReportPeople = async ( + c: Context, + ids: readonly (null | number | undefined)[], +): Promise> => { + const unique = [ + ...new Set(ids.filter((id): id is number => typeof id === "number")), + ]; + if (unique.length === 0) return new Map(); + + const rows = await c + .get("db") + .select({ + avatarColor: core_users.avatarColor, + avatarKey: core_files.key, + id: core_users.id, + name: core_users.name, + nameCode: core_users.nameCode, + roleColor: core_roles.color, + rolePrefix: core_roles.prefix, + }) + .from(core_users) + .leftJoin(core_roles, eq(core_roles.id, core_users.roleId)) + .leftJoin(core_files, eq(core_files.id, core_users.avatarId)) + .where(inArray(core_users.id, unique)); + + return new Map( + rows.map(row => [ + row.id, + { + avatarColor: row.avatarColor, + avatarUrl: storageUrlOf(c, row.avatarKey), + id: row.id, + name: row.name, + nameCode: row.nameCode, + role: { color: row.roleColor ?? null, prefix: row.rolePrefix ?? null }, + }, + ]), + ); +}; diff --git a/packages/vitnode/src/api/modules/moderation/lib/reports.ts b/packages/vitnode/src/api/modules/moderation/lib/reports.ts new file mode 100644 index 0000000000..29715cb06a --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/lib/reports.ts @@ -0,0 +1,271 @@ +import type { Context } from "hono"; + +import { and, count, desc, eq, gte, inArray, isNull, or } from "drizzle-orm"; +import { HTTPException } from "hono/http-exception"; + +import type { ModeratorContext } from "@/api/lib/moderation/access"; +import type { RegisteredReportTarget } from "@/api/lib/moderation/targets"; +import type { ContentDatabase } from "@/content/server/service"; +import type { ModerationReportEventType } from "@/lib/moderation/const"; + +import { + canOnReport, + syncReportTargetScope, +} from "@/api/lib/moderation/access"; +import { findReportTarget } from "@/api/lib/moderation/registry"; +import { + core_moderation_report_events, + core_moderation_reports, +} from "@/database/moderation"; +import { MODERATION_PERMISSIONS } from "@/lib/moderation/const"; + +export type ReportRow = typeof core_moderation_reports.$inferSelect; + +export const reportOpenKey = ({ + pluginId, + reporterId, + targetId, + targetType, +}: { + pluginId: string; + reporterId: number; + targetId: string; + targetType: string; +}): string => `${reporterId}:${pluginId}:${targetType}:${targetId}`; + +const jsonError = ( + status: 400 | 403 | 404 | 409 | 429, + body: Record, +): HTTPException => + new HTTPException(status, { + message: String(body.error), + res: Response.json(body, { status }), + }); + +export const reportNotFound = (): HTTPException => + jsonError(404, { error: "not_found" }); + +export const reportConflict = ( + current: null | Pick, + error = "conflict", +): HTTPException => + jsonError(409, { + current: current + ? { + assigneeId: current.assigneeId, + status: current.status, + version: current.version, + } + : null, + error, + }); + +export const reportError = jsonError; + +export const loadReport = async ( + db: ContentDatabase, + id: number, +): Promise => { + const [row] = await db + .select() + .from(core_moderation_reports) + .where(eq(core_moderation_reports.id, id)) + .limit(1); + + return row ?? null; +}; + +export const updateReport = async ( + db: ContentDatabase, + report: Pick, + patch: Partial< + Omit + >, +): Promise => { + const [updated] = await db + .update(core_moderation_reports) + .set({ ...patch, version: report.version + 1 }) + .where( + and( + eq(core_moderation_reports.id, report.id), + eq(core_moderation_reports.version, report.version), + ), + ) + .returning(); + if (updated) return updated; + + throw reportConflict(await loadReport(db, report.id)); +}; + +export const appendReportEvent = async ( + db: ContentDatabase, + event: { + actorId: null | number; + data?: Record; + reportId: number; + type: ModerationReportEventType; + }, +): Promise => { + await db.insert(core_moderation_report_events).values({ + actorId: event.actorId, + data: event.data ?? {}, + reportId: event.reportId, + type: event.type, + }); +}; + +export interface AuthorizedReport { + report: ReportRow; + scopeId: null | string; + target: RegisteredReportTarget | undefined; +} + +export const authorizeReport = async ( + c: Context, + moderator: ModeratorContext, + id: number, + { manage = false }: { manage?: boolean } = {}, +): Promise => { + const db = c.get("db"); + let report = await loadReport(db, id); + if (!report) throw reportNotFound(); + + const target = findReportTarget(c.get("core").moderation, { + pluginId: report.pluginId, + type: report.targetType, + }); + + if (target?.definition.scope) { + const current = await syncReportTargetScope(c, { + target, + targetId: report.targetId, + }); + if (current !== undefined && current !== report.scopeId) { + report = (await loadReport(db, id)) ?? report; + } + } + + const ref = { + pluginId: report.pluginId, + scopeId: report.scopeId, + targetType: report.targetType, + }; + if (!canOnReport(c, moderator.set, ref, MODERATION_PERMISSIONS.viewReports)) { + throw reportNotFound(); + } + if ( + manage && + !canOnReport(c, moderator.set, ref, MODERATION_PERMISSIONS.manageReports) + ) { + throw reportError(403, { error: "forbidden" }); + } + + return { report, scopeId: report.scopeId, target }; +}; + +export const countRecentReports = async ( + c: Context, + reporterId: number, +): Promise => { + const [row] = await c + .get("db") + .select({ value: count() }) + .from(core_moderation_reports) + .where( + and( + eq(core_moderation_reports.reporterId, reporterId), + gte( + core_moderation_reports.createdAt, + new Date(Date.now() - 60 * 60 * 1000), + ), + ), + ); + + return row?.value ?? 0; +}; + +export const relatedReports = async ( + c: Context, + moderator: ModeratorContext, + report: ReportRow, +) => { + const rows = await c + .get("db") + .select({ + createdAt: core_moderation_reports.createdAt, + description: core_moderation_reports.description, + id: core_moderation_reports.id, + reason: core_moderation_reports.reason, + reporterId: core_moderation_reports.reporterId, + scopeId: core_moderation_reports.scopeId, + status: core_moderation_reports.status, + }) + .from(core_moderation_reports) + .where( + and( + eq(core_moderation_reports.pluginId, report.pluginId), + eq(core_moderation_reports.targetType, report.targetType), + eq(core_moderation_reports.targetId, report.targetId), + ), + ) + .orderBy(desc(core_moderation_reports.createdAt)) + .limit(50); + + return rows + .filter(row => row.id !== report.id) + .filter(row => + canOnReport( + c, + moderator.set, + { + pluginId: report.pluginId, + scopeId: row.scopeId, + targetType: report.targetType, + }, + MODERATION_PERMISSIONS.viewReports, + ), + ) + .map(({ scopeId: _scope, ...row }) => row); +}; + +export const queueFilters = ({ + assigned, + status, + userId, +}: { + assigned: "any" | "me" | "unassigned"; + status: "all" | "done" | "in_progress" | "new" | "open"; + userId: number; +}) => { + const table = core_moderation_reports; + const byStatus = + status === "all" + ? undefined + : status === "open" + ? or(eq(table.status, "new"), eq(table.status, "in_progress")) + : eq(table.status, status); + const byAssignee = + assigned === "me" + ? eq(table.assigneeId, userId) + : assigned === "unassigned" + ? isNull(table.assigneeId) + : undefined; + + return [byStatus, byAssignee].filter(condition => condition !== undefined); +}; + +export const reportTargetTriplets = ( + rows: Pick[], +) => + or( + ...rows.map(row => + and( + eq(core_moderation_reports.pluginId, row.pluginId), + eq(core_moderation_reports.targetType, row.targetType), + eq(core_moderation_reports.targetId, row.targetId), + ), + ), + ); + +export const reportIdsOf = (ids: number[]) => + inArray(core_moderation_reports.id, ids); diff --git a/packages/vitnode/src/api/modules/moderation/lib/schema.ts b/packages/vitnode/src/api/modules/moderation/lib/schema.ts new file mode 100644 index 0000000000..0975bc95c5 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/lib/schema.ts @@ -0,0 +1,82 @@ +import { z } from "@hono/zod-openapi"; + +import { createRichTextDocumentSchema } from "@/content/rich-text/document"; +import { + MODERATION_LIMITS, + MODERATION_REPORT_EVENT_TYPES, + MODERATION_REPORT_REASONS, + MODERATION_REPORT_RESOLUTIONS, + MODERATION_REPORT_STATUSES, +} from "@/lib/moderation/const"; + +export const reportIdParams = z.object({ + id: z.coerce.number().int().positive().openapi({ example: 1 }), +}); + +export const expectedVersionBody = z.object({ + expectedVersion: z.number().int().positive(), +}); + +export const errorSchema = z.object({ error: z.string() }); + +export const conflictSchema = z.object({ + error: z.string(), + current: z + .object({ + assigneeId: z.number().nullable(), + status: z.enum(MODERATION_REPORT_STATUSES), + version: z.number(), + }) + .nullable(), +}); + +export const reportUserSchema = z.object({ + id: z.number(), + name: z.string(), + nameCode: z.string(), +}); + +export const reportPersonSchema = reportUserSchema.extend({ + avatarColor: z.string(), + avatarUrl: z.string().nullable(), + role: z.object({ + color: z.string().nullable(), + prefix: z.string().nullable(), + }), +}); + +export const reportStateSchema = z.object({ + assigneeId: z.number().nullable(), + status: z.enum(MODERATION_REPORT_STATUSES), + version: z.number(), +}); + +export const reasonSchema = z.enum(MODERATION_REPORT_REASONS); +export const resolutionSchema = z.enum(MODERATION_REPORT_RESOLUTIONS); +export const eventTypeSchema = z.enum(MODERATION_REPORT_EVENT_TYPES); + +export const noteSchema = z + .string() + .trim() + .min(MODERATION_LIMITS.explanationMinLength) + .max(MODERATION_LIMITS.noteMaxLength); + +export const richNoteSchema = z.union([ + noteSchema, + createRichTextDocumentSchema({ + maxBytes: MODERATION_LIMITS.richNoteMaxBytes, + required: true, + }), +]); + +export const optionalExplanationSchema = z + .string() + .trim() + .max(MODERATION_LIMITS.noteMaxLength) + .nullish() + .transform(value => (value === "" ? null : (value ?? null))); + +export const json = (schema: T, description: string) => ({ + content: { "application/json": { schema } }, + description, +}); diff --git a/packages/vitnode/src/api/modules/moderation/moderation.module.ts b/packages/vitnode/src/api/modules/moderation/moderation.module.ts new file mode 100644 index 0000000000..930fe3d0ee --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/moderation.module.ts @@ -0,0 +1,38 @@ +import { buildModule } from "@/api/lib/module"; +import { CONFIG_PLUGIN } from "@/config"; + +import { createReportRoute } from "./routes/create.route"; +import { listReportsRoute } from "./routes/list.route"; +import { + deleteReportNoteRoute, + editReportNoteRoute, +} from "./routes/notes.routes"; +import { showReportRoute } from "./routes/show.route"; +import { + assignReportRoute, + claimReportRoute, + noteReportRoute, + reopenReportRoute, + reportActionRoute, + reportAssigneesRoute, + resolveReportRoute, +} from "./routes/workflow.routes"; + +export const moderationModule = buildModule({ + pluginId: CONFIG_PLUGIN.pluginId, + name: "moderation", + routes: [ + createReportRoute, + listReportsRoute, + showReportRoute, + claimReportRoute, + assignReportRoute, + noteReportRoute, + editReportNoteRoute, + deleteReportNoteRoute, + resolveReportRoute, + reopenReportRoute, + reportActionRoute, + reportAssigneesRoute, + ], +}); diff --git a/packages/vitnode/src/api/modules/moderation/reports.test.ts b/packages/vitnode/src/api/modules/moderation/reports.test.ts new file mode 100644 index 0000000000..fe564912f5 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/reports.test.ts @@ -0,0 +1,586 @@ +import type { Context } from "hono"; + +import { OpenAPIHono } from "@hono/zod-openapi"; +import { describe, expect, it, vi } from "vitest"; + +import type { PermissionsStaffArgs } from "@/api/lib/permission-staff"; +import type { ModerationCaptureResult } from "@/api/moderation"; + +import { defineModerationScope, defineReportTarget } from "@/api/moderation"; +import { core_files } from "@/database/files"; +import { + core_moderation_report_events, + core_moderation_reports, +} from "@/database/moderation"; +import { core_roles } from "@/database/roles"; +import { core_users } from "@/database/users"; +import { createTestCache } from "@/tests/cache"; +import { createMemoryDb } from "@/tests/memory-db"; +import { + grantStaffPermissions, + ROOT_STAFF_PERMISSIONS, +} from "@/tests/staff-permissions"; + +import { moderationModule } from "./moderation.module"; + +const FORUM = "@vitnode/forum"; +const FAMILY = "forum.section"; +const TYPE = "forum.topic"; +const SECTION_A = "10"; +const SECTION_B = "20"; +const DRAFT_TOPIC = "99"; + +const MEMBER_ROLE = 3; +const REPORTER = 100; +const SECOND_REPORTER = 101; +const MOD_A = 200; +const SECOND_MOD_A = 201; +const MOD_B = 202; +const ROOT_MOD = 300; + +const topics = (permission: string, section: string): PermissionsStaffArgs => ({ + module: "topics", + permission, + plugin: FORUM, + scope: { family: FAMILY, ids: [section], mode: "selected" }, +}); + +const moderatorOf = (section: string) => [ + topics("can_view_reports", section), + topics("can_manage_reports", section), + topics("can_view_hidden", section), + topics("can_hide", section), +]; + +const harness = async () => { + const sections = new Map([ + ["1", SECTION_A], + ["2", SECTION_A], + ["3", SECTION_B], + ]); + const deleted = new Set(); + const hidden = new Set(); + const fixture = { + body: "Original body", + failHide: false, + onCapture: undefined as (() => Promise) | undefined, + servedLocale: "en", + }; + const effects = vi.fn(async () => Promise.resolve()); + + const target = defineReportTarget({ + actions: { + hide: { + available: state => !state.hidden, + permission: "can_hide", + run: async (_c, { targetId }) => { + if (fixture.failHide) throw new Error("hide failed"); + hidden.add(targetId); + + return Promise.resolve({ changed: true, effects }); + }, + }, + }, + capture: async ( + _c, + { targetId }, + ): Promise => { + await fixture.onCapture?.(); + if (targetId === DRAFT_TOPIC || deleted.has(targetId)) return null; + + return { + authors: [{ id: 1, name: "Author" }], + fields: [ + { kind: "text", label: null, name: "body", value: fixture.body }, + ], + locale: { + fallback: false, + requested: null, + served: fixture.servedLocale, + }, + scope: null, + source: { publishedAt: null, updatedAt: null, version: null }, + title: `Topic ${targetId}`, + url: `/topics/${targetId}`, + }; + }, + current: async (_c, { targetId }) => + Promise.resolve( + deleted.has(targetId) + ? null + : { hidden: hidden.has(targetId), url: `/topics/${targetId}` }, + ), + label: "Topic", + parseId: value => (/^\d+$/.test(value) ? value : null), + permissionModule: "topics", + resolveScope: async (_c, targetId) => + Promise.resolve( + deleted.has(targetId) ? undefined : sections.get(targetId), + ), + scope: FAMILY, + type: TYPE, + }); + const scope = defineModerationScope({ + find: async () => Promise.resolve([]), + id: FAMILY, + label: "Section", + list: async () => Promise.resolve({ items: [], nextCursor: null }), + }); + + const cache = createTestCache(); + for (const [userId, permissions] of [ + [MOD_A, moderatorOf(SECTION_A)], + [SECOND_MOD_A, moderatorOf(SECTION_A)], + [MOD_B, moderatorOf(SECTION_B)], + [ROOT_MOD, ROOT_STAFF_PERMISSIONS], + ] as const) { + await grantStaffPermissions(cache, { + permissions, + type: "moderator", + userId, + }); + } + + const users = [ + REPORTER, + SECOND_REPORTER, + MOD_A, + SECOND_MOD_A, + MOD_B, + ROOT_MOD, + ]; + const memory = createMemoryDb([ + [ + core_users, + users.map(id => ({ + email: `${id}@example.com`, + id, + name: `User ${id}`, + nameCode: `user-${id}`, + roleId: MEMBER_ROLE, + })), + ], + [core_roles, [{ color: null, id: MEMBER_ROLE, prefix: null }]], + [core_files, []], + [core_moderation_reports, []], + [core_moderation_report_events, []], + ]); + const emit = vi.fn(async () => Promise.resolve()); + + const app = new OpenAPIHono(); + app.use("*", async (c, next) => { + const userId = Number(c.req.header("x-user")); + c.set( + "user", + (users.includes(userId) + ? { id: userId, roleId: MEMBER_ROLE } + : null) as unknown as Context["var"]["user"], + ); + c.set("cache", cache); + c.set("db", memory.db as unknown as Context["var"]["db"]); + c.set("events", { emit } as unknown as Context["var"]["events"]); + c.set("core", { + moderation: { + scopes: [{ definition: scope, pluginId: FORUM }], + targets: [{ definition: target, pluginId: FORUM }], + }, + permissionStaff: [], + } as unknown as Context["var"]["core"]); + await next(); + }); + app.route("/", moderationModule.hono); + + const call = async ( + userId: number, + method: "GET" | "POST", + path: string, + body?: Record, + ) => + await app.request(path, { + method, + headers: { + "content-type": "application/json", + "x-user": String(userId), + }, + ...(body ? { body: JSON.stringify(body) } : {}), + }); + + const report = async ( + userId: number, + targetId: string, + extra: Record = {}, + ) => + await call(userId, "POST", "/reports", { + pluginId: FORUM, + reason: "spam", + targetId, + targetType: TYPE, + ...extra, + }); + + const reportId = async (userId: number, targetId: string) => { + const res = await report(userId, targetId); + expect(res.status).toBe(201); + + return ((await res.json()) as { id: number }).id; + }; + + const row = (id: number) => + memory.rows(core_moderation_reports).find(entry => entry.id === id); + const eventsOf = (id: number) => + memory + .rows(core_moderation_report_events) + .filter(entry => entry.reportId === id) + .map(entry => ({ data: entry.data, type: entry.type })); + + const seed = async (targetId: string, scopeId: string, createdAt: Date) => { + await memory.db.insert(core_moderation_reports).values({ + createdAt, + openKey: null, + pluginId: FORUM, + reason: "spam", + reporterId: null, + scopeFamily: FAMILY, + scopeId, + snapshot: {}, + targetId, + targetType: TYPE, + }); + }; + + return { + call, + deleted, + effects, + emit, + eventsOf, + fixture, + memory, + report, + reportId, + row, + sections, + seed, + }; +}; + +interface Detail { + current: { exists: boolean; hidden: boolean }; + related: { id: number }[]; + report: { scope: null | { id: string }; status: string; version: number }; + snapshot: { + fields: { value: unknown }[]; + locale: { + fallback: boolean; + requested: null | string; + served: null | string; + }; + title: string; + }; +} + +const detail = async ( + h: Awaited>, + userId: number, + id: number, +) => { + const res = await h.call(userId, "GET", `/reports/${id}`); + + return { + body: res.status === 200 ? ((await res.json()) as Detail) : null, + status: res.status, + }; +}; + +const queue = async ( + h: Awaited>, + userId: number, +) => { + const res = await h.call(userId, "GET", "/reports?status=all"); + expect(res.status).toBe(200); + + return (await res.json()) as { + items: { id: number; relatedCount: number }[]; + total: number; + }; +}; + +describe("filing a report", () => { + it("refuses a second open report from the same reporter, not from another", async () => { + const h = await harness(); + const first = await h.reportId(REPORTER, "1"); + + const again = await h.report(REPORTER, "1"); + expect(again.status).toBe(409); + expect(await again.json()).toEqual({ error: "duplicate" }); + + const other = await h.reportId(SECOND_REPORTER, "1"); + expect(other).not.toBe(first); + }); + + it("turns a duplicate that raced past the check into a 409", async () => { + const h = await harness(); + h.fixture.onCapture = async () => { + h.fixture.onCapture = undefined; + await h.seed("1", SECTION_A, new Date()); + await h.memory.db + .update(core_moderation_reports) + .set({ openKey: `${REPORTER}:${FORUM}:${TYPE}:1` }); + }; + + const res = await h.report(REPORTER, "1"); + + expect(res.status).toBe(409); + expect(await res.json()).toEqual({ error: "duplicate" }); + expect(h.memory.rows(core_moderation_reports)).toHaveLength(1); + expect(h.memory.rows(core_moderation_report_events)).toEqual([]); + }); + + it("answers 404 when the reporter cannot read the target", async () => { + const h = await harness(); + + const res = await h.report(REPORTER, DRAFT_TOPIC); + + expect(res.status).toBe(404); + expect(h.memory.rows(core_moderation_reports)).toEqual([]); + }); + + it("records that the snapshot was served in a fallback language", async () => { + const h = await harness(); + const plain = await h.reportId(REPORTER, "1"); + const localized = await h.report(SECOND_REPORTER, "1", { + locale: "pl", + requestedLocale: "pl", + }); + expect(localized.status).toBe(201); + const { id } = (await localized.json()) as { id: number }; + + expect((await detail(h, ROOT_MOD, id)).body?.snapshot.locale).toEqual({ + fallback: true, + requested: "pl", + served: "en", + }); + expect( + (await detail(h, ROOT_MOD, plain)).body?.snapshot.locale.fallback, + ).toBe(false); + }); +}); + +describe("the report queue", () => { + it("filters by the moderator's sections before counting and paginating", async () => { + const h = await harness(); + const day = (n: number) => new Date(Date.UTC(2026, 0, n)); + await h.seed("1", SECTION_A, day(1)); + await h.seed("2", SECTION_A, day(2)); + for (let n = 0; n < 30; n++) await h.seed("3", SECTION_B, day(3 + n)); + + const scoped = await queue(h, MOD_A); + expect(scoped.total).toBe(2); + expect(scoped.items).toHaveLength(2); + + const other = await queue(h, MOD_B); + expect(other.total).toBe(30); + expect(other.items).toHaveLength(25); + + expect((await queue(h, ROOT_MOD)).total).toBe(32); + }); + + it("counts related reports only among those the moderator may view", async () => { + const h = await harness(); + await h.reportId(REPORTER, "1"); + await h.reportId(SECOND_REPORTER, "1"); + + const { items } = await queue(h, MOD_A); + + expect(items.map(item => item.relatedCount)).toEqual([1, 1]); + expect((await queue(h, MOD_B)).items).toEqual([]); + }); +}); + +describe("a report's detail", () => { + it("is a 404 outside the moderator's sections, and lists related reports inside", async () => { + const h = await harness(); + const first = await h.reportId(REPORTER, "1"); + const second = await h.reportId(SECOND_REPORTER, "1"); + await h.reportId(REPORTER, "2"); + + expect((await detail(h, MOD_B, first)).status).toBe(404); + + const { body } = await detail(h, MOD_A, first); + expect(body?.related.map(entry => entry.id)).toEqual([second]); + }); + + it("keeps the stored snapshot after the target is edited and deleted", async () => { + const h = await harness(); + const id = await h.reportId(REPORTER, "1"); + const before = (await detail(h, MOD_A, id)).body?.snapshot; + expect(before?.fields).toEqual([ + expect.objectContaining({ value: "Original body" }), + ]); + + h.fixture.body = "Edited body"; + expect((await detail(h, MOD_A, id)).body?.snapshot).toEqual(before); + + h.deleted.add("1"); + const gone = await detail(h, MOD_A, id); + expect(gone.body?.snapshot).toEqual(before); + expect(gone.body?.current.exists).toBe(false); + expect(gone.body?.report.scope).toEqual({ family: FAMILY, id: SECTION_A }); + }); + + it("follows a topic moved to another section, unassigning who lost access", async () => { + const h = await harness(); + const id = await h.reportId(REPORTER, "2"); + const claim = await h.call(MOD_A, "POST", `/reports/${id}/claim`, { + expectedVersion: 1, + }); + expect(claim.status).toBe(200); + + h.sections.set("2", SECTION_B); + + expect((await detail(h, MOD_A, id)).status).toBe(404); + expect(h.row(id)).toEqual( + expect.objectContaining({ + assigneeId: null, + scopeId: SECTION_B, + status: "new", + }), + ); + expect(h.eventsOf(id)).toContainEqual({ + data: { previousAssigneeId: MOD_A, reason: "lost_access" }, + type: "unassigned", + }); + expect((await detail(h, MOD_B, id)).status).toBe(200); + }); +}); + +describe("working a report", () => { + it("lets one claim win and tells the other why it lost", async () => { + const h = await harness(); + const id = await h.reportId(REPORTER, "1"); + + const first = await h.call(MOD_A, "POST", `/reports/${id}/claim`, { + expectedVersion: 1, + }); + expect(await first.json()).toEqual({ + assigneeId: MOD_A, + status: "in_progress", + version: 2, + }); + + const stale = await h.call(SECOND_MOD_A, "POST", `/reports/${id}/claim`, { + expectedVersion: 1, + }); + expect(stale.status).toBe(409); + expect(await stale.json()).toEqual({ + current: { assigneeId: MOD_A, status: "in_progress", version: 2 }, + error: "conflict", + }); + + const taken = await h.call(SECOND_MOD_A, "POST", `/reports/${id}/claim`, { + expectedVersion: 2, + }); + expect(taken.status).toBe(409); + expect(await taken.json()).toEqual( + expect.objectContaining({ error: "already_claimed" }), + ); + }); + + it("resolves with an outcome and reopens with the history kept", async () => { + const h = await harness(); + const id = await h.reportId(REPORTER, "1"); + const resolve = async (body: Record) => + await h.call(MOD_A, "POST", `/reports/${id}/resolve`, { + expectedVersion: 1, + resolution: "no_violation", + ...body, + }); + + expect((await resolve({ resolution: "unknown" })).status).toBe(400); + + const resolved = await resolve({ explanation: "Not spam." }); + expect(await resolved.json()).toEqual({ + assigneeId: null, + status: "done", + version: 2, + }); + expect(h.row(id)).toEqual( + expect.objectContaining({ openKey: null, resolution: "no_violation" }), + ); + + const reopened = await h.call(MOD_A, "POST", `/reports/${id}/reopen`, { + expectedVersion: 2, + reason: "Missed context.", + }); + expect(await reopened.json()).toEqual({ + assigneeId: null, + status: "new", + version: 3, + }); + expect(h.row(id)).toEqual( + expect.objectContaining({ + openKey: `${REPORTER}:${FORUM}:${TYPE}:1`, + resolution: null, + }), + ); + expect(h.eventsOf(id).map(event => event.type)).toEqual([ + "created", + "resolved", + "reopened", + ]); + expect(h.eventsOf(id)[2]?.data).toEqual({ + previousResolution: "no_violation", + reason: "Missed context.", + }); + }); + + it("records a successful action and runs its effects after the commit", async () => { + const h = await harness(); + const id = await h.reportId(REPORTER, "1"); + const order: string[] = []; + const transaction = h.memory.db.transaction.bind(h.memory.db); + vi.spyOn(h.memory.db, "transaction").mockImplementation(async run => { + const result = await transaction(run); + order.push("committed"); + + return result; + }); + h.effects.mockImplementation(async () => { + order.push("effects"); + + return Promise.resolve(); + }); + + const res = await h.call(MOD_A, "POST", `/reports/${id}/actions/hide`, { + expectedVersion: 1, + }); + + expect(await res.json()).toEqual({ + assigneeId: null, + changed: true, + status: "new", + version: 2, + }); + expect(order).toEqual(["committed", "effects"]); + expect(h.eventsOf(id)).toContainEqual({ + data: { action: "hide" }, + type: "action", + }); + expect((await detail(h, MOD_A, id)).body?.current.hidden).toBe(true); + }); + + it("leaves no trace of an action that fails", async () => { + const h = await harness(); + const id = await h.reportId(REPORTER, "1"); + h.fixture.failHide = true; + + const res = await h.call(MOD_A, "POST", `/reports/${id}/actions/hide`, { + expectedVersion: 1, + }); + + expect(res.status).toBe(500); + expect(h.eventsOf(id).map(event => event.type)).toEqual(["created"]); + expect(h.row(id)?.version).toBe(1); + expect(h.effects).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/vitnode/src/api/modules/moderation/routes/create.route.ts b/packages/vitnode/src/api/modules/moderation/routes/create.route.ts new file mode 100644 index 0000000000..ac7771f92c --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/routes/create.route.ts @@ -0,0 +1,192 @@ +import { z } from "@hono/zod-openapi"; +import { and, eq } from "drizzle-orm"; +import { HTTPException } from "hono/http-exception"; + +import { isUniqueViolation } from "@/api/lib/db-errors"; +import { findReportTarget } from "@/api/lib/moderation/registry"; +import { sealReportSnapshot } from "@/api/lib/moderation/snapshot"; +import { buildRoute } from "@/api/lib/route"; +import { CONFIG_PLUGIN } from "@/config"; +import { core_moderation_reports } from "@/database/moderation"; +import { MODERATION_LIMITS } from "@/lib/moderation/const"; + +import { + appendReportEvent, + countRecentReports, + reportError, + reportOpenKey, +} from "../lib/reports"; +import { errorSchema, json, reasonSchema } from "../lib/schema"; + +const localeSchema = z + .string() + .max(20) + .regex(/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/); + +const createBody = z + .object({ + pluginId: z.string().min(1).max(100), + targetType: z.string().min(1).max(100), + targetId: z.string().min(1).max(64), + locale: localeSchema.nullable().optional(), + requestedLocale: localeSchema.nullable().optional(), + reason: reasonSchema, + description: z + .string() + .trim() + .max(MODERATION_LIMITS.descriptionMaxLength) + .nullable() + .optional(), + }) + .refine( + body => + body.reason !== "other" || + (body.description?.length ?? 0) >= + MODERATION_LIMITS.otherDescriptionMinLength, + { + message: `Describe the problem in at least ${MODERATION_LIMITS.otherDescriptionMinLength} characters when the reason is "other".`, + path: ["description"], + }, + ); + +export const createReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports", + description: + "Report content to the moderators. The server captures the snapshot - the client sends only the target, locale, reason and description", + request: { + body: { content: { "application/json": { schema: createBody } } }, + }, + responses: { + 201: json(z.object({ id: z.number() }), "Report filed"), + 400: { description: "Invalid reason or description" }, + 401: { description: "Sign in first" }, + 404: json( + errorSchema, + "The target does not exist, or the reporter cannot read it", + ), + 409: json( + errorSchema, + "The reporter already has an open report about this target", + ), + 429: json(errorSchema, "Too many reports"), + }, + }, + handler: async c => { + const user = c.get("user"); + if (!user) throw new HTTPException(401, { message: "Sign in first." }); + + const body = c.req.valid("json"); + const registered = findReportTarget(c.get("core").moderation, { + pluginId: body.pluginId, + type: body.targetType, + }); + if (!registered) throw reportError(404, { error: "not_found" }); + const { definition, pluginId } = registered; + + const targetId = definition.parseId(body.targetId); + if (targetId === null) throw reportError(404, { error: "not_found" }); + + if ( + (await countRecentReports(c, user.id)) >= + MODERATION_LIMITS.reportsPerUserPerHour + ) { + c.header("Retry-After", "3600"); + throw reportError(429, { error: "rate_limited" }); + } + + const openKey = reportOpenKey({ + pluginId, + reporterId: user.id, + targetId, + targetType: definition.type, + }); + const [existing] = await c + .get("db") + .select({ id: core_moderation_reports.id }) + .from(core_moderation_reports) + .where(and(eq(core_moderation_reports.openKey, openKey))) + .limit(1); + if (existing) throw reportError(409, { error: "duplicate" }); + + const capture = await definition.capture(c, { + locale: body.locale ?? null, + targetId, + }); + if (!capture) throw reportError(404, { error: "not_found" }); + + const scopeId = definition.scope + ? ((await definition.resolveScope?.(c, targetId)) ?? null) + : null; + const requested = body.requestedLocale ?? capture.locale.requested; + const snapshot = sealReportSnapshot({ + capture: { + ...capture, + locale: { + fallback: + requested !== null && + capture.locale.served !== null && + requested.toLowerCase() !== capture.locale.served.toLowerCase(), + requested, + served: capture.locale.served, + }, + scope: + definition.scope && scopeId + ? { family: definition.scope, id: scopeId } + : capture.scope, + }, + target: { id: targetId, pluginId, type: definition.type }, + }); + + let reportId: number; + try { + reportId = await c.get("db").transaction(async tx => { + const [created] = await tx + .insert(core_moderation_reports) + .values({ + description: + body.description?.trim() === "" + ? null + : (body.description ?? null), + openKey, + pluginId, + reason: body.reason, + reporterId: user.id, + scopeFamily: definition.scope ?? null, + scopeId, + snapshot, + targetId, + targetTitle: snapshot.title, + targetType: definition.type, + }) + .returning({ id: core_moderation_reports.id }); + + await appendReportEvent(tx, { + actorId: user.id, + data: { reason: body.reason }, + reportId: created.id, + type: "created", + }); + + return created.id; + }); + } catch (error) { + if (isUniqueViolation(error)) { + throw reportError(409, { error: "duplicate" }); + } + throw error; + } + + await c.get("events").emit("moderation.report.created", { + pluginId, + reason: body.reason, + reportId, + targetId, + targetType: definition.type, + }); + + return c.json({ id: reportId }, 201); + }, +}); diff --git a/packages/vitnode/src/api/modules/moderation/routes/list.route.ts b/packages/vitnode/src/api/modules/moderation/routes/list.route.ts new file mode 100644 index 0000000000..81e316c975 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/routes/list.route.ts @@ -0,0 +1,188 @@ +import { z } from "@hono/zod-openapi"; +import { and, count, desc, eq, ilike, or } from "drizzle-orm"; + +import { + requireModerator, + viewableReportsCondition, +} from "@/api/lib/moderation/access"; +import { findReportTarget } from "@/api/lib/moderation/registry"; +import { buildRoute } from "@/api/lib/route"; +import { CONFIG_PLUGIN } from "@/config"; +import { core_moderation_reports } from "@/database/moderation"; +import { containsLikePattern } from "@/lib/api/like-pattern"; +import { + MODERATION_LIMITS, + MODERATION_REPORT_STATUSES, +} from "@/lib/moderation/const"; + +import { loadReportPeople } from "../lib/people"; +import { queueFilters, reportTargetTriplets } from "../lib/reports"; +import { json, reasonSchema, reportPersonSchema } from "../lib/schema"; + +const itemSchema = z.object({ + id: z.number(), + pluginId: z.string(), + targetType: z.string(), + targetId: z.string(), + targetLabel: z.string().nullable(), + title: z.string().nullable(), + reason: reasonSchema, + status: z.enum(MODERATION_REPORT_STATUSES), + createdAt: z.date(), + version: z.number(), + assignee: reportPersonSchema.nullable(), + relatedCount: z.number(), +}); + +const searchedReportId = (search: string): number | undefined => { + const digits = search.replace(/^#/, ""); + const id = Number(digits); + + return /^[1-9]\d{0,9}$/.test(digits) && id <= 2_147_483_647 ? id : undefined; +}; + +const searchCondition = (search: string) => { + const id = searchedReportId(search); + + return or( + ilike(core_moderation_reports.targetTitle, containsLikePattern(search)), + id === undefined ? undefined : eq(core_moderation_reports.id, id), + ); +}; + +export const listReportsRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "get", + path: "/reports", + description: + "The ModCP report queue - only reports the moderator may view, filtered before counting and paginating", + request: { + query: z.object({ + status: z + .enum(["open", "new", "in_progress", "done", "all"]) + .default("open"), + assigned: z.enum(["any", "me", "unassigned"]).default("any"), + page: z.coerce.number().int().positive().max(10_000).default(1), + pageSize: z.coerce + .number() + .int() + .positive() + .max(100) + .default(MODERATION_LIMITS.queuePageSize), + search: z.string().trim().max(200).optional(), + }), + }, + responses: { + 200: json( + z.object({ + items: z.array(itemSchema), + page: z.number(), + pageSize: z.number(), + total: z.number(), + }), + "One page of reports", + ), + 401: { description: "Sign in first" }, + 403: { description: "Not a moderator" }, + }, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { assigned, page, pageSize, search, status } = c.req.valid("query"); + const table = core_moderation_reports; + + const where = and( + viewableReportsCondition(c, moderator.set), + ...queueFilters({ assigned, status, userId: moderator.user.id }), + search ? searchCondition(search) : undefined, + ); + + const [[totalRow], rows] = await Promise.all([ + c.get("db").select({ value: count() }).from(table).where(where), + c + .get("db") + .select({ + assigneeId: table.assigneeId, + createdAt: table.createdAt, + id: table.id, + pluginId: table.pluginId, + reason: table.reason, + targetTitle: table.targetTitle, + status: table.status, + targetId: table.targetId, + targetType: table.targetType, + version: table.version, + }) + .from(table) + .where(where) + .orderBy(desc(table.createdAt), desc(table.id)) + .limit(pageSize) + .offset((page - 1) * pageSize), + ]); + + const related = rows.length + ? await c + .get("db") + .select({ + pluginId: table.pluginId, + targetId: table.targetId, + targetType: table.targetType, + value: count(), + }) + .from(table) + .where( + and( + viewableReportsCondition(c, moderator.set), + reportTargetTriplets(rows), + ), + ) + .groupBy(table.pluginId, table.targetType, table.targetId) + : []; + + const registry = c.get("core").moderation; + const people = await loadReportPeople( + c, + rows.map(row => row.assigneeId), + ); + + return c.json( + { + items: rows.map(row => { + const group = related.find( + entry => + entry.pluginId === row.pluginId && + entry.targetType === row.targetType && + entry.targetId === row.targetId, + ); + + return { + id: row.id, + pluginId: row.pluginId, + targetType: row.targetType, + targetId: row.targetId, + targetLabel: + findReportTarget(registry, { + pluginId: row.pluginId, + type: row.targetType, + })?.definition.label ?? null, + title: row.targetTitle, + reason: row.reason, + status: row.status, + createdAt: row.createdAt, + version: row.version, + assignee: + row.assigneeId === null + ? null + : (people.get(row.assigneeId) ?? null), + relatedCount: Math.max(0, (group?.value ?? 1) - 1), + }; + }), + page, + pageSize, + total: totalRow?.value ?? 0, + }, + 200, + ); + }, +}); diff --git a/packages/vitnode/src/api/modules/moderation/routes/notes.routes.ts b/packages/vitnode/src/api/modules/moderation/routes/notes.routes.ts new file mode 100644 index 0000000000..3343520fa1 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/routes/notes.routes.ts @@ -0,0 +1,134 @@ +import { z } from "@hono/zod-openapi"; +import { eq } from "drizzle-orm"; + +import { requireModerator } from "@/api/lib/moderation/access"; +import { buildRoute } from "@/api/lib/route"; +import { CONFIG_PLUGIN } from "@/config"; +import { core_moderation_report_events } from "@/database/moderation"; + +import { canChangeNote, loadReportNote } from "../lib/notes"; +import { + appendReportEvent, + authorizeReport, + reportError, +} from "../lib/reports"; +import { + errorSchema, + json, + reportIdParams, + richNoteSchema, +} from "../lib/schema"; + +const noteParams = reportIdParams.extend({ + noteId: z.coerce.number().int().positive().openapi({ example: 1 }), +}); + +const noteResponses = { + 200: json(z.object({ ok: z.boolean() }), "Done"), + 400: { description: "Invalid input" }, + 401: { description: "Sign in first" }, + 403: json( + errorSchema, + "Not the note's author, and no permission for others' notes", + ), + 404: json( + errorSchema, + "No such report or note, or not one this moderator may see", + ), +}; + +export const editReportNoteRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/notes/{noteId}/edit", + description: + "Change an internal note. Authors edit their own notes; can_edit_notes edits anyone's", + request: { + params: noteParams, + body: { + content: { + "application/json": { schema: z.object({ body: richNoteSchema }) }, + }, + }, + }, + responses: noteResponses, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id, noteId } = c.req.valid("param"); + const { body } = c.req.valid("json"); + const { report } = await authorizeReport(c, moderator, id); + const note = await loadReportNote(c, report.id, noteId); + if (!canChangeNote(c, moderator, report, note, "edit")) { + throw reportError(403, { error: "forbidden" }); + } + + await c.get("db").transaction(async tx => { + await tx + .update(core_moderation_report_events) + .set({ + data: { + ...note.data, + body, + editedAt: new Date().toISOString(), + editedById: moderator.user.id, + }, + }) + .where(eq(core_moderation_report_events.id, note.id)); + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { after: body, before: note.data.body ?? null, noteId: note.id }, + reportId: report.id, + type: "note_edited", + }); + }); + + await c.get("events").emit("moderation.report.note_updated", { + noteId: note.id, + reportId: report.id, + }); + + return c.json({ ok: true }, 200); + }, +}); + +export const deleteReportNoteRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/notes/{noteId}/delete", + description: + "Remove an internal note. Authors delete their own notes; can_delete_notes deletes anyone's", + request: { params: noteParams }, + responses: noteResponses, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id, noteId } = c.req.valid("param"); + const { report } = await authorizeReport(c, moderator, id); + const note = await loadReportNote(c, report.id, noteId); + if (!canChangeNote(c, moderator, report, note, "delete")) { + throw reportError(403, { error: "forbidden" }); + } + + await c.get("db").transaction(async tx => { + await tx + .delete(core_moderation_report_events) + .where(eq(core_moderation_report_events.id, note.id)); + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { before: note.data.body ?? null, noteId: note.id }, + reportId: report.id, + type: "note_deleted", + }); + }); + + await c.get("events").emit("moderation.report.note_deleted", { + noteId: note.id, + reportId: report.id, + }); + + return c.json({ ok: true }, 200); + }, +}); diff --git a/packages/vitnode/src/api/modules/moderation/routes/show.route.ts b/packages/vitnode/src/api/modules/moderation/routes/show.route.ts new file mode 100644 index 0000000000..f36802a9c3 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/routes/show.route.ts @@ -0,0 +1,241 @@ +import { z } from "@hono/zod-openapi"; +import { asc, eq } from "drizzle-orm"; + +import { canOnReport, requireModerator } from "@/api/lib/moderation/access"; +import { buildRoute } from "@/api/lib/route"; +import { CONFIG_PLUGIN } from "@/config"; +import { core_moderation_report_events } from "@/database/moderation"; +import { + MODERATION_PERMISSIONS, + MODERATION_REPORT_STATUSES, + MODERATION_TARGET_ACTIONS, +} from "@/lib/moderation/const"; + +import { canChangeNote } from "../lib/notes"; +import { loadReportPeople } from "../lib/people"; +import { authorizeReport, relatedReports } from "../lib/reports"; +import { + errorSchema, + eventTypeSchema, + json, + reasonSchema, + reportIdParams, + reportPersonSchema, + resolutionSchema, +} from "../lib/schema"; + +const detailSchema = z.object({ + report: z.object({ + id: z.number(), + pluginId: z.string(), + targetType: z.string(), + targetId: z.string(), + reason: reasonSchema, + description: z.string().nullable(), + status: z.enum(MODERATION_REPORT_STATUSES), + resolution: resolutionSchema.nullable(), + resolutionNote: z.string().nullable(), + resolvedAt: z.date().nullable(), + createdAt: z.date(), + updatedAt: z.date(), + version: z.number(), + scope: z.object({ family: z.string(), id: z.string() }).nullable(), + }), + targetLabel: z.string().nullable(), + pluginLabel: z.string(), + snapshot: z.object({}).loose(), + authors: z.array(reportPersonSchema), + reporter: reportPersonSchema.nullable(), + assignee: reportPersonSchema.nullable(), + events: z.array( + z.object({ + id: z.number(), + type: eventTypeSchema, + actor: reportPersonSchema.nullable(), + data: z.record(z.string(), z.unknown()), + canEdit: z.boolean(), + canDelete: z.boolean(), + createdAt: z.date(), + }), + ), + related: z.array( + z.object({ + id: z.number(), + status: z.enum(MODERATION_REPORT_STATUSES), + reason: reasonSchema, + description: z.string().nullable(), + authors: z.array(reportPersonSchema), + reporter: reportPersonSchema.nullable(), + createdAt: z.date(), + }), + ), + current: z.object({ + exists: z.boolean(), + hidden: z.boolean(), + url: z.string().nullable(), + registered: z.boolean(), + }), + permissions: z.object({ + manage: z.boolean(), + actions: z.array( + z.object({ + action: z.enum(MODERATION_TARGET_ACTIONS), + allowed: z.boolean(), + available: z.boolean(), + }), + ), + }), +}); + +export const showReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "get", + path: "/reports/{id}", + description: + "One report with its snapshot, timeline and the related reports the moderator may see", + request: { params: reportIdParams }, + responses: { + 200: json(detailSchema, "The report"), + 401: { description: "Sign in first" }, + 403: { description: "Not a moderator" }, + 404: json( + errorSchema, + "No such report, or not one this moderator may see", + ), + }, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { report, target } = await authorizeReport(c, moderator, id); + const db = c.get("db"); + + const [events, related] = await Promise.all([ + db + .select({ + actorId: core_moderation_report_events.actorId, + createdAt: core_moderation_report_events.createdAt, + data: core_moderation_report_events.data, + id: core_moderation_report_events.id, + type: core_moderation_report_events.type, + }) + .from(core_moderation_report_events) + .where(eq(core_moderation_report_events.reportId, report.id)) + .orderBy(asc(core_moderation_report_events.id)), + relatedReports(c, moderator, report), + ]); + const authorIds = Array.isArray(report.snapshot.authors) + ? report.snapshot.authors.flatMap(author => + typeof author.id === "number" ? [author.id] : [], + ) + : []; + const people = await loadReportPeople(c, [ + ...authorIds, + report.reporterId, + report.assigneeId, + ...events.map(event => event.actorId), + ...related.map(entry => entry.reporterId), + ]); + const userOf = (userId: null | number) => + userId === null ? null : (people.get(userId) ?? null); + + const locale = + typeof report.snapshot.locale?.served === "string" + ? report.snapshot.locale.served + : null; + const current = target + ? await target.definition.current(c, { + locale, + targetId: report.targetId, + }) + : null; + + const ref = { + pluginId: report.pluginId, + scopeId: report.scopeId, + targetType: report.targetType, + }; + const manage = canOnReport( + c, + moderator.set, + ref, + MODERATION_PERMISSIONS.manageReports, + ); + + return c.json( + { + report: { + id: report.id, + pluginId: report.pluginId, + targetType: report.targetType, + targetId: report.targetId, + reason: report.reason, + description: report.description, + status: report.status, + resolution: report.resolution, + resolutionNote: report.resolutionNote, + resolvedAt: report.resolvedAt, + createdAt: report.createdAt, + updatedAt: report.updatedAt, + version: report.version, + scope: + report.scopeFamily && report.scopeId + ? { family: report.scopeFamily, id: report.scopeId } + : null, + }, + targetLabel: target?.definition.label ?? null, + pluginLabel: `${report.pluginId}.title`, + snapshot: { ...report.snapshot }, + authors: authorIds.flatMap(authorId => { + const person = people.get(authorId); + + return person ? [person] : []; + }), + reporter: userOf(report.reporterId), + assignee: userOf(report.assigneeId), + events: events.map(event => ({ + id: event.id, + type: event.type, + actor: userOf(event.actorId), + data: event.data, + canEdit: + event.type === "note" && + canChangeNote(c, moderator, report, event, "edit"), + canDelete: + event.type === "note" && + canChangeNote(c, moderator, report, event, "delete"), + createdAt: event.createdAt, + })), + related: related.map(({ reporterId, ...entry }) => ({ + ...entry, + reporter: userOf(reporterId), + })), + current: { + exists: current !== null, + hidden: current?.hidden ?? false, + url: current?.url ?? null, + registered: target !== undefined, + }, + permissions: { + manage, + actions: MODERATION_TARGET_ACTIONS.flatMap(action => { + const definition = target?.definition.actions?.[action]; + if (!definition) return []; + + return [ + { + action, + allowed: + manage && + canOnReport(c, moderator.set, ref, definition.permission), + available: current !== null && definition.available(current), + }, + ]; + }), + }, + }, + 200, + ); + }, +}); diff --git a/packages/vitnode/src/api/modules/moderation/routes/workflow.routes.ts b/packages/vitnode/src/api/modules/moderation/routes/workflow.routes.ts new file mode 100644 index 0000000000..04c52de0a1 --- /dev/null +++ b/packages/vitnode/src/api/modules/moderation/routes/workflow.routes.ts @@ -0,0 +1,518 @@ +import { z } from "@hono/zod-openapi"; +import { and, eq } from "drizzle-orm"; + +import { resolveStaffPermissions } from "@/api/lib/check-staff-permission"; +import { canOnReport, requireModerator } from "@/api/lib/moderation/access"; +import { buildRoute } from "@/api/lib/route"; +import { CONFIG_PLUGIN } from "@/config"; +import { core_moderation_reports } from "@/database/moderation"; +import { core_users } from "@/database/users"; +import { MODERATION_PERMISSIONS } from "@/lib/moderation/const"; + +import { listModeratorCandidates } from "../lib/candidates"; +import { loadReportPeople } from "../lib/people"; +import { + appendReportEvent, + authorizeReport, + reportConflict, + reportError, + reportOpenKey, + updateReport, +} from "../lib/reports"; +import { + conflictSchema, + errorSchema, + expectedVersionBody, + json, + noteSchema, + optionalExplanationSchema, + reportIdParams, + reportPersonSchema, + reportStateSchema, + resolutionSchema, + richNoteSchema, +} from "../lib/schema"; + +const stateOf = (report: { + assigneeId: null | number; + status: "done" | "in_progress" | "new"; + version: number; +}) => ({ + assigneeId: report.assigneeId, + status: report.status, + version: report.version, +}); + +const mutationResponses = { + 200: json(reportStateSchema, "The report's new state"), + 400: { description: "Invalid input" }, + 401: { description: "Sign in first" }, + 403: json(errorSchema, "The moderator may not manage this report"), + 404: json(errorSchema, "No such report, or not one this moderator may see"), + 409: json( + conflictSchema, + "The report changed since it was read, or is in the wrong state", + ), +}; + +const body = (schema: T) => ({ + body: { content: { "application/json": { schema } } }, +}); + +export const claimReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/claim", + description: + "Take a report: assigns it to the caller and moves it to in progress", + request: { params: reportIdParams, ...body(expectedVersionBody) }, + responses: mutationResponses, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { expectedVersion } = c.req.valid("json"); + const { report } = await authorizeReport(c, moderator, id, { + manage: true, + }); + + if (report.version !== expectedVersion) throw reportConflict(report); + if (report.status === "done") { + throw reportConflict(report, "report_closed"); + } + if (report.assigneeId !== null && report.assigneeId !== moderator.user.id) { + throw reportConflict(report, "already_claimed"); + } + + const updated = await c.get("db").transaction(async tx => { + const next = await updateReport(tx, report, { + assigneeId: moderator.user.id, + status: "in_progress", + }); + if (report.assigneeId !== moderator.user.id) { + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { assigneeId: moderator.user.id, previousAssigneeId: null }, + reportId: report.id, + type: "assigned", + }); + } + if (report.status !== "in_progress") { + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { from: report.status, to: "in_progress" }, + reportId: report.id, + type: "status_changed", + }); + } + + return next; + }); + + await c.get("events").emit("moderation.report.assigned", { + assigneeId: moderator.user.id, + previousAssigneeId: report.assigneeId, + reportId: report.id, + }); + + return c.json(stateOf(updated), 200); + }, +}); + +export const assignReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/assign", + description: + "Reassign a report to another moderator who may manage it, or unassign it", + request: { + params: reportIdParams, + ...body( + expectedVersionBody.extend({ + assigneeId: z.number().int().positive().nullable(), + }), + ), + }, + responses: mutationResponses, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { assigneeId, expectedVersion } = c.req.valid("json"); + const { report } = await authorizeReport(c, moderator, id, { + manage: true, + }); + + if (report.version !== expectedVersion) throw reportConflict(report); + if (report.status === "done") { + throw reportConflict(report, "report_closed"); + } + if (report.assigneeId === assigneeId) { + return c.json(stateOf(report), 200); + } + + if (assigneeId !== null) { + const [user] = await c + .get("db") + .select({ id: core_users.id, roleId: core_users.roleId }) + .from(core_users) + .where(eq(core_users.id, assigneeId)) + .limit(1); + const set = user + ? await resolveStaffPermissions(c, { type: "moderator", user }) + : null; + const eligible = + set?.staff === true && + canOnReport( + c, + set, + { + pluginId: report.pluginId, + scopeId: report.scopeId, + targetType: report.targetType, + }, + MODERATION_PERMISSIONS.manageReports, + ); + if (!eligible) { + throw reportError(400, { error: "assignee_not_eligible" }); + } + } + + const status = assigneeId === null ? "new" : "in_progress"; + const updated = await c.get("db").transaction(async tx => { + const next = await updateReport(tx, report, { assigneeId, status }); + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { assigneeId, previousAssigneeId: report.assigneeId }, + reportId: report.id, + type: assigneeId === null ? "unassigned" : "assigned", + }); + if (report.status !== status) { + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { from: report.status, to: status }, + reportId: report.id, + type: "status_changed", + }); + } + + return next; + }); + + await c.get("events").emit("moderation.report.assigned", { + assigneeId, + previousAssigneeId: report.assigneeId, + reportId: report.id, + }); + + return c.json(stateOf(updated), 200); + }, +}); + +export const noteReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/notes", + description: + "Add an internal note to the report's timeline. Notes are visible to moderators only", + request: { + params: reportIdParams, + ...body(z.object({ body: richNoteSchema })), + }, + responses: { + 201: json(z.object({ ok: z.boolean() }), "Note added"), + 400: mutationResponses[400], + 401: mutationResponses[401], + 403: mutationResponses[403], + 404: mutationResponses[404], + }, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { body: note } = c.req.valid("json"); + const { report } = await authorizeReport(c, moderator, id, { + manage: true, + }); + + await appendReportEvent(c.get("db"), { + actorId: moderator.user.id, + data: { body: note }, + reportId: report.id, + type: "note", + }); + + return c.json({ ok: true }, 201); + }, +}); + +export const resolveReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/resolve", + description: + "Close a report with an outcome and an optional explanation. Related reports stay open", + request: { + params: reportIdParams, + ...body( + expectedVersionBody.extend({ + resolution: resolutionSchema, + explanation: optionalExplanationSchema, + }), + ), + }, + responses: mutationResponses, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { expectedVersion, explanation, resolution } = c.req.valid("json"); + const { report } = await authorizeReport(c, moderator, id, { + manage: true, + }); + + if (report.version !== expectedVersion) throw reportConflict(report); + if (report.status === "done") { + throw reportConflict(report, "report_closed"); + } + + const updated = await c.get("db").transaction(async tx => { + const next = await updateReport(tx, report, { + openKey: null, + resolution, + resolutionNote: explanation, + resolvedAt: new Date(), + resolvedById: moderator.user.id, + status: "done", + }); + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: explanation ? { explanation, resolution } : { resolution }, + reportId: report.id, + type: "resolved", + }); + + return next; + }); + + await c.get("events").emit("moderation.report.resolved", { + reportId: report.id, + resolution, + }); + + return c.json(stateOf(updated), 200); + }, +}); + +export const reopenReportRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/reopen", + description: "Reopen a closed report. Needs a reason, kept in the timeline", + request: { + params: reportIdParams, + ...body(expectedVersionBody.extend({ reason: noteSchema })), + }, + responses: mutationResponses, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { expectedVersion, reason } = c.req.valid("json"); + const { report } = await authorizeReport(c, moderator, id, { + manage: true, + }); + + if (report.version !== expectedVersion) throw reportConflict(report); + if (report.status !== "done") { + throw reportConflict(report, "report_open"); + } + + const status = report.assigneeId === null ? "new" : "in_progress"; + const updated = await c.get("db").transaction(async tx => { + const key = + report.reporterId === null + ? null + : reportOpenKey({ + pluginId: report.pluginId, + reporterId: report.reporterId, + targetId: report.targetId, + targetType: report.targetType, + }); + const [holder] = key + ? await tx + .select({ id: core_moderation_reports.id }) + .from(core_moderation_reports) + .where(and(eq(core_moderation_reports.openKey, key))) + .limit(1) + : []; + + const next = await updateReport(tx, report, { + openKey: holder ? null : key, + resolution: null, + resolutionNote: null, + resolvedAt: null, + resolvedById: null, + status, + }); + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { + previousResolution: report.resolution, + reason, + }, + reportId: report.id, + type: "reopened", + }); + + return next; + }); + + await c.get("events").emit("moderation.report.reopened", { + reportId: report.id, + }); + + return c.json(stateOf(updated), 200); + }, +}); + +export const reportActionRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "post", + path: "/reports/{id}/actions/{action}", + description: + "Hide or restore the reported content. Recorded in the report's timeline only when it succeeds", + request: { + params: reportIdParams.extend({ action: z.enum(["hide", "unhide"]) }), + ...body(expectedVersionBody), + }, + responses: { + ...mutationResponses, + 200: json( + reportStateSchema.extend({ changed: z.boolean() }), + "The report's new state, and whether the content changed", + ), + }, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { action, id } = c.req.valid("param"); + const { expectedVersion } = c.req.valid("json"); + const { report, target } = await authorizeReport(c, moderator, id, { + manage: true, + }); + + if (report.version !== expectedVersion) throw reportConflict(report); + const definition = target?.definition.actions?.[action]; + if (!target || !definition) { + throw reportError(404, { error: "action_unavailable" }); + } + const ref = { + pluginId: report.pluginId, + scopeId: report.scopeId, + targetType: report.targetType, + }; + if (!canOnReport(c, moderator.set, ref, definition.permission)) { + throw reportError(403, { error: "forbidden" }); + } + + const result = await c.get("db").transaction(async tx => { + const outcome = await definition.run(c, { + actorUserId: moderator.user.id, + targetId: report.targetId, + tx, + }); + if (!outcome) return null; + if (!outcome.changed) { + return { outcome, state: stateOf(report) }; + } + + const next = await updateReport(tx, report, {}); + await appendReportEvent(tx, { + actorId: moderator.user.id, + data: { action }, + reportId: report.id, + type: "action", + }); + + return { outcome, state: stateOf(next) }; + }); + if (!result) throw reportError(404, { error: "target_gone" }); + + if (result.outcome.changed) { + await result.outcome.effects(); + await c.get("events").emit("moderation.report.action", { + action, + pluginId: report.pluginId, + reportId: report.id, + targetId: report.targetId, + targetType: report.targetType, + }); + } + + return c.json({ ...result.state, changed: result.outcome.changed }, 200); + }, +}); + +export const reportAssigneesRoute = buildRoute({ + pluginId: CONFIG_PLUGIN.pluginId, + route: { + method: "get", + path: "/reports/{id}/assignees", + description: "Moderators who may manage this report, for reassignment", + request: { params: reportIdParams }, + responses: { + 200: json(z.array(reportPersonSchema), "Eligible moderators"), + 401: mutationResponses[401], + 403: mutationResponses[403], + 404: mutationResponses[404], + }, + }, + handler: async c => { + const moderator = await requireModerator(c); + const { id } = c.req.valid("param"); + const { report } = await authorizeReport(c, moderator, id, { + manage: true, + }); + const candidates = await listModeratorCandidates(c); + + const resolved = await Promise.all( + candidates.map(async user => ({ + id: user.id, + set: await resolveStaffPermissions(c, { type: "moderator", user }), + })), + ); + const eligible = resolved + .filter( + ({ set }) => + set.staff && + canOnReport( + c, + set, + { + pluginId: report.pluginId, + scopeId: report.scopeId, + targetType: report.targetType, + }, + MODERATION_PERMISSIONS.manageReports, + ), + ) + .map(({ id }) => id); + const people = await loadReportPeople(c, eligible); + + return c.json( + eligible.flatMap(userId => { + const person = people.get(userId); + + return person ? [person] : []; + }), + 200, + ); + }, +}); diff --git a/packages/vitnode/src/api/modules/users/routes/permissions.route.ts b/packages/vitnode/src/api/modules/users/routes/permissions.route.ts index 213d475df5..0e5e5700f9 100644 --- a/packages/vitnode/src/api/modules/users/routes/permissions.route.ts +++ b/packages/vitnode/src/api/modules/users/routes/permissions.route.ts @@ -22,6 +22,16 @@ export const permissionsRoute = buildRoute({ plugin: z.string(), module: z.string(), permission: z.string(), + scope: z + .discriminatedUnion("mode", [ + z.object({ family: z.string(), mode: z.literal("all") }), + z.object({ + family: z.string(), + mode: z.literal("selected"), + ids: z.array(z.string()), + }), + ]) + .optional(), }), ), }), diff --git a/packages/vitnode/src/api/plugin.ts b/packages/vitnode/src/api/plugin.ts index 8a68cd9cc2..edc0fe3c7f 100644 --- a/packages/vitnode/src/api/plugin.ts +++ b/packages/vitnode/src/api/plugin.ts @@ -18,6 +18,7 @@ import { aiModule } from "./modules/ai/ai.module"; import { contentModule } from "./modules/content/content.module"; import { cronModule } from "./modules/cron/cron.module"; import { middlewareModule } from "./modules/middleware/middleware.module"; +import { moderationModule } from "./modules/moderation/moderation.module"; import { notificationsModule } from "./modules/notifications/notifications.module"; import { pagesModule } from "./modules/pages/pages.module"; import { queueModule } from "./modules/queue/queue.module"; @@ -41,6 +42,7 @@ export const newBuildPluginApiCore = buildApiPlugin({ modules: [ middlewareModule, usersModule, + moderationModule, notificationsModule, adminModule, aiModule, diff --git a/packages/vitnode/src/components/form/fields/input-users.tsx b/packages/vitnode/src/components/form/fields/input-users.tsx index 209a1c5ba4..ea2aa601ba 100644 --- a/packages/vitnode/src/components/form/fields/input-users.tsx +++ b/packages/vitnode/src/components/form/fields/input-users.tsx @@ -6,6 +6,7 @@ import { useTranslations } from "use-intl"; import { Avatar } from "@/components/avatar"; import { Button } from "@/components/ui/button"; import { FormMessage } from "@/components/ui/form"; +import { UserFormat } from "@/components/user-format"; import type { ItemAutoFormComponentProps } from "../auto-form"; @@ -18,11 +19,34 @@ export interface UserOption { id: number; name: string; nameCode: string; + role?: UserOptionRole; +} + +export interface UserOptionRole { + color: null | string; + prefix?: null | string; } export type PartialUserOption = Omit & Partial>; +const UserOptionName = ({ + className, + user, +}: { + className?: string; + user: PartialUserOption; +}) => + user.role ? ( + + ) : ( + {user.name} + ); + const UserAvatar = ({ size, user, @@ -59,7 +83,7 @@ export const UserOptionRow = ({ }) => (
- {user.name} + {!!user.nameCode && ( @{user.nameCode} @@ -139,7 +163,7 @@ export const AutoFormUser = ({ )} > - {current.name} + ) : ( diff --git a/packages/vitnode/src/components/side-nav.tsx b/packages/vitnode/src/components/side-nav.tsx new file mode 100644 index 0000000000..b06d4c696e --- /dev/null +++ b/packages/vitnode/src/components/side-nav.tsx @@ -0,0 +1,58 @@ +import { Link } from "@tanstack/react-router"; +import { cn } from "cn"; + +export const SideNavCard = ({ + className, + ...props +}: React.ComponentProps<"nav">) => ( +
- { - setIsOpen(false); - }} - pathname={pathname} - /> +
); }; +const SettingsNavCard = ({ + items, + pathname, +}: { + items: readonly SettingsNavItem[]; + pathname: string; +}) => { + const t = useTranslations("core.auth.settings"); + + return ( + + + + ); +}; + export const SettingsNavContent = ({ items = SETTINGS_NAV_ITEMS, pathname, @@ -151,8 +139,6 @@ export const SettingsNavContent = ({
-
- -
+ ); diff --git a/packages/vitnode/src/views/layouts/theme/header/user/user-header-model.ts b/packages/vitnode/src/views/layouts/theme/header/user/user-header-model.ts index 6fb1426699..33d76abe5c 100644 --- a/packages/vitnode/src/views/layouts/theme/header/user/user-header-model.ts +++ b/packages/vitnode/src/views/layouts/theme/header/user/user-header-model.ts @@ -1,12 +1,19 @@ import type { LucideIcon } from "lucide-react"; -import { FileIcon, KeyRoundIcon, SettingsIcon, UserIcon } from "lucide-react"; +import { + FileIcon, + KeyRoundIcon, + SettingsIcon, + ShieldIcon, + UserIcon, +} from "lucide-react"; export interface UserHeaderUser { avatarColor: string; avatarUrl?: null | string; email: string; isAdmin: boolean; + isModerator?: boolean; name: string; nameCode: string; } @@ -19,6 +26,7 @@ export type UserHeaderState = export const USER_HEADER_HREF = { adminCp: "/admin", files: "/files", + modCp: "/modcp/reports", settings: "/settings", signIn: "/login", signUp: "/register", @@ -45,6 +53,7 @@ export interface UserHeaderMenuItem { export type UserHeaderMenuItemKey = | "admin_cp" | "files" + | "mod_cp" | "my_profile" | "settings"; @@ -70,19 +79,29 @@ export const userHeaderMenu = ( { href: USER_HEADER_HREF.settings, Icon: SettingsIcon, key: "settings" }, ]; - if (!user.isAdmin) return [account]; - - return [ - account, - [ - { - href: USER_HEADER_HREF.adminCp, - Icon: KeyRoundIcon, - key: "admin_cp", - newTab: true, - }, - ], + const staff: UserHeaderMenuItem[] = [ + ...(user.isModerator + ? [ + { + href: USER_HEADER_HREF.modCp, + Icon: ShieldIcon, + key: "mod_cp" as const, + }, + ] + : []), + ...(user.isAdmin + ? [ + { + href: USER_HEADER_HREF.adminCp, + Icon: KeyRoundIcon, + key: "admin_cp" as const, + newTab: true, + }, + ] + : []), ]; + + return staff.length > 0 ? [account, staff] : [account]; }; export const userHeaderState = ({ diff --git a/packages/vitnode/src/views/moderation/modcp/board/board-card.tsx b/packages/vitnode/src/views/moderation/modcp/board/board-card.tsx new file mode 100644 index 0000000000..47a6a380f7 --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/board/board-card.tsx @@ -0,0 +1,213 @@ +import { useDraggable } from "@dnd-kit/core"; +import { Link } from "@tanstack/react-router"; +import { cn } from "cn"; +import { FlagIcon, GripVerticalIcon, MoreHorizontalIcon } from "lucide-react"; +import { useTranslations } from "use-intl"; + +import { DateFormat } from "@/components/date-format"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { TooltipWithContent } from "@/components/ui/tooltip"; + +import type { ModcpBoardReport, ModcpBoardStatus } from "../modcp-query"; + +import { MODCP_BOARD_STATUSES } from "../modcp-query"; +import { + Chip, + Person, + REASON_TONE, + StatusLozenge, + TONE_SURFACE, +} from "../report-tone"; +import { useTargetLabel } from "../status-badge"; + +export const BOARD_CARD_CLASS = + "bg-card text-card-foreground ring-foreground/10 relative flex flex-col gap-2 rounded-lg p-3 shadow-xs ring-1"; + +export const boardCardId = (id: number): string => `report-${id}`; + +const ExtraReports = ({ row }: { row: ModcpBoardReport }) => { + const t = useTranslations("core.moderation.modcp.reports.board"); + if (row.relatedCount === 0) return null; + + return ( + + + +{row.relatedCount} + + + ); +}; + +const CardMenu = ({ + onMove, + row, +}: { + onMove: (row: ModcpBoardReport, to: ModcpBoardStatus) => void; + row: ModcpBoardReport; +}) => { + const t = useTranslations("core.moderation.modcp"); + + return ( + { + event.stopPropagation(); + }} + > + + + } + > + + + {t("detail.status.move_to")} + {MODCP_BOARD_STATUSES.filter(status => status !== row.status).map( + status => ( + { + onMove(row, status); + }} + > + + + ), + )} + + + + ); +}; + +export const BoardCardBody = ({ + handle, + onMove, + row, +}: { + handle?: React.ReactNode; + onMove?: (row: ModcpBoardReport, to: ModcpBoardStatus) => void; + row: ModcpBoardReport; +}) => { + const t = useTranslations("core.moderation"); + const targetLabel = useTargetLabel(); + const title = row.title ?? t("modcp.reports.untitled"); + + return ( + <> +
+ + + {t(`reasons.${row.reason}`)} + + + + + {handle} + {onMove ? : null} + +
+ + {onMove ? ( + + {title} + + ) : ( + + {title} + + )} + +

+ #{row.id} · {targetLabel(row.targetLabel, row.targetType)} +

+ +
+ + {row.assignee ? ( + + ) : ( + + + + )} + + + + +
+ + ); +}; + +export const BoardCard = ({ + onMove, + row, +}: { + onMove: (row: ModcpBoardReport, to: ModcpBoardStatus) => void; + row: ModcpBoardReport; +}) => { + const t = useTranslations("core.moderation.modcp.reports.board"); + const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef } = + useDraggable({ data: { reportId: row.id }, id: boardCardId(row.id) }); + + return ( +
  • + +
  • + ); +}; diff --git a/packages/vitnode/src/views/moderation/modcp/board/board-moves.ts b/packages/vitnode/src/views/moderation/modcp/board/board-moves.ts new file mode 100644 index 0000000000..5cc6bc2064 --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/board/board-moves.ts @@ -0,0 +1,104 @@ +import type { ModcpBoardReport, ModcpBoardStatus } from "../modcp-query"; + +export type BoardPerson = NonNullable; + +export interface BoardOverride { + assignee: BoardPerson | null; + status: ModcpBoardStatus; +} + +export type BoardMove = + | { kind: "claim" } + | { kind: "reopen"; to: Exclude } + | { kind: "resolve" } + | { kind: "unassign" }; + +export const planBoardMove = ( + from: ModcpBoardStatus, + to: ModcpBoardStatus, +): BoardMove | null => { + if (from === to) return null; + if (to === "done") return { kind: "resolve" }; + if (from === "done") return { kind: "reopen", to }; + + return to === "in_progress" ? { kind: "claim" } : { kind: "unassign" }; +}; + +export const optimisticOverride = ({ + me, + row, + to, +}: { + me: BoardPerson; + row: ModcpBoardReport; + to: ModcpBoardStatus; +}): BoardOverride => ({ + assignee: to === "new" ? null : (row.assignee ?? me), + status: to, +}); + +const timeOf = (value: Date | string): number => new Date(value).getTime(); + +export const newestFirst = ( + left: Pick, + right: Pick, +): number => + timeOf(right.createdAt) - timeOf(left.createdAt) || right.id - left.id; + +export type BoardColumns = Record; + +export const boardColumns = ({ + loaded, + overrides, +}: { + loaded: BoardColumns; + overrides: ReadonlyMap; +}): BoardColumns => { + const latest = new Map(); + for (const row of [...loaded.new, ...loaded.in_progress, ...loaded.done]) { + const known = latest.get(row.id); + if (!known || row.version > known.version) latest.set(row.id, row); + } + + const columns: BoardColumns = { done: [], in_progress: [], new: [] }; + for (const row of latest.values()) { + const override = overrides.get(row.id); + const shown = override ? { ...row, ...override } : row; + columns[shown.status].push(shown); + } + + for (const rows of Object.values(columns)) rows.sort(newestFirst); + + return columns; +}; + +export const columnCount = ({ + loaded, + overrides, + status, + total, +}: { + loaded: BoardColumns; + overrides: ReadonlyMap; + status: ModcpBoardStatus; + total: number; +}): number => { + let count = total; + for (const row of [...loaded.new, ...loaded.in_progress, ...loaded.done]) { + const override = overrides.get(row.id); + if (!override || override.status === row.status) continue; + if (override.status === status) count += 1; + if (row.status === status) count -= 1; + } + + return Math.max(0, count); +}; + +export const slotIndex = ( + rows: readonly ModcpBoardReport[], + dragged: Pick, +): number => { + const index = rows.findIndex(row => newestFirst(dragged, row) < 0); + + return index === -1 ? rows.length : index; +}; diff --git a/packages/vitnode/src/views/moderation/modcp/board/reports-board.tsx b/packages/vitnode/src/views/moderation/modcp/board/reports-board.tsx new file mode 100644 index 0000000000..7559e68285 --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/board/reports-board.tsx @@ -0,0 +1,606 @@ +import type { + Announcements, + CollisionDetection, + DragEndEvent, + DragOverEvent, + DragStartEvent, + KeyboardCoordinateGetter, +} from "@dnd-kit/core"; + +import { + DndContext, + DragOverlay, + KeyboardSensor, + pointerWithin, + rectIntersection, + TouchSensor, + useDroppable, + useSensor, + useSensors, +} from "@dnd-kit/core"; +import { restrictToWindowEdges } from "@dnd-kit/modifiers"; +import { + useQueryClient, + useSuspenseInfiniteQuery, +} from "@tanstack/react-query"; +import { cn } from "cn"; +import { useReducedMotion } from "motion/react"; +import React from "react"; +import { toast } from "sonner"; +import { useTranslations } from "use-intl"; + +import type { LayoutFlipTarget, LayoutSnapshot } from "@/lib/dnd/layout-flip"; + +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { DragLift } from "@/lib/dnd/drag-lift"; +import { + DRAG_OVERLAY_LIFT_CLASS, + LIFTED_DROP_ANIMATION, +} from "@/lib/dnd/drag-motion"; +import { playLayoutFlip, snapshotLayout } from "@/lib/dnd/layout-flip"; +import { FinePointerSensor } from "@/lib/dnd/sensors"; + +import type { ReportState } from "../../moderation-mutations"; +import type { + ModcpBoardFilter, + ModcpBoardReport, + ModcpBoardStatus, +} from "../modcp-query"; +import type { BoardOverride, BoardPerson } from "./board-moves"; + +import { assignReport, claimReport } from "../../moderation-mutations"; +import { + invalidateModcp, + MODCP_BOARD_STATUSES, + modcpBoardColumnQueryOptions, +} from "../modcp-query"; +import { ModcpPluginMessages } from "../plugin-messages"; +import { + ReopenReportForm, + ResolveReportForm, + useReportFailure, +} from "../report-forms"; +import { StatusLozenge } from "../report-tone"; +import { BOARD_CARD_CLASS, BoardCard, BoardCardBody } from "./board-card"; +import { + boardColumns, + columnCount, + optimisticOverride, + planBoardMove, + slotIndex, +} from "./board-moves"; + +const COLUMN_PREFIX = "column-"; + +const CARDS: LayoutFlipTarget = { + keyOf: node => node.dataset.reportCard, + selector: "[data-report-card]", +}; + +const MIN_SLOT_HEIGHT = 96; + +const reportIdOf = (id: number | string): null | number => { + const match = /^report-(\d+)$/.exec(String(id)); + + return match ? Number(match[1]) : null; +}; + +const columnStatusOf = ( + id: null | number | string | undefined, +): ModcpBoardStatus | null => { + if (id === null || id === undefined) return null; + const value = String(id); + if (!value.startsWith(COLUMN_PREFIX)) return null; + const status = value.slice(COLUMN_PREFIX.length); + + return (MODCP_BOARD_STATUSES as readonly string[]).includes(status) + ? (status as ModcpBoardStatus) + : null; +}; + +const KEYBOARD_DROP_OFFSET = 48; + +const ARROW_STEP: Record = { + ArrowDown: 1, + ArrowLeft: -1, + ArrowRight: 1, + ArrowUp: -1, +}; + +const columnCoordinates: KeyboardCoordinateGetter = ( + event, + { context: { collisionRect, droppableContainers, droppableRects } }, +) => { + const step = ARROW_STEP[event.code]; + if (step === undefined || !collisionRect) return undefined; + event.preventDefault(); + + const columns = droppableContainers + .getEnabled() + .flatMap(container => { + const rect = droppableRects.get(container.id); + + return rect ? [rect] : []; + }) + .sort((left, right) => left.left - right.left || left.top - right.top); + if (columns.length === 0) return undefined; + + const centerX = collisionRect.left + collisionRect.width / 2; + const centerY = collisionRect.top + collisionRect.height / 2; + const current = columns.findIndex( + rect => + centerX >= rect.left && + centerX <= rect.left + rect.width && + centerY >= rect.top && + centerY <= rect.top + rect.height, + ); + const target = + columns[Math.min(columns.length - 1, Math.max(0, current + step))]; + if (!target) return undefined; + + return { + x: target.left + (target.width - collisionRect.width) / 2, + y: target.top + KEYBOARD_DROP_OFFSET, + }; +}; + +const collisionDetection: CollisionDetection = args => { + const within = pointerWithin(args); + + return within.length > 0 ? within : rectIntersection(args); +}; + +type Pending = null | { + kind: "reopen" | "resolve"; + row: ModcpBoardReport; + to: ModcpBoardStatus; +}; + +const DropSlot = ({ height, hint }: { height: number; hint: string }) => ( + +); + +const BoardColumn = ({ + count, + hasMore, + isLoadingMore, + onLoadMore, + onMove, + rows, + slot, + status, +}: { + count: number; + hasMore: boolean; + isLoadingMore: boolean; + onLoadMore: () => void; + onMove: (row: ModcpBoardReport, to: ModcpBoardStatus) => void; + rows: ModcpBoardReport[]; + slot: null | { height: number; hint: string; index: number }; + status: ModcpBoardStatus; +}) => { + const t = useTranslations("core.moderation.modcp.reports.board"); + const headingId = React.useId(); + const { setNodeRef } = useDroppable({ id: `${COLUMN_PREFIX}${status}` }); + const slotElement = + slot === null ? null : ( + + ); + + return ( +
    +

    + + + {count} + +

    + + {rows.length === 0 && slot === null ? ( +

    + {t("nothing_here")} +

    + ) : ( +
      + {rows.map((row, index) => ( + + {slot?.index === index ? slotElement : null} + + + ))} + {slot !== null && slot.index >= rows.length ? slotElement : null} +
    + )} + + {hasMore ? ( + + ) : null} +
    + ); +}; + +const BoardDialog = ({ + onCancel, + onDone, + onReopened, + pending, +}: { + onCancel: () => void; + onDone: () => Promise; + onReopened: (state: ReportState) => Promise; + pending: Pending; +}) => { + const t = useTranslations("core.moderation.modcp.detail"); + const row = pending?.row; + + return ( + { + if (!open) onCancel(); + }} + open={pending !== null} + > + + + + {pending?.kind === "reopen" + ? t("reopen.dialog_title", { id: row?.id ?? 0 }) + : t("resolve.dialog_title", { id: row?.id ?? 0 })} + + + {pending?.kind === "reopen" + ? t("reopen.dialog_desc") + : t("resolve.success_desc")} + + + {row === undefined ? null : pending?.kind === "reopen" ? ( + + ) : ( + + )} + + + ); +}; + +export const ModcpReportsBoard = ({ + filter, + me, +}: { + filter: ModcpBoardFilter; + me: BoardPerson; +}) => { + const t = useTranslations("core.moderation"); + const queryClient = useQueryClient(); + const reduceMotion = useReducedMotion(); + const fail = useReportFailure(); + const newColumn = useSuspenseInfiniteQuery( + modcpBoardColumnQueryOptions("new", filter), + ); + const progressColumn = useSuspenseInfiniteQuery( + modcpBoardColumnQueryOptions("in_progress", filter), + ); + const doneColumn = useSuspenseInfiniteQuery( + modcpBoardColumnQueryOptions("done", filter), + ); + const queries = { + done: doneColumn, + in_progress: progressColumn, + new: newColumn, + }; + + const [overrides, setOverrides] = React.useState< + ReadonlyMap + >(() => new Map()); + const [activeId, setActiveId] = React.useState(null); + const [overStatus, setOverStatus] = React.useState( + null, + ); + const [dragHeight, setDragHeight] = React.useState(0); + const [pending, setPending] = React.useState(null); + const boardRef = React.useRef(null); + const flipFromRef = React.useRef(null); + + const loaded = { + done: doneColumn.data.pages.flatMap(page => page.items), + in_progress: progressColumn.data.pages.flatMap(page => page.items), + new: newColumn.data.pages.flatMap(page => page.items), + }; + const columns = boardColumns({ loaded, overrides }); + const allRows = [...columns.new, ...columns.in_progress, ...columns.done]; + const active = + activeId === null + ? null + : (allRows.find(row => row.id === activeId) ?? null); + + const prepareFlip = () => { + if (reduceMotion) return; + flipFromRef.current ??= snapshotLayout(boardRef.current, CARDS); + }; + + React.useLayoutEffect(() => { + playLayoutFlip(boardRef.current, flipFromRef.current, CARDS); + flipFromRef.current = null; + }); + + const setOverride = (id: number, next: BoardOverride | null) => { + prepareFlip(); + setOverrides(current => { + const copy = new Map(current); + if (next === null) copy.delete(id); + else copy.set(id, next); + + return copy; + }); + }; + + const settle = async (id: number) => { + await invalidateModcp(queryClient); + setOverride(id, null); + }; + + const hintFor = (from: ModcpBoardStatus, to: ModcpBoardStatus): string => { + const plan = planBoardMove(from, to); + if (plan?.kind === "claim") return t("modcp.reports.board.hint_take"); + if (plan?.kind === "unassign") { + return t("modcp.reports.board.hint_unassign"); + } + if (plan?.kind === "resolve") return t("modcp.reports.board.hint_close"); + + return t("modcp.reports.board.hint_reopen"); + }; + + const move = async (row: ModcpBoardReport, to: ModcpBoardStatus) => { + const plan = planBoardMove(row.status, to); + if (plan === null) return; + + setOverride(row.id, optimisticOverride({ me, row, to })); + + if (plan.kind === "resolve" || plan.kind === "reopen") { + setPending({ kind: plan.kind, row, to }); + + return; + } + + const result = + plan.kind === "claim" + ? await claimReport({ expectedVersion: row.version, id: row.id }) + : await assignReport({ + assigneeId: null, + expectedVersion: row.version, + id: row.id, + }); + + if (!fail(result)) { + if (plan.kind === "claim") { + toast.success(t("modcp.detail.assignment.claimed"), { + description: t("modcp.detail.assignment.claimed_desc"), + }); + } else { + toast.success(t("modcp.reports.board.unassigned"), { + description: t("modcp.reports.board.unassigned_desc"), + }); + } + } + await settle(row.id); + }; + + const onReopened = async (state: ReportState) => { + if (pending === null) return; + const { row, to } = pending; + if (to === "in_progress" && state.status === "new") { + fail(await claimReport({ expectedVersion: state.version, id: row.id })); + } + if (to === "new" && state.status === "in_progress") { + fail( + await assignReport({ + assigneeId: null, + expectedVersion: state.version, + id: row.id, + }), + ); + } + }; + + const sensors = useSensors( + useSensor(FinePointerSensor, { activationConstraint: { distance: 8 } }), + useSensor(TouchSensor, { + activationConstraint: { delay: 200, tolerance: 8 }, + }), + useSensor(KeyboardSensor, { coordinateGetter: columnCoordinates }), + ); + + const statusName = (status: ModcpBoardStatus) => t(`statuses.${status}`); + + const announcements: Announcements = { + onDragCancel: ({ active: dragged }) => + t("modcp.reports.board.dnd.cancelled", { + id: reportIdOf(dragged.id) ?? 0, + }), + onDragEnd: ({ active: dragged, over }) => { + const status = columnStatusOf(over?.id); + const id = reportIdOf(dragged.id) ?? 0; + + return status === null + ? t("modcp.reports.board.dnd.cancelled", { id }) + : t("modcp.reports.board.dnd.dropped", { + column: statusName(status), + id, + }); + }, + onDragOver: ({ active: dragged, over }) => { + const status = columnStatusOf(over?.id); + const id = reportIdOf(dragged.id) ?? 0; + + return status === null + ? t("modcp.reports.board.dnd.outside", { id }) + : t("modcp.reports.board.dnd.over", { + column: statusName(status), + id, + }); + }, + onDragStart: ({ active: dragged }) => + t("modcp.reports.board.dnd.picked_up", { + id: reportIdOf(dragged.id) ?? 0, + }), + }; + + const onDragStart = ({ active: dragged }: DragStartEvent) => { + setActiveId(reportIdOf(dragged.id)); + setDragHeight(dragged.rect.current.initial?.height ?? 0); + }; + + const onDragOver = ({ active: dragged, over }: DragOverEvent) => { + const status = columnStatusOf(over?.id); + const height = dragged.rect.current.initial?.height ?? 0; + if (height !== dragHeight) setDragHeight(height); + if (status === overStatus) return; + prepareFlip(); + setOverStatus(status); + }; + + const reset = () => { + prepareFlip(); + setActiveId(null); + setOverStatus(null); + }; + + const onDragEnd = ({ over }: DragEndEvent) => { + const status = columnStatusOf(over?.id); + const row = active; + reset(); + if (row !== null && status !== null) void move(row, status); + }; + + const showsSlot = + active !== null && overStatus !== null && overStatus !== active.status; + + return ( + row.targetLabel)}> + +
    + {MODCP_BOARD_STATUSES.map(status => { + const query = queries[status]; + const rows = columns[status]; + + return ( + { + void query.fetchNextPage(); + }} + onMove={(row, to) => { + void move(row, to); + }} + rows={rows} + slot={ + showsSlot && overStatus === status + ? { + height: dragHeight, + hint: hintFor(active.status, status), + index: slotIndex(rows, active), + } + : null + } + status={status} + /> + ); + })} +
    + + + {active === null ? null : ( + +
    + +
    +
    + )} +
    + + { + if (pending !== null) setOverride(pending.row.id, null); + setPending(null); + }} + onDone={async () => { + const id = pending?.row.id; + setPending(null); + if (id !== undefined) await settle(id); + }} + onReopened={onReopened} + pending={pending} + /> +
    +
    + ); +}; diff --git a/packages/vitnode/src/views/moderation/modcp/modcp-nav.tsx b/packages/vitnode/src/views/moderation/modcp/modcp-nav.tsx new file mode 100644 index 0000000000..2e3c2d596d --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/modcp-nav.tsx @@ -0,0 +1,112 @@ +import { useQuery } from "@tanstack/react-query"; +import { Link } from "@tanstack/react-router"; +import { cn } from "cn"; +import { FlagIcon } from "lucide-react"; +import { useTranslations } from "use-intl"; + +import { SideNavCard, SideNavLink, SideNavList } from "@/components/side-nav"; + +import { modcpReportsQueryOptions } from "./modcp-query"; + +export type ModcpNavKey = "reports"; + +interface ModcpNavItem { + href: string; + icon: React.ComponentType<{ className?: string }>; + key: ModcpNavKey; +} + +export const MODCP_NAV_ITEMS: readonly ModcpNavItem[] = [ + { href: "/modcp/reports", icon: FlagIcon, key: "reports" }, +]; + +const OPEN_REPORTS_FILTER = { + assigned: "any", + page: 1, + pageSize: 1, + status: "open", +} as const; + +export const isModcpNavItemActive = ( + item: ModcpNavItem, + pathname: string, +): boolean => pathname === item.href || pathname.startsWith(`${item.href}/`); + +const useNavCounts = (): Partial> => { + const { data } = useQuery(modcpReportsQueryOptions(OPEN_REPORTS_FILTER)); + + return { reports: data?.total }; +}; + +const ModcpNavChip = ({ + count, + isActive, + item, +}: { + count?: number; + isActive: boolean; + item: ModcpNavItem; +}) => { + const t = useTranslations("core.moderation.modcp"); + const Icon = item.icon; + + return ( + +
    + ); +}; + +const Visibility = ({ data }: { data: ModcpReportDetail }) => { + const t = useTranslations("core.moderation.modcp.detail.current"); + + if (!data.current.registered || !data.current.exists) { + return ( + + + {t(data.current.registered ? "deleted" : "unregistered")} + + ); + } + + return data.current.hidden ? ( + + {t("hidden")} + + ) : ( + + {t("visible")} + + ); +}; + +export const ReportSidebar = ({ + data, + onDone, + pluginName, + typeLabel, + userId, +}: ReportContext & { pluginName: string; typeLabel: string }) => { + const t = useTranslations("core.moderation"); + const { report } = data; + const author = data.authors.at(0); + + return ( +
    +
    +
    + +
    + +
    +
    +

    + {t("modcp.detail.details.title")} +

    +
    + +
    +
    + + + + {pluginName} + + + + + + + {data.reporter ? ( + + ) : ( + + {t("modcp.detail.report.deleted_user")} + + )} + + {author ? ( + + + + ) : null} + + + {t(`reasons.${report.reason}`)} + + + + + + {report.resolution ? ( + + + {t(`resolutions.${report.resolution}`)} + + + ) : null} +
    +
    +
    +
    {t("modcp.detail.details.created")}
    +
    + +
    +
    {t("modcp.detail.details.updated")}
    +
    + +
    + {report.resolvedAt ? ( + <> +
    {t("modcp.detail.details.resolved")}
    +
    + +
    + + ) : null} +
    + {!data.permissions.manage ? ( +

    + {t("modcp.detail.read_only")} +

    + ) : null} +
    + ); +}; diff --git a/packages/vitnode/src/views/moderation/modcp/report-snapshot-peek.tsx b/packages/vitnode/src/views/moderation/modcp/report-snapshot-peek.tsx new file mode 100644 index 0000000000..53f4106302 --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/report-snapshot-peek.tsx @@ -0,0 +1,104 @@ +import React from "react"; +import { useTranslations } from "use-intl"; + +import type { + ModerationReportSnapshot, + ModerationSnapshotField, +} from "@/lib/moderation/snapshot"; + +import { DateFormat } from "@/components/date-format"; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet"; +import { isRichTextDocument } from "@/content/rich-text/document"; + +import type { ReportPerson } from "./report-tone"; + +import { PersonName } from "./report-tone"; +import { SnapshotView } from "./snapshot-view"; + +interface TextNode { + content?: TextNode[]; + text?: string; + type: string; +} + +const plainText = (node: TextNode): string => + node.text ?? (node.content ?? []).map(plainText).join(" "); + +const excerptOf = (fields: ModerationSnapshotField[]): string => { + for (const field of fields) { + if (field.kind === "richText" && isRichTextDocument(field.value)) { + const text = plainText(field.value).replaceAll(/\s+/g, " ").trim(); + if (text) return text; + } + if (field.kind === "text" && field.value) return field.value; + } + + return ""; +}; + +export const SnapshotPeek = ({ + author, + reportId, + snapshot, + typeLabel, +}: { + author: null | Pick; + reportId: number; + snapshot: ModerationReportSnapshot; + typeLabel: string; +}) => { + const t = useTranslations("core.moderation.modcp.detail.snapshot_card"); + const [isOpen, setIsOpen] = React.useState(false); + const excerpt = excerptOf(snapshot.fields); + + return ( + + + + + {t("sheet_title")} + + {t("sheet_desc", { id: reportId })} + + +
    + +
    +
    +
    + ); +}; diff --git a/packages/vitnode/src/views/moderation/modcp/report-tone.tsx b/packages/vitnode/src/views/moderation/modcp/report-tone.tsx new file mode 100644 index 0000000000..1b908830ab --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/report-tone.tsx @@ -0,0 +1,129 @@ +import { cn } from "cn"; +import { useTranslations } from "use-intl"; + +import type { ModerationReportReason } from "@/lib/moderation/const"; + +import { Avatar } from "@/components/avatar"; +import { FEEDBACK_TONE_TEXT } from "@/components/ui/feedback-tone"; +import { UserFormat } from "@/components/user-format"; + +import type { ModcpReportDetail } from "./modcp-query"; + +export type ReportPerson = NonNullable; +export type ReportStatus = ModcpReportDetail["report"]["status"]; + +export const TONE_SURFACE = { + destructive: cn("bg-destructive/10", FEEDBACK_TONE_TEXT.destructive), + info: cn("bg-primary/10", FEEDBACK_TONE_TEXT.info), + muted: "bg-muted text-muted-foreground", + success: cn("bg-success/12", FEEDBACK_TONE_TEXT.success), + warning: cn("bg-warn/12", FEEDBACK_TONE_TEXT.warning), +} as const; + +export type ToneName = keyof typeof TONE_SURFACE; + +export const STATUS_TONE: Record = { + done: "success", + in_progress: "info", + new: "muted", +}; + +export const REASON_TONE: Record = { + abusive: "destructive", + other: "muted", + rule_violation: "warning", + spam: "warning", +}; + +export const REASON_TEXT: Record = { + abusive: FEEDBACK_TONE_TEXT.destructive, + other: "text-muted-foreground", + rule_violation: FEEDBACK_TONE_TEXT.warning, + spam: FEEDBACK_TONE_TEXT.warning, +}; + +export const Chip = ({ + children, + icon: Icon, + tone, +}: { + children: React.ReactNode; + icon?: React.ComponentType<{ className?: string }>; + tone: ToneName; +}) => ( + + {Icon ? : null} + {children} + +); + +export const StatusLozenge = ({ status }: { status: ReportStatus }) => { + const t = useTranslations("core.moderation.statuses"); + + return ( + + {t(status)} + + ); +}; + +export const PersonAvatar = ({ + className, + person, + size = 24, +}: { + className?: string; + person: ReportPerson; + size?: number; +}) => ( + +); + +export const PersonName = ({ + className, + link = false, + person, +}: { + className?: string; + link?: boolean; + person: Partial> & + Pick; +}) => ( + +); + +export const Person = ({ + link = false, + person, + size = 24, +}: { + link?: boolean; + person: ReportPerson; + size?: number; +}) => ( + + + + +); diff --git a/packages/vitnode/src/views/moderation/modcp/reports-content.tsx b/packages/vitnode/src/views/moderation/modcp/reports-content.tsx new file mode 100644 index 0000000000..f3d096d12b --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/reports-content.tsx @@ -0,0 +1,59 @@ +import { useTranslations } from "use-intl"; + +import { FiltersDataTable } from "@/components/table/filters"; +import { SearchDataTable } from "@/components/table/search"; + +import type { BoardPerson } from "./board/board-moves"; +import type { ModcpBoardFilter } from "./modcp-query"; + +import { ModcpReportsBoard } from "./board/reports-board"; + +export const ModcpReportsContent = ({ + description, + filter, + me, + title, +}: { + description: string; + filter: ModcpBoardFilter; + me: BoardPerson; + title: string; +}) => { + const t = useTranslations("core.moderation.modcp.reports"); + + return ( +
    +
    +

    + {title} +

    +

    + {description} +

    +
    + +
    +
    +
    + +
    + +
    + + +
    +
    + ); +}; diff --git a/packages/vitnode/src/views/moderation/modcp/snapshot-view.tsx b/packages/vitnode/src/views/moderation/modcp/snapshot-view.tsx new file mode 100644 index 0000000000..ace74cfde8 --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/snapshot-view.tsx @@ -0,0 +1,173 @@ +import { CameraIcon, FileIcon, ScissorsIcon } from "lucide-react"; +import { useFormatter, useTranslations } from "use-intl"; + +import type { + ModerationReportSnapshot, + ModerationSnapshotField, +} from "@/lib/moderation/snapshot"; + +import { RichTextContent } from "@/components/rich-text"; +import { Badge } from "@/components/ui/badge"; +import { isRichTextDocument } from "@/content/rich-text/document"; +import { formatBytes } from "@/lib/format-bytes"; + +const isRecord = (value: unknown): value is Record => + typeof value === "object" && value !== null && !Array.isArray(value); + +const isSnapshot = (value: unknown): value is ModerationReportSnapshot => + isRecord(value) && Array.isArray(value.fields); + +export const readSnapshot = (value: unknown) => + isSnapshot(value) ? value : null; + +const FieldValue = ({ field }: { field: ModerationSnapshotField }) => { + const t = useTranslations("core.moderation.modcp.detail.snapshot"); + + switch (field.kind) { + case "file": + return field.value.length === 0 ? ( +

    {t("empty")}

    + ) : ( +
      + {field.value.map(file => ( +
    • + + + + {file.name ?? t("file_missing")} + + + {[file.mimeType, file.size ? formatBytes(file.size) : null] + .filter(Boolean) + .join(" · ")} + + + {t("file")} + + +
    • + ))} +
    + ); + case "richText": + return isRichTextDocument(field.value) ? ( + + ) : ( +

    {t("empty")}

    + ); + case "text": + return field.value ? ( +

    + {field.value} +

    + ) : ( +

    {t("empty")}

    + ); + default: + return ( +

    + {field.value === null || field.value === "" + ? t("empty") + : String(field.value)} +

    + ); + } +}; + +export const SnapshotView = ({ + snapshot, +}: { + snapshot: ModerationReportSnapshot; +}) => { + const t = useTranslations("core.moderation.modcp.detail.snapshot"); + const tRoot = useTranslations(); + const format = useFormatter(); + + const labelOf = (field: ModerationSnapshotField) => + field.label && tRoot.has(field.label as never) + ? tRoot(field.label as never) + : field.name; + + return ( +
    +
    +
    + + + {t("badge")} + +

    + {t("title")} +

    +
    +

    + {t("desc", { + date: format.dateTime(new Date(snapshot.capturedAt), { + dateStyle: "medium", + timeStyle: "short", + }), + })} +

    +

    + {snapshot.locale?.served ? ( + + {snapshot.locale.fallback && snapshot.locale.requested + ? t("fallback", { + requested: snapshot.locale.requested, + served: snapshot.locale.served, + }) + : t("locale", { served: snapshot.locale.served })} + + ) : null} + {snapshot.source?.version ? ( + {t("version", { version: snapshot.source.version })} + ) : null} + {snapshot.authors?.length ? ( + + {t("by", { + names: snapshot.authors.map(author => author.name).join(", "), + })} + + ) : null} +

    + {snapshot.truncated ? ( +

    + + {t("truncated")} +

    + ) : null} +
    + + {snapshot.title ? ( +

    + {snapshot.title} +

    + ) : null} + +
    + {snapshot.fields.map(field => ( +
    +
    + {labelOf(field)} +
    +
    + +
    +
    + ))} +
    +
    + ); +}; diff --git a/packages/vitnode/src/views/moderation/modcp/status-badge.tsx b/packages/vitnode/src/views/moderation/modcp/status-badge.tsx new file mode 100644 index 0000000000..16c004f384 --- /dev/null +++ b/packages/vitnode/src/views/moderation/modcp/status-badge.tsx @@ -0,0 +1,34 @@ +import { useTranslations } from "use-intl"; + +import { Badge } from "@/components/ui/badge"; + +export const ReportStatusBadge = ({ + status, +}: { + status: "done" | "in_progress" | "new"; +}) => { + const t = useTranslations("core.moderation.statuses"); + + return ( + + {t(status)} + + ); +}; + +export const useTargetLabel = () => { + const tRoot = useTranslations(); + + return (label: null | string, fallback: string): string => + label && tRoot.has(label as never) + ? tRoot(label as never, { count: 1 } as never) + : fallback; +}; diff --git a/packages/vitnode/src/views/moderation/moderation-mutations.ts b/packages/vitnode/src/views/moderation/moderation-mutations.ts new file mode 100644 index 0000000000..e9b7621351 --- /dev/null +++ b/packages/vitnode/src/views/moderation/moderation-mutations.ts @@ -0,0 +1,279 @@ +import type { RichTextDocument } from "@/content/rich-text/document"; +import type { ModerationReportReason } from "@/lib/moderation/const"; + +import { CONFIG_PLUGIN } from "@/config"; +import { fetcherClient } from "@/lib/fetcher-client"; + +const REPORTED_FAILURES = [ + "already_claimed", + "assignee_not_eligible", + "conflict", + "duplicate", + "forbidden", + "not_found", + "note_not_found", + "rate_limited", + "report_closed", + "report_open", + "target_gone", +] as const; + +export type ModerationFailure = + | "unknown" + | "validation" + | (typeof REPORTED_FAILURES)[number]; + +export type ModerationResult = + | { data: T; ok: true } + | { failure: ModerationFailure; ok: false }; + +const isReportedFailure = ( + value: unknown, +): value is (typeof REPORTED_FAILURES)[number] => + REPORTED_FAILURES.some(failure => failure === value); + +const reportedFailureOf = async (response: Response) => { + const body = (await response.json().catch(() => null)) as null | { + error?: unknown; + }; + + return isReportedFailure(body?.error) ? body.error : null; +}; + +const failureOf = async (response: Response): Promise => { + if (response.status === 429) return "rate_limited"; + const reported = await reportedFailureOf(response); + if (reported) return reported; + if (response.status === 400) return "validation"; + if (response.status === 403) return "forbidden"; + if (response.status === 404) return "not_found"; + + return "unknown"; +}; + +const settle = async ( + request: () => Promise, + expected: number, +): Promise> => { + try { + const response = await request(); + if (response.status !== expected) { + return { failure: await failureOf(response), ok: false }; + } + + return { data: (await response.json()) as T, ok: true }; + } catch { + return { failure: "unknown", ok: false }; + } +}; + +const options = { credentials: "include" } as const; + +export interface CreateReportInput { + description: null | string; + locale: null | string; + pluginId: string; + reason: ModerationReportReason; + requestedLocale?: null | string; + targetId: string; + targetType: string; +} + +export const createReport = async (input: CreateReportInput) => + await settle<{ id: number }>( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: input }, + method: "post", + module: "moderation", + options, + path: "/reports", + }), + 201, + ); + +export interface ReportState { + assigneeId: null | number; + status: "done" | "in_progress" | "new"; + version: number; +} + +export const claimReport = async ({ + expectedVersion, + id, +}: { + expectedVersion: number; + id: number; +}) => + await settle( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: { expectedVersion }, params: { id } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/claim", + }), + 200, + ); + +export const assignReport = async ({ + assigneeId, + expectedVersion, + id, +}: { + assigneeId: null | number; + expectedVersion: number; + id: number; +}) => + await settle( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: { assigneeId, expectedVersion }, params: { id } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/assign", + }), + 200, + ); + +export const addReportNote = async ({ + body, + id, +}: { + body: RichTextDocument | string; + id: number; +}) => + await settle<{ ok: boolean }>( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: { body }, params: { id } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/notes", + }), + 201, + ); + +export const editReportNote = async ({ + body, + id, + noteId, +}: { + body: RichTextDocument | string; + id: number; + noteId: number; +}) => + await settle<{ ok: boolean }>( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: { body }, params: { id, noteId } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/notes/{noteId}/edit", + }), + 200, + ); + +export const deleteReportNote = async ({ + id, + noteId, +}: { + id: number; + noteId: number; +}) => + await settle<{ ok: boolean }>( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { params: { id, noteId } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/notes/{noteId}/delete", + }), + 200, + ); + +export const resolveReport = async ({ + expectedVersion, + explanation, + id, + resolution, +}: { + expectedVersion: number; + explanation?: string; + id: number; + resolution: "action_taken" | "duplicate" | "no_violation"; +}) => + await settle( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { + body: { + expectedVersion, + explanation: explanation ?? null, + resolution, + }, + params: { id }, + }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/resolve", + }), + 200, + ); + +export const reopenReport = async ({ + expectedVersion, + id, + reason, +}: { + expectedVersion: number; + id: number; + reason: string; +}) => + await settle( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: { expectedVersion, reason }, params: { id } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/reopen", + }), + 200, + ); + +export const runReportAction = async ({ + action, + expectedVersion, + id, +}: { + action: "hide" | "unhide"; + expectedVersion: number; + id: number; +}) => + await settle( + async () => + await fetcherClient({ + plugin: CONFIG_PLUGIN.pluginId, + args: { body: { expectedVersion }, params: { action, id } }, + method: "post", + module: "moderation", + options, + path: "/reports/{id}/actions/{action}", + }), + 200, + ); diff --git a/packages/vitnode/src/views/moderation/report/report-dialog-content.tsx b/packages/vitnode/src/views/moderation/report/report-dialog-content.tsx new file mode 100644 index 0000000000..1aba88467d --- /dev/null +++ b/packages/vitnode/src/views/moderation/report/report-dialog-content.tsx @@ -0,0 +1,146 @@ +import { toast } from "sonner"; +import { useTranslations } from "use-intl"; +import { z } from "zod"; + +import type { AutoFormOnSubmit } from "@/components/form/auto-form"; + +import { AutoForm, AutoFormSubmitButton } from "@/components/form/auto-form"; +import { AutoFormRadioGroup } from "@/components/form/fields/radio-group"; +import { AutoFormTextarea } from "@/components/form/fields/textarea"; +import { Button } from "@/components/ui/button"; +import { + MODERATION_LIMITS, + MODERATION_REPORT_REASONS, +} from "@/lib/moderation/const"; + +import { createReport } from "../moderation-mutations"; + +export interface ReportDialogContentProps { + locale: null | string; + onClose: () => void; + pluginId: string; + requestedLocale: null | string; + targetId: string; + targetType: string; +} + +export const ReportDialogContent = ({ + locale, + onClose, + pluginId, + requestedLocale, + targetId, + targetType, +}: ReportDialogContentProps) => { + const t = useTranslations("core.moderation"); + + const formSchema = z + .object({ + reason: z.enum(MODERATION_REPORT_REASONS), + description: z + .string() + .trim() + .max(MODERATION_LIMITS.descriptionMaxLength) + .optional(), + }) + .superRefine((values, ctx) => { + if ( + values.reason === "other" && + (values.description?.length ?? 0) < + MODERATION_LIMITS.otherDescriptionMinLength + ) { + ctx.addIssue({ + code: "too_small", + minimum: MODERATION_LIMITS.otherDescriptionMinLength, + origin: "string", + path: ["description"], + message: t("report.errors.validation"), + }); + } + }); + + const onSubmit: AutoFormOnSubmit = async values => { + const result = await createReport({ + description: + values.description?.trim() === "" + ? null + : (values.description?.trim() ?? null), + locale, + pluginId, + reason: values.reason, + requestedLocale, + targetId, + targetType, + }); + + if (!result.ok) { + const key = + result.failure === "duplicate" || + result.failure === "not_found" || + result.failure === "rate_limited" || + result.failure === "validation" + ? result.failure + : "unknown"; + toast.error(t("report.errors.title"), { + description: t(`report.errors.${key}`), + }); + if (key === "duplicate" || key === "not_found") onClose(); + + return; + } + + toast.success(t("report.success"), { + description: t("report.success_desc"), + }); + onClose(); + }; + + return ( + ( + ({ + description: t(`reason_descs.${reason}`), + label: t(`reasons.${reason}`), + value: reason, + }))} + /> + ), + id: "reason", + }, + { + component: props => ( + + ), + id: "description", + }, + ]} + formSchema={formSchema} + layout={rendered => ( + <> + {rendered.reason} + {rendered.description} +
    + + {t("report.submit")} +
    + + )} + onSubmit={onSubmit} + /> + ); +}; + +export default ReportDialogContent; diff --git a/plugins/blog/src/content/post.ts b/plugins/blog/src/content/post.ts index c96773f7e1..72ba7df7e4 100644 --- a/plugins/blog/src/content/post.ts +++ b/plugins/blog/src/content/post.ts @@ -18,6 +18,8 @@ export const blogPostContentType = defineContentType({ visibility: true, + reports: true, + editorial: { revisions: { retention: 20 }, preview: { expiresInMinutes: 30 }, diff --git a/plugins/blog/src/locales/en.json b/plugins/blog/src/locales/en.json index 04552565b5..c99e58b908 100644 --- a/plugins/blog/src/locales/en.json +++ b/plugins/blog/src/locales/en.json @@ -179,8 +179,9 @@ "hidden": { "label": "Article hidden", "title": "This article is hidden", - "desc": "Only its authors and editors can see it. Everyone else gets a page not found, and it stays out of search and the sitemap." - } + "desc": "Only its authors, editors and moderators can see it. Everyone else gets a page not found, and it stays out of search and the sitemap." + }, + "report_type": "article" } }, "@vitnode/blog:posts": "Articles", @@ -191,6 +192,9 @@ "@vitnode/blog:posts:can_publish": "Publish and unpublish articles", "@vitnode/blog:posts:can_restore": "Restore an earlier version of an article", "@vitnode/blog:posts:can_hide": "Hide and unhide articles", + "@vitnode/blog:posts:can_view_reports": "View article reports", + "@vitnode/blog:posts:can_manage_reports": "Claim, assign and resolve article reports", + "@vitnode/blog:posts:can_view_hidden": "Open hidden articles", "@vitnode/blog:categories": "Categories", "@vitnode/blog:categories:can_view": "View categories list", "@vitnode/blog:categories:can_create": "Create categories", diff --git a/plugins/blog/src/pages/post-page.tsx b/plugins/blog/src/pages/post-page.tsx index 3f385379e9..624aedca13 100644 --- a/plugins/blog/src/pages/post-page.tsx +++ b/plugins/blog/src/pages/post-page.tsx @@ -21,11 +21,13 @@ import { } from "@vitnode/core/tanstack/content"; import { fetcher } from "@vitnode/core/tanstack/fetcher"; import { getIntlRuntime } from "@vitnode/core/tanstack/i18n"; +import { ReportButton } from "@vitnode/core/tanstack/moderation"; import { EyeOffIcon } from "lucide-react"; import { useTranslations } from "use-intl"; import { z } from "zod"; import { CONFIG_PLUGIN } from "@/const"; +import { blogPostContentType } from "@/content/post"; const zodBlogPost = z.object({ content: zodRichTextDocument, @@ -100,14 +102,30 @@ const BlogPostPage = ({ lang={metadata.locale ?? undefined} >
    - {item.publishedAt ? ( -

    - {t("published")}{" "} - -

    - ) : null} +
    + {item.publishedAt ? ( +

    + {t("published")}{" "} + +

    + ) : ( + + )} + + {!metadata.hidden && metadata.itemId !== null ? ( + + ) : null} +

    {metadata.hidden ? ( diff --git a/plugins/example/src/api/lib/moderation.ts b/plugins/example/src/api/lib/moderation.ts new file mode 100644 index 0000000000..45ad479ec4 --- /dev/null +++ b/plugins/example/src/api/lib/moderation.ts @@ -0,0 +1,43 @@ +import { defineModerationScope } from "@vitnode/core/api/moderation"; +import { and, asc, gt, ilike, inArray } from "drizzle-orm"; + +import { example_categories } from "@/database/categories"; + +export const exampleCategoryScope = defineModerationScope({ + id: "example.category", + label: "@vitnode/example.moderation.category.label", + description: "@vitnode/example.moderation.category.desc", + list: async (c, { cursor, limit, search }) => { + const rows = await c + .get("db") + .select({ id: example_categories.id, name: example_categories.name }) + .from(example_categories) + .where( + and( + cursor ? gt(example_categories.id, Number(cursor)) : undefined, + search ? ilike(example_categories.name, `%${search}%`) : undefined, + ), + ) + .orderBy(asc(example_categories.id)) + .limit(limit + 1); + + const page = rows.slice(0, limit); + + return { + items: page.map(row => ({ id: String(row.id), label: row.name })), + nextCursor: rows.length > limit ? String(page.at(-1)?.id) : null, + }; + }, + find: async (c, ids) => { + const numeric = ids.map(Number).filter(id => Number.isSafeInteger(id)); + if (numeric.length === 0) return []; + + const rows = await c + .get("db") + .select({ id: example_categories.id, name: example_categories.name }) + .from(example_categories) + .where(inArray(example_categories.id, numeric)); + + return rows.map(row => ({ id: String(row.id), label: row.name })); + }, +}); diff --git a/plugins/example/src/config.api.ts b/plugins/example/src/config.api.ts index 777f0e63e1..c5b016fd63 100644 --- a/plugins/example/src/config.api.ts +++ b/plugins/example/src/config.api.ts @@ -4,6 +4,7 @@ import { buildApiPlugin } from "@vitnode/core/api/lib/plugin"; import { buildContentPublicModule } from "@vitnode/core/content/server"; import { articleExcerptAiAction } from "@/api/ai/actions"; +import { exampleCategoryScope } from "@/api/lib/moderation"; import { adminModule } from "@/api/modules/admin/admin.module"; import { CONFIG_PLUGIN } from "@/const"; import { settingsPage } from "@/content/settings-page"; @@ -25,6 +26,7 @@ export const exampleApiPlugin = () => blocks: widgets, editablePages: [settingsPage], navigation: [{ href: "/example/browse", icon: "list", id: "browse" }], + moderation: { scopes: [exampleCategoryScope] }, permissionStaff: { moderator: { widgets: ["can_edit"], diff --git a/plugins/example/src/content/article.ts b/plugins/example/src/content/article.ts index bd73421b05..dfe6ed0baf 100644 --- a/plugins/example/src/content/article.ts +++ b/plugins/example/src/content/article.ts @@ -51,6 +51,8 @@ export const articleContentType = defineContentType({ publication: true, + reports: true, + publicApi: { path: "articles", fields: [ diff --git a/plugins/example/src/database/articles.ts b/plugins/example/src/database/articles.ts index 7a87aec887..97c6a8012d 100644 --- a/plugins/example/src/database/articles.ts +++ b/plugins/example/src/database/articles.ts @@ -13,6 +13,7 @@ export const articleContent = createContentModel(articleContentType, { // `core_files.id` itself and asking a plugin to name it would be a line of // boilerplate with one correct value. references: { category: () => example_categories.id }, + moderationScope: { column: "category", family: "example.category" }, }); export const example_articles = articleContent.table; diff --git a/plugins/example/src/locales/en.json b/plugins/example/src/locales/en.json index 0da3175550..536a54d678 100644 --- a/plugins/example/src/locales/en.json +++ b/plugins/example/src/locales/en.json @@ -131,6 +131,12 @@ }, "events": { "sessions": "Sessions" + }, + "moderation": { + "category": { + "label": "Categories", + "desc": "Limit this permission to articles in some categories." + } } }, "@vitnode/example:article": "Articles",