transceiver-db/sql/133-reach-substitution-policy.sql
root 91d19e152d fix(equivalences): resolve wavelength column mismatch + reach-tier substitution policy
Root cause of the equivalence review-queue backlog: spec-matcher read
transceivers.wavelengths (text), but the enricher wrote wavelength_tx_nm
(int) — 27,908 rows had the wavelength in the wrong column, and tx_nm
itself defaulted incorrectly to 1310nm in ~22% of disagreements with the
authoritative part-derived value.

sql/131: backfill + sync trigger from wavelength_tx_nm into wavelengths.
sql/132: correct authority (bare-number wavelengths, not tx_nm) + format
normalization + valid promotion on the full spec-matcher gate.
sql/133: one-directional reach-tier substitution (higher reach may satisfy
a lower-reach requirement, never the reverse; ZR/coherent excluded — real
link-budget/receiver-overload risk, not a simple tier comparison). Tagged
as its own status (compatible_superset), not merged into auto_approved.
2026-07-07 12:15:43 +00:00

47 lines
2.5 KiB
PL/PgSQL

-- sql/133 — One-directional reach-tier substitution policy
--
-- Decision (Rene, 2026-07-07): a higher-reach optic may satisfy a lower-reach
-- requirement (e.g. a 40km ER can serve where a 10km LR is asked for), never the
-- reverse — the shorter-reach part cannot close the link budget on a longer run.
-- ZR/coherent/amplified tiers are explicitly EXCLUDED from this automatic rule:
-- those can overload a short-haul receiver without an attenuator, which is a real
-- power-budget calculation, not a simple tier comparison. Those stay in manual review.
--
-- Result is tagged as its own status (compatible_superset), never merged into
-- auto_approved/exact-spec matches, so downstream consumers (Fossy/Beo/Pulso, pricing)
-- can distinguish "identical spec" from "safe higher-spec substitute" — they usually
-- differ in price and are not a like-for-like swap.
BEGIN;
-- widen the status check (additive — existing values still valid)
ALTER TABLE transceiver_equivalences DROP CONSTRAINT transceiver_equivalences_status_check;
ALTER TABLE transceiver_equivalences ADD CONSTRAINT transceiver_equivalences_status_check
CHECK (status::text = ANY (ARRAY['pending','approved','rejected','auto_approved','compatible_superset']::text[]));
UPDATE transceiver_equivalences e
SET status = 'compatible_superset',
confidence = GREATEST(e.confidence, 0.75),
match_notes = COALESCE(e.match_notes,'') || ' | sql/133: ' ||
CASE WHEN fx.reach_meters > cx.reach_meters
THEN 'flexoptix ('||tip_reach_tier(fx.reach_meters)||') covers competitor requirement ('||tip_reach_tier(cx.reach_meters)||')'
ELSE 'competitor ('||tip_reach_tier(cx.reach_meters)||') covers flexoptix requirement ('||tip_reach_tier(fx.reach_meters)||')'
END || ' — reach-tier substitute, not identical spec',
updated_at = now()
FROM transceivers fx, transceivers cx
WHERE e.flexoptix_id = fx.id
AND e.competitor_id = cx.id
AND e.status = 'pending'
AND fx.form_factor = cx.form_factor
AND fx.speed_gbps = cx.speed_gbps
AND fx.fiber_type IS NOT DISTINCT FROM cx.fiber_type
AND fx.reach_meters >= 10 AND cx.reach_meters >= 10
AND tip_extract_wavelength_nm(fx.wavelengths) IS NOT NULL
AND tip_extract_wavelength_nm(cx.wavelengths) IS NOT NULL
AND abs(tip_extract_wavelength_nm(fx.wavelengths) - tip_extract_wavelength_nm(cx.wavelengths)) <= 10
AND tip_reach_tier(fx.reach_meters) <> tip_reach_tier(cx.reach_meters)
AND tip_reach_tier(fx.reach_meters) <> 'ZR'
AND tip_reach_tier(cx.reach_meters) <> 'ZR';
COMMIT;