gendesign/tradein-mvp/backend/data/sql/060_postgres_fdw_extension.sql
lekss361 6507a5af64 fixup(tradein): address deep-review BLOCK findings on FDW PR
Critical:
- data/sql/100_tradein_fdw_role.sql — remove hardcoded password literal;
  role created LOGIN only; explicit REVOKE perimeter on all
  tables/sequences/functions in public; only v_tradein_cad_buildings grant
  remains. Password is now set by .forgejo/workflows/deploy.yml ALTER ROLE
  bootstrap step reading GENDESIGN_FDW_PASSWORD from backend/.env.runtime.
- tradein-mvp/backend/app/core/fdw.py — strict regex whitelist on password
  ([A-Za-z0-9_-]{32,256}) before inlining into DDL; ValueError on mismatch
  (no password in error message); pg_user_mappings query corrected for
  PUBLIC mapping (usename IS NULL); commit wrapped in try/rollback.

High:
- 060_postgres_fdw_extension.sql — connect_timeout='3' added to FOREIGN
  SERVER; ALTER SERVER ADD/SET fallback for re-apply path.
- geocoder.py — _cadastral_forward_sync / _cadastral_reverse_sync wrapped in
  asyncio.to_thread to avoid blocking event loop on FDW outage.

Tests:
- 3 new test_cadastral_reverse.py cases: SQL injection password rejected,
  short password rejected, valid hex password accepted with mapping creation.

Old password 40473b7c... remains in git history at 698ef4f (force-push
forbidden) — but the role was never created with it on prod (SQL not
deployed), so abandoned. New password 72df... lives only in VPS env files
and vault meta/00_credentials.md.
2026-05-24 11:50:51 +03:00

43 lines
1.5 KiB
PL/PgSQL

-- postgres_fdw extension for tradein → gendesign live reads.
-- Idempotent. Server config only (no USER MAPPING — that's set by backend startup with env password).
BEGIN;
CREATE EXTENSION IF NOT EXISTS postgres_fdw;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_foreign_server WHERE srvname = 'gendesign_remote') THEN
CREATE SERVER gendesign_remote
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'gendesign-postgres', dbname 'gendesign', port '5432',
extensions 'postgis', connect_timeout '3');
ELSE
-- Update existing server: add connect_timeout if missing, or set if already present.
BEGIN
ALTER SERVER gendesign_remote OPTIONS (ADD connect_timeout '3');
EXCEPTION WHEN OTHERS THEN
ALTER SERVER gendesign_remote OPTIONS (SET connect_timeout '3');
END;
END IF;
END$$;
-- Drop existing foreign table if mistakenly created with wrong schema (idempotent re-create below)
DROP FOREIGN TABLE IF EXISTS gendesign_cad_buildings;
CREATE FOREIGN TABLE gendesign_cad_buildings (
cad_num text,
readable_address text,
year_built integer,
floors integer,
area_m2 numeric,
purpose text,
lat double precision,
lon double precision
)
SERVER gendesign_remote
OPTIONS (schema_name 'public', table_name 'v_tradein_cad_buildings');
COMMENT ON FOREIGN TABLE gendesign_cad_buildings IS
'Live view of gendesign.cad_buildings (EKB only). USER MAPPING managed by backend startup.';
COMMIT;