-- Generated by aether-data-schema from schema/logical/*.toml. -- Do not edit generated files directly; edit logical schema or explicit overrides instead. CREATE TABLE IF NOT EXISTS public.users ( id character varying(64) NOT NULL, external_id character varying(255), email character varying(320), username character varying(255), password_hash character varying(255), role character varying(64), auth_source character varying(64) DEFAULT 'local' NOT NULL, email_verified boolean DEFAULT false NOT NULL, is_active boolean DEFAULT true NOT NULL, is_deleted boolean DEFAULT false NOT NULL, allowed_models jsonb, allowed_models_mode character varying(32) DEFAULT 'unrestricted' NOT NULL, allowed_providers jsonb, allowed_providers_mode character varying(32) DEFAULT 'unrestricted' NOT NULL, allowed_api_formats jsonb, allowed_api_formats_mode character varying(32) DEFAULT 'unrestricted' NOT NULL, model_capability_settings jsonb, rate_limit integer, rate_limit_mode character varying(32) DEFAULT 'system' NOT NULL, metadata jsonb, created_at bigint NOT NULL, updated_at bigint NOT NULL, last_login_at bigint, ldap_dn character varying(1024), ldap_username character varying(255) ); ALTER TABLE ONLY public.users ADD CONSTRAINT users_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.users ADD CONSTRAINT users_email_key UNIQUE (email); ALTER TABLE ONLY public.users ADD CONSTRAINT users_username_key UNIQUE (username); CREATE TABLE IF NOT EXISTS public.user_groups ( id character varying(64) NOT NULL, name character varying(100) NOT NULL, normalized_name character varying(100) NOT NULL, description text, priority integer DEFAULT 0 NOT NULL, allowed_providers jsonb, allowed_providers_mode character varying(32) DEFAULT 'inherit' NOT NULL, allowed_api_formats jsonb, allowed_api_formats_mode character varying(32) DEFAULT 'inherit' NOT NULL, allowed_models jsonb, allowed_models_mode character varying(32) DEFAULT 'inherit' NOT NULL, rate_limit integer, rate_limit_mode character varying(32) DEFAULT 'inherit' NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); ALTER TABLE ONLY public.user_groups ADD CONSTRAINT user_groups_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.user_groups ADD CONSTRAINT user_groups_normalized_name_key UNIQUE (normalized_name); CREATE INDEX IF NOT EXISTS user_groups_priority_name_idx ON public.user_groups USING btree (priority, name, id); CREATE TABLE IF NOT EXISTS public.user_group_members ( group_id character varying(64) NOT NULL, user_id character varying(64) NOT NULL, created_at bigint NOT NULL ); ALTER TABLE ONLY public.user_group_members ADD CONSTRAINT user_group_members_pkey PRIMARY KEY (group_id, user_id); CREATE INDEX IF NOT EXISTS user_group_members_user_id_idx ON public.user_group_members USING btree (user_id); CREATE TABLE IF NOT EXISTS public.api_keys ( id character varying(64) NOT NULL, user_id character varying(64) NOT NULL, key_hash character varying(255) NOT NULL, key_encrypted text, name character varying(255), key_prefix character varying(64), status character varying(64) DEFAULT 'active' NOT NULL, allowed_models jsonb, allowed_providers jsonb, allowed_api_formats jsonb, rate_limit integer DEFAULT 100, concurrent_limit integer, force_capabilities jsonb, is_active boolean DEFAULT true NOT NULL, is_locked boolean DEFAULT false NOT NULL, is_standalone boolean DEFAULT false NOT NULL, auto_delete_on_expiry boolean DEFAULT false NOT NULL, total_requests bigint DEFAULT 0 NOT NULL, total_tokens bigint DEFAULT 0 NOT NULL, total_cost_usd double precision DEFAULT 0 NOT NULL, metadata jsonb, expires_at bigint, last_used_at bigint, created_at bigint NOT NULL, updated_at bigint NOT NULL ); ALTER TABLE ONLY public.api_keys ADD CONSTRAINT api_keys_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.api_keys ADD CONSTRAINT api_keys_key_hash_key UNIQUE (key_hash); CREATE INDEX IF NOT EXISTS api_keys_user_id_idx ON public.api_keys USING btree (user_id); CREATE TABLE IF NOT EXISTS public.audit_logs ( id character varying(64) NOT NULL, event_type character varying(64) NOT NULL, user_id character varying(64), api_key_id character varying(64), description text NOT NULL, ip_address character varying(64), user_agent character varying(512), request_id character varying(128), event_metadata jsonb, status_code integer, error_message text, created_at bigint NOT NULL ); ALTER TABLE ONLY public.audit_logs ADD CONSTRAINT audit_logs_pkey PRIMARY KEY (id); CREATE INDEX IF NOT EXISTS audit_logs_created_at_idx ON public.audit_logs USING btree (created_at); CREATE INDEX IF NOT EXISTS audit_logs_event_type_idx ON public.audit_logs USING btree (event_type); CREATE INDEX IF NOT EXISTS audit_logs_request_id_idx ON public.audit_logs USING btree (request_id); CREATE INDEX IF NOT EXISTS audit_logs_user_id_idx ON public.audit_logs USING btree (user_id); CREATE TABLE IF NOT EXISTS public.announcements ( id character varying(64) NOT NULL, title character varying(200) NOT NULL, content text NOT NULL, type character varying(32) DEFAULT 'info' NOT NULL, priority integer DEFAULT 0 NOT NULL, author_id character varying(64), is_active boolean DEFAULT true NOT NULL, is_pinned boolean DEFAULT false NOT NULL, start_time bigint, end_time bigint, created_at bigint NOT NULL, updated_at bigint NOT NULL ); ALTER TABLE ONLY public.announcements ADD CONSTRAINT announcements_pkey PRIMARY KEY (id); CREATE INDEX IF NOT EXISTS announcements_author_id_idx ON public.announcements USING btree (author_id); CREATE INDEX IF NOT EXISTS announcements_created_at_idx ON public.announcements USING btree (created_at); CREATE INDEX IF NOT EXISTS announcements_is_active_idx ON public.announcements USING btree (is_active); CREATE TABLE IF NOT EXISTS public.announcement_reads ( id character varying(64) NOT NULL, user_id character varying(64) NOT NULL, announcement_id character varying(64) NOT NULL, read_at bigint NOT NULL ); ALTER TABLE ONLY public.announcement_reads ADD CONSTRAINT announcement_reads_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.announcement_reads ADD CONSTRAINT uq_user_announcement UNIQUE (user_id, announcement_id); CREATE INDEX IF NOT EXISTS announcement_reads_announcement_id_idx ON public.announcement_reads USING btree (announcement_id); CREATE INDEX IF NOT EXISTS announcement_reads_user_id_idx ON public.announcement_reads USING btree (user_id); CREATE TABLE IF NOT EXISTS public.management_tokens ( id character varying(64) NOT NULL, user_id character varying(64) NOT NULL, name character varying(255) NOT NULL, description text, token_hash character varying(255) NOT NULL, token_prefix character varying(64), allowed_ips jsonb, permissions jsonb, expires_at bigint, last_used_at bigint, last_used_ip character varying(255), usage_count bigint DEFAULT 0 NOT NULL, is_active boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); ALTER TABLE ONLY public.management_tokens ADD CONSTRAINT management_tokens_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.management_tokens ADD CONSTRAINT management_tokens_token_hash_key UNIQUE (token_hash); ALTER TABLE ONLY public.management_tokens ADD CONSTRAINT uq_management_tokens_user_name UNIQUE (user_id, name); CREATE INDEX IF NOT EXISTS management_tokens_user_id_idx ON public.management_tokens USING btree (user_id); CREATE TABLE IF NOT EXISTS public.user_preferences ( id character varying(64) NOT NULL, user_id character varying(64) NOT NULL, avatar_url character varying(500), bio text, default_provider_id character varying(64), theme character varying(20) DEFAULT 'light' NOT NULL, language character varying(10) DEFAULT 'zh-CN' NOT NULL, timezone character varying(50) DEFAULT 'Asia/Shanghai' NOT NULL, email_notifications boolean DEFAULT true NOT NULL, usage_alerts boolean DEFAULT true NOT NULL, announcement_notifications boolean DEFAULT true NOT NULL, created_at bigint NOT NULL, updated_at bigint NOT NULL ); ALTER TABLE ONLY public.user_preferences ADD CONSTRAINT user_preferences_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.user_preferences ADD CONSTRAINT user_preferences_user_id_key UNIQUE (user_id); CREATE INDEX IF NOT EXISTS user_preferences_default_provider_id_idx ON public.user_preferences USING btree (default_provider_id); CREATE INDEX IF NOT EXISTS user_preferences_user_id_idx ON public.user_preferences USING btree (user_id); CREATE TABLE IF NOT EXISTS public.user_sessions ( id character varying(64) NOT NULL, user_id character varying(64) NOT NULL, client_device_id character varying(128) NOT NULL, device_label character varying(120), device_type character varying(20) DEFAULT 'unknown' NOT NULL, browser_name character varying(50), browser_version character varying(50), os_name character varying(50), os_version character varying(50), device_model character varying(100), ip_address character varying(45), user_agent character varying(1000), client_hints jsonb, refresh_token_hash character varying(64) NOT NULL, prev_refresh_token_hash character varying(64), rotated_at bigint, last_seen_at bigint NOT NULL, expires_at bigint NOT NULL, revoked_at bigint, revoke_reason character varying(100), created_at bigint NOT NULL, updated_at bigint NOT NULL ); ALTER TABLE ONLY public.user_sessions ADD CONSTRAINT user_sessions_pkey PRIMARY KEY (id); CREATE INDEX IF NOT EXISTS user_sessions_user_active_idx ON public.user_sessions USING btree (user_id, revoked_at, expires_at); CREATE INDEX IF NOT EXISTS user_sessions_user_device_idx ON public.user_sessions USING btree (user_id, client_device_id);