CREATE TABLE IF NOT EXISTS gateway_portrait_assets ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE CASCADE, user_id text NOT NULL, gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL, tenant_id text, tenant_key text, name text NOT NULL DEFAULT '', description text NOT NULL DEFAULT '', source_type text NOT NULL, url text NOT NULL, preview text NOT NULL DEFAULT '', mime_type text NOT NULL DEFAULT '', byte_size bigint NOT NULL DEFAULT 0, source_sha256 text NOT NULL DEFAULT '', private_avatar_eligible boolean NOT NULL DEFAULT false, status text NOT NULL DEFAULT 'not_synced', last_error text NOT NULL DEFAULT '', metadata jsonb NOT NULL DEFAULT '{}'::jsonb, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS gateway_portrait_asset_bindings ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), asset_id uuid NOT NULL REFERENCES gateway_portrait_assets(id) ON DELETE CASCADE, platform_id uuid NOT NULL REFERENCES integration_platforms(id) ON DELETE CASCADE, project_name text NOT NULL DEFAULT '', asset_group_id text NOT NULL DEFAULT '', remote_asset_id text NOT NULL DEFAULT '', remote_asset_uri text NOT NULL DEFAULT '', status text NOT NULL DEFAULT 'pending', last_error_code text NOT NULL DEFAULT '', last_error_message text NOT NULL DEFAULT '', last_synced_at timestamptz, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), UNIQUE(asset_id, platform_id) ); CREATE INDEX IF NOT EXISTS idx_gateway_portrait_assets_user_created ON gateway_portrait_assets(gateway_user_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_gateway_portrait_assets_user_id_created ON gateway_portrait_assets(user_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_gateway_portrait_assets_user_hash ON gateway_portrait_assets(gateway_user_id, source_sha256) WHERE source_sha256 <> ''; CREATE INDEX IF NOT EXISTS idx_gateway_portrait_asset_bindings_asset_platform ON gateway_portrait_asset_bindings(asset_id, platform_id); UPDATE base_model_catalog SET capabilities = jsonb_set( COALESCE(capabilities, '{}'::jsonb), '{omni_video,supports_portrait_asset_reference}', 'true'::jsonb, true ), updated_at = now() WHERE provider_key = 'volces' AND provider_model_name LIKE 'doubao-seedance-2-0%' AND model_type @> '["omni_video"]'::jsonb; UPDATE platform_models m SET capabilities = jsonb_set( COALESCE(m.capabilities, '{}'::jsonb), '{omni_video,supports_portrait_asset_reference}', 'true'::jsonb, true ), updated_at = now() FROM integration_platforms p WHERE p.id = m.platform_id AND p.provider = 'volces' AND m.model_type @> '["omni_video"]'::jsonb AND COALESCE(NULLIF(m.provider_model_name, ''), m.model_name) LIKE 'doubao-seedance-2-0%';