feat(tradein): cian_session cookies management + admin endpoints (Wave 4 Worker A) #457
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#457
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-cian-session-cookies"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Stage 4 / Wave 4 of CianScraper v1. Cookie management infrastructure для Cian Valuation Calculator auth (Stage 7 dependency).
Files
app/services/cian_session.py(NEW)save_session(),load_session(),verify_session(),mark_session_invalid()app/api/v1/admin.py(MOD)app/core/config.py(MOD)cookie_encryption_keysetting (envCOOKIE_ENCRYPTION_KEY)tests/test_cian_session.py(NEW)scripts/upload-cian-cookies.sh(NEW)Endpoints added
/api/v1/admin/scrape/cian/upload-cookiespgp_sym_encryptUPSERT/api/v1/admin/scrape/cian/test-auth{authenticated, userId, reason}Both behind existing
require_adminX-Admin-Token middleware.CIAN_REQUIRED_COOKIES (finalized)
_ym_uid,_ym_d,_ym_isad,_cian_visitor_session_id,_cian_app_session_id,_cian_uid,_ga,tlsr_id,cf_clearance,session-id,anti_bot,csrftokenEncryption
pgp_sym_encryptviasettings.cookie_encryption_key(envCOOKIE_ENCRYPTION_KEY)cian_session_cookiestable (migration 027 — already в prod)state.user.isAuthenticatedcheck503 encryption_key_not_configured(graceful degradation)Reused existing admin.py patterns
router = APIRouter()(unchanged)dependencies=[Depends(require_admin)]— matches existingPOST /scrapepatternAnnotated[Session, Depends(get_db)]— same asgeocode_missingTests
pgp_sym_encrypt,CAST AS bigint,ON CONFLICT), commit assertions, params,verify_sessionpaths (no state /isAuthenticated=false/ authenticated → state)Ruff
New files clean. Pre-existing E501 в admin.py не тронуты.
Refs
decisions/CianScraper_v1_Implementation_Plan.mdsec "🔥 Cookie auth для Cian Valuation Calculator" + Stage 4decisions/Schema_Cian_SERP_Inventory.mdsec 24 (auth requirements)cian_session_cookiestable)Test plan
{authenticated:true, userId:...}load_session()доступнаMerged via deep-code-reviewer — verdict APPROVE with minor follow-ups.
Deep review summary
Status: APPROVE (squash merged, commit
2dd76ea5)Files reviewed: 7 (P0: 1 SQL-equivalent service, P1: 2 service+admin, P2: 1 config, P3: 3 tests+CLI)
LOC: +1206/-0
Critical concern resolved:
require_adminis alive and wellPR #437 / #442 context (removed
AdminTokenAuthfrom 43 endpoints) applies to mainbackend/app/, NOT totradein-mvp/backend/app/. This is a separate standalone trade-in MVP with its own auth:require_adminis locally defined intradein-mvp/backend/app/api/v1/admin.py:31-42and gates onsettings.admin_tokenenv var. ExistingPOST /scrape+POST /geocode-missinguse same pattern. New endpoints are consistent.Verified
cian_session_cookies) exists in repo (tradein-mvp/backend/data/sql/027_cian_session_cookies.sql) withpgcryptoextension + correct schema (account_user_id PK, cookies_encrypted bytea, expires_at_estimate, last_invalid_at, last_used_at, notes).cian_detail.save_detail_enrichmentexist in 019_listings_alter_cian.sql (windows_view_type,separate_wcs_count,combined_wcs_count,ceiling_height,repair_type,views_total,views_today).offer_price_historytable +agentstable +listings.agent_id_fkexist (022, 023).extract_state/extract_all_statesfunctions exist incian_state_parser.py.curl_cffi,httpx,pytest-asyncio(withasyncio_mode = "auto") already inpyproject.toml..forgejo/workflows/deploy-tradein.ymltriggers ontradein-mvp/backend/**.:key(not string interpolation) — encryption key not injected into SQL text.userIdand counts.CAST(:x AS bigint)everywhere — psycopg v3 compatible.ON CONFLICT DO UPDATEfor save,ON CONFLICT DO NOTHINGfor price history (correct idempotency).Discovered scope mismatch (informational)
PR description claims 5 files / 16 tests. Actual: 7 files including
cian_detail.py(324 lines, Stage 5) +test_cian_detail.py(324 lines) which were not mentioned in description. These are clean additions (no conflicts, mocked tests pass own coverage), but represents Stage 5 work landing inside a Stage 4 PR. Worth noting for Wave 4 tracker — Stage 5 was bundled, not separate PR.Minor follow-ups (non-blocking)
cookie_encryption_key: str = ""→ considerSecretStr— Pydantic plain str will show inrepr(settings)if ever logged. Not critical (key is non-public and admin-only), but Pydantic best practice. File:tradein-mvp/backend/app/core/config.py:33.cleanedcheck is weak —upload-cookiesaccepts payload with even a single recognized cookie (e.g. only_ym_uid) and proceeds toverify_session(). Auth will fail there gracefully (nocf_clearance→ 403/captcha from Cian), so safe — but might be clearer to reject upfront ifcf_clearance/_cian_uidmissing. Optional./test-auth— admin endpoint, but each call hits Cian. Document admin abuse risk in runbook. Optional.upload-cian-cookies.shreadsTRADEIN_ADMIN_TOKENfrom env first then.env.runtime— correct, no leak via argv.test_save_session_passes_correct_params(test_cian_session.py:79) — defensive param extraction tries multiple patterns (call_args[0][1]vscall_args[1].get("params")). Brittle but harmless. Could simplify after first CI run confirms which path.COOKIE_ENCRYPTION_KEYchanges, existing rows incian_session_cookiesbecome unrecoverable. Suggestdecisions/Cookie_Encryption_Strategy_May23.mddocumenting: key generation, rotation flow (re-upload all cookies after rotation), recovery path.Post-merge manual verification (per PR test plan)
deploy-tradein.ymlshould trigger onpaths: tradein-mvp/backend/**— verify green.test_cian_session.py+ 12 tests intest_cian_detail.pyshould all pass.COOKIE_ENCRYPTION_KEY=$(openssl rand -base64 32)to.env.runtime→ restart tradein-backend.scripts/upload-cian-cookies.sh cookies.json→ expect{"ok": true, "userId": N, "cookieCount": M}.GET /api/v1/admin/scrape/cian/test-auth→ expect{"authenticated": true, "userId": N}.cian_valuation.py) can now consumecian_session_svc.load_session(db).Risk / reversibility
cian_session.py,cian_detail.py); admin.py modifications are append-only; no existing logic touched.CREATE TABLE IF NOT EXISTS(idempotent, harmless if rolled back).