diff --git a/db/migrate/20241002103608_create_search_indexes.rb b/db/migrate/20241002103608_create_search_indexes.rb index 5933ffea3..339ef0213 100644 --- a/db/migrate/20241002103608_create_search_indexes.rb +++ b/db/migrate/20241002103608_create_search_indexes.rb @@ -1,6 +1,7 @@ class CreateSearchIndexes < ActiveRecord::Migration[8.0] def change - create_virtual_table :bubbles_search_index, "fts5", [ "title" ] - create_virtual_table :comments_search_index, "fts5", [ "body" ] + # # TODO:PLANB: need to replace SQLite FTS + # create_virtual_table :bubbles_search_index, "fts5", [ "title" ] + # create_virtual_table :comments_search_index, "fts5", [ "body" ] end end diff --git a/db/migrate/20241009183354_create_events.rb b/db/migrate/20241009183354_create_events.rb index 19c0f66da..269691999 100644 --- a/db/migrate/20241009183354_create_events.rb +++ b/db/migrate/20241009183354_create_events.rb @@ -3,7 +3,7 @@ class CreateEvents < ActiveRecord::Migration[8.0] create_table :events do |t| t.references :bubble, null: false, index: false t.references :creator, null: false - t.json :particulars, default: {} + t.column :particulars, :json, default: -> { '(JSON_OBJECT())' } t.string :action, null: false t.timestamps diff --git a/db/migrate/20241015224007_create_views.rb b/db/migrate/20241015224007_create_views.rb index 2acea70cd..19c4289e4 100644 --- a/db/migrate/20241015224007_create_views.rb +++ b/db/migrate/20241015224007_create_views.rb @@ -3,7 +3,7 @@ class CreateViews < ActiveRecord::Migration[8.0] create_table :bucket_views do |t| t.references :creator, null: false t.references :bucket, null: false - t.json :filters, default: {}, null: false + t.column :filters, :json, default: -> { '(JSON_OBJECT())' }, null: false t.timestamps end diff --git a/db/migrate/20241017202003_make_bucket_view_filters_unique.rb b/db/migrate/20241017202003_make_bucket_view_filters_unique.rb index 41e860cf4..d617464a2 100644 --- a/db/migrate/20241017202003_make_bucket_view_filters_unique.rb +++ b/db/migrate/20241017202003_make_bucket_view_filters_unique.rb @@ -1,6 +1,11 @@ class MakeBucketViewFiltersUnique < ActiveRecord::Migration[8.0] def change - add_index :bucket_views, %i[ bucket_id creator_id filters ], unique: true + # MySQL doesn't support direct indexing of JSON columns. To ensure uniqueness + # of the filters JSON content, we create a generated column that stores a SHA2 + # hash of the JSON data. This allows us to enforce that each creator can only + # have one view per bucket with the same filter configuration. + add_column :bucket_views, :filters_hash, :string, limit: 64, as: "SHA2(filters, 256)", stored: true + add_index :bucket_views, %i[ bucket_id creator_id filters_hash ], unique: true remove_index :bucket_views, :bucket_id end end diff --git a/db/migrate/20241105181312_rename_bucket_views_to_filters.rb b/db/migrate/20241105181312_rename_bucket_views_to_filters.rb index 6e02f2020..6c5381aeb 100644 --- a/db/migrate/20241105181312_rename_bucket_views_to_filters.rb +++ b/db/migrate/20241105181312_rename_bucket_views_to_filters.rb @@ -2,15 +2,19 @@ class RenameBucketViewsToFilters < ActiveRecord::Migration[8.0] def change rename_table :bucket_views, :filters - remove_index :filters, %i[ bucket_id creator_id filters ], unique: true + remove_index :filters, %i[ bucket_id creator_id filters_hash ], unique: true remove_index :filters, :creator_id + remove_column :filters, :filters_hash, :string remove_reference :filters, :bucket rename_column :filters, :filters, :params - add_column :filters, :fields, :jsonb, null: false, default: {} + add_column :filters, :fields, :json, null: false, default: -> { '(JSON_OBJECT())' } - add_index :filters, %i[ creator_id params ], unique: true + # MySQL doesn't support direct indexing of JSON columns. Create a generated + # hash column for the params JSON data to enforce uniqueness. + add_column :filters, :params_hash, :string, limit: 64, as: "SHA2(params, 256)", stored: true + add_index :filters, %i[ creator_id params_hash ], unique: true end end diff --git a/db/migrate/20241108205445_hash_filter_params.rb b/db/migrate/20241108205445_hash_filter_params.rb index 95fb80413..7379e13a9 100644 --- a/db/migrate/20241108205445_hash_filter_params.rb +++ b/db/migrate/20241108205445_hash_filter_params.rb @@ -1,7 +1,10 @@ class HashFilterParams < ActiveRecord::Migration[8.0] def change - change_column_default :filters, :params, from: {}, to: nil - change_column :filters, :params, :string, null: false - rename_column :filters, :params, :params_digest + remove_index :filters, %i[ creator_id params_hash ], unique: true + remove_column :filters, :params_hash + remove_column :filters, :params + + add_column :filters, :params_digest, :string, null: false + add_index :filters, %i[ creator_id params_digest ], unique: true end end diff --git a/db/migrate/20241120222444_make_taggings_unique_per_bubble.rb b/db/migrate/20241120222444_make_taggings_unique_per_bubble.rb index 06edb6170..34797bd11 100644 --- a/db/migrate/20241120222444_make_taggings_unique_per_bubble.rb +++ b/db/migrate/20241120222444_make_taggings_unique_per_bubble.rb @@ -1,6 +1,9 @@ class MakeTaggingsUniquePerBubble < ActiveRecord::Migration[8.0] def change - remove_index :taggings, :bubble_id + # Add the composite index first, then remove the old single-column index. + # MySQL requires an index for foreign key constraints, so we need the new + # composite index in place before removing the old one. add_index :taggings, %i[ bubble_id tag_id ], unique: true + remove_index :taggings, :bubble_id end end diff --git a/db/migrate/20241126193431_create_action_text_markdowns.rb b/db/migrate/20241126193431_create_action_text_markdowns.rb deleted file mode 100644 index 056b037fa..000000000 --- a/db/migrate/20241126193431_create_action_text_markdowns.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateActionTextMarkdowns < ActiveRecord::Migration[8.0] - def change - create_table :action_text_markdowns do |t| - t.references :record, polymorphic: true, null: false - t.string :name, null: false - t.text :content, null: false, default: "" - t.timestamps - end - - add_column :active_storage_attachments, :slug, :string - add_index :active_storage_attachments, :slug, unique: true - end -end diff --git a/db/migrate/20250107165422_add_status_to_bubbles.rb b/db/migrate/20250107165422_add_status_to_bubbles.rb index abe8b481f..06a1eb566 100644 --- a/db/migrate/20250107165422_add_status_to_bubbles.rb +++ b/db/migrate/20250107165422_add_status_to_bubbles.rb @@ -1,5 +1,5 @@ class AddStatusToBubbles < ActiveRecord::Migration[8.1] def change - add_column :bubbles, :status, :text, default: :drafted, null: false + add_column :bubbles, :status, :string, default: "drafted", null: false end end diff --git a/db/migrate/20250117142146_associate_events_with_bubbles.rb b/db/migrate/20250117142146_associate_events_with_bubbles.rb index f855bd5b7..30f824d96 100644 --- a/db/migrate/20250117142146_associate_events_with_bubbles.rb +++ b/db/migrate/20250117142146_associate_events_with_bubbles.rb @@ -4,12 +4,12 @@ class AssociateEventsWithBubbles < ActiveRecord::Migration[8.1] t.references :bubble, foreign_key: true end + # MySQL uses JOIN syntax for multi-table updates, not FROM clause execute " update events - set bubble_id = m.bubble_id - from event_summaries es - join messages m on m.messageable_type = 'EventSummary' and m.messageable_id = es.id - where events.summary_id = es.id + join event_summaries es on events.summary_id = es.id + join messages m on m.messageable_type = 'EventSummary' and m.messageable_id = es.id + set events.bubble_id = m.bubble_id " change_column_null :events, :bubble_id, false diff --git a/db/migrate/20250212103251_add_auto_pop_at_to_bubbles.rb b/db/migrate/20250212103251_add_auto_pop_at_to_bubbles.rb index 39f59c3db..a5483094a 100644 --- a/db/migrate/20250212103251_add_auto_pop_at_to_bubbles.rb +++ b/db/migrate/20250212103251_add_auto_pop_at_to_bubbles.rb @@ -4,15 +4,16 @@ class AddAutoPopAtToBubbles < ActiveRecord::Migration[8.1] t.datetime :auto_pop_at, index: true end + # MySQL uses JOIN syntax for multi-table updates and DATE_ADD for date arithmetic execute " update bubbles - set auto_pop_at = datetime(activity.last_active_at, '+30 days') - from ( - select bubbles.id as bubble_id, coalesce(max(events.created_at), bubbles.created_at) as last_active_at - from bubbles - left join events on bubbles.id = events.bubble_id group by bubbles.id - ) as activity - where bubbles.id = activity.bubble_id + join ( + select bubbles.id as bubble_id, coalesce(max(events.created_at), bubbles.created_at) as last_active_at + from bubbles + left join events on bubbles.id = events.bubble_id + group by bubbles.id + ) as activity on bubbles.id = activity.bubble_id + set bubbles.auto_pop_at = DATE_ADD(activity.last_active_at, INTERVAL 30 DAY) " change_column_null :bubbles, :auto_pop_at, false diff --git a/db/migrate/20250319161627_drop_subscriptions.rb b/db/migrate/20250319161627_drop_subscriptions.rb index 9734075c8..82347e0a7 100644 --- a/db/migrate/20250319161627_drop_subscriptions.rb +++ b/db/migrate/20250319161627_drop_subscriptions.rb @@ -3,10 +3,12 @@ class DropSubscriptions < ActiveRecord::Migration[8.1] execute " update accesses set involvement = 'access_only' " + # MySQL uses JOIN syntax for multi-table updates execute " - update accesses set involvement = 'watching' - from (select user_id, subscribable_id as bucket_id from subscriptions) as subscriptions - where subscriptions.user_id = accesses.user_id and subscriptions.bucket_id = accesses.bucket_id + update accesses + join (select user_id, subscribable_id as bucket_id from subscriptions) as subscriptions + on subscriptions.user_id = accesses.user_id and subscriptions.bucket_id = accesses.bucket_id + set accesses.involvement = 'watching' " drop_table :subscriptions diff --git a/db/migrate/20250404072651_add_last_active_at_to_bubbles.rb b/db/migrate/20250404072651_add_last_active_at_to_bubbles.rb index e49446f30..050b501bd 100644 --- a/db/migrate/20250404072651_add_last_active_at_to_bubbles.rb +++ b/db/migrate/20250404072651_add_last_active_at_to_bubbles.rb @@ -3,15 +3,16 @@ class AddLastActiveAtToBubbles < ActiveRecord::Migration[8.1] add_column :bubbles, :last_active_at, :datetime add_index :bubbles, %i[ last_active_at status ] + # MySQL uses JOIN syntax for multi-table updates execute <<~SQL update bubbles - set last_active_at = activity.last_active_at - from ( - select bubbles.id as bubble_id, coalesce(max(events.created_at), bubbles.created_at) as last_active_at - from bubbles - left join events on bubbles.id = events.bubble_id group by bubbles.id - ) as activity - where bubbles.id = activity.bubble_id + join ( + select bubbles.id as bubble_id, coalesce(max(events.created_at), bubbles.created_at) as last_active_at + from bubbles + left join events on bubbles.id = events.bubble_id + group by bubbles.id + ) as activity on bubbles.id = activity.bubble_id + set bubbles.last_active_at = activity.last_active_at SQL change_column_null :bubbles, :last_active_at, false diff --git a/db/migrate/20250409043626_rename_bubbles_to_cards.rb b/db/migrate/20250409043626_rename_bubbles_to_cards.rb index bdb31e05c..c842bbaf2 100644 --- a/db/migrate/20250409043626_rename_bubbles_to_cards.rb +++ b/db/migrate/20250409043626_rename_bubbles_to_cards.rb @@ -24,30 +24,32 @@ class RenameBubblesToCards < ActiveRecord::Migration[8.1] rename_column "collections_filters", "bucket_id", "collection_id" # Indexes - rename_index "assignments", "index_assignments_on_bubble_id", "index_assignments_on_card_id" - rename_index "card_engagements", "index_bubble_engagements_on_bubble_id", "index_card_engagements_on_card_id" - rename_index "events", "index_events_on_bubble_id", "index_events_on_card_id" - rename_index "messages", "index_messages_on_bubble_id", "index_messages_on_card_id" - rename_index "notifications", "index_notifications_on_bubble_id", "index_notifications_on_card_id" - rename_index "pins", "index_pins_on_bubble_id", "index_pins_on_card_id" - rename_index "pins", "index_pins_on_bubble_id_and_user_id", "index_pins_on_card_id_and_user_id" - rename_index "closures", "index_pops_on_bubble_id", "index_closures_on_card_id" - rename_index "closures", "index_pops_on_bubble_id_and_created_at", "index_closures_on_card_id_and_created_at" - rename_index "watches", "index_watches_on_bubble_id", "index_watches_on_card_id" - rename_index "taggings", "index_taggings_on_bubble_id_and_tag_id", "index_taggings_on_card_id_and_tag_id" + # # No longer necessary in MySQL + # rename_index "assignments", "index_assignments_on_bubble_id", "index_assignments_on_card_id" + # rename_index "card_engagements", "index_bubble_engagements_on_bubble_id", "index_card_engagements_on_card_id" + # rename_index "events", "index_events_on_bubble_id", "index_events_on_card_id" + # rename_index "messages", "index_messages_on_bubble_id", "index_messages_on_card_id" + # rename_index "notifications", "index_notifications_on_bubble_id", "index_notifications_on_card_id" + # rename_index "pins", "index_pins_on_bubble_id", "index_pins_on_card_id" + # rename_index "pins", "index_pins_on_bubble_id_and_user_id", "index_pins_on_card_id_and_user_id" + # rename_index "closures", "index_pops_on_bubble_id", "index_closures_on_card_id" + # rename_index "closures", "index_pops_on_bubble_id_and_created_at", "index_closures_on_card_id_and_created_at" + # rename_index "watches", "index_watches_on_bubble_id", "index_watches_on_card_id" + # rename_index "taggings", "index_taggings_on_bubble_id_and_tag_id", "index_taggings_on_card_id_and_tag_id" - rename_index "accesses", "index_accesses_on_bucket_id", "index_accesses_on_collection_id" - rename_index "accesses", "index_accesses_on_bucket_id_and_user_id", "index_accesses_on_collection_id_and_user_id" - rename_index "collections_filters", "index_buckets_filters_on_bucket_id", "index_collections_filters_on_collection_id" + # rename_index "accesses", "index_accesses_on_bucket_id", "index_accesses_on_collection_id" + # rename_index "accesses", "index_accesses_on_bucket_id_and_user_id", "index_accesses_on_collection_id_and_user_id" + # rename_index "collections_filters", "index_buckets_filters_on_bucket_id", "index_collections_filters_on_collection_id" # Search tables - execute <<~SQL - CREATE VIRTUAL TABLE cards_search_index USING fts5(title); - INSERT INTO cards_search_index(title) SELECT title FROM bubbles_search_index; - SQL + # # TODO:PLANB: need to replace SQLite FTS + # execute <<~SQL + # CREATE VIRTUAL TABLE cards_search_index USING fts5(title); + # INSERT INTO cards_search_index(title) SELECT title FROM bubbles_search_index; + # SQL - execute <<~SQL - DROP TABLE bubbles_search_index; - SQL + # execute <<~SQL + # DROP TABLE bubbles_search_index; + # SQL end end diff --git a/db/migrate/20250505123008_create_commands.rb b/db/migrate/20250505123008_create_commands.rb index 83959e389..ee47da225 100644 --- a/db/migrate/20250505123008_create_commands.rb +++ b/db/migrate/20250505123008_create_commands.rb @@ -3,7 +3,7 @@ class CreateCommands < ActiveRecord::Migration[8.1] create_table :commands do |t| t.references :user, null: false, foreign_key: true, index: true t.string :type - t.json :data, default: {} + t.column :data, :json, default: -> { '(JSON_OBJECT())' } t.timestamps diff --git a/db/migrate/20250601161653_drop_action_text_markdowns.rb b/db/migrate/20250601161653_drop_action_text_markdowns.rb deleted file mode 100644 index 23a972df8..000000000 --- a/db/migrate/20250601161653_drop_action_text_markdowns.rb +++ /dev/null @@ -1,5 +0,0 @@ -class DropActionTextMarkdowns < ActiveRecord::Migration[8.1] - def change - drop_table :action_text_markdowns - end -end diff --git a/db/migrate/20250624055720_add_description_to_cards_search_index.rb b/db/migrate/20250624055720_add_description_to_cards_search_index.rb index a2f77f19a..75c5b4157 100644 --- a/db/migrate/20250624055720_add_description_to_cards_search_index.rb +++ b/db/migrate/20250624055720_add_description_to_cards_search_index.rb @@ -1,8 +1,9 @@ class AddDescriptionToCardsSearchIndex < ActiveRecord::Migration[8.1] def change - execute <<~SQL - DROP TABLE cards_search_index; - SQL - create_virtual_table :cards_search_index, "fts5", [ "title", "description" ] + # # TODO:PLANB: need to replace SQLite FTS + # execute <<~SQL + # DROP TABLE cards_search_index; + # SQL + # create_virtual_table :cards_search_index, "fts5", [ "title", "description" ] end end diff --git a/db/migrate/20250624080408_create_search_queries.rb b/db/migrate/20250624080408_create_search_queries.rb index f5a5a0b6c..574edd941 100644 --- a/db/migrate/20250624080408_create_search_queries.rb +++ b/db/migrate/20250624080408_create_search_queries.rb @@ -6,7 +6,10 @@ class CreateSearchQueries < ActiveRecord::Migration[8.1] t.timestamps - t.index %i[ user_id terms ] + # MySQL has a max key length of 3072 bytes. With utf8mb4 (4 bytes/char), + # we can only index 768 characters. Using a 255 character prefix is + # sufficient for search query lookups while staying well under the limit. + t.index "user_id, terms(255)", name: "index_search_queries_on_user_id_and_terms" end end end diff --git a/db/migrate/20250625111932_add_stemming.rb b/db/migrate/20250625111932_add_stemming.rb index 217a861f2..e1168775d 100644 --- a/db/migrate/20250625111932_add_stemming.rb +++ b/db/migrate/20250625111932_add_stemming.rb @@ -1,9 +1,10 @@ class AddStemming < ActiveRecord::Migration[8.1] def change - drop_table :cards_search_index - drop_table :comments_search_index + # # TODO:PLANB: need to replace SQLite FTS + # drop_table :cards_search_index + # drop_table :comments_search_index - create_virtual_table "cards_search_index", "fts5", [ "title", "description", "tokenize='porter'" ] - create_virtual_table "comments_search_index", "fts5", [ "body", "tokenize='porter'" ] + # create_virtual_table "cards_search_index", "fts5", [ "title", "description", "tokenize='porter'" ] + # create_virtual_table "comments_search_index", "fts5", [ "body", "tokenize='porter'" ] end end diff --git a/db/migrate/20250721110000_create_event_activity_summaries.rb b/db/migrate/20250721110000_create_event_activity_summaries.rb index 0a38dc53f..0209d0d57 100644 --- a/db/migrate/20250721110000_create_event_activity_summaries.rb +++ b/db/migrate/20250721110000_create_event_activity_summaries.rb @@ -3,7 +3,7 @@ class CreateEventActivitySummaries < ActiveRecord::Migration[8.1] create_table :event_activity_summaries do |t| t.string :key, null: false t.text :contents, null: false - t.json :data, default: {} + t.column :data, :json, default: -> { '(JSON_OBJECT())' } t.timestamps diff --git a/db/migrate/20250909113219_create_webhooks.rb b/db/migrate/20250909113219_create_webhooks.rb index 29d952552..f9fc08301 100644 --- a/db/migrate/20250909113219_create_webhooks.rb +++ b/db/migrate/20250909113219_create_webhooks.rb @@ -4,10 +4,13 @@ class CreateWebhooks < ActiveRecord::Migration[8.1] t.boolean :active, default: true, null: false t.string :name t.text :url, null: false - t.text :subscribed_actions, index: true + t.text :subscribed_actions t.string :signing_secret, null: false t.timestamps + + # MySQL requires a prefix length for TEXT column indexes + t.index "subscribed_actions(255)", name: "index_webhooks_on_subscribed_actions" end end end diff --git a/db/migrate/20251015081645_create_account_join_codes.rb b/db/migrate/20251015081645_create_account_join_codes.rb index e603d5805..b7e59100b 100644 --- a/db/migrate/20251015081645_create_account_join_codes.rb +++ b/db/migrate/20251015081645_create_account_join_codes.rb @@ -10,9 +10,10 @@ class CreateAccountJoinCodes < ActiveRecord::Migration[8.1] reversible do |dir| dir.up do + # MySQL uses NOW() instead of SQLite's datetime('now') execute <<-SQL INSERT INTO account_join_codes (code, usage_count, usage_limit, created_at, updated_at) - SELECT join_code, 0, 10, datetime('now'), datetime('now') + SELECT join_code, 0, 10, NOW(), NOW() FROM accounts WHERE join_code IS NOT NULL; SQL diff --git a/db/migrate/20251015170934_move_email_to_identity.rb b/db/migrate/20251015170934_move_email_to_identity.rb index cf9be0120..3b482b54c 100644 --- a/db/migrate/20251015170934_move_email_to_identity.rb +++ b/db/migrate/20251015170934_move_email_to_identity.rb @@ -3,9 +3,10 @@ class MoveEmailToIdentity < ActiveRecord::Migration[8.1] add_column :identities, :email_address, :string # Create identities for each unique email + # MySQL uses NOW() instead of SQLite's datetime('now') execute <<-SQL INSERT INTO identities (email_address, created_at, updated_at) - SELECT DISTINCT email_address, datetime('now'), datetime('now') + SELECT DISTINCT email_address, NOW(), NOW() FROM memberships WHERE email_address IS NOT NULL AND email_address NOT IN (SELECT email_address FROM identities WHERE email_address IS NOT NULL); diff --git a/db/migrate/20251024081104_create_identity_sessions.rb b/db/migrate/20251024081104_create_identity_sessions.rb index 8c81fdcd0..d8eb81342 100644 --- a/db/migrate/20251024081104_create_identity_sessions.rb +++ b/db/migrate/20251024081104_create_identity_sessions.rb @@ -1,14 +1,11 @@ class CreateIdentitySessions < ActiveRecord::Migration[8.2] def change create_table "sessions", force: :cascade do |t| - t.datetime "created_at", null: false + t.references "identity", null: false, foreign_key: true t.string "ip_address" - t.datetime "updated_at", null: false t.string "user_agent" - t.integer "identity_id", null: false - t.index [ "identity_id" ], name: "index_sessions_on_identity_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end - - add_foreign_key "sessions", "identities" end end diff --git a/db/migrate/20251105082803_add_unique_constraint_on_identity_id_and_tenant_to_memberships.rb b/db/migrate/20251105082803_add_unique_constraint_on_identity_id_and_tenant_to_memberships.rb index 5d42ac6ed..b1941065c 100644 --- a/db/migrate/20251105082803_add_unique_constraint_on_identity_id_and_tenant_to_memberships.rb +++ b/db/migrate/20251105082803_add_unique_constraint_on_identity_id_and_tenant_to_memberships.rb @@ -1,13 +1,15 @@ class AddUniqueConstraintOnIdentityIdAndTenantToMemberships < ActiveRecord::Migration[8.2] def change # Remove duplicates, keeping the youngest membership for each identity_id + tenant combination + # MySQL doesn't allow referencing the target table in a subquery, so we use a JOIN approach execute <<-SQL - DELETE FROM memberships - WHERE id NOT IN ( - SELECT MAX(id) + DELETE m1 FROM memberships m1 + LEFT JOIN ( + SELECT MAX(id) as max_id FROM memberships GROUP BY identity_id, tenant - ) + ) m2 ON m1.id = m2.max_id + WHERE m2.max_id IS NULL SQL add_index :memberships, %i[ tenant identity_id ], unique: true diff --git a/db/schema.rb b/db/schema.rb index b1119ac14..8d6a4960d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,20 +11,20 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do - create_table "accesses", force: :cascade do |t| + create_table "accesses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "accessed_at" - t.integer "board_id", null: false + t.bigint "board_id", null: false t.datetime "created_at", null: false t.string "involvement", default: "access_only", null: false t.datetime "updated_at", null: false - t.integer "user_id", null: false + t.bigint "user_id", null: false t.index ["accessed_at"], name: "index_accesses_on_accessed_at", order: :desc t.index ["board_id", "user_id"], name: "index_accesses_on_board_id_and_user_id", unique: true t.index ["board_id"], name: "index_accesses_on_board_id" t.index ["user_id"], name: "index_accesses_on_user_id" end - create_table "account_join_codes", force: :cascade do |t| + create_table "account_join_codes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "code", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -33,7 +33,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["code"], name: "index_account_join_codes_on_code", unique: true end - create_table "accounts", force: :cascade do |t| + create_table "accounts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.integer "external_account_id" t.string "name", null: false @@ -41,8 +41,8 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["external_account_id"], name: "index_accounts_on_external_account_id", unique: true end - create_table "action_text_rich_texts", force: :cascade do |t| - t.text "body" + create_table "action_text_rich_texts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.text "body", size: :long t.datetime "created_at", null: false t.string "name", null: false t.bigint "record_id", null: false @@ -51,19 +51,17 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true end - create_table "active_storage_attachments", force: :cascade do |t| + create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "blob_id", null: false t.datetime "created_at", null: false t.string "name", null: false t.bigint "record_id", null: false t.string "record_type", null: false - t.string "slug" t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true - t.index ["slug"], name: "index_active_storage_attachments_on_slug", unique: true end - create_table "active_storage_blobs", force: :cascade do |t| + create_table "active_storage_blobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "byte_size", null: false t.string "checksum" t.string "content_type" @@ -75,38 +73,38 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end - create_table "active_storage_variant_records", force: :cascade do |t| + create_table "active_storage_variant_records", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "blob_id", null: false t.string "variation_digest", null: false t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end - create_table "assignees_filters", id: false, force: :cascade do |t| - t.integer "assignee_id", null: false - t.integer "filter_id", null: false + create_table "assignees_filters", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "assignee_id", null: false + t.bigint "filter_id", null: false t.index ["assignee_id"], name: "index_assignees_filters_on_assignee_id" t.index ["filter_id"], name: "index_assignees_filters_on_filter_id" end - create_table "assigners_filters", id: false, force: :cascade do |t| - t.integer "assigner_id", null: false - t.integer "filter_id", null: false + create_table "assigners_filters", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "assigner_id", null: false + t.bigint "filter_id", null: false t.index ["assigner_id"], name: "index_assigners_filters_on_assigner_id" t.index ["filter_id"], name: "index_assigners_filters_on_filter_id" end - create_table "assignments", force: :cascade do |t| - t.integer "assignee_id", null: false + create_table "assignments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "assignee_id", null: false t.integer "assigner_id", null: false - t.integer "card_id", null: false + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["assignee_id", "card_id"], name: "index_assignments_on_assignee_id_and_card_id", unique: true t.index ["card_id"], name: "index_assignments_on_card_id" end - create_table "board_publications", force: :cascade do |t| - t.integer "board_id", null: false + create_table "board_publications", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "board_id", null: false t.datetime "created_at", null: false t.string "key" t.datetime "updated_at", null: false @@ -114,31 +112,31 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["key"], name: "index_board_publications_on_key", unique: true end - create_table "boards", force: :cascade do |t| + create_table "boards", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.boolean "all_access", default: false, null: false t.datetime "created_at", null: false - t.integer "creator_id", null: false + t.bigint "creator_id", null: false t.string "name", null: false t.datetime "updated_at", null: false t.index ["creator_id"], name: "index_boards_on_creator_id" end - create_table "boards_filters", id: false, force: :cascade do |t| - t.integer "board_id", null: false - t.integer "filter_id", null: false + create_table "boards_filters", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "board_id", null: false + t.bigint "filter_id", null: false t.index ["board_id"], name: "index_boards_filters_on_board_id" t.index ["filter_id"], name: "index_boards_filters_on_filter_id" end - create_table "card_activity_spikes", force: :cascade do |t| - t.integer "card_id", null: false + create_table "card_activity_spikes", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["card_id"], name: "index_card_activity_spikes_on_card_id" end - create_table "card_engagements", force: :cascade do |t| - t.integer "card_id" + create_table "card_engagements", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id" t.datetime "created_at", null: false t.string "status", default: "doing", null: false t.datetime "updated_at", null: false @@ -146,30 +144,30 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["status"], name: "index_card_engagements_on_status" end - create_table "card_goldnesses", force: :cascade do |t| - t.integer "card_id", null: false + create_table "card_goldnesses", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["card_id"], name: "index_card_goldnesses_on_card_id", unique: true end - create_table "card_not_nows", force: :cascade do |t| - t.integer "card_id", null: false + create_table "card_not_nows", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "user_id" + t.bigint "user_id" t.index ["card_id"], name: "index_card_not_nows_on_card_id", unique: true t.index ["user_id"], name: "index_card_not_nows_on_user_id" end - create_table "cards", force: :cascade do |t| - t.integer "board_id", null: false - t.integer "column_id" + create_table "cards", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "board_id", null: false + t.bigint "column_id" t.datetime "created_at", null: false t.integer "creator_id", null: false t.date "due_on" t.datetime "last_active_at", null: false - t.text "status", default: "drafted", null: false + t.string "status", default: "drafted", null: false t.string "title" t.datetime "updated_at", null: false t.index ["board_id"], name: "index_cards_on_board_id" @@ -177,25 +175,25 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["last_active_at", "status"], name: "index_cards_on_last_active_at_and_status" end - create_table "closers_filters", id: false, force: :cascade do |t| + create_table "closers_filters", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "closer_id", null: false t.integer "filter_id", null: false t.index ["closer_id"], name: "index_closers_filters_on_closer_id" t.index ["filter_id"], name: "index_closers_filters_on_filter_id" end - create_table "closures", force: :cascade do |t| - t.integer "card_id", null: false + create_table "closures", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "user_id" + t.bigint "user_id" t.index ["card_id", "created_at"], name: "index_closures_on_card_id_and_created_at" t.index ["card_id"], name: "index_closures_on_card_id", unique: true t.index ["user_id"], name: "index_closures_on_user_id" end - create_table "columns", force: :cascade do |t| - t.integer "board_id", null: false + create_table "columns", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "board_id", null: false t.string "color", null: false t.datetime "created_at", null: false t.string "name", null: false @@ -205,24 +203,24 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["board_id"], name: "index_columns_on_board_id" end - create_table "comments", force: :cascade do |t| - t.integer "card_id", null: false + create_table "comments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.integer "creator_id", null: false t.datetime "updated_at", null: false t.index ["card_id"], name: "index_comments_on_card_id" end - create_table "creators_filters", id: false, force: :cascade do |t| + create_table "creators_filters", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "creator_id", null: false t.integer "filter_id", null: false t.index ["creator_id"], name: "index_creators_filters_on_creator_id" t.index ["filter_id"], name: "index_creators_filters_on_filter_id" end - create_table "entropies", force: :cascade do |t| + create_table "entropies", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "auto_postpone_period", default: 2592000, null: false - t.integer "container_id", null: false + t.bigint "container_id", null: false t.string "container_type", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -230,14 +228,14 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["container_type", "container_id"], name: "index_entropy_configurations_on_container", unique: true end - create_table "events", force: :cascade do |t| + create_table "events", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "action", null: false - t.integer "board_id", null: false + t.bigint "board_id", null: false t.datetime "created_at", null: false - t.integer "creator_id", null: false - t.integer "eventable_id", null: false + t.bigint "creator_id", null: false + t.bigint "eventable_id", null: false t.string "eventable_type", null: false - t.json "particulars", default: {} + t.json "particulars", default: -> { "(json_object())" } t.datetime "updated_at", null: false t.index ["action"], name: "index_events_on_summary_id_and_action" t.index ["board_id", "action", "created_at"], name: "index_events_on_board_id_and_action_and_created_at" @@ -246,43 +244,43 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["eventable_type", "eventable_id"], name: "index_events_on_eventable" end - create_table "filters", force: :cascade do |t| + create_table "filters", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false - t.integer "creator_id", null: false - t.json "fields", default: {}, null: false + t.bigint "creator_id", null: false + t.json "fields", default: -> { "(json_object())" }, null: false t.string "params_digest", null: false t.datetime "updated_at", null: false t.index ["creator_id", "params_digest"], name: "index_filters_on_creator_id_and_params_digest", unique: true end - create_table "filters_tags", id: false, force: :cascade do |t| - t.integer "filter_id", null: false - t.integer "tag_id", null: false + create_table "filters_tags", id: false, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "filter_id", null: false + t.bigint "tag_id", null: false t.index ["filter_id"], name: "index_filters_tags_on_filter_id" t.index ["tag_id"], name: "index_filters_tags_on_tag_id" end - create_table "identities", force: :cascade do |t| + create_table "identities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.string "email_address", null: false t.datetime "updated_at", null: false t.index ["email_address"], name: "index_identities_on_email_address", unique: true end - create_table "magic_links", force: :cascade do |t| + create_table "magic_links", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "code", null: false t.datetime "created_at", null: false t.datetime "expires_at", null: false - t.integer "identity_id" + t.bigint "identity_id" t.datetime "updated_at", null: false t.index ["code"], name: "index_magic_links_on_code", unique: true t.index ["expires_at"], name: "index_magic_links_on_expires_at" t.index ["identity_id"], name: "index_magic_links_on_identity_id" end - create_table "memberships", force: :cascade do |t| + create_table "memberships", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false - t.integer "identity_id", null: false + t.bigint "identity_id", null: false t.string "join_code" t.string "tenant", null: false t.datetime "updated_at", null: false @@ -291,11 +289,11 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["tenant"], name: "index_memberships_on_user_tenant_and_user_id" end - create_table "mentions", force: :cascade do |t| + create_table "mentions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false - t.integer "mentionee_id", null: false - t.integer "mentioner_id", null: false - t.integer "source_id", null: false + t.bigint "mentionee_id", null: false + t.bigint "mentioner_id", null: false + t.bigint "source_id", null: false t.string "source_type", null: false t.datetime "updated_at", null: false t.index ["mentionee_id"], name: "index_mentions_on_mentionee_id" @@ -303,50 +301,50 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["source_type", "source_id"], name: "index_mentions_on_source" end - create_table "notification_bundles", force: :cascade do |t| + create_table "notification_bundles", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "ends_at", null: false t.datetime "starts_at", null: false t.integer "status", default: 0, null: false t.datetime "updated_at", null: false - t.integer "user_id", null: false + t.bigint "user_id", null: false t.index ["ends_at", "status"], name: "index_notification_bundles_on_ends_at_and_status" t.index ["user_id", "starts_at", "ends_at"], name: "idx_on_user_id_starts_at_ends_at_7eae5d3ac5" t.index ["user_id", "status"], name: "index_notification_bundles_on_user_id_and_status" end - create_table "notifications", force: :cascade do |t| + create_table "notifications", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false - t.integer "creator_id" + t.bigint "creator_id" t.datetime "read_at" - t.integer "source_id", null: false + t.bigint "source_id", null: false t.string "source_type", null: false t.datetime "updated_at", null: false - t.integer "user_id", null: false + t.bigint "user_id", null: false t.index ["creator_id"], name: "index_notifications_on_creator_id" t.index ["source_type", "source_id"], name: "index_notifications_on_source" t.index ["user_id", "read_at", "created_at"], name: "index_notifications_on_user_id_and_read_at_and_created_at", order: { read_at: :desc, created_at: :desc } t.index ["user_id"], name: "index_notifications_on_user_id" end - create_table "pins", force: :cascade do |t| - t.integer "card_id", null: false + create_table "pins", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "user_id", null: false + t.bigint "user_id", null: false t.index ["card_id", "user_id"], name: "index_pins_on_card_id_and_user_id", unique: true t.index ["card_id"], name: "index_pins_on_card_id" t.index ["user_id"], name: "index_pins_on_user_id" end - create_table "push_subscriptions", force: :cascade do |t| + create_table "push_subscriptions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.string "auth_key" t.datetime "created_at", null: false t.string "endpoint" t.string "p256dh_key" t.datetime "updated_at", null: false t.string "user_agent" - t.integer "user_id", null: false + t.bigint "user_id", null: false t.index ["endpoint", "p256dh_key", "auth_key"], name: "idx_on_endpoint_p256dh_key_auth_key_7553014576" t.index ["endpoint"], name: "index_push_subscriptions_on_endpoint" t.index ["user_agent"], name: "index_push_subscriptions_on_user_agent" @@ -354,7 +352,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["user_id"], name: "index_push_subscriptions_on_user_id" end - create_table "reactions", force: :cascade do |t| + create_table "reactions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "comment_id", null: false t.string "content", limit: 16, null: false t.datetime "created_at", null: false @@ -364,32 +362,32 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["reacter_id"], name: "index_reactions_on_reacter_id" end - create_table "search_queries", force: :cascade do |t| + create_table "search_queries", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.string "terms", limit: 2000, null: false t.datetime "updated_at", null: false - t.integer "user_id", null: false - t.index ["user_id", "terms"], name: "index_search_queries_on_user_id_and_terms" + t.bigint "user_id", null: false + t.index ["user_id", "terms"], name: "index_search_queries_on_user_id_and_terms", length: { terms: 255 } t.index ["user_id", "updated_at"], name: "index_search_queries_on_user_id_and_updated_at", unique: true t.index ["user_id"], name: "index_search_queries_on_user_id" end - create_table "search_results", force: :cascade do |t| + create_table "search_results", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "sessions", force: :cascade do |t| + create_table "sessions", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false - t.integer "identity_id", null: false + t.bigint "identity_id", null: false t.string "ip_address" t.datetime "updated_at", null: false t.string "user_agent" t.index ["identity_id"], name: "index_sessions_on_identity_id" end - create_table "steps", force: :cascade do |t| - t.integer "card_id", null: false + create_table "steps", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.boolean "completed", default: false, null: false t.text "content", null: false t.datetime "created_at", null: false @@ -398,33 +396,33 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["card_id"], name: "index_steps_on_card_id" end - create_table "taggings", force: :cascade do |t| - t.integer "card_id", null: false + create_table "taggings", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false - t.integer "tag_id", null: false + t.bigint "tag_id", null: false t.datetime "updated_at", null: false t.index ["card_id", "tag_id"], name: "index_taggings_on_card_id_and_tag_id", unique: true t.index ["tag_id"], name: "index_taggings_on_tag_id" end - create_table "tags", force: :cascade do |t| + create_table "tags", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false t.string "title" t.datetime "updated_at", null: false t.index ["title"], name: "index_tags_on_title", unique: true end - create_table "user_settings", force: :cascade do |t| + create_table "user_settings", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "bundle_email_frequency", default: 0, null: false t.datetime "created_at", null: false t.string "timezone_name" t.datetime "updated_at", null: false - t.integer "user_id", null: false + t.bigint "user_id", null: false t.index ["user_id", "bundle_email_frequency"], name: "index_user_settings_on_user_id_and_bundle_email_frequency" t.index ["user_id"], name: "index_user_settings_on_user_id" end - create_table "users", force: :cascade do |t| + create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.boolean "active", default: true, null: false t.datetime "created_at", null: false t.integer "membership_id" @@ -435,41 +433,41 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.index ["role"], name: "index_users_on_role" end - create_table "watches", force: :cascade do |t| - t.integer "card_id", null: false + create_table "watches", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.bigint "card_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.integer "user_id", null: false + t.bigint "user_id", null: false t.boolean "watching", default: true, null: false t.index ["card_id"], name: "index_watches_on_card_id" t.index ["user_id", "card_id"], name: "index_watches_on_user_id_and_card_id" t.index ["user_id"], name: "index_watches_on_user_id" end - create_table "webhook_delinquency_trackers", force: :cascade do |t| + create_table "webhook_delinquency_trackers", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.integer "consecutive_failures_count", default: 0 t.datetime "created_at", null: false t.datetime "first_failure_at" t.datetime "updated_at", null: false - t.integer "webhook_id", null: false + t.bigint "webhook_id", null: false t.index ["webhook_id"], name: "index_webhook_delinquency_trackers_on_webhook_id" end - create_table "webhook_deliveries", force: :cascade do |t| + create_table "webhook_deliveries", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.datetime "created_at", null: false - t.integer "event_id", null: false + t.bigint "event_id", null: false t.text "request" t.text "response" t.string "state", null: false t.datetime "updated_at", null: false - t.integer "webhook_id", null: false + t.bigint "webhook_id", null: false t.index ["event_id"], name: "index_webhook_deliveries_on_event_id" t.index ["webhook_id"], name: "index_webhook_deliveries_on_webhook_id" end - create_table "webhooks", force: :cascade do |t| + create_table "webhooks", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.boolean "active", default: true, null: false - t.integer "board_id", null: false + t.bigint "board_id", null: false t.datetime "created_at", null: false t.string "name" t.string "signing_secret", null: false @@ -477,7 +475,7 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do t.datetime "updated_at", null: false t.text "url", null: false t.index ["board_id"], name: "index_webhooks_on_board_id" - t.index ["subscribed_actions"], name: "index_webhooks_on_subscribed_actions" + t.index ["subscribed_actions"], name: "index_webhooks_on_subscribed_actions", length: 255 end add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" @@ -515,9 +513,4 @@ ActiveRecord::Schema[8.2].define(version: 2025_11_06_154151) do add_foreign_key "webhook_deliveries", "events" add_foreign_key "webhook_deliveries", "webhooks" add_foreign_key "webhooks", "boards" - - # Virtual tables defined in this database. - # Note that virtual tables may not work with other database engines. Be careful if changing database. - create_virtual_table "cards_search_index", "fts5", ["title", "description", "tokenize='porter'"] - create_virtual_table "comments_search_index", "fts5", ["body", "tokenize='porter'"] end