mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
383 lines
16 KiB
SQL
383 lines
16 KiB
SQL
create table schema_migrations (
|
|
version integer primary key,
|
|
name text not null,
|
|
applied_at text not null
|
|
);
|
|
|
|
pragma foreign_keys = on;
|
|
|
|
-- ============================================
|
|
-- Admin Users
|
|
-- ============================================
|
|
create table admin_users (
|
|
id text primary key,
|
|
password_hash text not null,
|
|
created_at text not null,
|
|
updated_at text not null
|
|
);
|
|
|
|
-- ============================================
|
|
-- Admin Sessions
|
|
-- ============================================
|
|
create table admin_sessions (
|
|
id text primary key,
|
|
user_id text not null references admin_users(id) on delete cascade,
|
|
expires_at text not null,
|
|
created_at text not null
|
|
);
|
|
|
|
create index idx_admin_sessions_expires on admin_sessions(expires_at);
|
|
|
|
-- ============================================
|
|
-- Client API Keys
|
|
-- ============================================
|
|
create table client_api_keys (
|
|
id text primary key,
|
|
name text not null,
|
|
prefix text not null,
|
|
key text not null unique,
|
|
label text,
|
|
enabled integer not null default 1 check (enabled in (0, 1)),
|
|
created_at text not null,
|
|
last_used_at text
|
|
);
|
|
|
|
create index idx_client_api_keys_key_enabled on client_api_keys(key) where enabled = 1;
|
|
create index idx_client_api_keys_created_id on client_api_keys(created_at desc, id desc);
|
|
|
|
-- ============================================
|
|
-- Runtime Settings
|
|
-- ============================================
|
|
create table runtime_settings (
|
|
id integer primary key check (id = 1),
|
|
model_aliases_json text not null default '{}',
|
|
refresh_margin_seconds integer not null check (refresh_margin_seconds > 0),
|
|
refresh_concurrency integer not null check (refresh_concurrency > 0),
|
|
max_concurrent_per_account integer not null check (max_concurrent_per_account > 0),
|
|
request_interval_ms integer not null check (request_interval_ms >= 0),
|
|
rotation_strategy text not null check (rotation_strategy in ('smart', 'quota_reset_priority', 'round_robin', 'sticky')),
|
|
admin_api_key text,
|
|
updated_at text not null
|
|
);
|
|
|
|
-- ============================================
|
|
-- Accounts
|
|
-- ============================================
|
|
create table accounts (
|
|
id text primary key,
|
|
email text,
|
|
chatgpt_account_id text,
|
|
chatgpt_user_id text,
|
|
label text,
|
|
plan_type text,
|
|
access_token text not null,
|
|
refresh_token text,
|
|
access_token_expires_at text,
|
|
next_refresh_at text,
|
|
status text not null check (status in ('active', 'expired', 'quota_exhausted', 'refreshing', 'disabled', 'banned')),
|
|
quota_json text,
|
|
quota_fetched_at text,
|
|
quota_limit_reached integer not null default 0 check (quota_limit_reached in (0, 1)),
|
|
quota_verify_required integer not null default 0 check (quota_verify_required in (0, 1)),
|
|
quota_cooldown_until text,
|
|
cloudflare_cooldown_until text,
|
|
added_at text not null,
|
|
updated_at text not null
|
|
);
|
|
|
|
create index idx_accounts_status on accounts(status);
|
|
create index idx_accounts_added_id on accounts(added_at desc, id desc);
|
|
create unique index ux_accounts_chatgpt_identity
|
|
on accounts(chatgpt_account_id, coalesce(chatgpt_user_id, ''))
|
|
where chatgpt_account_id is not null;
|
|
|
|
-- ============================================
|
|
-- Account Refresh Leases
|
|
-- ============================================
|
|
create table account_refresh_leases (
|
|
account_id text primary key references accounts(id) on delete cascade,
|
|
owner text not null,
|
|
expires_at text not null,
|
|
updated_at text not null
|
|
);
|
|
|
|
create index idx_account_refresh_leases_expires on account_refresh_leases(expires_at);
|
|
|
|
-- ============================================
|
|
-- Account Usage Statistics
|
|
-- ============================================
|
|
create table account_usage (
|
|
account_id text primary key references accounts(id) on delete cascade,
|
|
request_count integer not null default 0 check (request_count >= 0),
|
|
empty_response_count integer not null default 0 check (empty_response_count >= 0),
|
|
input_tokens integer not null default 0 check (input_tokens >= 0),
|
|
output_tokens integer not null default 0 check (output_tokens >= 0),
|
|
cached_tokens integer not null default 0 check (cached_tokens >= 0),
|
|
reasoning_tokens integer not null default 0 check (reasoning_tokens >= 0),
|
|
total_tokens integer not null default 0 check (total_tokens >= 0),
|
|
image_input_tokens integer not null default 0 check (image_input_tokens >= 0),
|
|
image_output_tokens integer not null default 0 check (image_output_tokens >= 0),
|
|
image_request_count integer not null default 0 check (image_request_count >= 0),
|
|
image_request_failed_count integer not null default 0 check (image_request_failed_count >= 0),
|
|
window_request_count integer not null default 0 check (window_request_count >= 0),
|
|
window_input_tokens integer not null default 0 check (window_input_tokens >= 0),
|
|
window_output_tokens integer not null default 0 check (window_output_tokens >= 0),
|
|
window_cached_tokens integer not null default 0 check (window_cached_tokens >= 0),
|
|
window_image_input_tokens integer not null default 0 check (window_image_input_tokens >= 0),
|
|
window_image_output_tokens integer not null default 0 check (window_image_output_tokens >= 0),
|
|
window_image_request_count integer not null default 0 check (window_image_request_count >= 0),
|
|
window_image_request_failed_count integer not null default 0 check (window_image_request_failed_count >= 0),
|
|
window_started_at text,
|
|
window_reset_at text,
|
|
limit_window_seconds integer check (limit_window_seconds is null or limit_window_seconds > 0),
|
|
last_used_at text
|
|
);
|
|
|
|
create index idx_account_usage_last_used_account
|
|
on account_usage(last_used_at desc, account_id desc);
|
|
|
|
-- ============================================
|
|
-- Account Model Usage Statistics
|
|
-- ============================================
|
|
create table account_model_usage (
|
|
account_id text not null references accounts(id) on delete cascade,
|
|
model text not null,
|
|
request_count integer not null default 0 check (request_count >= 0),
|
|
error_count integer not null default 0 check (error_count >= 0),
|
|
input_tokens integer not null default 0 check (input_tokens >= 0),
|
|
output_tokens integer not null default 0 check (output_tokens >= 0),
|
|
cached_tokens integer not null default 0 check (cached_tokens >= 0),
|
|
last_used_at text,
|
|
primary key (account_id, model)
|
|
);
|
|
|
|
create index idx_account_model_usage_last_used
|
|
on account_model_usage(last_used_at desc, account_id, model);
|
|
|
|
-- ============================================
|
|
-- Usage Time Buckets
|
|
-- ============================================
|
|
create table usage_time_buckets (
|
|
bucket_start text not null,
|
|
account_id text not null default '',
|
|
model text not null default '',
|
|
service_tier text not null default '',
|
|
request_count integer not null default 0 check (request_count >= 0),
|
|
error_count integer not null default 0 check (error_count >= 0),
|
|
input_tokens integer not null default 0 check (input_tokens >= 0),
|
|
output_tokens integer not null default 0 check (output_tokens >= 0),
|
|
cached_tokens integer not null default 0 check (cached_tokens >= 0),
|
|
first_token_latency_sum integer not null default 0 check (first_token_latency_sum >= 0),
|
|
first_token_latency_count integer not null default 0 check (first_token_latency_count >= 0),
|
|
latency_sum integer not null default 0 check (latency_sum >= 0),
|
|
latency_count integer not null default 0 check (latency_count >= 0),
|
|
max_latency_ms integer not null default 0 check (max_latency_ms >= 0),
|
|
min_latency_ms integer not null default 0 check (min_latency_ms >= 0),
|
|
updated_at text not null,
|
|
primary key (bucket_start, account_id, model, service_tier)
|
|
);
|
|
|
|
create index idx_usage_time_buckets_bucket
|
|
on usage_time_buckets(bucket_start);
|
|
create index idx_usage_time_buckets_model_bucket
|
|
on usage_time_buckets(model, bucket_start);
|
|
|
|
-- ============================================
|
|
-- Account Cookies
|
|
-- ============================================
|
|
create table account_cookies (
|
|
id text primary key,
|
|
account_id text not null references accounts(id) on delete cascade,
|
|
domain text not null,
|
|
name text not null,
|
|
value text not null,
|
|
path text not null default '/',
|
|
expires_at text,
|
|
updated_at text not null,
|
|
unique(account_id, domain, name, path)
|
|
);
|
|
|
|
create index idx_account_cookies_account on account_cookies(account_id);
|
|
create index idx_account_cookies_account_domain on account_cookies(account_id, domain);
|
|
create index idx_account_cookies_expires
|
|
on account_cookies(expires_at)
|
|
where expires_at is not null;
|
|
|
|
-- ============================================
|
|
-- Device Fingerprints
|
|
-- ============================================
|
|
create table fingerprints (
|
|
id text primary key,
|
|
originator text not null,
|
|
app_version text not null,
|
|
build_number text not null,
|
|
platform text not null,
|
|
arch text not null,
|
|
chromium_version text not null,
|
|
user_agent_template text not null,
|
|
default_headers_json text not null,
|
|
header_order_json text not null,
|
|
source text not null,
|
|
created_at text not null,
|
|
updated_at text not null
|
|
);
|
|
|
|
create table fingerprint_update_history (
|
|
id text primary key,
|
|
current_fingerprint_id text not null references fingerprints(id) on delete cascade,
|
|
app_version text not null,
|
|
build_number text not null,
|
|
chromium_version text,
|
|
source text not null,
|
|
manifest_json text,
|
|
created_at text not null
|
|
);
|
|
|
|
create index idx_fingerprint_update_history_created_id
|
|
on fingerprint_update_history(created_at desc, id desc);
|
|
|
|
-- ============================================
|
|
-- Usage Records
|
|
-- ============================================
|
|
create table usage_records (
|
|
id text primary key,
|
|
request_id text,
|
|
kind text not null,
|
|
level text not null check (level in ('debug', 'info', 'warn', 'error')),
|
|
account_id text,
|
|
route text,
|
|
model text,
|
|
status_code integer check (status_code is null or (status_code >= 100 and status_code <= 599)),
|
|
transport text,
|
|
attempt_index integer check (attempt_index is null or attempt_index >= 0),
|
|
upstream_status_code integer check (upstream_status_code is null or (upstream_status_code >= 100 and upstream_status_code <= 599)),
|
|
failure_class text,
|
|
response_id text,
|
|
upstream_request_id text,
|
|
latency_ms integer check (latency_ms is null or latency_ms >= 0),
|
|
message text not null,
|
|
metadata_json text not null,
|
|
created_at text not null
|
|
);
|
|
|
|
create index idx_usage_records_created_id on usage_records(created_at desc, id desc);
|
|
create index idx_usage_records_kind_created on usage_records(kind, created_at desc);
|
|
create index idx_usage_records_request_id on usage_records(request_id);
|
|
create index idx_usage_records_account on usage_records(account_id, created_at desc) where account_id is not null;
|
|
create index idx_usage_records_transport on usage_records(transport, created_at desc) where transport is not null;
|
|
create index idx_usage_records_failure_class on usage_records(failure_class, created_at desc) where failure_class is not null;
|
|
create index idx_usage_records_response_id on usage_records(response_id) where response_id is not null;
|
|
create index idx_usage_records_upstream_request_id on usage_records(upstream_request_id) where upstream_request_id is not null;
|
|
create index idx_usage_records_level_created on usage_records(level, created_at desc);
|
|
create index idx_usage_records_route_created on usage_records(route, created_at desc) where route is not null;
|
|
create index idx_usage_records_model_created on usage_records(model, created_at desc) where model is not null;
|
|
create index idx_usage_records_status_created on usage_records(status_code, created_at desc) where status_code is not null;
|
|
create index idx_usage_records_upstream_status_created on usage_records(upstream_status_code, created_at desc) where upstream_status_code is not null;
|
|
|
|
-- ============================================
|
|
-- Model Plan Snapshots
|
|
-- ============================================
|
|
create table model_plan_snapshots (
|
|
plan_type text primary key,
|
|
models_json text not null,
|
|
fetched_at text not null
|
|
);
|
|
|
|
-- ============================================
|
|
-- Session Affinities
|
|
-- ============================================
|
|
create table session_affinities (
|
|
response_id text primary key,
|
|
account_id text not null references accounts(id) on delete cascade,
|
|
conversation_id text not null,
|
|
turn_state text,
|
|
instructions_hash text,
|
|
input_tokens integer check (input_tokens is null or input_tokens >= 0),
|
|
function_call_ids_json text not null default '[]',
|
|
variant_hash text,
|
|
expires_at text not null,
|
|
created_at text not null
|
|
);
|
|
|
|
create index idx_session_affinities_conversation on session_affinities(conversation_id, created_at desc);
|
|
create index idx_session_affinities_expires on session_affinities(expires_at);
|
|
create index idx_session_affinities_active_order on session_affinities(expires_at, created_at, response_id);
|
|
|
|
create table runtime_settings_new (
|
|
id integer primary key check (id = 1),
|
|
model_aliases_json text not null default '{}',
|
|
refresh_margin_seconds integer not null check (refresh_margin_seconds > 0),
|
|
refresh_concurrency integer not null check (refresh_concurrency > 0),
|
|
max_concurrent_per_account integer not null check (max_concurrent_per_account > 0),
|
|
request_interval_ms integer not null check (request_interval_ms >= 0),
|
|
rotation_strategy text not null check (rotation_strategy in ('smart', 'quota_reset_priority', 'round_robin', 'sticky')),
|
|
admin_api_key text,
|
|
updated_at text not null
|
|
);
|
|
|
|
insert into runtime_settings_new (
|
|
id,
|
|
model_aliases_json,
|
|
refresh_margin_seconds,
|
|
refresh_concurrency,
|
|
max_concurrent_per_account,
|
|
request_interval_ms,
|
|
rotation_strategy,
|
|
admin_api_key,
|
|
updated_at
|
|
)
|
|
select
|
|
id,
|
|
model_aliases_json,
|
|
refresh_margin_seconds,
|
|
refresh_concurrency,
|
|
max_concurrent_per_account,
|
|
request_interval_ms,
|
|
case rotation_strategy
|
|
when 'least_used' then 'quota_reset_priority'
|
|
else rotation_strategy
|
|
end,
|
|
admin_api_key,
|
|
updated_at
|
|
from runtime_settings;
|
|
|
|
drop table runtime_settings;
|
|
alter table runtime_settings_new rename to runtime_settings;
|
|
|
|
create table ops_error_logs (
|
|
id text primary key,
|
|
request_id text,
|
|
kind text not null,
|
|
account_id text,
|
|
route text,
|
|
model text,
|
|
status_code integer check (status_code is null or (status_code >= 100 and status_code <= 599)),
|
|
client_status_code integer check (client_status_code is null or (client_status_code >= 100 and client_status_code <= 599)),
|
|
upstream_status_code integer check (upstream_status_code is null or (upstream_status_code >= 100 and upstream_status_code <= 599)),
|
|
transport text,
|
|
attempt_index integer check (attempt_index is null or attempt_index >= 0),
|
|
failure_class text,
|
|
response_id text,
|
|
upstream_request_id text,
|
|
latency_ms integer check (latency_ms is null or latency_ms >= 0),
|
|
message text not null,
|
|
metadata_json text not null,
|
|
created_at text not null
|
|
);
|
|
|
|
create index idx_ops_error_logs_created_id on ops_error_logs(created_at desc, id desc);
|
|
create index idx_ops_error_logs_request_id on ops_error_logs(request_id) where request_id is not null;
|
|
create index idx_ops_error_logs_account on ops_error_logs(account_id, created_at desc) where account_id is not null;
|
|
create index idx_ops_error_logs_route_created on ops_error_logs(route, created_at desc) where route is not null;
|
|
create index idx_ops_error_logs_model_created on ops_error_logs(model, created_at desc) where model is not null;
|
|
create index idx_ops_error_logs_status_created on ops_error_logs(status_code, created_at desc) where status_code is not null;
|
|
create index idx_ops_error_logs_transport_created on ops_error_logs(transport, created_at desc) where transport is not null;
|
|
create index idx_ops_error_logs_failure_class on ops_error_logs(failure_class, created_at desc) where failure_class is not null;
|
|
create index idx_ops_error_logs_response_id on ops_error_logs(response_id) where response_id is not null;
|
|
create index idx_ops_error_logs_upstream_request_id on ops_error_logs(upstream_request_id) where upstream_request_id is not null;
|
|
|
|
insert into schema_migrations (version, name, applied_at) values
|
|
(1, 'initial', '2026-01-01T00:00:00Z'),
|
|
(2, 'rename_rotation_strategies', '2026-01-01T00:00:00Z'),
|
|
(3, 'ops_error_logs', '2026-01-01T00:00:00Z');
|