From 479a0dbe56d484117226ccf8cdac87bed94f1b8a Mon Sep 17 00:00:00 2001 From: root Date: Mon, 6 Jul 2026 06:58:25 +0000 Subject: [PATCH] feat(switch-db): durable guard + validator for switch/compat quality - trg_compat_speed_guard: BEFORE INSERT/UPDATE on compatibility forces algorithmic (spec_match/community) rows whose transceiver is faster than the switch max port speed to status=incompatible. Curated rows never touched. Makes the "no physically-impossible compatibility" invariant structural, so it survives a scraper regression. - check_switch_quality(): on-demand proof; CI gate is `select bool_and(pass) from check_switch_quality() where enforced` (must be true). Data-source gaps (coding coverage, speed<=0, datasheet) tracked as enforced=false so they do not fail the gate before the data exists. --- sql/126-switch-quality-enforcement.sql | 98 ++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 sql/126-switch-quality-enforcement.sql diff --git a/sql/126-switch-quality-enforcement.sql b/sql/126-switch-quality-enforcement.sql new file mode 100644 index 0000000..cfb0787 --- /dev/null +++ b/sql/126-switch-quality-enforcement.sql @@ -0,0 +1,98 @@ +-- sql/126-switch-quality-enforcement.sql +-- Durable enforcement + on-demand validation for the switch/compatibility DB. +-- Complements sql/125 (which cleaned the data): makes the "no physically-impossible +-- compatibility rows" invariant structural, so it survives a scraper regression. +-- +-- Design (same "no false positives" rule as 125): +-- * The guard NEVER touches curated rows (vendor_matrix/vendor_compat/tested/datasheet) +-- -- those are trusted and, on understated switches, are the source of truth. +-- * For algorithmic rows (spec_match/community), if the transceiver is faster than the +-- switch's fastest known port (stored max_speed_gbps OR ports_config-derived), the row +-- is FORCED to status='incompatible' rather than dropped -- it stays recorded but is +-- excluded by every consumer that filters status='compatible' (e.g. queries.ts:302). +-- * Forcing (not RETURN NULL) means the guard never conflicts with the 125 flagging +-- UPDATE and never silently loses data. Idempotent; safe to re-run. +-- +-- Depends on sql/125 (fn_ports_max_gbps + the v_* views). Apply after 125. + +-- ── Guard: keep physically-impossible algorithmic matches out of 'compatible' ── +create or replace function compat_speed_guard() returns trigger +language plpgsql as $$ +declare + sw_ceiling numeric; + tx_speed numeric; +begin + -- Trust curated/vendor/tested sources; they define reality on understated switches. + if NEW.verification_method in ('vendor_matrix','vendor_compat','tested','datasheet') then + return NEW; + end if; + if NEW.status is distinct from 'compatible' then + return NEW; -- only guard rows claiming compatibility + end if; + + select greatest(coalesce(s.max_speed_gbps,0), coalesce(fn_ports_max_gbps(s.ports_config),0)) + into sw_ceiling + from switches s where s.id = NEW.switch_id; + + select t.speed_gbps into tx_speed + from transceivers t where t.id = NEW.transceiver_id; + + if sw_ceiling is not null and sw_ceiling > 0 + and tx_speed is not null and tx_speed > sw_ceiling then + NEW.status := 'incompatible'; + if NEW.notes is null or NEW.notes = '' then + NEW.notes := 'auto(126): transceiver speed exceeds switch max port speed'; + elsif position('auto(12' in NEW.notes) = 0 then + NEW.notes := NEW.notes || ' | auto(126): transceiver speed exceeds switch max port speed'; + end if; + end if; + return NEW; +end $$; + +comment on function compat_speed_guard() is + 'BEFORE INSERT/UPDATE guard on compatibility: forces algorithmic (non-curated) rows whose transceiver is faster than the switch max port speed to status=incompatible. Never alters curated rows.'; + +drop trigger if exists trg_compat_speed_guard on compatibility; +create trigger trg_compat_speed_guard + before insert or update on compatibility + for each row execute function compat_speed_guard(); + +-- ── Validator: prove switch-DB quality on demand (CI / cron) ────────────────── +-- Hard invariants have enforced=true; data-source gaps (coverage, datasheet) are +-- reported but enforced=false so they don't fail the gate before the data exists. +-- CI gate: select bool_and(pass) from check_switch_quality() where enforced; -- must be true +create or replace function check_switch_quality() +returns table(check_name text, detail text, pass boolean, enforced boolean) +language sql stable as $$ + select 'no_impossible_spec_match_compat', + (select count(*) from v_compat_speed_errors)::text || ' impossible rows', + (select count(*) from v_compat_speed_errors) = 0, + true + union all + select 'coding_coverage_100G_ge_50pct', + coalesce((select coverage_pct from v_coding_coverage where tier = 100), 0)::text || '%', + coalesce((select coverage_pct from v_coding_coverage where tier = 100), 0) >= 50, + false + union all + select 'transceivers_speed_positive', + (select count(*) from v_transceiver_speed_errors)::text || ' with speed<=0', + (select count(*) from v_transceiver_speed_errors) = 0, + false + union all + select 'switches_have_max_speed', + (select count(*) from v_switch_completeness where max_speed_gbps is null)::text || ' missing', + (select count(*) from v_switch_completeness where max_speed_gbps is null) = 0, + false + union all + select 'no_understated_switch_ports', + (select count(*) from v_switch_understated_ports)::text || ' understated', + (select count(*) from v_switch_understated_ports) = 0, + false; +$$; + +comment on function check_switch_quality() is + 'Switch-DB quality proof. select bool_and(pass) from check_switch_quality() where enforced; must be true (no physically-impossible compatibility rows). enforced=false rows track datasheet/data-source gaps.'; + +insert into _migrations (filename, applied_at) +select '126-switch-quality-enforcement.sql', now() +where not exists (select 1 from _migrations where filename = '126-switch-quality-enforcement.sql');