-- 274_yandex_session_cookies.sql -- Purpose: Encrypted storage for Yandex.Nedvizhimost browser session cookies. -- Uses pgcrypto pgp_sym_encrypt for AES encryption at rest (зеркалит -- 027_cian_session_cookies.sql / 174_domclick_session_cookies.sql). -- -- ⚠️ ОБОСНОВАНИЕ ЭТОЙ ТАБЛИЦЫ ОПРОВЕРГНУТО (#3192, замер 2026-08-28). -- Шапка этого файла утверждала, что авторизованная сессия раскрывает -- author.phoneNumbers. Повторный замер на прод-транспорте (curl_cffi + -- прокси, а не сайдкар) показал: у целевой карточки -- (offerCard.card.author) телефонов нет никогда — 12 из 12 объявлений, -- с куками и без, только encryptedPhones + redirectPhones. -- phoneNumbers встречается ТОЛЬКО под offerCard.visitedOffers[*].author -- — это история просмотров НАШЕЙ учётки, растущая на +1 с каждым -- фетчем; именно её рост первый замер принял за данные объявления. -- Таблица создана и пуста. Оставлена как есть: DROP без явного решения -- владельца не делаем (#3192, label needs-human). Разбор — в тикете и -- в докстринге app/services/yandex_session.py. -- Dependencies: -- - pgcrypto extension (installed here via CREATE EXTENSION IF NOT EXISTS) -- Deploy order: Apply after 273. -- -- Security notes: -- - cookies_encrypted stores AES-encrypted JSON blob via pgp_sym_encrypt. -- - Encryption key lives in .env.runtime (COOKIE_ENCRYPTION_KEY), never in DB. -- - Access restricted to admin-token-gated API endpoint only. -- -- Schema note: ключ записи — account_label (text), НЕ числовой id как у Cian -- (account_user_id) / DomClick (account_cas_id) — у Яндекса нет внутреннего -- числового id аккаунта, доступного из cookie-дампа; используем произвольную -- текстовую метку аккаунта, которую задаёт оператор при заливке дампа. -- -- Sources: issue #3192 (Yandex session cookies — author.phoneNumbers reveal) BEGIN; -- #2752: без lock_timeout CREATE INDEX встанет в очередь за чужой долгой -- сессией и уведёт за собой запросы приложения — таблица новая и пустая, но -- очередь блокировок этого не знает. Гейт check-migration-lock-timeout.py -- держит правило на каждом PR. SET LOCAL lock_timeout = '5s'; CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE TABLE IF NOT EXISTS yandex_session_cookies ( account_label text PRIMARY KEY, -- произвольная метка аккаунта (нет числового id) cookies_encrypted bytea NOT NULL, -- pgp_sym_encrypt(json_cookies, key) expires_at_estimate timestamptz NOT NULL, -- estimated expiry (~30 days from upload) uploaded_at timestamptz NOT NULL DEFAULT NOW(), last_used_at timestamptz, -- set on each successful authenticated fetch last_invalid_at timestamptz, -- set when session no longer authenticated notes text -- e.g. 'Account: