create table if not exists "user" ( uid uuid not null primary key, username varchar(255) not null, display_name varchar(255), avatar_url varchar(255), website_url varchar(255), organization varchar(255), last_sign_in_at timestamp with time zone, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_user_username on "user" (username); create table if not exists user_password ( "user" uuid not null primary key, password_hash varchar(255) not null, password_salt varchar(255), is_active boolean default true not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create table if not exists user_email ( "user" uuid not null primary key, email varchar(255) not null, created_at timestamp with time zone not null ); create index if not exists idx_user_email_email on user_email (email); create table if not exists user_2fa ( "user" uuid not null primary key, method varchar(255) not null, secret varchar(255), backup_codes jsonb not null, is_enabled boolean default false not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create table if not exists user_notification ( "user" uuid not null primary key, email_enabled boolean default false not null, in_app_enabled boolean default true not null, push_enabled boolean default false not null, digest_mode varchar(255) not null, dnd_enabled boolean default false not null, dnd_start_minute integer, dnd_end_minute integer, marketing_enabled boolean default true not null, security_enabled boolean default true not null, product_enabled boolean default true not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, push_subscription_endpoint text, push_subscription_keys_p256dh text, push_subscription_keys_auth text ); create table if not exists user_preferences ( "user" uuid not null primary key, language varchar(255) not null, theme varchar(255) not null, timezone varchar(255) not null, email_notifications boolean default true not null, in_app_notifications boolean default true not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create table if not exists user_password_reset ( token varchar(255) not null primary key, user_uid uuid not null, expires_at timestamp with time zone not null, used boolean default false not null, created_at timestamp with time zone not null ); create index if not exists idx_user_password_reset_user_uid on user_password_reset (user_uid); create table if not exists user_relation ( id bigserial primary key, "user" uuid not null, target uuid not null, relation_type varchar(255) not null, created_at timestamp with time zone not null ); create index if not exists idx_user_relation_user on user_relation ("user"); create index if not exists idx_user_relation_target on user_relation (target); create table if not exists user_ssh_key ( id bigserial primary key, "user" uuid not null, title varchar(255) not null, public_key text not null, fingerprint varchar(255) not null, key_type varchar(255) not null, key_bits integer, is_verified boolean default false not null, last_used_at timestamp with time zone, expires_at timestamp with time zone, is_revoked boolean default false not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_user_ssh_key_user on user_ssh_key ("user"); create table if not exists user_token ( id bigserial primary key, "user" uuid not null, name varchar(255) not null, token_hash varchar(255) not null, scopes jsonb not null, expires_at timestamp with time zone, is_revoked boolean default false not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_user_token_user on user_token ("user"); create table if not exists user_activity_log ( id bigserial primary key, user_uid uuid, action varchar(255) not null, ip_address varchar(255), user_agent varchar(255), details jsonb not null, created_at timestamp with time zone not null ); create index if not exists idx_user_activity_log_user_uid on user_activity_log (user_uid); create index if not exists idx_user_activity_log_created_at on user_activity_log (created_at); create table if not exists project_access_log ( id bigserial primary key, project uuid not null, actor_uid uuid, action varchar(255) not null, ip_address varchar(255), user_agent varchar(255), created_at timestamp with time zone not null ); create index if not exists idx_project_access_log_project on project_access_log (project); create index if not exists idx_project_access_log_created_at on project_access_log (created_at); create table if not exists project_audit_log ( id bigserial primary key, project uuid not null, actor uuid not null, action text not null, details jsonb, ip_address varchar(255), user_agent varchar(255), created_at timestamp with time zone not null ); create index if not exists idx_project_audit_log_project on project_audit_log (project); create index if not exists idx_project_audit_log_created_at on project_audit_log (created_at); create table if not exists project_billing ( project_uuid uuid not null primary key, balance numeric default 0.0 not null, currency text not null, user_uuid uuid, updated_at timestamp with time zone not null, created_at timestamp with time zone not null ); create table if not exists project_billing_history ( uid uuid not null primary key, project uuid not null, "user" uuid, amount numeric not null, currency text not null, reason text not null, extra jsonb, created_at timestamp with time zone not null ); create index if not exists idx_project_billing_history_project on project_billing_history (project); create table if not exists project_follow ( id bigserial primary key, project uuid not null, "user" uuid not null, created_at timestamp with time zone not null, unique (project, "user") ); create unique index if not exists idx_project_follow_project_user on project_follow (project, "user"); create table if not exists project_history_name ( id bigserial primary key, project_uid uuid not null, history_name varchar(255) not null, changed_at timestamp with time zone not null ); create index if not exists idx_project_history_name_project_uid on project_history_name (project_uid); create table if not exists project_label ( id bigserial primary key, project_uuid uuid not null, label_id bigint not null, relation_at timestamp with time zone not null ); create index if not exists idx_project_label_project on project_label (project_uuid); create table if not exists project_like ( project uuid not null, "user" uuid not null, created_at timestamp with time zone not null, primary key (project, "user") ); create table if not exists project_member_invitations ( id bigserial primary key, project uuid not null, "user" uuid not null, invited_by uuid not null, scope varchar(255) not null, accepted boolean default false not null, accepted_at timestamp with time zone, rejected boolean default false not null, rejected_at timestamp with time zone, created_at timestamp with time zone not null ); create index if not exists idx_project_member_invitations_project_user on project_member_invitations (project, "user"); create table if not exists project_member_join_answers ( id bigserial primary key, project uuid not null, "user" uuid not null, request_id bigint not null, question varchar(255) not null, answer varchar(255) not null, created_at timestamp with time zone not null ); create index if not exists idx_project_member_join_answers_request_id on project_member_join_answers (request_id); create table if not exists project_member_join_request ( id bigserial primary key, project uuid not null, "user" uuid not null, status varchar(255) not null, message text, processed_by uuid, processed_at timestamp with time zone, reject_reason text, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_project_member_join_request_project_user on project_member_join_request (project, "user"); create index if not exists idx_project_member_join_request_status on project_member_join_request (status); create table if not exists project_member_join_settings ( id bigserial primary key, project uuid not null, require_approval boolean default false not null, require_questions boolean default false not null, questions jsonb not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create table if not exists project_members ( id bigserial primary key, project_uuid uuid not null, user_uuid uuid not null, scope varchar(255) not null, joined_at timestamp with time zone not null, unique (project_uuid, user_uuid) ); create unique index if not exists idx_project_members_project_user on project_members (project_uuid, user_uuid); create table if not exists project_watch ( id bigserial primary key, project uuid not null, "user" uuid not null, notifications_enabled boolean default true not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, unique (project, "user") ); create unique index if not exists idx_project_watch_project_user on project_watch (project, "user"); create table if not exists repo ( id uuid not null primary key, repo_name varchar(255) not null, project uuid not null, description text, default_branch varchar(255) not null, is_private boolean default false not null, storage_path varchar(255) not null, created_by uuid not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, ai_code_review_enabled boolean default false not null ); create index if not exists idx_repo_project on repo (project); create index if not exists idx_repo_repo_name on repo (repo_name); create table if not exists repo_branch ( repo uuid not null, name varchar(255) not null, oid varchar(255) not null, upstream varchar(255), head boolean default false not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, primary key (repo, name) ); create index if not exists idx_repo_branch_repo on repo_branch (repo); create table if not exists repo_branch_protect ( id bigserial primary key, repo_uuid uuid not null, branch varchar(255) not null, forbid_push boolean default false not null, forbid_pull boolean default false not null, forbid_merge boolean default false not null, forbid_deletion boolean default false not null, forbid_force_push boolean default false not null, forbid_tag_push boolean default false not null, required_approvals integer default 0 not null, dismiss_stale_reviews boolean default false not null, require_linear_history boolean default false not null, allow_fork_syncing boolean default true not null, unique (repo_uuid, branch) ); create unique index if not exists idx_repo_branch_protect_repo_branch on repo_branch_protect (repo_uuid, branch); create table if not exists repo_collaborator ( repo uuid not null, "user" uuid not null, scope varchar(255) not null, created_at timestamp with time zone not null, primary key (repo, "user") ); create table if not exists repo_commit ( id bigserial primary key, repo uuid not null, oid varchar(255) not null, author_name varchar(255) not null, author_email varchar(255) not null, author uuid, commiter_name varchar(255) not null, commiter_email varchar(255) not null, commiter uuid, message text not null, parent jsonb not null, created_at timestamp with time zone not null ); create index if not exists idx_repo_commit_repo on repo_commit (repo); create index if not exists idx_repo_commit_oid on repo_commit (oid); create table if not exists repo_fork ( id bigserial primary key, parent_repo uuid not null, forked_repo uuid not null, forked_by uuid not null, forked_at timestamp with time zone not null ); create index if not exists idx_repo_fork_parent_repo on repo_fork (parent_repo); create unique index if not exists idx_repo_fork_forked_repo on repo_fork (forked_repo); create table if not exists repo_history_name ( id bigserial primary key, repo_uuid uuid not null, project_uid uuid not null, name varchar(255) not null, change_at timestamp with time zone not null ); create index if not exists idx_repo_history_name_repo on repo_history_name (repo_uuid); create table if not exists repo_hook ( id bigserial primary key, repo_uuid uuid not null, event jsonb not null, script text not null, created_at timestamp with time zone not null ); create index if not exists idx_repo_hook_repo on repo_hook (repo_uuid); create table if not exists repo_lfs_lock ( repo_uuid uuid not null, path varchar(255) not null, lock_type varchar(255) not null, locked_by uuid not null, locked_at timestamp with time zone not null, unlocked_at timestamp with time zone, primary key (repo_uuid, path) ); create table if not exists repo_lfs_object ( id bigserial primary key, oid varchar(255) not null, repo_uuid uuid not null, size bigint not null, storage_path varchar(255) not null, uploaded_by uuid, uploaded_at timestamp with time zone not null ); create index if not exists idx_repo_lfs_object_repo_oid on repo_lfs_object (repo_uuid, oid); create table if not exists repo_lock ( repo_uuid uuid not null, path varchar(255) not null, lock_type varchar(255) not null, locked_by uuid not null, acquired_at timestamp with time zone not null, released_at timestamp with time zone, primary key (repo_uuid, path) ); create table if not exists repo_star ( id bigserial primary key, repo_uuid uuid not null, user_uuid uuid not null, created_at timestamp with time zone not null, unique (repo_uuid, user_uuid) ); create unique index if not exists idx_repo_star_repo_user on repo_star (repo_uuid, user_uuid); create table if not exists repo_tag ( repo_uuid uuid not null, name varchar(255) not null, oid varchar(255) not null, color varchar(255), description text, created_at timestamp with time zone not null, tagger_name varchar(255) not null, tagger_email varchar(255) not null, tagger_uuid uuid, primary key (repo_uuid, name) ); create table if not exists repo_upstream ( id bigserial primary key, repo_uuid uuid not null unique, source_url varchar(255) not null, direction varchar(255) not null, schedule_cron varchar(255), last_run_at timestamp with time zone, next_run_at timestamp with time zone, status varchar(255) not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create unique index if not exists idx_repo_upstream_repo on repo_upstream (repo_uuid); create table if not exists repo_watch ( id bigserial primary key, user_uuid uuid not null, repo_uuid uuid not null, show_dashboard boolean default false not null, notify_email boolean default false not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, unique (user_uuid, repo_uuid) ); create unique index if not exists idx_repo_watch_user_repo on repo_watch (user_uuid, repo_uuid); create table if not exists repo_webhook ( id bigserial primary key, repo_uuid uuid not null, event jsonb not null, url varchar(255), access_key varchar(255), secret_key varchar(255), created_at timestamp with time zone not null, last_delivered_at timestamp with time zone, touch_count bigint default 0 not null ); create index if not exists idx_repo_webhook_repo on repo_webhook (repo_uuid); create table if not exists issue ( id uuid not null primary key, project uuid not null, number bigint not null, title varchar(255) not null, body text, state varchar(255) not null, author uuid not null, milestone varchar(255), created_at timestamp with time zone not null, updated_at timestamp with time zone not null, closed_at timestamp with time zone, created_by_ai boolean default false not null ); create index if not exists idx_issue_project on issue (project); create index if not exists idx_issue_author on issue (author); create index if not exists idx_issue_state on issue (state); create table if not exists issue_assignee ( issue uuid not null, "user" uuid not null, assigned_at timestamp with time zone not null, primary key (issue, "user") ); create table if not exists issue_comment ( id bigserial primary key, issue uuid not null, author uuid not null, body text not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_issue_comment_issue on issue_comment (issue); create table if not exists issue_comment_reaction ( comment_id bigint not null, user_uuid uuid not null, reaction varchar(255) not null, created_at timestamp with time zone not null, primary key (comment_id, user_uuid, reaction) ); create table if not exists issue_label ( issue uuid not null, label bigint not null, relation_at timestamp with time zone not null, primary key (issue, label) ); create table if not exists issue_pull_request ( issue uuid not null, repo uuid not null, number bigint not null, relation_at timestamp with time zone not null, primary key (issue, repo, number) ); create table if not exists issue_reaction ( issue_uuid uuid not null, user_uuid uuid not null, reaction varchar(255) not null, created_at timestamp with time zone not null, primary key (issue_uuid, user_uuid, reaction) ); create table if not exists issue_repo ( issue uuid not null, repo uuid not null, relation_at timestamp with time zone not null, primary key (issue, repo) ); create table if not exists issue_subscriber ( issue uuid not null, "user" uuid not null, subscribed boolean default true not null, created_at timestamp with time zone not null, primary key (issue, "user") ); create table if not exists pull_request ( repo uuid not null, number bigint not null, issue uuid not null, title varchar(255) not null, body text, author uuid not null, base varchar(255) not null, head varchar(255) not null, status varchar(255) not null, merged_by uuid, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, merged_at timestamp with time zone, created_by_ai boolean default false not null, primary key (repo, number) ); create index if not exists idx_pull_request_repo on pull_request (repo); create index if not exists idx_pull_request_author on pull_request (author); create index if not exists idx_pull_request_status on pull_request (status); create table if not exists pull_request_commit ( repo uuid not null, number bigint not null, commit varchar(255) not null, message text not null, author_name varchar(255) not null, author_email varchar(255) not null, authored_at timestamp with time zone not null, committer_name varchar(255) not null, committer_email varchar(255) not null, committed_at timestamp with time zone not null, created_at timestamp with time zone not null, primary key (repo, number, commit) ); create table if not exists pull_request_review ( repo uuid not null, number bigint not null, reviewer uuid not null, state varchar(255) not null, body text, submitted_at timestamp with time zone, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, primary key (repo, number, reviewer) ); create table if not exists pull_request_review_comment ( repo uuid not null, number bigint not null, id bigint not null, review uuid, path text, side varchar(255), line bigint, old_line bigint, body text not null, author uuid not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, resolved boolean default false not null, in_reply_to bigint, primary key (repo, number, id) ); create table if not exists room_category ( id uuid not null primary key, project_uuid uuid not null, name varchar(255) not null, position integer not null, created_by uuid not null, created_at timestamp with time zone not null ); create index if not exists idx_room_category_project on room_category (project_uuid); create table if not exists room ( id uuid not null primary key, project uuid not null, room_name varchar(255) not null, public boolean default false not null, category uuid, created_by uuid not null, created_at timestamp with time zone not null, last_msg_at timestamp with time zone not null ); create index if not exists idx_room_project on room (project); create index if not exists idx_room_category on room (category); create table if not exists room_ai ( room uuid not null, model uuid not null, version uuid, call_count bigint default 0 not null, last_call_at timestamp with time zone, history_limit bigint, system_prompt text, temperature double precision, max_tokens bigint, use_exact boolean default false not null, think boolean default false not null, min_score real, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, stream boolean default true not null, agent_type varchar(50), primary key (room, model) ); create index if not exists idx_room_ai_agent_type on room_ai (agent_type) where (agent_type IS NOT NULL); create table if not exists room_message ( id uuid not null primary key, seq bigint not null, room uuid not null, sender_type varchar(255) not null, sender_id uuid, thread uuid, content text not null, content_type varchar(255) not null, edited_at timestamp with time zone, send_at timestamp with time zone not null, revoked timestamp with time zone, revoked_by uuid, in_reply_to uuid, content_tsv tsvector, model_id uuid, thinking_content text ); create index if not exists idx_room_message_room_seq on room_message (room, seq); create index if not exists idx_room_message_thread on room_message (thread); create index if not exists idx_room_message_send_at on room_message (send_at); create index if not exists idx_room_message_content_tsv on room_message using gin (content_tsv); create index if not exists idx_room_message_model_id on room_message (model_id) where (model_id IS NOT NULL); create table if not exists room_pin ( room uuid not null, message uuid not null, pinned_by uuid not null, pinned_at timestamp with time zone not null, primary key (room, message) ); create table if not exists room_thread ( id uuid not null primary key, room uuid not null, parent bigint not null, created_by uuid not null, participants jsonb not null, last_message_at timestamp with time zone not null, last_message_preview text, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_room_thread_room on room_thread (room); create table if not exists ai_model_provider ( id uuid not null primary key, name varchar(255) not null, display_name varchar(255) not null, website varchar(255), status varchar(255) not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create table if not exists ai_model ( id uuid not null primary key, provider_id uuid not null, name varchar(255) not null, modality varchar(255) not null, capability varchar(255) not null, context_length bigint not null, max_output_tokens bigint, training_cutoff timestamp with time zone, is_open_source boolean default false not null, status varchar(255) not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create index if not exists idx_ai_model_provider_id on ai_model (provider_id); create table if not exists ai_model_version ( id uuid not null primary key, model_id uuid not null, version varchar(255) not null, release_date timestamp with time zone, change_log text, is_default boolean default false not null, status varchar(255) not null, created_at timestamp with time zone not null ); create index if not exists idx_ai_model_version_model_id on ai_model_version (model_id); create table if not exists ai_model_capability ( id bigserial primary key, model_version_id uuid not null, capability varchar(255) not null, is_supported boolean default false not null, created_at timestamp with time zone not null ); create index if not exists idx_ai_model_capability_model_version_id on ai_model_capability (model_version_id); create table if not exists ai_model_parameter_profile ( id bigserial primary key, model_version_id uuid not null unique, temperature_min double precision not null, temperature_max double precision not null, top_p_min double precision not null, top_p_max double precision not null, frequency_penalty_supported boolean default false not null, presence_penalty_supported boolean default false not null ); create unique index if not exists idx_ai_model_parameter_profile_model_version_id on ai_model_parameter_profile (model_version_id); create table if not exists ai_model_pricing ( id bigserial primary key, model_version_id uuid not null, input_price_per_1k_tokens varchar(255) not null, output_price_per_1k_tokens varchar(255) not null, currency varchar(255) not null, effective_from timestamp with time zone not null ); create index if not exists idx_ai_model_pricing_model_version_id on ai_model_pricing (model_version_id); create table if not exists ai_session ( id uuid not null primary key, room uuid not null, model uuid not null, version uuid not null, token_input bigint default 0 not null, token_output bigint default 0 not null, latency_ms bigint, cost double precision, currency varchar(255), error_message text, error_code varchar(255), created_at timestamp with time zone not null ); create index if not exists idx_ai_session_room on ai_session (room); create table if not exists ai_tool_call ( tool_call_id varchar(255) not null, session uuid not null, tool_name varchar(255) not null, caller uuid not null, arguments jsonb not null, result jsonb not null, status varchar(255) not null, execution_time_ms bigint, error_message text, error_stack text, retry_count integer default 0 not null, created_at timestamp with time zone not null, completed_at timestamp with time zone, updated_at timestamp with time zone not null, primary key (tool_call_id, session) ); create index if not exists idx_ai_tool_call_session on ai_tool_call (session); create index if not exists idx_ai_tool_call_status on ai_tool_call (status); create table if not exists ai_tool_auth ( session uuid not null, tool_call_id varchar(255) not null, method varchar(255) not null, arguments text not null, decision boolean default false not null, reason varchar(255) not null, decision_by uuid not null, decision_comment text, logs jsonb not null, expires_at timestamp with time zone, authorized_at timestamp with time zone, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, primary key (session, tool_call_id) ); create table if not exists label ( id bigserial primary key, project_uuid uuid not null, name varchar(255) not null, color varchar(255) not null ); create index if not exists idx_label_project on label (project_uuid); create table if not exists notify ( id bigserial primary key, user_uuid uuid not null, title varchar(255) not null, description text, content text not null, url varchar(255), kind integer not null, read_at timestamp with time zone, deleted_at timestamp with time zone, created_at timestamp with time zone not null ); create index if not exists idx_notify_user on notify (user_uuid); create index if not exists idx_notify_created_at on notify (created_at); create table if not exists room_notifications ( id uuid not null primary key, room uuid, project uuid, user_id uuid, notification_type varchar(255) not null, related_message_id uuid, related_user_id uuid, related_room_id uuid, title varchar(255) not null, content text, metadata jsonb, is_read boolean default false not null, is_archived boolean default false not null, created_at timestamp with time zone not null, read_at timestamp with time zone, expires_at timestamp with time zone ); create index if not exists idx_room_notifications_user_id_is_read on room_notifications (user_id, is_read); create index if not exists idx_room_notifications_user_id_created_at on room_notifications (user_id, created_at); create index if not exists idx_room_notifications_expires_at on room_notifications (expires_at); create table if not exists user_email_change ( token varchar(255) not null primary key, user_uid uuid not null, new_email varchar(255) not null, expires_at timestamp with time zone not null, used boolean default false not null, created_at timestamp with time zone not null ); create index if not exists idx_user_email_change_user_uid on user_email_change (user_uid); create table if not exists project_activity ( id bigserial primary key, project uuid not null, repo uuid, actor uuid not null, event_type varchar(50) not null, event_id uuid, event_sub_id bigint, title varchar(500) not null, content text, metadata jsonb, is_private boolean default false not null, created_at timestamp with time zone not null ); create index if not exists idx_project_activity_project on project_activity (project); create index if not exists idx_project_activity_created_at on project_activity (created_at desc); create index if not exists idx_project_activity_event_type on project_activity (event_type); create table if not exists room_message_reaction ( id uuid not null primary key, room uuid not null references room on delete cascade, message uuid not null references room_message on delete cascade, "user" uuid not null references "user" on delete cascade, emoji varchar(50) not null, created_at timestamp with time zone default now() not null, unique (message, "user", emoji) ); create index if not exists idx_room_message_reaction_message on room_message_reaction (message); create index if not exists idx_room_message_reaction_user on room_message_reaction ("user"); create index if not exists idx_room_message_reaction_room on room_message_reaction (room); create table if not exists room_message_edit_history ( id uuid not null primary key, message uuid not null references room_message on delete cascade, "user" uuid not null references "user" on delete cascade, old_content text not null, new_content text not null, edited_at timestamp with time zone default now() not null ); create index if not exists idx_room_message_edit_history_message on room_message_edit_history (message); create index if not exists idx_room_message_edit_history_user on room_message_edit_history ("user"); create table if not exists project_board ( id uuid default gen_random_uuid() not null primary key, project_uuid uuid not null, name varchar(255) not null, description text, created_by uuid not null, created_at timestamp with time zone default now() not null, updated_at timestamp with time zone default now() not null ); create index if not exists idx_project_board_project on project_board (project_uuid); create table if not exists project_board_column ( id uuid default gen_random_uuid() not null primary key, board_uuid uuid not null references project_board on delete cascade, name varchar(255) not null, position integer default 0 not null, wip_limit integer, color varchar(20) ); create index if not exists idx_project_board_column_board on project_board_column (board_uuid); create table if not exists project_board_card ( id uuid default gen_random_uuid() not null primary key, column_uuid uuid not null references project_board_column on delete cascade, issue_id bigint, project uuid, title varchar(500) not null, description text, position integer default 0 not null, assignee_id uuid, due_date timestamp with time zone, priority varchar(10), created_by uuid not null, created_at timestamp with time zone default now() not null, updated_at timestamp with time zone default now() not null ); create index if not exists idx_project_board_card_column on project_board_card (column_uuid); create index if not exists idx_project_board_card_issue on project_board_card (issue_id) where (issue_id IS NOT NULL); create table if not exists pull_request_review_request ( repo uuid not null, number bigint not null, reviewer uuid not null, requested_by uuid not null, requested_at timestamp with time zone default now() not null, dismissed_at timestamp with time zone, dismissed_by uuid, primary key (repo, number, reviewer) ); create table if not exists workspace ( id uuid not null primary key, slug varchar(255) not null, name varchar(255) not null, description text, avatar_url varchar(255), plan varchar(50) default 'free'::character varying not null, billing_email varchar(255), stripe_customer_id varchar(255), stripe_subscription_id varchar(255), plan_expires_at timestamp with time zone, deleted_at timestamp with time zone, created_at timestamp with time zone not null, updated_at timestamp with time zone not null ); create table if not exists project ( id uuid not null primary key, name varchar(255) not null, display_name varchar(255) not null, avatar_url varchar(255), description text, is_public boolean default false not null, created_by uuid not null, created_at timestamp with time zone not null, updated_at timestamp with time zone not null, workspace_id uuid references workspace on delete set null ); create index if not exists idx_project_name on project (name); create index if not exists idx_project_created_by on project (created_by); create index if not exists idx_project_workspace_id on project (workspace_id) where (workspace_id IS NOT NULL); create unique index if not exists idx_workspace_slug on workspace (slug); create index if not exists idx_workspace_deleted_at on workspace (deleted_at); create table if not exists workspace_membership ( id bigserial primary key, workspace_id uuid not null, user_id uuid not null, role varchar(50) default 'member'::character varying not null, status varchar(50) default 'active'::character varying not null, invited_by uuid, joined_at timestamp with time zone not null, invite_token varchar(255), invite_expires_at timestamp with time zone, unique (workspace_id, user_id) ); create unique index if not exists idx_workspace_membership_ws_user on workspace_membership (workspace_id, user_id); create index if not exists idx_workspace_membership_user on workspace_membership (user_id); create index if not exists idx_workspace_membership_invite_token on workspace_membership (invite_token) where (invite_token IS NOT NULL); create table if not exists workspace_billing ( workspace_id uuid not null primary key references workspace on delete cascade, balance numeric(20, 4) default 0 not null, currency varchar(10) default 'USD'::character varying not null, monthly_quota numeric(20, 4) default 0 not null, total_spent numeric(20, 4) default 0 not null, updated_at timestamp with time zone not null, created_at timestamp with time zone not null ); create table if not exists workspace_billing_history ( uid uuid not null primary key, workspace_id uuid not null references workspace on delete cascade, user_id uuid, amount numeric(20, 4) not null, currency varchar(10) default 'USD'::character varying not null, reason varchar(100) not null, extra jsonb, created_at timestamp with time zone not null ); create index if not exists idx_wsbh_workspace_id on workspace_billing_history (workspace_id); create index if not exists idx_wsbh_created_at on workspace_billing_history (created_at desc); create table if not exists project_skill ( id bigserial primary key, project_uuid uuid not null, slug varchar(255) not null, name varchar(255) not null, description text, source varchar(20) default 'manual'::character varying not null, repo_id uuid, content text default ''::text not null, metadata jsonb default '{}'::jsonb not null, enabled boolean default true not null, created_by uuid, created_at timestamp with time zone default now() not null, updated_at timestamp with time zone default now() not null, commit_sha varchar(40), blob_hash varchar(40), unique (project_uuid, slug) ); create index if not exists idx_project_skill_project on project_skill (project_uuid); create index if not exists idx_project_skill_slug on project_skill (slug); create index if not exists idx_project_skill_source on project_skill (source); create index if not exists idx_project_skill_commit_sha on project_skill (commit_sha); create index if not exists idx_project_skill_blob_hash on project_skill (blob_hash); create table if not exists agent_task ( id bigserial primary key, project_uuid uuid not null, parent_id bigint constraint fk_agent_task_parent references agent_task on delete set null, agent_type varchar(20) default 'react'::character varying not null, status varchar(20) default 'pending'::character varying not null, title varchar(255), input text not null, output text, error text, created_by uuid, created_at timestamp with time zone default now() not null, updated_at timestamp with time zone default now() not null, started_at timestamp with time zone, done_at timestamp with time zone, progress varchar(255), issue_id uuid, retry_count integer default 0 ); create index if not exists idx_agent_task_project on agent_task (project_uuid); create index if not exists idx_agent_task_parent on agent_task (parent_id); create index if not exists idx_agent_task_status on agent_task (status); create index if not exists idx_agent_task_created_by on agent_task (created_by); create index if not exists idx_agent_task_created_at on agent_task (created_at); create index if not exists idx_agent_task_issue on agent_task (issue_id); create index if not exists idx_agent_task_retry_count on agent_task (retry_count); create table if not exists admin_user ( id serial primary key, username varchar(255) not null unique, password_hash varchar(255) not null, is_active boolean default true not null, created_at timestamp with time zone default now() not null, updated_at timestamp with time zone default now() not null ); create index if not exists idx_admin_user_username on admin_user (username); create table if not exists admin_role ( id serial primary key, name varchar(255) not null unique, description text, created_at timestamp with time zone default now() not null ); create table if not exists admin_permission ( id serial primary key, name varchar(255) not null, code varchar(255) not null unique, description text, created_at timestamp with time zone default now() not null ); create table if not exists admin_user_role ( user_id integer not null references admin_user on delete cascade, role_id integer not null references admin_role on delete cascade, primary key (user_id, role_id) ); create table if not exists admin_role_permission ( role_id integer not null references admin_role on delete cascade, permission_id integer not null references admin_permission on delete cascade, primary key (role_id, permission_id) ); create table if not exists admin_audit_log ( id bigserial primary key, user_id integer not null, username varchar(255) not null, action varchar(50) not null, resource varchar(255) not null, resource_id varchar(255), request_params jsonb, ip_address varchar(255), user_agent text, result varchar(20) default 'success'::character varying not null, error_message text, created_at timestamp with time zone default now() not null ); create index if not exists idx_admin_audit_log_user_id on admin_audit_log (user_id); create index if not exists idx_admin_audit_log_created_at on admin_audit_log (created_at desc); create index if not exists idx_admin_audit_log_action on admin_audit_log (action); create index if not exists idx_admin_audit_log_resource on admin_audit_log (resource); create table if not exists admin_api_token ( id serial primary key, name varchar(255) not null, token_hash varchar(64) not null unique, token_prefix varchar(32) not null, permissions text[] default '{}'::text[] not null, created_by integer not null references admin_user on delete set null, created_at timestamp with time zone default now() not null, last_used_at timestamp with time zone, expires_at timestamp with time zone, is_active boolean default true not null ); comment on table admin_api_token is 'Admin API Token for programmatic access'; create index if not exists idx_admin_api_token_hash on admin_api_token (token_hash); create table if not exists workspace_alert_config ( id serial primary key, workspace_id uuid not null, alert_type varchar(32) not null, threshold numeric(10, 4) not null, email_enabled boolean default true, enabled boolean default true, created_by integer, created_at timestamp with time zone default now(), updated_at timestamp with time zone default now(), unique (workspace_id, alert_type) ); create index if not exists idx_alert_config_workspace on workspace_alert_config (workspace_id); create table if not exists room_attachment ( id uuid not null primary key, room uuid not null, message uuid not null, uploader uuid not null, file_name varchar(255) not null, file_size bigint not null, content_type varchar(100) not null, s3_key varchar(500) not null, created_at timestamp with time zone default now() not null ); create index if not exists idx_room_attachment_room on room_attachment (room); create index if not exists idx_room_attachment_message on room_attachment (message); create index if not exists idx_room_attachment_uploader on room_attachment (uploader); create table if not exists room_access ( room uuid not null, "user" uuid not null, granted_by uuid not null, granted_at timestamp with time zone default now() not null, primary key (room, "user") ); create index if not exists idx_room_access_user on room_access ("user"); create table if not exists room_user_state ( room uuid not null, "user" uuid not null, last_read_seq bigint, do_not_disturb boolean default false not null, dnd_start_hour smallint, dnd_end_hour smallint, joined_at timestamp with time zone, primary key (room, "user") ); create index if not exists idx_room_user_state_user on room_user_state ("user"); create table if not exists project_role_priority ( id bigserial primary key, project_uuid uuid not null, role_key varchar(64) not null, display_name varchar(128) not null, priority integer default 0 not null, color varchar(32), created_at timestamp with time zone default now(), updated_at timestamp with time zone default now(), unique (project_uuid, role_key) ); create index if not exists idx_project_role_priority_project on project_role_priority (project_uuid); create index if not exists idx_project_role_priority_priority on project_role_priority (project_uuid, priority); create table if not exists ai_conversation ( id uuid default gen_random_uuid() not null primary key, user_id uuid not null, project_id uuid constraint fk_ai_conv_project references project on delete cascade, scope varchar(16) not null, title varchar(512), model varchar(128) default 'gpt-4'::character varying not null, model_config jsonb, status varchar(32) default 'active'::character varying not null, root_message_id uuid, fork_count integer default 0 not null, is_shared boolean default false not null, message_count integer default 0 not null, token_usage_total integer, created_at timestamp with time zone default now() not null, updated_at timestamp with time zone default now() not null, access_visibility varchar(32) default 'owner'::character varying not null, can_ask varchar(32) default 'owner'::character varying not null, project_uid integer, model_uid uuid, model_name varchar(256) ); create index if not exists idx_ai_conv_user_id on ai_conversation (user_id); create index if not exists idx_ai_conv_project_id on ai_conversation (project_id); create index if not exists idx_ai_conv_scope on ai_conversation (scope); create index if not exists idx_ai_conv_user_created on ai_conversation (user_id asc, created_at desc); create index if not exists idx_ai_conv_project_created on ai_conversation (project_id asc, created_at desc); create index if not exists idx_ai_conv_access_vis on ai_conversation (access_visibility); create index if not exists idx_ai_conv_project_uid on ai_conversation (project_id, project_uid) where (project_uid IS NOT NULL); create table if not exists ai_message ( id uuid default gen_random_uuid() not null primary key, conversation_id uuid not null constraint fk_ai_msg_conv references ai_conversation on delete cascade, parent_message_id uuid constraint fk_ai_msg_parent references ai_message on delete set null, role varchar(16) not null, content jsonb not null, model varchar(128), is_fork_origin boolean default false not null, stop_reason varchar(32), input_tokens integer, output_tokens integer, latency_ms integer, metadata jsonb, room_id uuid, created_at timestamp with time zone default now() not null ); create index if not exists idx_ai_msg_conv on ai_message (conversation_id, created_at); create index if not exists idx_ai_msg_parent on ai_message (parent_message_id); create table if not exists ai_message_fork ( id uuid default gen_random_uuid() not null primary key, source_message_id uuid not null constraint fk_ai_fork_source references ai_message on delete cascade, fork_message_id uuid not null constraint fk_ai_fork_fork references ai_message on delete cascade, created_at timestamp with time zone default now() not null ); create index if not exists idx_ai_fork_source on ai_message_fork (source_message_id); create index if not exists idx_ai_fork_fork on ai_message_fork (fork_message_id); create table if not exists ai_shared_conversation ( id uuid default gen_random_uuid() not null primary key, conversation_id uuid not null constraint fk_ai_share_conv references ai_conversation on delete cascade, share_token varchar(128) not null unique, created_by uuid not null, view_count integer default 0 not null, created_at timestamp with time zone default now() not null, expires_at timestamp with time zone ); create index if not exists idx_ai_share_conv on ai_shared_conversation (conversation_id); create index if not exists idx_ai_share_token on ai_shared_conversation (share_token); create table if not exists ai_token_usage ( id uuid default gen_random_uuid() not null primary key, user_id uuid not null, conversation_id uuid, model varchar(128) not null, input_tokens integer not null, output_tokens integer not null, cost_usd numeric(10, 6), recorded_at timestamp with time zone default now() not null ); create index if not exists idx_ai_token_user on ai_token_usage (user_id); create index if not exists idx_ai_token_conv on ai_token_usage (conversation_id); create index if not exists idx_ai_token_recorded on ai_token_usage (recorded_at);