* fix(parcels): _parse_floors handle int (post-migration #169 schema change) After PR #169 cad_buildings schema migration, `floors` column is INT (was TEXT in legacy schema). Existing `_parse_floors(r.get("floors"))` call in analyze_parcel → _neighbors_summary crashes with: AttributeError: 'int' object has no attribute 'strip' Fix: type union str | int | None. If int → return directly (no strip). Preserve TEXT range parsing ("5-7" → 7) for backwards-compat with any legacy data still in cad_buildings_old_apr26. * test(smoke): production smoke tests for post-deploy regressions (#168) Add tests/smoke/test_prod_smoke.py covering known regression surfaces. Marks: prod_smoke + slow. Env: PROD_SMOKE_BASE_URL, PROD_SMOKE_ADMIN_TOKEN. Run manually: cd backend && uv run pytest tests/smoke/ -m prod_smoke -v * fix(cadastre): exact-match headers to nspd_lite to bypass NSPD WAF (#168) Pilot v2 (job_id=2) failed 50/50 with HTTP 403 WAF block. Comparing nspd_bulk_client.DEFAULT_HEADERS vs legacy nspd_lite.HEADERS (which works on VPS IP since April 2026): PascalCase keys → lowercase keys Chrome/148 UA → Chrome/144 UA No cache-control / pragma → "no-cache" both accept-language ru first → en first No origin → "https://nspd.gov.ru" referer "/map" → "/map?thematic=PKK" NSPD WAF (BotShield-class) likely fingerprints на header order + values combined with TLS fingerprint. Matching legacy exactly minimizes deltas. Test plan: retry pilot job after deploy, expect 0 WAF blocks for first 5 quarters. * fix(test): exclude prod_smoke tests by default (#168) CI ran tests/smoke/test_prod_smoke.py and they hit production https://gendsgn.ru/api/v1/parcels/.../analyze which currently returns 500 (parse_floors regression — exactly what this PR fixes). Catch-22: PR can't merge because smoke tests fail against pre-merge prod. Fix: add `addopts = ["-m", "not prod_smoke"]` so default pytest excludes them. Run manually post-deploy with: pytest -m prod_smoke -v --------- Co-authored-by: lekss361 <claudestars@proton.me>
0 lines
Python
0 lines
Python