gendesign/tradein-mvp/backend/data/sql/274_yandex_session_cookies.sql
bot-backend 5be64c6688
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Successful in 2m18s
Deploy Trade-In / test (push) Successful in 4m4s
Deploy Trade-In / build-backend (push) Successful in 1m36s
Deploy Trade-In / deploy (push) Successful in 2m0s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 11s
fix(tradein/scrapers): хранилище авторизованной сессии Яндекс.Недвижимости (#3195)
2026-08-28 19:02:05 +00:00

61 lines
3.9 KiB
PL/PgSQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 274_yandex_session_cookies.sql
-- Purpose: Encrypted storage for Yandex.Nedvizhimost browser session cookies.
-- Замер на проде (сайдкар, две карточки, вперемежку с/без кук, 2026-08-28):
-- author.phoneNumbers присутствует ТОЛЬКО в авторизованном режиме
-- (0 без кук → 2 с куками, одинаково на обеих карточках), плюс три
-- номера в author.phones сверху. Это контакт продавца с тегом канала
-- и redirectId.
-- NB: mainPhone НЕ собирать — он лежит в паспортном блоке рядом с
-- login/passportHost/passportPhones, то есть это номер НАШЕЙ учётки,
-- а не продавца. Первая версия этого замера приняла его за данные
-- объявления; счётчики по конкретным полям это опровергли.
-- encryptedPhones одинаков в обоих режимах (54) — зашифрованные токены
-- отдаются всегда, различие не в них.
-- Uses pgcrypto pgp_sym_encrypt for AES encryption at rest (зеркалит
-- 027_cian_session_cookies.sql / 174_domclick_session_cookies.sql).
-- 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: <label / email>'
);
-- Most recent upload first (admin dashboard ordering)
CREATE INDEX IF NOT EXISTS yandex_cookies_uploaded_idx
ON yandex_session_cookies (uploaded_at DESC);
-- Active session lookup (non-expired and not invalidated)
CREATE INDEX IF NOT EXISTS yandex_cookies_active_idx
ON yandex_session_cookies (expires_at_estimate)
WHERE last_invalid_at IS NULL;
COMMIT;