-- 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,
    feature_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,
    feature_settings 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);

