diff --git a/migrations/20260928175116_documents_trash_and_links/migration.sql b/migrations/20260928175116_documents_trash_and_links/migration.sql new file mode 100644 index 000000000..e72f5bca3 --- /dev/null +++ b/migrations/20260928175116_documents_trash_and_links/migration.sql @@ -0,0 +1,7 @@ +ALTER TABLE "cover_letter" ADD COLUMN "tags" text[] DEFAULT '{}'::text[] NOT NULL;--> statement-breakpoint +ALTER TABLE "cover_letter" ADD COLUMN "is_locked" boolean DEFAULT false NOT NULL;--> statement-breakpoint +ALTER TABLE "cover_letter" ADD COLUMN "trashed_at" timestamp with time zone;--> statement-breakpoint +ALTER TABLE "resume" ADD COLUMN "application_id" text;--> statement-breakpoint +ALTER TABLE "resume" ADD COLUMN "trashed_at" timestamp with time zone;--> statement-breakpoint +ALTER TABLE "resume" ADD COLUMN "auto_name" boolean DEFAULT false NOT NULL;--> statement-breakpoint +ALTER TABLE "resume" ADD CONSTRAINT "resume_application_id_application_id_fkey" FOREIGN KEY ("application_id") REFERENCES "application"("id") ON DELETE SET NULL; \ No newline at end of file diff --git a/migrations/20260928175116_documents_trash_and_links/snapshot.json b/migrations/20260928175116_documents_trash_and_links/snapshot.json new file mode 100644 index 000000000..3a69173d8 --- /dev/null +++ b/migrations/20260928175116_documents_trash_and_links/snapshot.json @@ -0,0 +1,6736 @@ +{ + "version": "8", + "dialect": "postgres", + "id": "4c9e3f5a-cb40-4eba-ba56-7836d88747ad", + "prevIds": ["96dc012b-8a44-446b-8421-0ece7c117feb"], + "ddl": [ + { + "isRlsEnabled": false, + "name": "agent_actions", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "agent_attachments", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "agent_messages", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "agent_threads", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "ai_providers", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "application", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "account", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "apikey", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "jwks", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_access_token", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_client", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_client_assertion", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_client_resource", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_consent", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_refresh_token", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "oauth_resource", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "passkey", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "session", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "two_factor", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "user", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "verification", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "cover_letter", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "resume", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "resume_slug_redirect", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "resume_statistics", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "resume_statistics_daily", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "resume_version", + "entityType": "tables", + "schema": "public" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "thread_id", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "message_id", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_id", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'applied'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "summary", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "operations", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "snapshot_data", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "base_updated_at", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "applied_updated_at", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reverted_at", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "revert_message", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "agent_actions" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "thread_id", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "message_id", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "storage_key", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "filename", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "media_type", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "size", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "agent_attachments" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "thread_id", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "role", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'completed'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "sequence", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ui_message", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "error", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "agent_messages" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ai_provider_id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "source_resume_id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "working_resume_id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'active'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "review_patches", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "active_run_id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "active_stream_id", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "active_run_started_at", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "last_message_at", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "archived_at", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deleted_at", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "agent_threads" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "label", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "model", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "base_url", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "encrypted_api_key", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "api_key_salt", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "api_key_hash", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "api_key_preview", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'untested'", + "generated": null, + "identity": null, + "name": "test_status", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "test_error", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_tested_at", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_used_at", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "enabled", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "ai_providers" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "company", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "role", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "location", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "salary", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'saved'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "archived", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_id", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "source", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "tags", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "source_url", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "job_description", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "match_score", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ai_metadata", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "notes", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_file_url", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_file_name", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cover_letter_url", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cover_letter_name", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "follow_up_at", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "follow_up_note", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "contacts", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'[]'", + "generated": null, + "identity": null, + "name": "activity", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "applied_at", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "application" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "account_id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'credential'", + "generated": null, + "identity": null, + "name": "provider_id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "issuer", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scope", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id_token", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "password", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "access_token", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refresh_token", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "access_token_expires_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refresh_token_expires_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "start", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "prefix", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "key", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'default'", + "generated": null, + "identity": null, + "name": "config_id", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reference_id", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refill_interval", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refill_amount", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_refill_at", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "enabled", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "rate_limit_enabled", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "86400000", + "generated": null, + "identity": null, + "name": "rate_limit_time_window", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "10", + "generated": null, + "identity": null, + "name": "rate_limit_max", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "request_count", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "remaining", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_request", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "permissions", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "apikey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "public_key", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "private_key", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "alg", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "crv", + "entityType": "columns", + "schema": "public", + "table": "jwks" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "authorization_code_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "resources", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "requested_user_info_claims", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "revoked", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "confirmation", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "session_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reference_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refresh_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "scopes", + "entityType": "columns", + "schema": "public", + "table": "oauth_access_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_discovery_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "client_credentials_scopes", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "backchannel_logout_uri", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "backchannel_logout_session_required", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "application_type", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "jwks", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "jwks_uri", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "dpop_bound_access_tokens", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_secret", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "disabled", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "skip_consent", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "enable_end_session", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "subject_type", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "scopes", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "uri", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "icon", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "contacts", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "tos", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "policy", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "software_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "software_version", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "software_statement", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "redirect_uris", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "post_logout_redirect_uris", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token_endpoint_auth_method", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "grant_types", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "response_types", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "public", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "require_pkce", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reference_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "oauth_client" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_assertion" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_assertion" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resource_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "resources", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "requested_user_info_claims", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reference_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "scopes", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_consent" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "authorization_code_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "resources", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "requested_user_info_claims", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "rotated_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "rotation_replay_response", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "rotation_replay_expires_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "confirmation", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "client_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "session_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reference_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "revoked", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "auth_time", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "scopes", + "entityType": "columns", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "identifier", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "access_token_ttl", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refresh_token_ttl", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "signing_algorithm", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "signing_key_id", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 1, + "default": null, + "generated": null, + "identity": null, + "name": "allowed_scopes", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "custom_claims", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "dpop_bound_access_tokens_required", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "disabled", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "policy_version", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "oauth_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "aaguid", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "public_key", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "credential_id", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "counter", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "device_type", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "backed_up", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "transports", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "passkey" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ip_address", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_agent", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "impersonated_by", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "secret", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "backup_codes", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "verified", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "failed_verification_count", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "locked_until", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "image", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "email_verified", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "username", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "display_username", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "two_factor_enabled", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_active_at", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "'user'", + "generated": null, + "identity": null, + "name": "role", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "banned", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ban_reason", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp(6) with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ban_expires", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "identifier", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "recipient", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "style", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "source_resume_id", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "source_application_id", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "tags", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "is_locked", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "trashed_at", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "revision", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "cover_letter" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 1, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "tags", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "is_public", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "show_download_buttons", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "is_locked", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "password", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "application_id", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "trashed_at", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "auto_name", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "data", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "resume" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_id", + "entityType": "columns", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "views", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "downloads", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_viewed_at", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_downloaded_at", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_id", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "date", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "date", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "views", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "downloads", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_id", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resume_id", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "data", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "label", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'auto'", + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "session_id", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "resume_version" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "thread_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "created_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_actions_thread_id_created_at_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_actions_resume_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "message_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_actions_message_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "thread_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_attachments_thread_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_attachments" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "message_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_attachments_message_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_attachments" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_attachments_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_attachments" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "thread_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "sequence", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_messages_thread_id_sequence_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_messages" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "created_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_messages_user_id_created_at_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_messages" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "status", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "last_message_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_threads_user_id_status_last_message_at_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "working_resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_threads_working_resume_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "ai_provider_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_threads_ai_provider_id_index", + "entityType": "indexes", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "working_resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "source_resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"status\" = 'active' and \"deleted_at\" is null", + "with": "", + "method": "btree", + "concurrently": false, + "name": "agent_threads_active_in_place_unique", + "entityType": "indexes", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "enabled", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "ai_providers_user_id_enabled_index", + "entityType": "indexes", + "schema": "public", + "table": "ai_providers" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "last_used_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "ai_providers_user_id_last_used_at_index", + "entityType": "indexes", + "schema": "public", + "table": "ai_providers" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "created_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "ai_providers_user_id_created_at_index", + "entityType": "indexes", + "schema": "public", + "table": "ai_providers" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "application_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "application" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "updated_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "application_user_id_updated_at_index", + "entityType": "indexes", + "schema": "public", + "table": "application" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "account_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "account" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "reference_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "apikey_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "apikey" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "apikey_key_index", + "entityType": "indexes", + "schema": "public", + "table": "apikey" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "config_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "apikey_config_id_index", + "entityType": "indexes", + "schema": "public", + "table": "apikey" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "enabled", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "reference_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "apikey_enabled_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "apikey" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "token", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_access_token_token_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_access_token" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "client_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_client_client_id_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_client" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "client_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_client_resource_client_id_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "resource_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_client_resource_resource_id_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "client_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "resource_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_client_resource_client_id_resource_id_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "client_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_consent_user_id_client_id_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_consent" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "token", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "oauth_refresh_token_token_index", + "entityType": "indexes", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "passkey_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "passkey" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "token", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "session_token_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "session" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "expires_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "session_expires_at_index", + "entityType": "indexes", + "schema": "public", + "table": "session" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "two_factor_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "two_factor" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "secret", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "two_factor_secret_index", + "entityType": "indexes", + "schema": "public", + "table": "two_factor" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "created_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "user_created_at_index", + "entityType": "indexes", + "schema": "public", + "table": "user" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "lower(\"email\")", + "isExpression": true, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "user_email_lower_unique_idx", + "entityType": "indexes", + "schema": "public", + "table": "user" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "identifier", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "verification_identifier_index", + "entityType": "indexes", + "schema": "public", + "table": "verification" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "updated_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "cover_letter_user_id_updated_at_id_index", + "entityType": "indexes", + "schema": "public", + "table": "cover_letter" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "created_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_created_at_index", + "entityType": "indexes", + "schema": "public", + "table": "resume" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "updated_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_user_id_updated_at_index", + "entityType": "indexes", + "schema": "public", + "table": "resume" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "is_public", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_is_public_slug_user_id_index", + "entityType": "indexes", + "schema": "public", + "table": "resume" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_slug_redirect_resume_id_index", + "entityType": "indexes", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "date", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_statistics_daily_resume_id_date_index", + "entityType": "indexes", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "nameExplicit": false, + "columns": [ + { + "value": "resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "created_at", + "isExpression": false, + "asc": false, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_version_resume_id_created_at_index", + "entityType": "indexes", + "schema": "public", + "table": "resume_version" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "resume_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "session_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"kind\" = 'auto'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "resume_version_session_unique", + "entityType": "indexes", + "schema": "public", + "table": "resume_version" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_actions_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": ["thread_id"], + "schemaTo": "public", + "tableTo": "agent_threads", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_actions_thread_id_agent_threads_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": ["message_id"], + "schemaTo": "public", + "tableTo": "agent_messages", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "agent_actions_message_id_agent_messages_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "agent_actions_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_actions" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_attachments_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_attachments" + }, + { + "nameExplicit": false, + "columns": ["thread_id"], + "schemaTo": "public", + "tableTo": "agent_threads", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_attachments_thread_id_agent_threads_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_attachments" + }, + { + "nameExplicit": false, + "columns": ["message_id"], + "schemaTo": "public", + "tableTo": "agent_messages", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "agent_attachments_message_id_agent_messages_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_attachments" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_messages_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_messages" + }, + { + "nameExplicit": false, + "columns": ["thread_id"], + "schemaTo": "public", + "tableTo": "agent_threads", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_messages_thread_id_agent_threads_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_messages" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "agent_threads_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": ["ai_provider_id"], + "schemaTo": "public", + "tableTo": "ai_providers", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "agent_threads_ai_provider_id_ai_providers_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": ["source_resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "agent_threads_source_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": ["working_resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "agent_threads_working_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "agent_threads" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "ai_providers_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "ai_providers" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "application_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "application" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "application_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "application" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "account_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "account" + }, + { + "nameExplicit": false, + "columns": ["reference_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "apikey_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "apikey" + }, + { + "nameExplicit": false, + "columns": ["client_id"], + "schemaTo": "public", + "tableTo": "oauth_client", + "columnsTo": ["client_id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_access_token_client_id_oauth_client_client_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_access_token" + }, + { + "nameExplicit": false, + "columns": ["session_id"], + "schemaTo": "public", + "tableTo": "session", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "oauth_access_token_session_id_session_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_access_token" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_access_token_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_access_token" + }, + { + "nameExplicit": false, + "columns": ["refresh_id"], + "schemaTo": "public", + "tableTo": "oauth_refresh_token", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_access_token_refresh_id_oauth_refresh_token_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_access_token" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_client_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_client" + }, + { + "nameExplicit": false, + "columns": ["client_id"], + "schemaTo": "public", + "tableTo": "oauth_client", + "columnsTo": ["client_id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_client_resource_client_id_oauth_client_client_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "nameExplicit": false, + "columns": ["resource_id"], + "schemaTo": "public", + "tableTo": "oauth_resource", + "columnsTo": ["identifier"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_client_resource_dn2L1gs9Dolm_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_client_resource" + }, + { + "nameExplicit": false, + "columns": ["client_id"], + "schemaTo": "public", + "tableTo": "oauth_client", + "columnsTo": ["client_id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_consent_client_id_oauth_client_client_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_consent" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_consent_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_consent" + }, + { + "nameExplicit": false, + "columns": ["client_id"], + "schemaTo": "public", + "tableTo": "oauth_client", + "columnsTo": ["client_id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_refresh_token_client_id_oauth_client_client_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "nameExplicit": false, + "columns": ["session_id"], + "schemaTo": "public", + "tableTo": "session", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "oauth_refresh_token_session_id_session_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "oauth_refresh_token_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "oauth_refresh_token" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "passkey_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "passkey" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "session_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "session" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "two_factor_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "two_factor" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "cover_letter_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "cover_letter" + }, + { + "nameExplicit": false, + "columns": ["source_resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "cover_letter_source_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "cover_letter" + }, + { + "nameExplicit": false, + "columns": ["source_application_id"], + "schemaTo": "public", + "tableTo": "application", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "cover_letter_source_application_id_application_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "cover_letter" + }, + { + "nameExplicit": false, + "columns": ["application_id"], + "schemaTo": "public", + "tableTo": "application", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "resume_application_id_application_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_slug_redirect_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_slug_redirect_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_statistics_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume_statistics" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_statistics_daily_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "schemaTo": "public", + "tableTo": "resume", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_version_resume_id_resume_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume_version" + }, + { + "nameExplicit": false, + "columns": ["user_id"], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": ["id"], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "resume_version_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "resume_version" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "agent_actions_pkey", + "schema": "public", + "table": "agent_actions", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "agent_attachments_pkey", + "schema": "public", + "table": "agent_attachments", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "agent_messages_pkey", + "schema": "public", + "table": "agent_messages", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "agent_threads_pkey", + "schema": "public", + "table": "agent_threads", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "ai_providers_pkey", + "schema": "public", + "table": "ai_providers", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "application_pkey", + "schema": "public", + "table": "application", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "account_pkey", + "schema": "public", + "table": "account", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "apikey_pkey", + "schema": "public", + "table": "apikey", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "jwks_pkey", + "schema": "public", + "table": "jwks", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_access_token_pkey", + "schema": "public", + "table": "oauth_access_token", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_client_pkey", + "schema": "public", + "table": "oauth_client", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_client_assertion_pkey", + "schema": "public", + "table": "oauth_client_assertion", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_client_resource_pkey", + "schema": "public", + "table": "oauth_client_resource", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_consent_pkey", + "schema": "public", + "table": "oauth_consent", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_refresh_token_pkey", + "schema": "public", + "table": "oauth_refresh_token", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "oauth_resource_pkey", + "schema": "public", + "table": "oauth_resource", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "passkey_pkey", + "schema": "public", + "table": "passkey", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "session_pkey", + "schema": "public", + "table": "session", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "two_factor_pkey", + "schema": "public", + "table": "two_factor", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "user_pkey", + "schema": "public", + "table": "user", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "verification_pkey", + "schema": "public", + "table": "verification", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "cover_letter_pkey", + "schema": "public", + "table": "cover_letter", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "resume_pkey", + "schema": "public", + "table": "resume", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "resume_slug_redirect_pkey", + "schema": "public", + "table": "resume_slug_redirect", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "resume_statistics_pkey", + "schema": "public", + "table": "resume_statistics", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "resume_statistics_daily_pkey", + "schema": "public", + "table": "resume_statistics_daily", + "entityType": "pks" + }, + { + "columns": ["id"], + "nameExplicit": false, + "name": "resume_version_pkey", + "schema": "public", + "table": "resume_version", + "entityType": "pks" + }, + { + "nameExplicit": false, + "columns": ["slug", "user_id"], + "nullsNotDistinct": false, + "name": "resume_slug_user_id_unique", + "entityType": "uniques", + "schema": "public", + "table": "resume" + }, + { + "nameExplicit": false, + "columns": ["user_id", "slug"], + "nullsNotDistinct": false, + "name": "resume_slug_redirect_user_id_slug_unique", + "entityType": "uniques", + "schema": "public", + "table": "resume_slug_redirect" + }, + { + "nameExplicit": false, + "columns": ["resume_id", "date"], + "nullsNotDistinct": false, + "name": "resume_statistics_daily_resume_id_date_unique", + "entityType": "uniques", + "schema": "public", + "table": "resume_statistics_daily" + }, + { + "nameExplicit": false, + "columns": ["token"], + "nullsNotDistinct": false, + "name": "oauth_access_token_token_key", + "schema": "public", + "table": "oauth_access_token", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["client_id"], + "nullsNotDistinct": false, + "name": "oauth_client_client_id_key", + "schema": "public", + "table": "oauth_client", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["identifier"], + "nullsNotDistinct": false, + "name": "oauth_resource_identifier_key", + "schema": "public", + "table": "oauth_resource", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["token"], + "nullsNotDistinct": false, + "name": "session_token_key", + "schema": "public", + "table": "session", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["email"], + "nullsNotDistinct": false, + "name": "user_email_key", + "schema": "public", + "table": "user", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["username"], + "nullsNotDistinct": false, + "name": "user_username_key", + "schema": "public", + "table": "user", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["display_username"], + "nullsNotDistinct": false, + "name": "user_display_username_key", + "schema": "public", + "table": "user", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["identifier"], + "nullsNotDistinct": false, + "name": "verification_identifier_key", + "schema": "public", + "table": "verification", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": ["resume_id"], + "nullsNotDistinct": false, + "name": "resume_statistics_resume_id_key", + "schema": "public", + "table": "resume_statistics", + "entityType": "uniques" + } + ], + "renames": [] +} diff --git a/packages/api/src/dto/documents.ts b/packages/api/src/dto/documents.ts new file mode 100644 index 000000000..c049ceb9e --- /dev/null +++ b/packages/api/src/dto/documents.ts @@ -0,0 +1,66 @@ +import z from "zod"; + +const documentTypeSchema = z.enum(["resume", "letter"]).describe("resume, or letter (a saved cover letter)."); +const documentRefSchema = z.object({ + type: documentTypeSchema, + id: z.string().min(1).describe("The ID of the resume or cover letter."), +}); + +const documentSchema = z.object({ + type: documentTypeSchema, + id: z.string(), + name: z.string(), + tags: z.array(z.string()), + isLocked: z.boolean(), + trashedAt: z.date().nullable().describe("When the document moved to Trash; null while it's live."), + createdAt: z.date(), + updatedAt: z.date(), + application: z + .object({ id: z.string(), company: z.string(), role: z.string() }) + .nullable() + .describe("The job application this document was made for, if any."), +}); + +export type DocumentSummary = z.infer; + +export const documentsDto = { + list: { + input: z + .object({ trashed: z.boolean().default(false).describe("List the documents in Trash instead.") }) + .default({ trashed: false }), + output: z.array(documentSchema), + }, + counts: { + input: z.void(), + output: z.object({ resume: z.number(), letter: z.number(), trash: z.number() }), + }, + rename: { + input: documentRefSchema.extend({ name: z.string().trim().min(1).max(100) }), + output: z.void(), + }, + setTags: { + input: documentRefSchema.extend({ tags: z.array(z.string().trim().min(1).max(40)).max(20) }), + output: z.void(), + }, + setLocked: { + input: documentRefSchema.extend({ isLocked: z.boolean() }), + output: z.void(), + }, + linkApplication: { + input: documentRefSchema.extend({ + applicationId: z.string().min(1).nullable().describe("The application to link, or null to unlink."), + }), + output: z.void(), + }, + trash: { input: documentRefSchema, output: z.void() }, + restore: { input: documentRefSchema, output: z.void() }, + purge: { input: documentRefSchema, output: z.void() }, + copyForJob: { + input: z.object({ + resumeId: z.string().min(1).describe("The resume to copy."), + applicationId: z.string().min(1).optional().describe("The job the copy is for; omit for no job yet."), + name: z.string().trim().min(1).max(100).optional().describe("Defaults to “{source} — {company}”."), + }), + output: z.string().describe("The ID of the copy."), + }, +}; diff --git a/packages/api/src/dto/resume.ts b/packages/api/src/dto/resume.ts index 903dfe309..1185cf3b7 100644 --- a/packages/api/src/dto/resume.ts +++ b/packages/api/src/dto/resume.ts @@ -18,7 +18,10 @@ const resumeSchema = createSelectSchema(schema.resume, { userId: z.string().describe("The ID of the user who owns the resume."), createdAt: z.date().describe("The date and time the resume was created."), updatedAt: z.date().describe("The date and time the resume was last updated."), -}); +}) + // Document-library columns (Trash, the application a copy was made for, automatic naming) stay internal to + // the documents API. + .omit({ applicationId: true, trashedAt: true, autoName: true }); const versionSchema = z.object({ id: z.string().describe("The ID of the version."), @@ -62,6 +65,10 @@ export const resumeDto = { create: { input: resumeSchema.pick({ name: true, tags: true }).extend({ + autoName: z + .boolean() + .optional() + .describe("While true, the resume's name follows its headline until someone renames it."), slug: resumeSchema.shape.slug .optional() .describe("The slug of the resume. Generated from the name, and made unique, when omitted."), diff --git a/packages/api/src/features/cover-letters/router.ts b/packages/api/src/features/cover-letters/router.ts index 425432363..affca4fdb 100644 --- a/packages/api/src/features/cover-letters/router.ts +++ b/packages/api/src/features/cover-letters/router.ts @@ -88,9 +88,10 @@ export const coverLettersRouter = { path: "/cover-letters/{id}", tags: ["Cover Letters"], operationId: "deleteCoverLetter", - summary: "Delete a cover letter", - description: "Permanently deletes a saved cover letter using its expected revision.", - successDescription: "The cover letter was deleted successfully.", + summary: "Move a cover letter to Trash", + description: + "Moves a saved cover letter to Trash using its expected revision. It stays there for 30 days, then it is deleted; until then it can be restored (documents.restore) or deleted at once (documents.purge). Locked letters can't be moved.", + successDescription: "The cover letter is in Trash.", }) .input(coverLetterDto.delete.input) .output(coverLetterDto.delete.output) diff --git a/packages/api/src/features/cover-letters/service.ts b/packages/api/src/features/cover-letters/service.ts index 0e0b18bfd..630649acf 100644 --- a/packages/api/src/features/cover-letters/service.ts +++ b/packages/api/src/features/cover-letters/service.ts @@ -2,7 +2,7 @@ import type { CoverLetter, CoverLetterDocument, CoverLetterStyle } from "@reacti import type { Template } from "@reactive-resume/schema/templates"; import type { CoverLetterListInput, CoverLetterUpdateInput } from "../../dto/cover-letter"; import { ORPCError } from "@orpc/client"; -import { and, count, desc, eq, ilike, sql } from "drizzle-orm"; +import { and, count, desc, eq, ilike, isNull, sql } from "drizzle-orm"; import { db } from "@reactive-resume/db/client"; import * as schema from "@reactive-resume/db/schema"; import { copyCoverLetterStyle } from "@reactive-resume/resume/cover-letter"; @@ -89,18 +89,29 @@ async function updateRevision( eq(schema.coverLetter.id, input.id), eq(schema.coverLetter.userId, input.userId), eq(schema.coverLetter.revision, input.expectedRevision), + eq(schema.coverLetter.isLocked, false), ), ) .returning(); if (row) return coverLetterSchema.parse(row); - await getById(input); + await assertUnlocked(input); throw new ORPCError("CONFLICT", { message: "This cover letter changed elsewhere. Reload it before saving again." }); } +/** Locked letters, like locked resumes, can't be edited or moved to Trash. */ +async function assertUnlocked(input: OwnedId) { + const [row] = await db + .select({ isLocked: schema.coverLetter.isLocked }) + .from(schema.coverLetter) + .where(and(eq(schema.coverLetter.id, input.id), eq(schema.coverLetter.userId, input.userId))); + if (!row) throw new ORPCError("NOT_FOUND"); + if (row.isLocked) throw new ORPCError("DOCUMENT_LOCKED", { status: 400, message: "Unlock the letter first." }); +} + export const coverLetterService = { getById, list: async (input: CoverLetterListInput & { userId: string }) => { - const filters = [eq(schema.coverLetter.userId, input.userId)]; + const filters = [eq(schema.coverLetter.userId, input.userId), isNull(schema.coverLetter.trashedAt)]; if (input.resumeId) filters.push(eq(schema.coverLetter.sourceResumeId, input.resumeId)); if (input.applicationId) filters.push(eq(schema.coverLetter.sourceApplicationId, input.applicationId)); if (input.search?.trim()) @@ -155,19 +166,22 @@ export const coverLetterService = { const letter = await getById(input); return insert({ ...letter, userId: input.userId, name: input.name ?? `${letter.name} (copy)`.slice(0, 100) }); }, + /** Moves the letter to Trash (30 days, then deleted); Trash offers Restore and Delete now. */ delete: async (input: RevisionInput): Promise => { const rows = await db - .delete(schema.coverLetter) + .update(schema.coverLetter) + .set({ trashedAt: new Date(), revision: sql`${schema.coverLetter.revision} + 1` }) .where( and( eq(schema.coverLetter.id, input.id), eq(schema.coverLetter.userId, input.userId), eq(schema.coverLetter.revision, input.expectedRevision), + eq(schema.coverLetter.isLocked, false), ), ) .returning({ id: schema.coverLetter.id }); if (rows.length) return; - await getById(input); + await assertUnlocked(input); throw new ORPCError("CONFLICT", { message: "This cover letter changed elsewhere. Reload it before deleting." }); }, copyEmbedded: async (input: { diff --git a/packages/api/src/features/documents/router.ts b/packages/api/src/features/documents/router.ts new file mode 100644 index 000000000..0dfdb2740 --- /dev/null +++ b/packages/api/src/features/documents/router.ts @@ -0,0 +1,161 @@ +import { protectedProcedure } from "../../context"; +import { documentsDto } from "../../dto/documents"; +import { resumeMutationRateLimit } from "../../middleware/rate-limit"; +import { documentsService } from "./service"; + +const route = ( + method: "GET" | "POST", + path: `/${string}`, + operationId: string, + summary: string, + description: string, +) => ({ + method, + path, + tags: ["Documents"], + operationId, + summary, + description: `${description} Requires authentication.`, +}); + +/** Resumes and saved cover letters as one library: list, rename, tag, lock, link, Trash and Copy for a job. */ +export const documentsRouter = { + list: protectedProcedure + .route( + route( + "GET", + "/documents", + "listDocuments", + "List documents", + "Returns the user's resumes and saved cover letters (or those in Trash), newest edit first, with the job application each was made for. Documents in Trash for more than 30 days are deleted first.", + ), + ) + .input(documentsDto.list.input) + .output(documentsDto.list.output) + .handler(({ context, input }) => documentsService.list({ userId: context.user.id, trashed: input.trashed })), + + counts: protectedProcedure + .route( + route( + "GET", + "/documents/counts", + "countDocuments", + "Count documents", + "Counts live resumes and letters, and everything in Trash.", + ), + ) + .output(documentsDto.counts.output) + .handler(({ context }) => documentsService.counts({ userId: context.user.id })), + + rename: protectedProcedure + .route(route("POST", "/documents/rename", "renameDocument", "Rename a document", "Renames a resume or letter.")) + .input(documentsDto.rename.input) + .use(resumeMutationRateLimit) + .output(documentsDto.rename.output) + .handler(({ context, input }) => documentsService.rename({ ...input, userId: context.user.id })), + + setTags: protectedProcedure + .route( + route( + "POST", + "/documents/tags", + "setDocumentTags", + "Set a document's tags", + "Replaces a resume's or letter's tags.", + ), + ) + .input(documentsDto.setTags.input) + .use(resumeMutationRateLimit) + .output(documentsDto.setTags.output) + .handler(({ context, input }) => documentsService.setTags({ ...input, userId: context.user.id })), + + setLocked: protectedProcedure + .route( + route( + "POST", + "/documents/lock", + "lockDocument", + "Lock or unlock a document", + "Locks a resume or letter against edits and Trash, or unlocks it.", + ), + ) + .input(documentsDto.setLocked.input) + .use(resumeMutationRateLimit) + .output(documentsDto.setLocked.output) + .handler(({ context, input }) => documentsService.setLocked({ ...input, userId: context.user.id })), + + linkApplication: protectedProcedure + .route( + route( + "POST", + "/documents/application", + "linkDocumentApplication", + "Link a document to an application", + "Records the job application a resume or letter was made for, or clears it.", + ), + ) + .input(documentsDto.linkApplication.input) + .use(resumeMutationRateLimit) + .output(documentsDto.linkApplication.output) + .handler(({ context, input }) => documentsService.linkApplication({ ...input, userId: context.user.id })), + + trash: protectedProcedure + .route( + route( + "POST", + "/documents/trash", + "trashDocument", + "Move a document to Trash", + "Moves a resume or letter to Trash, where it stays for 30 days. A resume in Trash isn't shared. Locked documents can't be moved.", + ), + ) + .input(documentsDto.trash.input) + .use(resumeMutationRateLimit) + .output(documentsDto.trash.output) + .handler(({ context, input }) => documentsService.trash({ ...input, userId: context.user.id })), + + restore: protectedProcedure + .route( + route( + "POST", + "/documents/restore", + "restoreDocument", + "Restore a document", + "Brings a document back from Trash.", + ), + ) + .input(documentsDto.restore.input) + .use(resumeMutationRateLimit) + .output(documentsDto.restore.output) + .handler(({ context, input }) => documentsService.restore({ ...input, userId: context.user.id })), + + purge: protectedProcedure + .route( + route( + "POST", + "/documents/purge", + "purgeDocument", + "Delete a document now", + "Permanently deletes a document that is already in Trash.", + ), + ) + .input(documentsDto.purge.input) + .use(resumeMutationRateLimit) + .output(documentsDto.purge.output) + .handler(({ context, input }) => documentsService.purge({ ...input, userId: context.user.id })), + + copyForJob: protectedProcedure + .route( + route( + "POST", + "/documents/copy-for-job", + "copyResumeForJob", + "Copy a resume for a job", + "Duplicates a resume and links the copy to a job application; the application gets the copy if it has no resume yet.", + ), + ) + .input(documentsDto.copyForJob.input) + .use(resumeMutationRateLimit) + .output(documentsDto.copyForJob.output) + .handler(({ context, input }) => documentsService.copyForJob({ ...input, userId: context.user.id })), +}; diff --git a/packages/api/src/features/documents/service.test.ts b/packages/api/src/features/documents/service.test.ts new file mode 100644 index 000000000..4f504220e --- /dev/null +++ b/packages/api/src/features/documents/service.test.ts @@ -0,0 +1,161 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const dbMock = vi.hoisted(() => ({ select: vi.fn(), update: vi.fn(), delete: vi.fn() })); +const resumeServiceMock = vi.hoisted(() => ({ + getById: vi.fn(), + create: vi.fn(), + delete: vi.fn(), + setLocked: vi.fn(), +})); +vi.mock("@reactive-resume/db/client", () => ({ db: dbMock })); +vi.mock("../resume/service", () => ({ resumeService: resumeServiceMock })); + +const { documentsService, suggestCopyName } = await import("./service"); + +// `select().from().where()` (optionally `.leftJoin()` first) resolving to `rows`. +const rows = (result: unknown[]) => { + const where = () => Promise.resolve(result); + return { from: () => ({ where, leftJoin: () => ({ where }) }) }; +}; + +const updates = () => { + const set = vi.fn((_changes: Record) => ({ + where: () => Object.assign(Promise.resolve(), { returning: async () => [{ id: "x" }] }), + })); + dbMock.update.mockReturnValue({ set }); + return set; +}; + +beforeEach(() => { + for (const mock of [...Object.values(dbMock), ...Object.values(resumeServiceMock)]) mock.mockReset(); + dbMock.delete.mockReturnValue({ where: async () => undefined }); +}); + +describe("suggestCopyName", () => { + it("uses the source's base name and the company, or marks a plain copy", () => { + expect(suggestCopyName("Product Designer — Lumen", "Orbital")).toBe("Product Designer — Orbital"); + expect(suggestCopyName("Product Designer")).toBe("Product Designer (copy)"); + }); +}); + +describe("Trash", () => { + it("won't move a locked document, and keeps the resume's error code", async () => { + dbMock.select.mockReturnValueOnce(rows([{ isLocked: true, trashedAt: null }])); + + await expect(documentsService.trash({ userId: "u1", type: "resume", id: "r1" })).rejects.toMatchObject({ + code: "RESUME_LOCKED", + }); + expect(dbMock.update).not.toHaveBeenCalled(); + }); + + it("moves an unlocked letter to Trash and moves its revision on", async () => { + dbMock.select.mockReturnValueOnce(rows([{ isLocked: false, trashedAt: null }])); + const set = updates(); + + await documentsService.trash({ userId: "u1", type: "letter", id: "l1" }); + + expect(set).toHaveBeenCalledWith( + expect.objectContaining({ trashedAt: expect.any(Date), revision: expect.anything() }), + ); + }); + + it("deletes for good only what is already in Trash", async () => { + dbMock.select.mockReturnValueOnce(rows([{ isLocked: false, trashedAt: null }])); + await expect(documentsService.purge({ userId: "u1", type: "resume", id: "r1" })).rejects.toMatchObject({ + code: "BAD_REQUEST", + }); + + dbMock.select.mockReturnValueOnce(rows([{ isLocked: false, trashedAt: new Date() }])); + await documentsService.purge({ userId: "u1", type: "resume", id: "r1" }); + expect(resumeServiceMock.delete).toHaveBeenCalledWith({ id: "r1", userId: "u1" }); + }); +}); + +describe("list", () => { + it("purges documents trashed over 30 days ago, then merges resumes and letters by last edit", async () => { + const day = (n: number) => new Date(2026, 8, n); + dbMock.select + // Expired Trash: one old resume, no letters. + .mockReturnValueOnce(rows([{ id: "old" }])) + .mockReturnValueOnce(rows([])) + // The live documents. + .mockReturnValueOnce( + rows([ + { + id: "r1", + name: "Resume", + tags: [], + isLocked: false, + trashedAt: null, + createdAt: day(1), + updatedAt: day(2), + applicationId: "a1", + company: "Lumen", + role: "Designer", + }, + ]), + ) + .mockReturnValueOnce( + rows([ + { + id: "l1", + name: "Letter", + tags: [], + isLocked: false, + trashedAt: null, + createdAt: day(1), + updatedAt: day(5), + applicationId: null, + company: null, + role: null, + }, + ]), + ); + + const documents = await documentsService.list({ userId: "u1", trashed: false }); + + expect(resumeServiceMock.delete).toHaveBeenCalledWith({ id: "old", userId: "u1" }); + expect(documents.map((document) => [document.type, document.id])).toEqual([ + ["letter", "l1"], + ["resume", "r1"], + ]); + expect(documents[1]?.application).toEqual({ id: "a1", company: "Lumen", role: "Designer" }); + expect(documents[0]?.application).toBeNull(); + }); +}); + +describe("copyForJob", () => { + const source = { + name: "Product Designer — Lumen", + tags: ["design"], + data: { metadata: { page: { locale: "en-US" } } }, + }; + + it("links the copy to the job, and gives the job the copy when it has no resume", async () => { + resumeServiceMock.getById.mockResolvedValueOnce(source); + dbMock.select.mockReturnValueOnce(rows([{ id: "a1", company: "Orbital", resumeId: null }])); + resumeServiceMock.create.mockResolvedValueOnce("copy"); + const set = updates(); + + const id = await documentsService.copyForJob({ userId: "u1", resumeId: "r1", applicationId: "a1" }); + + expect(id).toBe("copy"); + expect(resumeServiceMock.create).toHaveBeenCalledWith( + expect.objectContaining({ name: "Product Designer — Orbital", tags: ["design"] }), + ); + expect(set).toHaveBeenCalledWith({ applicationId: "a1" }); + expect(set).toHaveBeenCalledWith({ resumeId: "copy" }); + }); + + it("leaves an application's existing resume alone", async () => { + resumeServiceMock.getById.mockResolvedValueOnce(source); + dbMock.select.mockReturnValueOnce(rows([{ id: "a1", company: "Orbital", resumeId: "base" }])); + resumeServiceMock.create.mockResolvedValueOnce("copy"); + const set = updates(); + + await documentsService.copyForJob({ userId: "u1", resumeId: "r1", applicationId: "a1", name: "Mine" }); + + expect(resumeServiceMock.create).toHaveBeenCalledWith(expect.objectContaining({ name: "Mine" })); + expect(set).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/api/src/features/documents/service.ts b/packages/api/src/features/documents/service.ts new file mode 100644 index 000000000..1164fa38a --- /dev/null +++ b/packages/api/src/features/documents/service.ts @@ -0,0 +1,251 @@ +import type { DocumentSummary } from "../../dto/documents"; +import { ORPCError } from "@orpc/client"; +import { and, count, eq, isNotNull, isNull, lt, sql } from "drizzle-orm"; +import { db } from "@reactive-resume/db/client"; +import * as schema from "@reactive-resume/db/schema"; +import { resumeService } from "../resume/service"; + +type DocumentType = DocumentSummary["type"]; +type DocumentRef = { userId: string; type: DocumentType; id: string }; + +// Trash keeps documents this long before deleting them for good. +const TRASH_RETENTION_MS = 30 * 24 * 60 * 60 * 1000; + +// Resumes keep their existing error code, which API and MCP clients already handle. +const locked = (type: DocumentType) => + type === "resume" + ? new ORPCError("RESUME_LOCKED") + : new ORPCError("DOCUMENT_LOCKED", { status: 400, message: "Unlock the letter first." }); + +/** "{source} — {company}" for a copy made for a job, "{source} (copy)" without one. */ +export function suggestCopyName(sourceName: string, company?: string) { + const base = sourceName.split(" — ")[0]?.trim() || sourceName; + return (company ? `${base} — ${company}` : `${base} (copy)`).slice(0, 100); +} + +async function assertOwnedApplication(userId: string, applicationId: string) { + const [application] = await db + .select({ id: schema.application.id, company: schema.application.company, resumeId: schema.application.resumeId }) + .from(schema.application) + .where(and(eq(schema.application.id, applicationId), eq(schema.application.userId, userId))); + + if (!application) throw new ORPCError("NOT_FOUND", { message: "Application not found." }); + return application; +} + +/** A resume's or letter's row in its own table, scoped to its owner. */ +const owned = ({ type, id, userId }: DocumentRef) => + type === "resume" + ? and(eq(schema.resume.id, id), eq(schema.resume.userId, userId)) + : and(eq(schema.coverLetter.id, id), eq(schema.coverLetter.userId, userId)); + +type ResumeChanges = Partial; +type LetterChanges = Partial; + +/** The same change to either table; `letter` differs only where the columns do (the linked application). */ +async function update(ref: DocumentRef, resume: ResumeChanges, letter: LetterChanges = resume as LetterChanges) { + const rows = + ref.type === "resume" + ? await db.update(schema.resume).set(resume).where(owned(ref)).returning({ id: schema.resume.id }) + : await db + .update(schema.coverLetter) + // Letters carry a revision for their editor's optimistic saves; any change moves it on. + .set({ ...letter, revision: sql`${schema.coverLetter.revision} + 1` }) + .where(owned(ref)) + .returning({ id: schema.coverLetter.id }); + + if (rows.length === 0) throw new ORPCError("NOT_FOUND"); +} + +async function readState(ref: DocumentRef) { + const [row] = + ref.type === "resume" + ? await db + .select({ isLocked: schema.resume.isLocked, trashedAt: schema.resume.trashedAt }) + .from(schema.resume) + .where(owned(ref)) + : await db + .select({ isLocked: schema.coverLetter.isLocked, trashedAt: schema.coverLetter.trashedAt }) + .from(schema.coverLetter) + .where(owned(ref)); + + if (!row) throw new ORPCError("NOT_FOUND"); + return row; +} + +/** Deletes for good: resumes through their own path (storage too), letters directly. */ +async function deleteForGood(ref: DocumentRef) { + if (ref.type === "resume") return resumeService.delete({ id: ref.id, userId: ref.userId }); + await db.delete(schema.coverLetter).where(owned(ref)); +} + +/** Documents trashed more than 30 days ago go for good. It runs when the user lists documents, so no scheduler. */ +async function purgeExpired(userId: string) { + const cutoff = new Date(Date.now() - TRASH_RETENTION_MS); + const [resumes, letters] = await Promise.all([ + db + .select({ id: schema.resume.id }) + .from(schema.resume) + .where(and(eq(schema.resume.userId, userId), lt(schema.resume.trashedAt, cutoff))), + db + .select({ id: schema.coverLetter.id }) + .from(schema.coverLetter) + .where(and(eq(schema.coverLetter.userId, userId), lt(schema.coverLetter.trashedAt, cutoff))), + ]); + + await Promise.allSettled([ + ...resumes.map(({ id }) => deleteForGood({ userId, type: "resume", id })), + ...letters.map(({ id }) => deleteForGood({ userId, type: "letter", id })), + ]); +} + +export const documentsService = { + /** Every live resume and letter (or everything in Trash), newest edit first. The app filters and sorts them. */ + list: async (input: { userId: string; trashed: boolean }): Promise => { + await purgeExpired(input.userId); + + const [resumes, letters] = await Promise.all([ + db + .select({ + id: schema.resume.id, + name: schema.resume.name, + tags: schema.resume.tags, + isLocked: schema.resume.isLocked, + trashedAt: schema.resume.trashedAt, + createdAt: schema.resume.createdAt, + updatedAt: schema.resume.updatedAt, + applicationId: schema.application.id, + company: schema.application.company, + role: schema.application.role, + }) + .from(schema.resume) + .leftJoin(schema.application, eq(schema.resume.applicationId, schema.application.id)) + .where( + and( + eq(schema.resume.userId, input.userId), + input.trashed ? isNotNull(schema.resume.trashedAt) : isNull(schema.resume.trashedAt), + ), + ), + db + .select({ + id: schema.coverLetter.id, + name: schema.coverLetter.name, + tags: schema.coverLetter.tags, + isLocked: schema.coverLetter.isLocked, + trashedAt: schema.coverLetter.trashedAt, + createdAt: schema.coverLetter.createdAt, + updatedAt: schema.coverLetter.updatedAt, + applicationId: schema.application.id, + company: schema.application.company, + role: schema.application.role, + }) + .from(schema.coverLetter) + .leftJoin(schema.application, eq(schema.coverLetter.sourceApplicationId, schema.application.id)) + .where( + and( + eq(schema.coverLetter.userId, input.userId), + input.trashed ? isNotNull(schema.coverLetter.trashedAt) : isNull(schema.coverLetter.trashedAt), + ), + ), + ]); + + const toSummary = + (type: DocumentType) => + ({ applicationId, company, role, ...row }: (typeof resumes)[number]): DocumentSummary => ({ + type, + ...row, + application: applicationId ? { id: applicationId, company: company ?? "", role: role ?? "" } : null, + }); + + return [...resumes.map(toSummary("resume")), ...letters.map(toSummary("letter"))].sort( + (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime(), + ); + }, + + counts: async (input: { userId: string }) => { + const [[resumes], [letters], [trashedResumes], [trashedLetters]] = await Promise.all([ + db + .select({ total: count() }) + .from(schema.resume) + .where(and(eq(schema.resume.userId, input.userId), isNull(schema.resume.trashedAt))), + db + .select({ total: count() }) + .from(schema.coverLetter) + .where(and(eq(schema.coverLetter.userId, input.userId), isNull(schema.coverLetter.trashedAt))), + db + .select({ total: count() }) + .from(schema.resume) + .where(and(eq(schema.resume.userId, input.userId), isNotNull(schema.resume.trashedAt))), + db + .select({ total: count() }) + .from(schema.coverLetter) + .where(and(eq(schema.coverLetter.userId, input.userId), isNotNull(schema.coverLetter.trashedAt))), + ]); + + return { + resume: resumes?.total ?? 0, + letter: letters?.total ?? 0, + trash: (trashedResumes?.total ?? 0) + (trashedLetters?.total ?? 0), + }; + }, + + /** A name typed by hand ends a blank resume's automatic naming. */ + rename: (input: DocumentRef & { name: string }) => + update(input, { name: input.name, autoName: false }, { name: input.name }), + + setTags: (input: DocumentRef & { tags: string[] }) => update(input, { tags: [...new Set(input.tags)] }), + + setLocked: (input: DocumentRef & { isLocked: boolean }) => + input.type === "resume" + ? resumeService.setLocked({ id: input.id, userId: input.userId, isLocked: input.isLocked }) + : update(input, { isLocked: input.isLocked }), + + linkApplication: async (input: DocumentRef & { applicationId: string | null }) => { + if (input.applicationId) await assertOwnedApplication(input.userId, input.applicationId); + await update(input, { applicationId: input.applicationId }, { sourceApplicationId: input.applicationId }); + }, + + /** Undoable: Trash hides the document and stops its public link; Restore brings it back intact. */ + trash: async (input: DocumentRef) => { + const state = await readState(input); + if (state.isLocked) throw locked(input.type); + await update(input, { trashedAt: new Date() }); + }, + + restore: (input: DocumentRef) => update(input, { trashedAt: null }), + + /** "Delete now…": only for documents already in Trash. */ + purge: async (input: DocumentRef) => { + const state = await readState(input); + if (!state.trashedAt) throw new ORPCError("BAD_REQUEST", { message: "Move the document to Trash first." }); + await deleteForGood(input); + }, + + /** Duplicates a resume for a job: the copy is linked to the application, which gets it if it has no resume yet. */ + copyForJob: async (input: { + userId: string; + resumeId: string; + applicationId?: string | undefined; + name?: string | undefined; + }) => { + const source = await resumeService.getById({ id: input.resumeId, userId: input.userId }); + const application = input.applicationId ? await assertOwnedApplication(input.userId, input.applicationId) : null; + + const id = await resumeService.create({ + userId: input.userId, + name: input.name ?? suggestCopyName(source.name, application?.company), + tags: source.tags, + locale: source.data.metadata.page.locale as never, + data: source.data, + }); + + if (application) { + await db.update(schema.resume).set({ applicationId: application.id }).where(eq(schema.resume.id, id)); + if (!application.resumeId) { + await db.update(schema.application).set({ resumeId: id }).where(eq(schema.application.id, application.id)); + } + } + + return id; + }, +}; diff --git a/packages/api/src/features/resume/crud.ts b/packages/api/src/features/resume/crud.ts index 3d68f2390..26c17ecf9 100644 --- a/packages/api/src/features/resume/crud.ts +++ b/packages/api/src/features/resume/crud.ts @@ -2,6 +2,7 @@ import { generateId, generateRandomName } from "@reactive-resume/utils/string"; import { protectedProcedure } from "../../context"; import { resumeDto } from "../../dto/resume"; import { resumeMutationRateLimit } from "../../middleware/rate-limit"; +import { documentsService } from "../documents/service"; import { createResumeData } from "./initial-data"; import { parseStoredResumeData } from "./resume-data-validation"; import { resumeService } from "./service"; @@ -67,6 +68,7 @@ export const crudRouter = { resumeService.create({ name: input.name, ...(input.slug ? { slug: input.slug } : {}), + ...(input.autoName ? { autoName: true } : {}), tags: input.tags, locale: context.locale, userId: context.user.id, @@ -236,13 +238,13 @@ export const crudRouter = { path: "/resumes/{id}", tags: ["Resumes"], operationId: "deleteResume", - summary: "Delete a resume", + summary: "Move a resume to Trash", description: - "Permanently deletes a resume and its associated files (screenshots, PDFs) from storage. Locked resumes cannot be deleted; unlock the resume first. Requires authentication.", - successDescription: "The resume and its associated files were deleted successfully.", + "Moves a resume to Trash, which stops its public link. It stays there for 30 days, then it and its files are deleted; until then it can be restored (documents.restore) or deleted at once (documents.purge). Locked resumes can't be moved; unlock the resume first. Requires authentication.", + successDescription: "The resume is in Trash.", }) .input(resumeDto.delete.input) .use(resumeMutationRateLimit) .output(resumeDto.delete.output) - .handler(({ context, input }) => resumeService.delete({ id: input.id, userId: context.user.id })), + .handler(({ context, input }) => documentsService.trash({ type: "resume", id: input.id, userId: context.user.id })), }; diff --git a/packages/api/src/features/resume/service.test.ts b/packages/api/src/features/resume/service.test.ts index ebb95b063..4c0cef544 100644 --- a/packages/api/src/features/resume/service.test.ts +++ b/packages/api/src/features/resume/service.test.ts @@ -67,6 +67,7 @@ vi.mock("drizzle-orm", () => ({ eq: (...a: unknown[]) => a, gte: (...a: unknown[]) => a, isNotNull: (...a: unknown[]) => a, + isNull: (...a: unknown[]) => a, notInArray: (...a: unknown[]) => a, sql: Object.assign((strings: TemplateStringsArray, ...values: unknown[]) => ({ strings, values }), { join: (values: unknown[]) => values, @@ -513,10 +514,25 @@ describe("update", () => { const { update } = updateHarness({ slug: "Legacy_Slug" }); await resumeService.update({ id: "r1", userId: "u1", name: "Renamed", slug: "Legacy_Slug" }); - expect(update.set).toHaveBeenCalledWith({ name: "Renamed", slug: "Legacy_Slug" }); + // A name typed by hand also ends automatic naming. + expect(update.set).toHaveBeenCalledWith({ name: "Renamed", autoName: false, slug: "Legacy_Slug" }); expect(recordSlugChangeMock).not.toHaveBeenCalled(); }); + it("names a blank resume after its headline until someone renames it", async () => { + const data = structuredClone(defaultResumeData); + data.basics.headline = " Product Designer "; + const select = createLockedSelectChain([{ data: defaultResumeData, isLocked: false, slug: "s", autoName: true }]); + const update = createUpdateChain([{ ...createResumeRow(data), name: "Product Designer" }]); + dbMock.transaction.mockImplementationOnce(async (callback: (tx: unknown) => Promise) => + callback({ select: () => select.chain, update: () => update.chain }), + ); + + await resumeService.update({ id: "r1", userId: "u1", data }); + + expect(update.set).toHaveBeenCalledWith(expect.objectContaining({ name: "Product Designer" })); + }); + it("passes the editing session to the autosave version, and skips it for restores", async () => { updateHarness({ slug: "s" }); await resumeService.update({ id: "r1", userId: "u1", data: defaultResumeData, sessionId: "visit-1" }); diff --git a/packages/api/src/features/resume/service.ts b/packages/api/src/features/resume/service.ts index bc993957a..8c6642a9c 100644 --- a/packages/api/src/features/resume/service.ts +++ b/packages/api/src/features/resume/service.ts @@ -4,7 +4,7 @@ import type { Locale } from "@reactive-resume/utils/locale"; import type { ResumeUpdatedEvent } from "./events"; import { ORPCError } from "@orpc/client"; import { compare, hash } from "bcrypt"; -import { and, arrayContains, asc, desc, eq, gte, isNotNull, sql } from "drizzle-orm"; +import { and, arrayContains, asc, desc, eq, gte, isNotNull, isNull, sql } from "drizzle-orm"; import { get } from "es-toolkit/compat"; import { match } from "ts-pattern"; import { db } from "@reactive-resume/db/client"; @@ -415,6 +415,7 @@ export const resumeService = { .where( and( eq(schema.resume.userId, input.userId), + isNull(schema.resume.trashedAt), match(input.tags.length) .with(0, () => undefined) .otherwise(() => arrayContains(schema.resume.tags, input.tags)), @@ -475,7 +476,7 @@ export const resumeService = { }) .from(schema.resume) .innerJoin(schema.user, eq(schema.resume.userId, schema.user.id)) - .where(and(matchesSlug(input.slug), eq(schema.user.username, input.username))) + .where(and(matchesSlug(input.slug), eq(schema.user.username, input.username), isNull(schema.resume.trashedAt))) // A resume's current slug wins over another's redirect (renames delete clashing redirects anyway). .orderBy(desc(sql`${schema.resume.slug} = ${input.slug}`)) .limit(1); @@ -519,6 +520,8 @@ export const resumeService = { data?: ResumeData; /** The first version in History: "created", or "import" for an imported document. */ origin?: "created" | "import"; + /** The name follows the headline until someone renames the resume. */ + autoName?: boolean; }) => { const id = input.id ?? generateId(); const data = parseWritableResumeData(structuredClone(input.data ?? defaultResumeData)); @@ -529,6 +532,7 @@ export const resumeService = { await db.insert(schema.resume).values({ id, name: input.name, + autoName: input.autoName ?? false, slug, tags: input.tags, userId: input.userId, @@ -581,6 +585,7 @@ export const resumeService = { data: schema.resume.data, slug: schema.resume.slug, isLocked: schema.resume.isLocked, + autoName: schema.resume.autoName, }) .from(schema.resume) .where(and(eq(schema.resume.id, input.id), eq(schema.resume.userId, input.userId))) @@ -606,8 +611,14 @@ export const resumeService = { const normalizedData = input.data ? parseWritableResumeData(input.data, parseStoredResumeData(existing.data)) : undefined; + // A blank resume is named after its headline until someone names it by hand. + const followedName = + existing.autoName && input.name === undefined && normalizedData + ? normalizedData.basics.headline.trim().slice(0, 100) || undefined + : undefined; const updateData: Partial = { - ...(input.name !== undefined ? { name: input.name } : {}), + ...(input.name !== undefined ? { name: input.name, autoName: false } : {}), + ...(followedName ? { name: followedName } : {}), ...(input.slug !== undefined ? { slug: input.slug } : {}), ...(input.tags !== undefined ? { tags: input.tags } : {}), ...(normalizedData ? { data: normalizedData } : {}), @@ -742,7 +753,14 @@ export const resumeService = { .select({ id: schema.resume.id, password: schema.resume.password }) .from(schema.resume) .innerJoin(schema.user, eq(schema.resume.userId, schema.user.id)) - .where(and(isNotNull(schema.resume.password), matchesSlug(input.slug), eq(schema.user.username, input.username))) + .where( + and( + isNotNull(schema.resume.password), + matchesSlug(input.slug), + eq(schema.user.username, input.username), + isNull(schema.resume.trashedAt), + ), + ) .orderBy(desc(sql`${schema.resume.slug} = ${input.slug}`)) .limit(1); diff --git a/packages/api/src/routers/index.ts b/packages/api/src/routers/index.ts index 301ed5709..d66ba8091 100644 --- a/packages/api/src/routers/index.ts +++ b/packages/api/src/routers/index.ts @@ -4,6 +4,7 @@ import { aiProvidersRouter } from "../features/ai-providers/router"; import { applicationsRouter } from "../features/applications/router"; import { authRouter } from "../features/auth/router"; import { coverLettersRouter } from "../features/cover-letters/router"; +import { documentsRouter } from "../features/documents/router"; import { flagsRouter } from "../features/flags/router"; import { resumeRouter } from "../features/resume/router"; import { statisticsRouter } from "../features/statistics/router"; @@ -16,6 +17,7 @@ export default { applications: applicationsRouter, auth: authRouter, coverLetters: coverLettersRouter, + documents: documentsRouter, flags: flagsRouter, resume: resumeRouter, statistics: statisticsRouter, diff --git a/packages/db/src/schema/cover-letter.ts b/packages/db/src/schema/cover-letter.ts index 292ed4fad..3173bcb66 100644 --- a/packages/db/src/schema/cover-letter.ts +++ b/packages/db/src/schema/cover-letter.ts @@ -23,6 +23,10 @@ export const coverLetter = pg.pgTable( style: pg.jsonb("style").$type().notNull(), sourceResumeId: pg.text("source_resume_id").references(() => resume.id, { onDelete: "set null" }), sourceApplicationId: pg.text("source_application_id").references(() => application.id, { onDelete: "set null" }), + tags: pg.text("tags").array().notNull().default([]), + isLocked: pg.boolean("is_locked").notNull().default(false), + // In Trash since this moment; purged after 30 days. + trashedAt: pg.timestamp("trashed_at", { withTimezone: true }), revision: pg.integer("revision").notNull().default(1), createdAt: pg.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: pg diff --git a/packages/db/src/schema/resume.ts b/packages/db/src/schema/resume.ts index 22d754168..0c5528a82 100644 --- a/packages/db/src/schema/resume.ts +++ b/packages/db/src/schema/resume.ts @@ -1,8 +1,10 @@ import type { ResumeData } from "@reactive-resume/schema/resume/data"; +import type { AnyPgColumn } from "drizzle-orm/pg-core"; import { sql } from "drizzle-orm"; import * as pg from "drizzle-orm/pg-core"; import { defaultResumeData } from "@reactive-resume/schema/resume/default"; import { generateId } from "@reactive-resume/utils/string"; +import { application } from "./applications"; import { user } from "./auth"; export const resume = pg.pgTable( @@ -20,6 +22,13 @@ export const resume = pg.pgTable( showDownloadButtons: pg.boolean("show_download_buttons").notNull().default(true), isLocked: pg.boolean("is_locked").notNull().default(false), password: pg.text("password"), + // "Made for this application": Check's job match, the assistant and Copy for a job use its posting. + // Separate from application.resume_id, the resume linked to (or sent with) an application. + applicationId: pg.text("application_id").references((): AnyPgColumn => application.id, { onDelete: "set null" }), + // In Trash since this moment; purged after 30 days. Trashed resumes are hidden and not shared. + trashedAt: pg.timestamp("trashed_at", { withTimezone: true }), + // A blank resume's name follows its headline until the user renames it. + autoName: pg.boolean("auto_name").notNull().default(false), data: pg .jsonb("data") .notNull() diff --git a/packages/mcp/src/tool-meta.ts b/packages/mcp/src/tool-meta.ts index 0d1b6348b..efd41d085 100644 --- a/packages/mcp/src/tool-meta.ts +++ b/packages/mcp/src/tool-meta.ts @@ -329,10 +329,10 @@ export const TOOL_META = { [T.deleteResume]: { title: "Delete Resume", description: [ - "Permanently delete a resume and all its associated files (screenshots, PDFs), removing public access if published.", + "Move a resume to Trash, removing public access if published.", "", - `This action is IRREVERSIBLE. Locked resumes cannot be deleted; use \`${T.unlockResume}\` first.`, - `Consider using \`${T.duplicateResume}\` to create a backup before deleting.`, + "It stays in Trash for 30 days, where the user can restore it from the app; then it and its files are deleted.", + `Locked resumes cannot be moved; use \`${T.unlockResume}\` first.`, ].join("\n"), inputSchema: z.object({ id: resumeIdSchema }), annotations: { ...WRITE_DESTRUCTIVE, openWorldHint: true },