2026-07-04 19:22:11 +00:00
# retoor <retoor@molodetz.nl>
2026-07-19 18:57:43 +02:00
from .core import DEFAULT_CORRECTION_PROMPT , DEFAULT_MODIFIER_PROMPT , INTERNAL_GATEWAY_URL , _drop_index , _index , _uid_index , db , defaultdict , get_table , logger
2026-07-04 19:22:11 +00:00
from .settings import get_setting , set_setting
from .soft_delete import SOFT_DELETE_TABLES , ensure_soft_delete_columns
from .ranking import _authors_cache
BUG_TABLE_RENAMES = (
( "bug_tickets" , "issue_tickets" ),
( "bug_comment_authors" , "issue_comment_authors" ),
)
def migrate_bug_tables_to_issue_tables () -> None :
for source_name , destination_name in BUG_TABLE_RENAMES :
if source_name not in db . tables :
continue
source = db [ source_name ]
destination = get_table ( destination_name )
copied = 0
for row in source . all ():
payload = { key : value for key , value in row . items () if key != "id" }
destination . insert_ignore ( payload , [ "uid" ])
copied += 1
logger . info (
"Migrated %s rows from %s into %s " , copied , source_name , destination_name
)
source . drop ()
logger . info ( "Dropped table %s after migration" , source_name )
def init_db ():
tables = db . tables
_index ( db , "users" , "idx_users_username" , [ "username" ])
_index ( db , "users" , "idx_users_email" , [ "email" ])
_index ( db , "users" , "idx_users_api_key" , [ "api_key" ])
_index ( db , "users" , "idx_users_role" , [ "role" , "created_at" ])
2026-07-04 22:08:20 +00:00
_index ( db , "users" , "idx_users_last_seen" , [ "last_seen" ])
2026-07-06 03:57:47 +00:00
_index ( db , "users" , "idx_users_created_at" , [ "created_at" ])
2026-09-03 04:19:58 +00:00
_ensure_users_uid ()
2026-07-04 19:22:11 +00:00
_index ( db , "posts" , "idx_posts_user_uid" , [ "user_uid" ])
_index ( db , "posts" , "idx_posts_created_at" , [ "created_at" ])
_index ( db , "posts" , "idx_posts_topic" , [ "topic" ])
2026-07-06 03:57:47 +00:00
_index ( db , "posts" , "idx_posts_slug" , [ "slug" ])
2026-07-26 20:50:56 +00:00
_index ( db , "posts" , "idx_posts_project_uid" , [ "project_uid" ])
2026-07-04 19:22:11 +00:00
if "posts" in tables :
posts_table = get_table ( "posts" )
if not posts_table . has_column ( "tags" ):
posts_table . create_column_by_example ( "tags" , "" )
if "devrant_tokens" in tables :
devrant_tokens = get_table ( "devrant_tokens" )
for column , example in (
( "uid" , "" ),
( "key" , "" ),
( "user_uid" , "" ),
( "user_id" , 0 ),
( "expire_time" , 0 ),
( "created_at" , "" ),
):
if not devrant_tokens . has_column ( column ):
devrant_tokens . create_column_by_example ( column , example )
_index ( db , "devrant_tokens" , "idx_devrant_tokens_key" , [ "key" ])
_index ( db , "devrant_tokens" , "idx_devrant_tokens_user" , [ "user_uid" ])
if "access_tokens" in tables :
access_tokens = get_table ( "access_tokens" )
for column , example in (
( "uid" , "" ),
( "token" , "" ),
( "user_uid" , "" ),
( "label" , "" ),
( "expires_at" , "" ),
( "created_at" , "" ),
):
if not access_tokens . has_column ( column ):
access_tokens . create_column_by_example ( column , example )
_index ( db , "access_tokens" , "idx_access_tokens_token" , [ "token" ])
_index ( db , "access_tokens" , "idx_access_tokens_user" , [ "user_uid" ])
if "telegram_pairings" in tables :
telegram_pairings = get_table ( "telegram_pairings" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "code_hash" , "" ),
( "expires_at" , "" ),
( "used" , 0 ),
( "created_at" , "" ),
):
if not telegram_pairings . has_column ( column ):
telegram_pairings . create_column_by_example ( column , example )
_index ( db , "telegram_pairings" , "idx_telegram_pairings_code" , [ "code_hash" ])
_index ( db , "telegram_pairings" , "idx_telegram_pairings_user" , [ "user_uid" ])
if "telegram_links" in tables :
telegram_links = get_table ( "telegram_links" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "chat_id" , 0 ),
( "from_id" , 0 ),
( "created_at" , "" ),
):
if not telegram_links . has_column ( column ):
telegram_links . create_column_by_example ( column , example )
_index ( db , "telegram_links" , "idx_telegram_links_chat" , [ "chat_id" ])
_index ( db , "telegram_links" , "idx_telegram_links_user" , [ "user_uid" ])
telegram_outbox = get_table ( "telegram_outbox" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "chat_id" , 0 ),
( "text" , "" ),
( "status" , "pending" ),
( "attempts" , 0 ),
( "created_at" , "" ),
( "sent_at" , "" ),
):
if not telegram_outbox . has_column ( column ):
telegram_outbox . create_column_by_example ( column , example )
_index ( db , "telegram_outbox" , "idx_telegram_outbox_status" , [ "status" , "id" ])
_index ( db , "comments" , "idx_comments_post_uid" , [ "post_uid" ])
_index ( db , "comments" , "idx_comments_target" , [ "target_type" , "target_uid" ])
_index ( db , "comments" , "idx_comments_user_uid" , [ "user_uid" ])
_index ( db , "comments" , "idx_comments_created_at" , [ "created_at" ])
_index ( db , "votes" , "idx_votes_target" , [ "target_uid" , "target_type" ])
2026-08-10 00:23:20 +02:00
messages = get_table ( "messages" )
for column , example in (
( "uid" , "" ),
( "sender_uid" , "" ),
( "receiver_uid" , "" ),
( "content" , "" ),
( "read" , False ),
( "created_at" , "" ),
):
if not messages . has_column ( column ):
messages . create_column_by_example ( column , example )
2026-07-04 19:22:11 +00:00
_index ( db , "messages" , "idx_messages_sender" , [ "sender_uid" ])
_index ( db , "messages" , "idx_messages_receiver" , [ "receiver_uid" ])
2026-07-06 03:57:47 +00:00
_index (
db , "messages" , "idx_messages_conversation" , [ "sender_uid" , "receiver_uid" ]
)
_index (
db ,
"messages" ,
"idx_messages_conversation_rev" ,
[ "receiver_uid" , "sender_uid" ],
)
2026-07-04 19:22:11 +00:00
_index ( db , "notifications" , "idx_notifications_user" , [ "user_uid" ])
_index ( db , "notifications" , "idx_notifications_user_read" , [ "user_uid" , "read" ])
2026-07-31 22:43:10 +02:00
push_registration = get_table ( "push_registration" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "provider" , "webpush" ),
( "endpoint" , "" ),
( "key_auth" , "" ),
( "key_p256dh" , "" ),
( "token" , "" ),
( "created_at" , "" ),
( "deleted_at" , "" ),
):
if not push_registration . has_column ( column ):
push_registration . create_column_by_example ( column , example )
2026-07-04 19:22:11 +00:00
_index ( db , "push_registration" , "idx_push_registration_user" , [ "user_uid" ])
2026-07-31 22:43:10 +02:00
_index ( db , "push_registration" , "idx_push_registration_provider" , [ "provider" ])
if "push_registration" in db . tables :
with db :
db . query (
"UPDATE push_registration SET provider = 'webpush' "
"WHERE provider IS NULL OR provider = ''"
)
2026-07-04 19:22:11 +00:00
_index ( db , "sessions" , "idx_sessions_token" , [ "session_token" ])
projects = get_table ( "projects" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "slug" , "" ),
( "created_at" , "" ),
( "stars" , 0 ),
( "project_type" , "" ),
( "is_private" , 0 ),
( "read_only" , 0 ),
( "updated_at" , "" ),
2026-07-28 13:33:07 +00:00
( "title" , "" ),
( "description" , "" ),
( "status" , "" ),
2026-08-15 00:18:04 +02:00
( "platforms" , "" ),
( "release_date" , "" ),
( "demo_date" , "" ),
( "website_url" , "" ),
( "repo_url" , "" ),
( "cover_attachment_uid" , "" ),
( "logo_attachment_uid" , "" ),
2026-07-04 19:22:11 +00:00
):
if not projects . has_column ( column ):
projects . create_column_by_example ( column , example )
_index ( db , "projects" , "idx_projects_user" , [ "user_uid" ])
2026-07-06 03:57:47 +00:00
_index ( db , "projects" , "idx_projects_slug" , [ "slug" ])
2026-07-04 19:22:11 +00:00
_index ( db , "projects" , "idx_projects_private" , [ "is_private" ])
_index ( db , "projects" , "idx_projects_stars" , [ "stars" ])
_index ( db , "projects" , "idx_projects_type" , [ "project_type" ])
project_files = get_table ( "project_files" )
for column , example in (
( "uid" , "" ),
( "project_uid" , "" ),
( "user_uid" , "" ),
( "path" , "" ),
( "name" , "" ),
( "parent_path" , "" ),
( "type" , "" ),
( "content" , "" ),
( "is_binary" , 0 ),
( "stored_name" , "" ),
( "directory" , "" ),
( "mime_type" , "" ),
( "size" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not project_files . has_column ( column ):
project_files . create_column_by_example ( column , example )
_index ( db , "project_files" , "idx_project_files_path" , [ "project_uid" , "path" ])
_index (
db , "project_files" , "idx_project_files_parent" , [ "project_uid" , "parent_path" ]
)
_index ( db , "badges" , "idx_badges_user" , [ "user_uid" ])
2026-07-06 03:57:47 +00:00
_index ( db , "badges" , "idx_badges_user_name" , [ "user_uid" , "badge_name" ])
2026-07-19 18:57:43 +02:00
_drop_index ( db , "idx_follows_follower" )
_drop_index ( db , "idx_follows_following" )
_index ( db , "follows" , "idx_follows_follower_created" , [ "follower_uid" , "created_at" ])
_index ( db , "follows" , "idx_follows_following_created" , [ "following_uid" , "created_at" ])
2026-07-04 19:22:11 +00:00
user_relations = get_table ( "user_relations" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "target_uid" , "" ),
( "kind" , "" ),
( "created_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not user_relations . has_column ( column ):
user_relations . create_column_by_example ( column , example )
_index ( db , "user_relations" , "idx_user_relations_owner_kind" , [ "user_uid" , "kind" ])
_index ( db , "user_relations" , "idx_user_relations_target_kind" , [ "target_uid" , "kind" ])
_index ( db , "password_resets" , "idx_password_resets_token" , [ "token" ])
_index ( db , "gists" , "idx_gists_user_uid" , [ "user_uid" ])
_index ( db , "gists" , "idx_gists_language" , [ "language" ])
2026-07-06 03:57:47 +00:00
_index ( db , "gists" , "idx_gists_slug" , [ "slug" ])
2026-07-04 19:22:11 +00:00
attachments = get_table ( "attachments" )
for column , example in (
( "uid" , "" ),
( "target_type" , "" ),
( "target_uid" , "" ),
( "resource_type" , "" ),
( "resource_uid" , "" ),
( "user_uid" , "" ),
( "original_filename" , "" ),
( "stored_name" , "" ),
( "directory" , "" ),
( "file_size" , 0 ),
( "mime_type" , "" ),
( "image_width" , 0 ),
( "image_height" , 0 ),
( "has_thumbnail" , 0 ),
( "thumbnail_name" , "" ),
( "gitea_asset_id" , 0 ),
( "created_at" , "" ),
( "deleted_at" , "" ),
):
if not attachments . has_column ( column ):
attachments . create_column_by_example ( column , example )
_index (
db , "attachments" , "idx_attachments_resource" , [ "resource_type" , "resource_uid" ]
)
_index ( db , "attachments" , "idx_attachments_target" , [ "target_type" , "target_uid" ])
_index ( db , "attachments" , "idx_attachments_user_created" , [ "user_uid" , "created_at" ])
_index ( db , "reactions" , "idx_reactions_target" , [ "target_type" , "target_uid" ])
_index (
db ,
"reactions" ,
"idx_reactions_user_target" ,
[ "user_uid" , "target_type" , "target_uid" ],
)
_index ( db , "bookmarks" , "idx_bookmarks_user" , [ "user_uid" ])
_index ( db , "bookmarks" , "idx_bookmarks_target" , [ "target_type" , "target_uid" ])
_index ( db , "polls" , "idx_polls_post" , [ "post_uid" ])
_index ( db , "poll_options" , "idx_poll_options_poll" , [ "poll_uid" ])
_index ( db , "poll_votes" , "idx_poll_votes_poll" , [ "poll_uid" ])
_index ( db , "poll_votes" , "idx_poll_votes_user" , [ "poll_uid" , "user_uid" ])
if "site_settings" in tables :
defaults = {
"site_name" : "DevPlace" ,
"site_description" : "The Developer Social Network" ,
2026-08-09 00:18:20 +02:00
"site_tagline" : "Track industry shifts. Discover bold releases. Share what you are building in an open environment built by developers, for developers." ,
2026-07-04 19:22:11 +00:00
}
for key , value in defaults . items ():
existing = db [ "site_settings" ] . find_one ( key = key )
if not existing :
db [ "site_settings" ] . insert (
{ "uid" : f "default_ { key } " , "key" : key , "value" : value }
)
2026-07-06 03:57:47 +00:00
_index ( db , "site_settings" , "idx_site_settings_key" , [ "key" ])
2026-07-04 19:22:11 +00:00
news = get_table ( "news" )
for column , example in (
( "uid" , "" ),
( "slug" , "" ),
( "title" , "" ),
( "external_id" , "" ),
( "status" , "" ),
( "source_name" , "" ),
( "url" , "" ),
( "description" , "" ),
( "content" , "" ),
( "synced_at" , "" ),
( "grade" , 0 ),
( "ai_grade" , 0 ),
( "show_on_landing" , 0 ),
( "featured" , 0 ),
( "author" , "" ),
( "article_published" , "" ),
( "image_url" , "" ),
( "has_unique_image" , 0 ),
( "featured_locked" , 0 ),
( "landing_locked" , 0 ),
):
if not news . has_column ( column ):
news . create_column_by_example ( column , example )
_index ( db , "news" , "idx_news_external_id" , [ "external_id" ])
2026-07-06 03:57:47 +00:00
_index ( db , "news" , "idx_news_slug" , [ "slug" ])
2026-07-04 19:22:11 +00:00
_index ( db , "news" , "idx_news_synced_at" , [ "synced_at" ])
_index ( db , "news" , "idx_news_status" , [ "status" ])
_index ( db , "news" , "idx_news_featured" , [ "featured" ])
_index ( db , "news" , "idx_news_landing" , [ "show_on_landing" ])
news_images = get_table ( "news_images" )
for column , example in (
( "news_uid" , "" ),
( "url" , "" ),
( "alt_text" , "" ),
( "phash" , "" ),
( "width" , 0 ),
( "height" , 0 ),
( "is_placeholder" , 0 ),
):
if not news_images . has_column ( column ):
news_images . create_column_by_example ( column , example )
news_sync = get_table ( "news_sync" )
if not news_sync . has_column ( "external_id" ):
news_sync . create_column_by_example ( "external_id" , "" )
_index ( db , "news_images" , "idx_news_images_news_uid" , [ "news_uid" ])
_index ( db , "news_sync" , "idx_news_sync_external_id" , [ "external_id" ])
issue_tickets = get_table ( "issue_tickets" )
for column , example in (
( "uid" , "" ),
( "gitea_number" , 0 ),
( "author_uid" , "" ),
( "original_title" , "" ),
( "original_description" , "" ),
( "enhanced_title" , "" ),
( "html_url" , "" ),
( "last_status" , "" ),
( "last_comment_count" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not issue_tickets . has_column ( column ):
issue_tickets . create_column_by_example ( column , example )
issue_comment_authors = get_table ( "issue_comment_authors" )
for column , example in (
( "uid" , "" ),
( "gitea_comment_id" , 0 ),
( "gitea_number" , 0 ),
( "author_uid" , "" ),
( "created_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not issue_comment_authors . has_column ( column ):
issue_comment_authors . create_column_by_example ( column , example )
_index ( db , "issue_tickets" , "idx_issue_tickets_number" , [ "gitea_number" ])
_index ( db , "issue_tickets" , "idx_issue_tickets_author" , [ "author_uid" ])
_index (
db ,
"issue_comment_authors" ,
"idx_issue_comment_authors_comment" ,
[ "gitea_comment_id" ],
)
_index (
db , "issue_comment_authors" , "idx_issue_comment_authors_number" , [ "gitea_number" ]
)
2026-07-22 23:54:42 +02:00
ws_tickets = get_table ( "ws_tickets" )
for column , example in (
( "uid" , "" ),
( "token" , "" ),
( "user_uid" , "" ),
( "created_at" , "" ),
( "expires_at" , "" ),
( "used_at" , "" ),
):
if not ws_tickets . has_column ( column ):
ws_tickets . create_column_by_example ( column , example )
_index ( db , "ws_tickets" , "idx_ws_tickets_token" , [ "token" ], unique = True )
_index ( db , "ws_tickets" , "idx_ws_tickets_expires" , [ "expires_at" ])
2026-07-04 19:22:11 +00:00
migrate_bug_tables_to_issue_tables ()
_index ( db , "service_state" , "idx_service_state_name" , [ "name" ])
if "devii_conversations" in db . tables :
conversations = get_table ( "devii_conversations" )
if not conversations . has_column ( "channel" ):
conversations . create_column_by_example ( "channel" , "main" )
try :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"UPDATE devii_conversations SET channel='main' WHERE channel IS NULL"
)
2026-07-04 19:22:11 +00:00
except Exception as e : # noqa: BLE001
logger . warning ( f "Could not backfill devii_conversations.channel: { e } " )
_index (
db ,
"devii_conversations" ,
"idx_devii_conv_owner" ,
[ "owner_kind" , "owner_id" , "channel" ],
)
_index (
db ,
"devii_usage_ledger" ,
"idx_devii_ledger_owner_time" ,
[ "owner_kind" , "owner_id" , "created_at" ],
)
_index (
db ,
"devii_turns" ,
"idx_devii_turns_owner_time" ,
[ "owner_kind" , "owner_id" , "started_at" ],
)
2026-07-26 14:57:18 +02:00
if "devii_tasks" in db . tables :
tasks = get_table ( "devii_tasks" )
for column , example in (
( "expires_at" , "" ),
( "failure_count" , 0 ),
( "notify" , 0 ),
( "tz" , "" ),
):
if not tasks . has_column ( column ):
tasks . create_column_by_example ( column , example )
try :
with db :
db . query (
"UPDATE devii_tasks SET failure_count = 0 WHERE failure_count IS NULL"
)
except Exception as e : # noqa: BLE001
logger . warning ( f "Could not backfill devii_tasks.failure_count: { e } " )
2026-07-26 16:45:38 +02:00
task_runs = get_table ( "devii_task_runs" )
for column , example in (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "task_uid" , "" ),
( "created_at" , "" ),
):
if not task_runs . has_column ( column ):
task_runs . create_column_by_example ( column , example )
_index (
db ,
"devii_task_runs" ,
"idx_devii_task_runs_owner_time" ,
[ "owner_kind" , "owner_id" , "created_at" ],
)
_index ( db , "devii_task_runs" , "idx_devii_task_runs_time" , [ "created_at" ])
_index (
db ,
"devii_tasks" ,
"idx_devii_tasks_owner_created" ,
[ "owner_kind" , "owner_id" , "created_at" ],
)
2026-07-04 19:22:11 +00:00
_index ( db , "devii_tasks" , "idx_devii_tasks_owner" , [ "owner_kind" , "owner_id" ])
_index (
db , "devii_tasks" , "idx_devii_tasks_due" , [ "enabled" , "status" , "next_run_at" ]
)
_index ( db , "devii_lessons" , "idx_devii_lessons_owner" , [ "owner_kind" , "owner_id" ])
2026-07-19 18:57:43 +02:00
_index ( db , "devii_lessons" , "idx_devii_lessons_owner_created" , [ "owner_kind" , "owner_id" , "created_at" ])
2026-07-04 19:22:11 +00:00
_index (
db , "devii_virtual_tools" , "idx_devii_vtools_owner" , [ "owner_kind" , "owner_id" ]
)
_index (
db ,
"devii_virtual_tools" ,
"idx_devii_vtools_name" ,
[ "owner_kind" , "owner_id" , "name" ],
)
_index ( db , "devii_behavior" , "idx_devii_behavior_owner" , [ "owner_kind" , "owner_id" ])
_index ( db , "user_customizations" , "idx_user_cust_owner" , [ "owner_kind" , "owner_id" ])
_index (
db ,
"user_customizations" ,
"idx_user_cust_scope" ,
[ "owner_kind" , "owner_id" , "scope" , "lang" ],
)
_index ( db , "gateway_usage_ledger" , "idx_gw_usage_time" , [ "created_at" ])
_index (
db ,
"gateway_usage_ledger" ,
"idx_gw_usage_backend_time" ,
[ "backend" , "created_at" ],
)
_index (
db , "gateway_usage_ledger" , "idx_gw_usage_model_time" , [ "model" , "created_at" ]
)
_index (
db ,
"gateway_usage_ledger" ,
"idx_gw_usage_owner_time" ,
[ "owner_kind" , "owner_id" , "created_at" ],
)
_index (
db ,
"gateway_usage_ledger" ,
"idx_gw_usage_endpoint_time" ,
[ "endpoint" , "created_at" ],
)
2026-07-19 18:57:43 +02:00
_index (
db ,
"gateway_usage_ledger" ,
"idx_gw_usage_appref_time" ,
[ "app_reference" , "created_at" ],
)
2026-07-04 19:22:11 +00:00
_index ( db , "gateway_concurrency_samples" , "idx_gw_conc_time" , [ "created_at" ])
jobs_table = get_table ( "jobs" )
for column , example in (
( "uid" , "" ),
( "kind" , "" ),
( "status" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "preferred_name" , "" ),
( "payload" , "" ),
( "result" , "" ),
( "error" , "" ),
( "retry_count" , 0 ),
( "created_at" , "" ),
( "started_at" , "" ),
( "completed_at" , "" ),
( "updated_at" , "" ),
( "duration_ms" , 0 ),
( "last_accessed_at" , "" ),
( "expires_at" , "" ),
( "bytes_in" , 0 ),
( "bytes_out" , 0 ),
( "item_count" , 0 ),
):
if not jobs_table . has_column ( column ):
jobs_table . create_column_by_example ( column , example )
_index ( db , "jobs" , "idx_jobs_kind_status" , [ "kind" , "status" ])
_index ( db , "jobs" , "idx_jobs_owner" , [ "owner_kind" , "owner_id" ])
_index ( db , "jobs" , "idx_jobs_expires" , [ "expires_at" ])
_index ( db , "project_forks" , "idx_project_forks_source" , [ "source_project_uid" ])
_index ( db , "project_forks" , "idx_project_forks_forked" , [ "forked_project_uid" ])
2026-07-22 23:54:42 +02:00
instances = get_table ( "instances" )
for column , example in (
( "uid" , "" ),
( "project_uid" , "" ),
( "slug" , "" ),
( "name" , "" ),
( "status" , "" ),
2026-08-09 00:18:20 +02:00
( "created_at" , "" ),
( "owner_uid" , "" ),
( "created_by" , "" ),
2026-07-22 23:54:42 +02:00
( "desired_state" , "" ),
( "container_id" , "" ),
( "ingress_slug" , "" ),
( "ingress_port" , 0 ),
( "ports_json" , "" ),
( "container_gateway" , "" ),
( "run_as_uid" , "" ),
( "boot_language" , "none" ),
( "boot_script" , "" ),
( "start_on_boot" , 0 ),
2026-08-07 10:53:08 +02:00
( "is_workspace" , 0 ),
( "workspace_owner_uid" , "" ),
( "editor_port" , 0 ),
( "editor_host_port" , 0 ),
2026-08-07 13:46:40 +02:00
( "editor_password" , "" ),
2026-08-07 10:53:08 +02:00
( "tunnel_name" , "" ),
( "last_active_at" , "" ),
( "idle_warned_at" , "" ),
( "delete_warned_at" , "" ),
( "disk_bytes" , 0 ),
( "disk_sampled_at" , "" ),
( "egress_bytes" , 0 ),
( "request_count" , 0 ),
( "flagged_at" , "" ),
( "flag_reason" , "" ),
( "suspended_at" , "" ),
( "suspended_by" , "" ),
2026-08-10 00:23:20 +02:00
( "boot_marker" , "" ),
( "workspace_cpu_millicores" , 0 ),
( "workspace_memory_mb" , 0 ),
( "workspace_disk_quota_mb" , 0 ),
2026-07-22 23:54:42 +02:00
):
if not instances . has_column ( column ):
instances . create_column_by_example ( column , example )
2026-07-04 19:22:11 +00:00
2026-08-07 10:53:08 +02:00
tunnels = get_table ( "tunnels" )
for column , example in (
( "uid" , "" ),
( "instance_uid" , "" ),
( "project_uid" , "" ),
( "user_uid" , "" ),
( "hostname" , "" ),
( "label" , "" ),
( "container_port" , 0 ),
( "desired_state" , "present" ),
( "status" , "pending" ),
( "cert_status" , "" ),
( "cert_checked_at" , "" ),
( "request_count" , 0 ),
( "bytes_out" , 0 ),
( "last_request_at" , "" ),
( "last_error" , "" ),
( "last_synced_at" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not tunnels . has_column ( column ):
tunnels . create_column_by_example ( column , example )
quota_rules = get_table ( "workspace_quota_rules" )
for column , example in (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "label" , "" ),
( "max_workspaces" , 0 ),
( "max_tunnels" , 0 ),
( "disk_quota_mb" , 0 ),
( "egress_quota_mb" , 0 ),
( "idle_stop_minutes" , 0 ),
( "retention_days" , 0 ),
2026-08-10 00:23:20 +02:00
( "cpu_millicores" , 0 ),
( "memory_mb" , 0 ),
2026-08-07 10:53:08 +02:00
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not quota_rules . has_column ( column ):
quota_rules . create_column_by_example ( column , example )
2026-08-10 00:23:20 +02:00
editor_prefs = get_table ( "workspace_editor_prefs" )
for column , example in (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "font_size" , 0 ),
( "terminal_font_size" , 0 ),
( "zoom_level" , - 99 ),
( "theme" , "" ),
( "layout" , "" ),
( "panel_preset" , "" ),
( "window_mode" , "" ),
( "window_width" , 0 ),
( "window_height" , 0 ),
( "boot_agent" , "" ),
( "boot_shell" , - 1 ),
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not editor_prefs . has_column ( column ):
editor_prefs . create_column_by_example ( column , example )
2026-08-07 10:53:08 +02:00
flags = get_table ( "workspace_flags" )
for column , example in (
( "uid" , "" ),
( "instance_uid" , "" ),
( "user_uid" , "" ),
( "kind" , "" ),
( "severity" , "warn" ),
( "detail" , "" ),
( "metric_value" , 0.0 ),
( "threshold" , 0.0 ),
( "status" , "open" ),
( "resolved_by" , "" ),
( "resolved_at" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not flags . has_column ( column ):
flags . create_column_by_example ( column , example )
_index ( db , "instances" , "idx_instances_workspace" , [ "is_workspace" , "status" ])
_index ( db , "instances" , "idx_instances_workspace_owner" , [ "workspace_owner_uid" ])
_index ( db , "instances" , "idx_instances_tunnel_name" , [ "tunnel_name" ])
_index ( db , "tunnels" , "idx_tunnels_hostname" , [ "hostname" ])
_index ( db , "tunnels" , "idx_tunnels_instance" , [ "instance_uid" ])
_index ( db , "tunnels" , "idx_tunnels_user" , [ "user_uid" ])
_index ( db , "tunnels" , "idx_tunnels_state" , [ "desired_state" , "status" ])
_index (
db ,
"workspace_quota_rules" ,
"idx_workspace_quota_owner" ,
[ "owner_kind" , "owner_id" ],
)
2026-08-10 00:23:20 +02:00
_index (
db ,
"workspace_editor_prefs" ,
"idx_workspace_editor_prefs_owner" ,
[ "owner_kind" , "owner_id" ],
)
2026-08-07 10:53:08 +02:00
_index ( db , "workspace_flags" , "idx_workspace_flags_open" , [ "status" , "created_at" ])
_index (
db ,
"workspace_flags" ,
"idx_workspace_flags_instance" ,
[ "instance_uid" , "kind" ],
)
_index ( db , "workspace_flags" , "idx_workspace_flags_user" , [ "user_uid" ])
2026-07-04 19:22:11 +00:00
_index ( db , "instances" , "idx_instances_project" , [ "project_uid" ])
2026-07-06 03:57:47 +00:00
_index ( db , "instances" , "idx_instances_slug" , [ "slug" ])
_index ( db , "instances" , "idx_instances_name" , [ "name" ])
2026-07-04 19:22:11 +00:00
_index ( db , "instances" , "idx_instances_state" , [ "desired_state" , "status" ])
_index ( db , "instances" , "idx_instances_container" , [ "container_id" ])
_index ( db , "instances" , "idx_instances_ingress" , [ "ingress_slug" ])
_index (
db ,
"instance_events" ,
"idx_instance_events_instance" ,
[ "instance_uid" , "created_at" ],
)
_index (
db ,
"instance_metrics" ,
"idx_instance_metrics_instance_ts" ,
[ "instance_uid" , "ts" ],
)
_index (
db ,
"instance_schedules" ,
"idx_instance_schedules_due" ,
[ "enabled" , "next_run_at" ],
)
from devplacepy.services.audit import store as audit_store
audit_store . ensure_tables ()
from devplacepy.services.backup import store as backup_store
backup_store . ensure_tables ()
from devplacepy.services.openai_gateway import routing as gateway_routing
gateway_routing . ensure_tables ()
2026-07-21 09:48:37 +02:00
from devplacepy.services.openai_gateway import quota as gateway_quota
gateway_quota . ensure_tables ()
2026-07-04 19:22:11 +00:00
_index ( db , "audit_log" , "idx_audit_created_at" , [ "created_at" ])
_index ( db , "audit_log" , "idx_audit_event_key" , [ "event_key" ])
_index ( db , "audit_log" , "idx_audit_category" , [ "category" ])
_index ( db , "audit_log" , "idx_audit_actor_uid" , [ "actor_uid" ])
_index ( db , "audit_log" , "idx_audit_actor_role" , [ "actor_role" ])
_index ( db , "audit_log" , "idx_audit_origin" , [ "origin" ])
_index ( db , "audit_log" , "idx_audit_target" , [ "target_type" , "target_uid" ])
_index ( db , "audit_log" , "idx_audit_result" , [ "result" ])
_index ( db , "audit_log_links" , "idx_audit_links_audit" , [ "audit_uid" ])
_index ( db , "audit_log_links" , "idx_audit_links_object" , [ "object_type" , "object_uid" ])
_index ( db , "audit_log_links" , "idx_audit_links_relation" , [ "relation" ])
notification_preferences = get_table ( "notification_preferences" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "notification_type" , "" ),
( "in_app_enabled" , 1 ),
( "push_enabled" , 1 ),
( "telegram_enabled" , 1 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not notification_preferences . has_column ( column ):
notification_preferences . create_column_by_example ( column , example )
_index ( db , "notification_preferences" , "idx_notif_prefs_user" , [ "user_uid" ])
_index (
db ,
"notification_preferences" ,
"idx_notif_prefs_user_type" ,
[ "user_uid" , "notification_type" ],
)
correction_usage = get_table ( "correction_usage" )
for column , example in (
( "user_uid" , "" ),
( "calls" , 0 ),
( "prompt_tokens" , 0 ),
( "completion_tokens" , 0 ),
( "total_tokens" , 0 ),
( "cost_usd" , 0.0 ),
( "upstream_latency_ms" , 0.0 ),
( "total_latency_ms" , 0.0 ),
( "updated_at" , "" ),
):
if not correction_usage . has_column ( column ):
correction_usage . create_column_by_example ( column , example )
try :
if "correction_usage" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_correction_usage_user "
"ON correction_usage (user_uid)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on correction_usage: { e } " )
modifier_usage = get_table ( "modifier_usage" )
for column , example in (
( "user_uid" , "" ),
( "calls" , 0 ),
( "prompt_tokens" , 0 ),
( "completion_tokens" , 0 ),
( "total_tokens" , 0 ),
( "cost_usd" , 0.0 ),
( "upstream_latency_ms" , 0.0 ),
( "total_latency_ms" , 0.0 ),
( "updated_at" , "" ),
):
if not modifier_usage . has_column ( column ):
modifier_usage . create_column_by_example ( column , example )
try :
if "modifier_usage" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_modifier_usage_user "
"ON modifier_usage (user_uid)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on modifier_usage: { e } " )
news_usage = get_table ( "news_usage" )
for column , example in (
( "user_uid" , "" ),
( "calls" , 0 ),
( "prompt_tokens" , 0 ),
( "completion_tokens" , 0 ),
( "total_tokens" , 0 ),
( "cost_usd" , 0.0 ),
( "upstream_latency_ms" , 0.0 ),
( "total_latency_ms" , 0.0 ),
( "updated_at" , "" ),
):
if not news_usage . has_column ( column ):
news_usage . create_column_by_example ( column , example )
try :
if "news_usage" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_news_usage_user "
"ON news_usage (user_uid)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on news_usage: { e } " )
issue_usage = get_table ( "issue_usage" )
for column , example in (
( "user_uid" , "" ),
( "calls" , 0 ),
( "prompt_tokens" , 0 ),
( "completion_tokens" , 0 ),
( "total_tokens" , 0 ),
( "cost_usd" , 0.0 ),
( "upstream_latency_ms" , 0.0 ),
( "total_latency_ms" , 0.0 ),
( "updated_at" , "" ),
):
if not issue_usage . has_column ( column ):
issue_usage . create_column_by_example ( column , example )
try :
if "issue_usage" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_issue_usage_user "
"ON issue_usage (user_uid)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on issue_usage: { e } " )
seo_usage = get_table ( "seo_usage" )
for column , example in (
( "user_uid" , "" ),
( "calls" , 0 ),
( "prompt_tokens" , 0 ),
( "completion_tokens" , 0 ),
( "total_tokens" , 0 ),
( "cost_usd" , 0.0 ),
( "upstream_latency_ms" , 0.0 ),
( "total_latency_ms" , 0.0 ),
( "updated_at" , "" ),
):
if not seo_usage . has_column ( column ):
seo_usage . create_column_by_example ( column , example )
try :
if "seo_usage" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_seo_usage_user "
"ON seo_usage (user_uid)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on seo_usage: { e } " )
2026-07-09 02:52:54 +02:00
award_usage = get_table ( "award_usage" )
for column , example in (
( "user_uid" , "" ),
( "calls" , 0 ),
( "prompt_tokens" , 0 ),
( "completion_tokens" , 0 ),
( "total_tokens" , 0 ),
( "cost_usd" , 0.0 ),
( "upstream_latency_ms" , 0.0 ),
( "total_latency_ms" , 0.0 ),
( "updated_at" , "" ),
):
if not award_usage . has_column ( column ):
award_usage . create_column_by_example ( column , example )
try :
if "award_usage" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_award_usage_user "
"ON award_usage (user_uid)"
)
2026-07-09 02:52:54 +02:00
except Exception as e :
logger . warning ( f "Could not create unique index on award_usage: { e } " )
awards = get_table ( "awards" )
for column , example in (
( "uid" , "" ),
( "slug" , "" ),
( "description" , "" ),
( "giver_uid" , "" ),
( "receiver_uid" , "" ),
( "attachment_uid_512" , "" ),
( "attachment_uid_256" , "" ),
( "attachment_uid_64" , "" ),
( "generated_at" , "" ),
( "created_at" , "" ),
( "job_uid" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not awards . has_column ( column ):
awards . create_column_by_example ( column , example )
try :
if "awards" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_awards_slug ON awards (slug)"
)
db . query (
"CREATE INDEX IF NOT EXISTS idx_awards_receiver_created "
"ON awards (receiver_uid, created_at)"
)
db . query (
"CREATE INDEX IF NOT EXISTS idx_awards_giver_created "
"ON awards (giver_uid, created_at)"
)
db . query (
"CREATE INDEX IF NOT EXISTS idx_awards_generated "
"ON awards (receiver_uid, generated_at)"
)
2026-07-09 02:52:54 +02:00
except Exception as e :
logger . warning ( f "Could not create awards indexes: { e } " )
2026-07-04 19:22:11 +00:00
seo_metadata = get_table ( "seo_metadata" )
for column , example in (
( "uid" , "" ),
( "target_type" , "" ),
( "target_uid" , "" ),
( "seo_title" , "" ),
( "seo_description" , "" ),
( "seo_keywords" , "" ),
( "status" , "" ),
( "source" , "" ),
( "generated_at" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not seo_metadata . has_column ( column ):
seo_metadata . create_column_by_example ( column , example )
_index (
db ,
"seo_metadata" ,
"idx_seo_metadata_target" ,
[ "target_type" , "target_uid" ],
unique = True ,
)
email_accounts = get_table ( "email_accounts" )
for column , example in (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "label" , "" ),
( "imap_host" , "" ),
( "imap_port" , 993 ),
( "imap_ssl" , 1 ),
( "imap_starttls" , 0 ),
( "smtp_host" , "" ),
( "smtp_port" , 587 ),
( "smtp_ssl" , 0 ),
( "smtp_starttls" , 1 ),
( "username" , "" ),
( "password" , "" ),
( "from_address" , "" ),
( "from_name" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not email_accounts . has_column ( column ):
email_accounts . create_column_by_example ( column , example )
_index ( db , "email_accounts" , "idx_email_accounts_owner" , [ "owner_kind" , "owner_id" ])
_index (
db ,
"email_accounts" ,
"idx_email_accounts_label" ,
[ "owner_kind" , "owner_id" , "label" ],
)
user_activity = get_table ( "user_activity" )
for column , example in (
( "user_uid" , "" ),
( "action" , "" ),
( "count" , 0 ),
( "first_at" , "" ),
( "last_at" , "" ),
):
if not user_activity . has_column ( column ):
user_activity . create_column_by_example ( column , example )
try :
if "user_activity" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_user_activity_user_action "
"ON user_activity (user_uid, action)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on user_activity: { e } " )
user_activity_seen = get_table ( "user_activity_seen" )
for column , example in (
( "user_uid" , "" ),
( "action" , "" ),
( "target" , "" ),
( "created_at" , "" ),
):
if not user_activity_seen . has_column ( column ):
user_activity_seen . create_column_by_example ( column , example )
try :
if "user_activity_seen" in db . tables :
2026-07-19 18:57:43 +02:00
with db :
db . query (
"CREATE UNIQUE INDEX IF NOT EXISTS idx_user_activity_seen_unique "
"ON user_activity_seen (user_uid, action, target)"
)
2026-07-04 19:22:11 +00:00
except Exception as e :
logger . warning ( f "Could not create unique index on user_activity_seen: { e } " )
deepsearch_sessions = get_table ( "deepsearch_sessions" )
for column , example in (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "query" , "" ),
( "status" , "" ),
( "depth" , 0 ),
( "max_pages" , 0 ),
( "score" , 0 ),
( "confidence" , 0.0 ),
( "source_diversity" , 0.0 ),
( "page_count" , 0 ),
( "chunk_count" , 0 ),
( "collection" , "" ),
( "summary" , "" ),
( "created_at" , "" ),
( "completed_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not deepsearch_sessions . has_column ( column ):
deepsearch_sessions . create_column_by_example ( column , example )
_index ( db , "deepsearch_sessions" , "idx_deepsearch_sessions_owner" , [ "owner_kind" , "owner_id" ])
_index ( db , "deepsearch_sessions" , "idx_deepsearch_sessions_status" , [ "status" ])
_index ( db , "deepsearch_sessions" , "idx_deepsearch_sessions_created" , [ "created_at" ])
deepsearch_messages = get_table ( "deepsearch_messages" )
for column , example in (
( "uid" , "" ),
( "session_uid" , "" ),
( "role" , "" ),
( "content" , "" ),
( "citations" , "" ),
( "created_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not deepsearch_messages . has_column ( column ):
deepsearch_messages . create_column_by_example ( column , example )
_index ( db , "deepsearch_messages" , "idx_deepsearch_messages_session" , [ "session_uid" ])
deepsearch_url_cache = get_table ( "deepsearch_url_cache" )
for column , example in (
( "uid" , "" ),
( "url_hash" , "" ),
( "url" , "" ),
( "title" , "" ),
( "content_hash" , "" ),
( "status" , 0 ),
( "byte_size" , 0 ),
( "fetched_at" , "" ),
):
if not deepsearch_url_cache . has_column ( column ):
deepsearch_url_cache . create_column_by_example ( column , example )
_index ( db , "deepsearch_url_cache" , "idx_deepsearch_url_cache_hash" , [ "url_hash" ])
2026-07-06 03:57:47 +00:00
isslop_analyses = get_table ( "isslop_analyses" )
for column , example in (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "source_url" , "" ),
( "source_kind" , "" ),
( "status" , "" ),
( "created_at" , "" ),
( "finished_at" , "" ),
( "content_hash" , "" ),
( "grade" , "" ),
( "slop_score" , 0.0 ),
( "origin_score" , 0.0 ),
( "quality_deficit_score" , 0.0 ),
( "human_percent" , 0.0 ),
( "ai_percent" , 0.0 ),
( "category" , "" ),
( "confidence" , "" ),
( "files_total" , 0 ),
( "files_analyzed" , 0 ),
( "error_message_text" , "" ),
( "detected_builder" , "" ),
( "dom_slop_score" , 0.0 ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not isslop_analyses . has_column ( column ):
isslop_analyses . create_column_by_example ( column , example )
_index ( db , "isslop_analyses" , "idx_isslop_analyses_owner" , [ "owner_kind" , "owner_id" , "created_at" ])
_index ( db , "isslop_analyses" , "idx_isslop_analyses_status" , [ "status" ])
_index ( db , "isslop_analyses" , "idx_isslop_analyses_hash" , [ "content_hash" ])
isslop_events = get_table ( "isslop_events" )
for column , example in (
( "analysis_uid" , "" ),
( "seq" , 0 ),
( "kind" , "" ),
( "message" , "" ),
( "payload" , "" ),
( "created_at" , "" ),
):
if not isslop_events . has_column ( column ):
isslop_events . create_column_by_example ( column , example )
_index ( db , "isslop_events" , "idx_isslop_events_analysis" , [ "analysis_uid" , "seq" ])
isslop_file_results = get_table ( "isslop_file_results" )
for column , example in (
( "analysis_uid" , "" ),
( "path" , "" ),
( "language" , "" ),
( "lines" , 0 ),
( "origin_score" , 0.0 ),
( "quality_deficit_score" , 0.0 ),
( "category" , "" ),
( "signals" , "" ),
( "source" , "" ),
):
if not isslop_file_results . has_column ( column ):
isslop_file_results . create_column_by_example ( column , example )
_index ( db , "isslop_file_results" , "idx_isslop_file_results_analysis" , [ "analysis_uid" ])
isslop_image_results = get_table ( "isslop_image_results" )
for column , example in (
( "analysis_uid" , "" ),
( "path" , "" ),
( "ai_probability" , 0.0 ),
( "grade" , "" ),
( "verdict" , "" ),
( "image_kind" , "" ),
( "tells" , "" ),
( "description" , "" ),
( "thumb" , "" ),
):
if not isslop_image_results . has_column ( column ):
isslop_image_results . create_column_by_example ( column , example )
_index ( db , "isslop_image_results" , "idx_isslop_image_results_analysis" , [ "analysis_uid" ])
isslop_dom_results = get_table ( "isslop_dom_results" )
for column , example in (
( "analysis_uid" , "" ),
( "url" , "" ),
( "detected_builder" , "" ),
( "signal_count" , 0 ),
( "screenshot" , "" ),
( "signals" , "" ),
):
if not isslop_dom_results . has_column ( column ):
isslop_dom_results . create_column_by_example ( column , example )
_index ( db , "isslop_dom_results" , "idx_isslop_dom_results_analysis" , [ "analysis_uid" ])
isslop_reports = get_table ( "isslop_reports" )
for column , example in (
( "analysis_uid" , "" ),
( "markdown" , "" ),
( "model_used" , "" ),
( "generated_at" , "" ),
):
if not isslop_reports . has_column ( column ):
isslop_reports . create_column_by_example ( column , example )
_index ( db , "isslop_reports" , "idx_isslop_reports_analysis" , [ "analysis_uid" ], unique = True )
2026-07-04 19:22:11 +00:00
game_farms = get_table ( "game_farms" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "coins" , 0 ),
( "xp" , 0 ),
( "level" , 1 ),
( "ci_tier" , 1 ),
( "plot_count" , 0 ),
( "total_harvests" , 0 ),
( "prestige" , 0 ),
( "streak" , 0 ),
( "last_daily_at" , "" ),
( "perk_yield" , 0 ),
( "perk_growth" , 0 ),
( "perk_discount" , 0 ),
( "perk_xp" , 0 ),
( "stars" , 0 ),
( "legacy_autoharvest" , 0 ),
( "legacy_multiplier" , 0 ),
( "legacy_speed" , 0 ),
( "legacy_plots" , 0 ),
( "legacy_defense" , 0 ),
2026-07-23 01:14:10 +02:00
( "legacy_carryover" , 0 ),
( "last_grant_week" , "" ),
2026-07-21 03:36:29 +02:00
( "prestiged_at" , "" ),
( "mastery_points" , 0 ),
( "mastery_points_earned_total" , 0 ),
( "mastery_autoreplant" , 0 ),
( "mastery_analytics" , 0 ),
( "mastery_contracts" , 0 ),
( "lifetime_coins_earned" , 0 ),
( "lifetime_harvests" , 0 ),
( "infra_registry" , 0 ),
( "infra_canary" , 0 ),
( "infra_observability" , 0 ),
( "defense_level" , 0 ),
( "defense_last_upkeep_at" , "" ),
2026-07-26 14:57:18 +02:00
( "upkeep_amnesty" , 0 ),
2026-07-21 03:36:29 +02:00
( "active_title" , "" ),
( "underdog_boost_until" , "" ),
( "contract_boost_until" , "" ),
( "harvests_week" , 0 ),
( "harvests_week_start" , "" ),
( "last_kernel_harvest_prestige" , 0 ),
( "time_to_kernel_seconds" , 0 ),
( "era_coins" , 0 ),
( "era_harvests" , 0 ),
( "era_joined_at" , "" ),
2026-07-04 19:22:11 +00:00
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not game_farms . has_column ( column ):
game_farms . create_column_by_example ( column , example )
_index ( db , "game_farms" , "idx_game_farms_user" , [ "user_uid" ], unique = True )
_index ( db , "game_farms" , "idx_game_farms_rank" , [ "level" , "xp" ])
game_steals = get_table ( "game_steals" )
for column , example in (
( "uid" , "" ),
( "thief_uid" , "" ),
( "owner_uid" , "" ),
( "slot_index" , 0 ),
( "crop_key" , "" ),
( "coins" , 0 ),
( "stolen_at" , "" ),
( "created_at" , "" ),
):
if not game_steals . has_column ( column ):
game_steals . create_column_by_example ( column , example )
_index (
db , "game_steals" , "idx_game_steals_pair" , [ "thief_uid" , "owner_uid" , "stolen_at" ]
)
2026-07-26 14:57:18 +02:00
_index ( db , "game_steals" , "idx_game_steals_owner_time" , [ "owner_uid" , "stolen_at" ])
2026-07-04 19:22:11 +00:00
game_quests = get_table ( "game_quests" )
for column , example in (
( "uid" , "" ),
( "farm_uid" , "" ),
( "user_uid" , "" ),
( "day" , "" ),
2026-07-21 03:36:29 +02:00
( "scope" , "daily" ),
2026-07-04 19:22:11 +00:00
( "slot_index" , 0 ),
( "kind" , "" ),
( "label" , "" ),
( "goal" , 0 ),
( "progress" , 0 ),
( "reward_coins" , 0 ),
( "reward_xp" , 0 ),
2026-07-21 03:36:29 +02:00
( "reward_stars" , 0 ),
2026-07-04 19:22:11 +00:00
( "claimed" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not game_quests . has_column ( column ):
game_quests . create_column_by_example ( column , example )
2026-07-21 03:36:29 +02:00
with db :
db . query ( "UPDATE game_quests SET scope = 'daily' WHERE scope IS NULL OR scope = ''" )
2026-07-04 19:22:11 +00:00
_index ( db , "game_quests" , "idx_game_quests_farm_day" , [ "farm_uid" , "day" ])
2026-07-21 03:36:29 +02:00
_index ( db , "game_quests" , "idx_game_quests_farm_day_scope" , [ "farm_uid" , "day" , "scope" ])
2026-07-04 19:22:11 +00:00
game_plots = get_table ( "game_plots" )
for column , example in (
( "uid" , "" ),
( "farm_uid" , "" ),
( "user_uid" , "" ),
( "slot_index" , 0 ),
( "crop_key" , "" ),
( "planted_at" , "" ),
( "ready_at" , "" ),
( "watered_by" , "[]" ),
2026-07-26 14:57:18 +02:00
( "raided_fraction" , 0.0 ),
2026-07-04 19:22:11 +00:00
( "created_at" , "" ),
( "updated_at" , "" ),
):
if not game_plots . has_column ( column ):
game_plots . create_column_by_example ( column , example )
_index ( db , "game_plots" , "idx_game_plots_farm" , [ "farm_uid" , "slot_index" ])
2026-07-21 03:36:29 +02:00
game_market_ticks = get_table ( "game_market_ticks" )
for column , example in (
( "uid" , "" ),
( "crop_key" , "" ),
( "hour_bucket" , "" ),
( "harvests" , 0 ),
( "updated_at" , "" ),
):
if not game_market_ticks . has_column ( column ):
game_market_ticks . create_column_by_example ( column , example )
_index (
db ,
"game_market_ticks" ,
"idx_game_market_ticks_bucket" ,
[ "crop_key" , "hour_bucket" ],
unique = True ,
)
game_cosmetics = get_table ( "game_cosmetics" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "cosmetic_key" , "" ),
( "purchased_at" , "" ),
( "created_at" , "" ),
):
if not game_cosmetics . has_column ( column ):
game_cosmetics . create_column_by_example ( column , example )
_index (
db ,
"game_cosmetics" ,
"idx_game_cosmetics_owner" ,
[ "user_uid" , "cosmetic_key" ],
unique = True ,
)
2026-07-23 01:14:10 +02:00
game_treasury = get_table ( "game_treasury" )
for column , example in (
( "uid" , "" ),
( "balance" , 0 ),
( "collected_total" , 0 ),
( "granted_total" , 0 ),
( "updated_at" , "" ),
):
if not game_treasury . has_column ( column ):
game_treasury . create_column_by_example ( column , example )
2026-07-21 03:36:29 +02:00
game_eras = get_table ( "game_eras" )
for column , example in (
( "uid" , "" ),
( "era_number" , 0 ),
( "name" , "" ),
( "started_at" , "" ),
( "ends_at" , "" ),
( "active" , 0 ),
( "created_at" , "" ),
):
if not game_eras . has_column ( column ):
game_eras . create_column_by_example ( column , example )
_index ( db , "game_eras" , "idx_game_eras_active" , [ "active" ])
game_era_results = get_table ( "game_era_results" )
for column , example in (
( "uid" , "" ),
( "era_number" , 0 ),
( "user_uid" , "" ),
( "rank" , 0 ),
( "era_score" , 0 ),
( "era_coins_final" , 0 ),
2026-07-26 14:57:18 +02:00
( "joined_at" , "" ),
2026-07-21 03:36:29 +02:00
( "reward_stars" , 0 ),
( "reward_cosmetic_key" , "" ),
( "created_at" , "" ),
):
if not game_era_results . has_column ( column ):
game_era_results . create_column_by_example ( column , example )
_index ( db , "game_era_results" , "idx_game_era_results_era" , [ "era_number" , "rank" ])
2026-07-26 14:57:18 +02:00
quizzes = get_table ( "quizzes" )
for column , example in (
( "uid" , "" ),
( "user_uid" , "" ),
( "slug" , "" ),
( "title" , "" ),
( "description" , "" ),
( "status" , "draft" ),
( "published_at" , "" ),
( "shuffle_questions" , 0 ),
( "shuffle_options" , 0 ),
( "reveal_answers" , 0 ),
( "allow_review" , 0 ),
( "time_limit_seconds" , 0 ),
( "pass_percent" , 0 ),
( "question_count" , 0 ),
( "total_points" , 0 ),
( "attempt_count" , 0 ),
( "stars" , 0 ),
( "content_version" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not quizzes . has_column ( column ):
quizzes . create_column_by_example ( column , example )
_index ( db , "quizzes" , "idx_quizzes_slug" , [ "slug" ], unique = True )
_index ( db , "quizzes" , "idx_quizzes_user_created" , [ "user_uid" , "created_at" ])
_index ( db , "quizzes" , "idx_quizzes_status_created" , [ "status" , "created_at" ])
_index (
db ,
"quizzes" ,
"idx_quizzes_live_created" ,
[ "created_at" ],
where = "deleted_at IS NULL" ,
)
quiz_questions = get_table ( "quiz_questions" )
for column , example in (
( "uid" , "" ),
( "quiz_uid" , "" ),
( "position" , 0 ),
( "kind" , "" ),
( "prompt" , "" ),
( "explanation" , "" ),
( "points" , 1 ),
( "media_attachment_uid" , "" ),
( "correct_boolean" , 0 ),
( "expected_answer" , "" ),
( "grading_criteria" , "" ),
( "numeric_value" , 0.0 ),
( "numeric_tolerance" , 0.0 ),
( "case_sensitive" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not quiz_questions . has_column ( column ):
quiz_questions . create_column_by_example ( column , example )
_index (
db , "quiz_questions" , "idx_quiz_questions_quiz_position" , [ "quiz_uid" , "position" ]
)
quiz_options = get_table ( "quiz_options" )
for column , example in (
( "uid" , "" ),
( "question_uid" , "" ),
( "quiz_uid" , "" ),
( "position" , 0 ),
( "label" , "" ),
( "match_value" , "" ),
( "is_correct" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not quiz_options . has_column ( column ):
quiz_options . create_column_by_example ( column , example )
_index (
db ,
"quiz_options" ,
"idx_quiz_options_question_position" ,
[ "question_uid" , "position" ],
)
_index ( db , "quiz_options" , "idx_quiz_options_quiz" , [ "quiz_uid" ])
quiz_attempts = get_table ( "quiz_attempts" )
for column , example in (
( "uid" , "" ),
( "quiz_uid" , "" ),
( "user_uid" , "" ),
( "status" , "in_progress" ),
( "question_order" , "[]" ),
( "started_at" , "" ),
( "expires_at" , "" ),
( "completed_at" , "" ),
( "answered_count" , 0 ),
( "score_points" , 0.0 ),
( "max_points" , 0 ),
( "score_percent" , 0.0 ),
( "passed" , 0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not quiz_attempts . has_column ( column ):
quiz_attempts . create_column_by_example ( column , example )
_index ( db , "quiz_attempts" , "idx_quiz_attempts_user_created" , [ "user_uid" , "created_at" ])
_index ( db , "quiz_attempts" , "idx_quiz_attempts_quiz_status" , [ "quiz_uid" , "status" ])
_index ( db , "quiz_attempts" , "idx_quiz_attempts_user_quiz" , [ "user_uid" , "quiz_uid" ])
_index ( db , "quiz_attempts" , "idx_quiz_attempts_status_user" , [ "status" , "user_uid" ])
quiz_answers = get_table ( "quiz_answers" )
for column , example in (
( "uid" , "" ),
( "attempt_uid" , "" ),
( "question_uid" , "" ),
( "quiz_uid" , "" ),
( "position" , 0 ),
( "answer_text" , "" ),
( "option_uids" , "[]" ),
( "answered_at" , "" ),
( "is_correct" , 0 ),
( "awarded_points" , 0.0 ),
( "feedback" , "" ),
( "graded_by" , "" ),
( "confidence" , 0.0 ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not quiz_answers . has_column ( column ):
quiz_answers . create_column_by_example ( column , example )
_index (
db , "quiz_answers" , "idx_quiz_answers_attempt_position" , [ "attempt_uid" , "position" ]
)
_index ( db , "quiz_answers" , "idx_quiz_answers_quiz" , [ "quiz_uid" ])
2026-08-20 23:30:02 +02:00
opinion_wars = get_table ( "opinion_wars" )
for column , example in (
( "uid" , "" ),
( "post_uid" , "" ),
( "user_uid" , "" ),
( "faction_a" , "" ),
( "faction_b" , "" ),
( "hp_a" , 0 ),
( "hp_b" , 0 ),
( "leader" , "" ),
( "status" , "active" ),
( "winner" , "" ),
( "created_at" , "" ),
( "ends_at" , "" ),
( "resolved_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not opinion_wars . has_column ( column ):
opinion_wars . create_column_by_example ( column , example )
_index ( db , "opinion_wars" , "idx_opinion_wars_post" , [ "post_uid" ], unique = True )
_index ( db , "opinion_wars" , "idx_opinion_wars_status_ends" , [ "status" , "ends_at" ])
_index (
db ,
"opinion_wars" ,
"idx_opinion_wars_live_created" ,
[ "created_at" ],
where = "deleted_at IS NULL" ,
)
opinion_war_fighters = get_table ( "opinion_war_fighters" )
for column , example in (
( "uid" , "" ),
( "war_uid" , "" ),
( "user_uid" , "" ),
( "faction" , "" ),
( "hp_a" , 0 ),
( "hp_b" , 0 ),
( "fight_count" , 0 ),
( "last_fight_at" , "" ),
( "cooldown_notified_at" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not opinion_war_fighters . has_column ( column ):
opinion_war_fighters . create_column_by_example ( column , example )
_index (
db ,
"opinion_war_fighters" ,
"idx_opinion_war_fighters_war_user" ,
[ "war_uid" , "user_uid" ],
unique = True ,
)
_index (
db ,
"opinion_war_fighters" ,
"idx_opinion_war_fighters_war_faction" ,
[ "war_uid" , "faction" ],
)
_index (
db ,
"opinion_war_fighters" ,
"idx_opinion_war_fighters_last_fight" ,
[ "last_fight_at" ],
)
opinion_war_events = get_table ( "opinion_war_events" )
for column , example in (
( "uid" , "" ),
( "war_uid" , "" ),
( "seq" , 0 ),
( "kind" , "" ),
( "message" , "" ),
( "payload" , "" ),
( "actor_uid" , "" ),
( "created_at" , "" ),
( "deleted_at" , "" ),
( "deleted_by" , "" ),
):
if not opinion_war_events . has_column ( column ):
opinion_war_events . create_column_by_example ( column , example )
_index (
db ,
"opinion_war_events" ,
"idx_opinion_war_events_war_seq" ,
[ "war_uid" , "seq" ],
unique = True ,
)
2026-07-04 19:22:11 +00:00
_index ( db , "posts" , "idx_posts_user_created" , [ "user_uid" , "created_at" ])
_index (
db ,
"posts" ,
"idx_posts_live_created" ,
[ "created_at" ],
where = "deleted_at IS NULL" ,
)
_index (
db ,
"comments" ,
"idx_comments_target_created" ,
[ "target_type" , "target_uid" , "created_at" ],
)
_index ( db , "comments" , "idx_comments_user_created" , [ "user_uid" , "created_at" ])
_index ( db , "votes" , "idx_votes_user_target" , [ "user_uid" , "target_uid" ])
_index ( db , "gists" , "idx_gists_user_created" , [ "user_uid" , "created_at" ])
_index ( db , "projects" , "idx_projects_user_created" , [ "user_uid" , "created_at" ])
_index (
db ,
"notifications" ,
"idx_notifications_user_created" ,
[ "user_uid" , "created_at" ],
)
2026-08-09 00:18:20 +02:00
_ensure_moderation_tables ()
2026-07-04 19:22:11 +00:00
for table in db . tables :
_uid_index ( db , table )
for table in SOFT_DELETE_TABLES :
ensure_soft_delete_columns ( table )
_index (
db ,
"comments" ,
"idx_comments_target_live" ,
[ "target_type" , "target_uid" ],
where = "deleted_at IS NULL" ,
)
_index (
db ,
"votes" ,
"idx_votes_target_live" ,
[ "target_uid" , "value" ],
where = "deleted_at IS NULL" ,
)
_index (
db ,
"reactions" ,
"idx_reactions_target_live" ,
[ "target_type" , "target_uid" ],
where = "deleted_at IS NULL" ,
)
_index (
db ,
"gists" ,
"idx_gists_live_created" ,
[ "created_at" ],
where = "deleted_at IS NULL" ,
)
_index (
db ,
"projects" ,
"idx_projects_live_created" ,
[ "created_at" ],
where = "deleted_at IS NULL" ,
)
_index (
db ,
"attachments" ,
"idx_attachments_user_created_live" ,
[ "user_uid" , "created_at" ],
where = "deleted_at IS NULL" ,
)
_index ( db , "seo_metadata" , "idx_seo_metadata_status" , [ "status" , "deleted_at" ])
if "news" in tables :
for article in db [ "news" ] . find ( status = None ):
was_featured = article . get ( "featured" , 0 )
db [ "news" ] . update (
{
"uid" : article [ "uid" ],
"status" : "published" if was_featured else "draft" ,
},
[ "uid" ],
)
for article in db [ "news" ] . find ( show_on_landing = None ):
db [ "news" ] . update (
{
"uid" : article [ "uid" ],
"show_on_landing" : 0 ,
},
[ "uid" ],
)
for article in db [ "news" ] . find ( slug = None ):
from devplacepy.utils import make_combined_slug
slug = make_combined_slug (
article . get ( "title" , "" ) or "news" , article [ "uid" ]
)
db [ "news" ] . update (
{
"uid" : article [ "uid" ],
"slug" : slug ,
},
[ "uid" ],
)
if "news_sync" in tables :
for entry in db [ "news_sync" ] . find ():
current = entry . get ( "status" , "" )
if current in ( "below_threshold" , "" ):
db [ "news_sync" ] . update (
{
"id" : entry [ "id" ],
"status" : "graded" ,
},
[ "id" ],
)
if "site_settings" in tables :
news_defaults = {
"news_grade_threshold" : "7" ,
"news_api_url" : "https://news.app.molodetz.nl/api" ,
"news_ai_url" : INTERNAL_GATEWAY_URL ,
"news_ai_model" : "molodetz" ,
}
for key , value in news_defaults . items ():
existing = db [ "site_settings" ] . find_one ( key = key )
if not existing :
db [ "site_settings" ] . insert (
{ "uid" : f "default_ { key } " , "key" : key , "value" : value }
)
upload_defaults = {
"max_upload_size_mb" : "10" ,
"allowed_file_types" : "" ,
"max_attachments_per_resource" : "10" ,
}
for key , value in upload_defaults . items ():
existing = db [ "site_settings" ] . find_one ( key = key )
if not existing :
db [ "site_settings" ] . insert (
{ "uid" : f "default_ { key } " , "key" : key , "value" : value }
)
operational_defaults = {
"rate_limit_per_minute" : "60" ,
"rate_limit_window_seconds" : "60" ,
"news_service_interval" : "3600" ,
"session_max_age_days" : "7" ,
"session_remember_days" : "30" ,
"registration_open" : "1" ,
"maintenance_mode" : "0" ,
"maintenance_message" : "DevPlace is undergoing scheduled maintenance. Please check back shortly." ,
"customization_enabled" : "1" ,
"customization_js_enabled" : "1" ,
"audit_log_retention_days" : "90" ,
2026-07-09 02:52:54 +02:00
"statistics_tracking_enabled" : "1" ,
2026-07-04 19:22:11 +00:00
"docs_search_mode" : "agent" ,
2026-07-09 02:52:54 +02:00
"outbound_proxy_url" : "" ,
2026-08-16 01:50:59 +00:00
"ios_app_url" : "https://apps.apple.com/app/devplace/id6797215143" ,
2026-07-19 18:57:43 +02:00
"devii_lessons_max_per_owner" : "500" ,
"devii_lessons_max_age_days" : "90" ,
2026-08-09 00:18:20 +02:00
"moderation_sla_hours" : "24" ,
"moderation_filter_mode" : "review" ,
"moderation_filter_review_score" : "2" ,
"moderation_minimum_age" : "16" ,
"moderation_mature_default_hidden" : "1" ,
"contact_email" : "" ,
"contact_phone" : "" ,
"contact_address" : "" ,
"terms_version" : "1" ,
"privacy_version" : "1" ,
"guidelines_version" : "1" ,
"ai_third_party_provider" : "" ,
"account_deletion_grace_hours" : "24" ,
2026-07-04 19:22:11 +00:00
}
for key , value in operational_defaults . items ():
existing = db [ "site_settings" ] . find_one ( key = key )
if not existing :
db [ "site_settings" ] . insert (
{ "uid" : f "default_ { key } " , "key" : key , "value" : value }
)
2026-07-09 02:52:54 +02:00
with db :
db . query (
"CREATE TABLE IF NOT EXISTS visit_stats_hourly ("
"bucket_start TEXT NOT NULL, "
"page_group TEXT NOT NULL, "
"referrer_group TEXT NOT NULL, "
"views INTEGER NOT NULL DEFAULT 0, "
"member_views INTEGER NOT NULL DEFAULT 0, "
"guest_views INTEGER NOT NULL DEFAULT 0)"
)
db . query (
"CREATE TABLE IF NOT EXISTS visit_unique_slots ("
"bucket_start TEXT NOT NULL, "
"visitor_hash TEXT NOT NULL, "
"page_group TEXT NOT NULL, "
"user_uid TEXT)"
)
_index ( db , "visit_stats_hourly" , "idx_visit_hourly_bucket" , [ "bucket_start" ])
_index (
db ,
"visit_stats_hourly" ,
"idx_visit_hourly_page_time" ,
[ "page_group" , "bucket_start" ],
)
_index (
db ,
"visit_stats_hourly" ,
"idx_visit_hourly_ref_time" ,
[ "referrer_group" , "bucket_start" ],
)
_index (
db ,
"visit_stats_hourly" ,
"idx_visit_hourly_unique_row" ,
[ "bucket_start" , "page_group" , "referrer_group" ],
unique = True ,
)
_index ( db , "visit_unique_slots" , "idx_visit_unique_bucket" , [ "bucket_start" ])
_index (
db ,
"visit_unique_slots" ,
"idx_visit_unique_hash" ,
[ "bucket_start" , "visitor_hash" ],
)
_index (
db ,
"visit_unique_slots" ,
"idx_visit_unique_row" ,
[ "bucket_start" , "visitor_hash" , "page_group" ],
unique = True ,
)
_index ( db , "issue_tickets" , "idx_issue_tickets_created" , [ "created_at" ])
_index ( db , "devii_turns" , "idx_devii_turns_started" , [ "started_at" ])
_index ( db , "instance_events" , "idx_instance_events_created" , [ "created_at" ])
_index ( db , "game_steals" , "idx_game_steals_stolen_at" , [ "stolen_at" ])
_index ( db , "messages" , "idx_messages_created_at" , [ "created_at" ])
_index ( db , "notifications" , "idx_notifications_created" , [ "created_at" ])
_index ( db , "follows" , "idx_follows_created_at" , [ "created_at" ])
_index ( db , "reactions" , "idx_reactions_created_at" , [ "created_at" ])
_index ( db , "votes" , "idx_votes_created_at" , [ "created_at" ])
_index ( db , "bookmarks" , "idx_bookmarks_created_at" , [ "created_at" ])
_index ( db , "badges" , "idx_badges_created_at" , [ "created_at" ])
_index ( db , "audit_log" , "idx_audit_result_created" , [ "result" , "created_at" ])
_index ( db , "jobs" , "idx_jobs_created_at" , [ "created_at" ])
_index ( db , "attachments" , "idx_attachments_created_at" , [ "created_at" ])
2026-07-04 19:22:11 +00:00
_backfill_gamification ()
backfill_api_keys ()
migrate_ai_gateway_settings ()
_refresh_query_planner_stats ()
2026-08-09 00:18:20 +02:00
MODERATION_COLUMNS : dict [ str , tuple [ tuple [ str , object ], ... ]] = {
"content_reports" : (
( "uid" , "" ),
( "reporter_uid" , "" ),
( "target_type" , "" ),
( "target_uid" , "" ),
( "owner_uid" , "" ),
( "reason" , "" ),
( "detail" , "" ),
( "severity" , "warn" ),
( "status" , "open" ),
( "origin" , "member" ),
( "categories" , "" ),
( "resolved_by" , "" ),
( "resolved_at" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
),
"moderation_actions" : (
( "uid" , "" ),
( "report_uid" , "" ),
( "actor_uid" , "" ),
( "action" , "" ),
( "target_type" , "" ),
( "target_uid" , "" ),
( "subject_uid" , "" ),
( "reason" , "" ),
( "notes" , "" ),
( "expires_at" , "" ),
( "created_at" , "" ),
),
"content_maturity" : (
( "uid" , "" ),
( "target_type" , "" ),
( "target_uid" , "" ),
( "level" , "general" ),
( "source" , "" ),
( "set_by" , "" ),
( "created_at" , "" ),
( "updated_at" , "" ),
),
"user_consents" : (
( "uid" , "" ),
( "owner_kind" , "" ),
( "owner_id" , "" ),
( "kind" , "" ),
( "version" , "1" ),
( "state" , "" ),
( "granted_at" , "" ),
( "withdrawn_at" , "" ),
( "created_at" , "" ),
),
}
MODERATION_INDEXES : tuple [ tuple [ str , str , list [ str ]], ... ] = (
( "content_reports" , "idx_content_reports_queue" , [ "status" , "created_at" ]),
( "content_reports" , "idx_content_reports_target" , [ "target_type" , "target_uid" ]),
( "content_reports" , "idx_content_reports_reporter" , [ "reporter_uid" ]),
( "content_reports" , "idx_content_reports_owner" , [ "owner_uid" ]),
( "moderation_actions" , "idx_moderation_actions_report" , [ "report_uid" ]),
( "moderation_actions" , "idx_moderation_actions_subject" , [ "subject_uid" ]),
( "moderation_actions" , "idx_moderation_actions_created" , [ "created_at" ]),
( "content_maturity" , "idx_content_maturity_target" , [ "target_type" , "target_uid" ]),
( "user_consents" , "idx_user_consents_owner" , [ "owner_kind" , "owner_id" , "kind" ]),
)
def _ensure_moderation_tables () -> None :
for table_name , columns in MODERATION_COLUMNS . items ():
table = get_table ( table_name )
for column , example in columns :
if not table . has_column ( column ):
table . create_column_by_example ( column , example )
for table_name , index_name , columns in MODERATION_INDEXES :
_index ( db , table_name , index_name , columns )
2026-07-04 19:22:11 +00:00
def _refresh_query_planner_stats () -> None :
try :
has_stats = bool (
list ( db . query ( "SELECT name FROM sqlite_master WHERE name='sqlite_stat1'" ))
)
with db :
if not has_stats :
db . query ( "ANALYZE" )
db . query ( "PRAGMA optimize" )
except Exception as e :
logger . warning ( f "Could not refresh query planner stats: { e } " )
logger . info ( "Database initialized" )
OLD_GATEWAY_URL = "https://openai.app.molodetz.nl/v1/chat/completions"
def migrate_ai_gateway_settings () -> None :
import os
import uuid
if not get_setting ( "gateway_internal_key" , "" ):
set_setting ( "gateway_internal_key" , str ( uuid . uuid4 ()))
logger . info ( "Generated internal gateway key" )
deepseek = os . environ . get ( "DEEPSEEK_API_KEY" , "" )
openrouter = os . environ . get ( "OPENROUTER_API_KEY" , "" )
if not get_setting ( "gateway_api_key" , "" ) and ( deepseek or openrouter ):
set_setting ( "gateway_api_key" , deepseek or openrouter )
logger . info ( "Migrated gateway upstream key from environment" )
if not get_setting ( "gateway_vision_key" , "" ) and openrouter :
set_setting ( "gateway_vision_key" , openrouter )
logger . info ( "Migrated gateway vision key from environment" )
for key in ( "news_ai_url" , "bot_api_url" , "devii_ai_url" ):
if get_setting ( key , "" ) == OLD_GATEWAY_URL :
set_setting ( key , INTERNAL_GATEWAY_URL )
logger . info ( f "Migrated { key } to the internal gateway" )
if get_setting ( "bot_model" , "" ) == "deepseek-chat" :
set_setting ( "bot_model" , "molodetz" )
logger . info ( "Migrated bot_model to molodetz" )
2026-07-09 02:52:54 +02:00
from devplacepy.services.openai_gateway.routing import (
migrate_retired_image_gateway ,
seed_default_deepseek_routes ,
seed_default_image_routes ,
)
seed_default_deepseek_routes ()
seed_default_image_routes ()
migrate_retired_image_gateway ()
2026-07-04 19:22:11 +00:00
2026-09-03 04:19:58 +00:00
def _ensure_users_uid () -> int :
if "users" not in db . tables :
return 0
users = get_table ( "users" )
if not users . has_column ( "uid" ):
users . create_column_by_example ( "uid" , "" )
import uuid_utils
updated = 0
for user in users . find ():
if not user . get ( "uid" ):
users . update (
{ "id" : user [ "id" ], "uid" : str ( uuid_utils . uuid7 ())}, [ "id" ]
)
updated += 1
if updated :
logger . info ( "Backfilled uid for %s user(s)" , updated )
return updated
2026-07-04 19:22:11 +00:00
def backfill_api_keys () -> int :
2026-08-06 19:19:21 +02:00
users = get_table ( "users" )
2026-07-04 19:22:11 +00:00
if not users . has_column ( "api_key" ):
users . create_column_by_example ( "api_key" , "" )
2026-07-26 16:45:38 +02:00
if not users . has_column ( "created_at" ):
users . create_column_by_example ( "created_at" , "" )
2026-07-04 19:22:11 +00:00
if not users . has_column ( "cust_disable_global" ):
users . create_column_by_example ( "cust_disable_global" , 0 )
if not users . has_column ( "cust_disable_pagetype" ):
users . create_column_by_example ( "cust_disable_pagetype" , 0 )
if not users . has_column ( "ai_correction_enabled" ):
users . create_column_by_example ( "ai_correction_enabled" , 0 )
if not users . has_column ( "ai_correction_prompt" ):
users . create_column_by_example ( "ai_correction_prompt" , DEFAULT_CORRECTION_PROMPT )
if not users . has_column ( "ai_correction_sync" ):
users . create_column_by_example ( "ai_correction_sync" , 0 )
if not users . has_column ( "ai_modifier_enabled" ):
users . create_column_by_example ( "ai_modifier_enabled" , 1 )
if not users . has_column ( "ai_modifier_sync" ):
users . create_column_by_example ( "ai_modifier_sync" , 1 )
if not users . has_column ( "ai_modifier_prompt" ):
users . create_column_by_example ( "ai_modifier_prompt" , DEFAULT_MODIFIER_PROMPT )
2026-07-19 18:57:43 +02:00
if not users . has_column ( "interactions_enabled" ):
users . create_column_by_example ( "interactions_enabled" , - 1 )
2026-07-04 19:22:11 +00:00
if not users . has_column ( "timezone" ):
users . create_column_by_example ( "timezone" , "" )
if not users . has_column ( "avatar_seed" ):
users . create_column_by_example ( "avatar_seed" , "" )
2026-07-04 22:08:20 +00:00
if not users . has_column ( "last_seen" ):
users . create_column_by_example ( "last_seen" , "" )
2026-07-09 02:52:54 +02:00
if not users . has_column ( "award_count" ):
users . create_column_by_example ( "award_count" , 0 )
if not users . has_column ( "last_award_at" ):
users . create_column_by_example ( "last_award_at" , "" )
if not users . has_column ( "last_award_slug" ):
users . create_column_by_example ( "last_award_slug" , "" )
if not users . has_column ( "last_award_uid" ):
users . create_column_by_example ( "last_award_uid" , "" )
2026-08-09 00:18:20 +02:00
if not users . has_column ( "terms_version" ):
users . create_column_by_example ( "terms_version" , "" )
if not users . has_column ( "terms_accepted_at" ):
users . create_column_by_example ( "terms_accepted_at" , "" )
if not users . has_column ( "age_band" ):
users . create_column_by_example ( "age_band" , "" )
if not users . has_column ( "age_declared_at" ):
users . create_column_by_example ( "age_declared_at" , "" )
if not users . has_column ( "mature_opt_in" ):
users . create_column_by_example ( "mature_opt_in" , 0 )
if not users . has_column ( "suspended_until" ):
users . create_column_by_example ( "suspended_until" , "" )
if not users . has_column ( "suspension_reason" ):
users . create_column_by_example ( "suspension_reason" , "" )
if not users . has_column ( "deletion_requested_at" ):
users . create_column_by_example ( "deletion_requested_at" , "" )
2026-07-04 19:22:11 +00:00
with db :
db . query (
"UPDATE users SET ai_modifier_enabled = 1 WHERE ai_modifier_enabled IS NULL"
)
db . query ( "UPDATE users SET ai_modifier_sync = 1 WHERE ai_modifier_sync IS NULL" )
db . query (
"UPDATE users SET ai_modifier_prompt = :prompt "
"WHERE ai_modifier_prompt IS NULL OR ai_modifier_prompt = ''" ,
prompt = DEFAULT_MODIFIER_PROMPT ,
)
2026-07-19 18:57:43 +02:00
db . query (
"UPDATE users SET interactions_enabled = -1 "
"WHERE interactions_enabled IS NULL"
)
2026-08-09 00:18:20 +02:00
db . query ( "UPDATE users SET mature_opt_in = 0 WHERE mature_opt_in IS NULL" )
2026-07-04 19:22:11 +00:00
import uuid_utils
updated = 0
for user in users . find ():
if not user . get ( "api_key" ):
users . update (
{ "uid" : user [ "uid" ], "api_key" : str ( uuid_utils . uuid7 ())}, [ "uid" ]
)
updated += 1
return updated
2026-07-27 11:17:48 +02:00
MILESTONE_SOURCES = (
( "posts" , "user_uid" ),
( "comments" , "user_uid" ),
( "projects" , "user_uid" ),
( "gists" , "user_uid" ),
( "follows" , "follower_uid" ),
( "follows" , "following_uid" ),
( "user_activity" , "user_uid" ),
)
def _milestone_candidates () -> set :
tables = db . tables
candidates = set ()
for table , column in MILESTONE_SOURCES :
if table not in tables :
continue
for row in db . query ( f "SELECT DISTINCT { column } AS uid FROM { table } " ):
if row [ "uid" ]:
candidates . add ( row [ "uid" ])
return candidates
2026-07-04 19:22:11 +00:00
def _backfill_gamification ():
if "users" not in db . tables :
return
from devplacepy.utils import (
level_for_xp ,
check_milestone_badges ,
XP_POST ,
XP_COMMENT ,
XP_PROJECT ,
XP_GIST ,
XP_UPVOTE ,
XP_FOLLOW ,
)
pending = list ( db [ "users" ] . find ( xp = 0 ))
if not pending :
return
xp_by_user = defaultdict ( int )
def add_counts ( table , column , points ):
if table not in db . tables :
return
for row in db . query (
f "SELECT { column } AS uid, COUNT(*) AS c FROM { table } GROUP BY { column } "
):
if row [ "uid" ]:
xp_by_user [ row [ "uid" ]] += row [ "c" ] * points
add_counts ( "posts" , "user_uid" , XP_POST )
add_counts ( "comments" , "user_uid" , XP_COMMENT )
add_counts ( "projects" , "user_uid" , XP_PROJECT )
add_counts ( "gists" , "user_uid" , XP_GIST )
add_counts ( "follows" , "following_uid" , XP_FOLLOW )
if "votes" in db . tables :
for content_table , target_type in (
( "posts" , "post" ),
( "projects" , "project" ),
( "gists" , "gist" ),
( "comments" , "comment" ),
):
if content_table not in db . tables :
continue
rows = db . query (
f "SELECT c.user_uid AS uid, COUNT(*) AS c "
f "FROM votes v JOIN { content_table } c ON v.target_uid = c.uid "
f "WHERE v.target_type = :t AND v.value = 1 GROUP BY c.user_uid" ,
t = target_type ,
)
for row in rows :
if row [ "uid" ]:
xp_by_user [ row [ "uid" ]] += row [ "c" ] * XP_UPVOTE
for user in pending :
xp = xp_by_user . get ( user [ "uid" ], 0 )
if xp <= 0 :
continue
db [ "users" ] . update (
{ "uid" : user [ "uid" ], "xp" : xp , "level" : level_for_xp ( xp )}, [ "uid" ]
)
_authors_cache . clear ()
2026-07-27 11:17:48 +02:00
candidates = _milestone_candidates ()
checked = [ user for user in pending if user [ "uid" ] in candidates ]
for user in checked :
2026-07-04 19:22:11 +00:00
check_milestone_badges ( user [ "uid" ])
2026-07-27 11:17:48 +02:00
logger . info (
f "Gamification backfill processed { len ( pending ) } users, "
f " { len ( checked ) } with milestone-eligible activity"
)
2026-07-26 20:50:56 +00:00
2026-08-16 01:50:59 +00:00