new-site/api/migrations/053_line_105_taxonomy.sql
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

75 lines
3.6 KiB
SQL

-- 053: Line 105 ranked multi-select taxonomy + category-specific metadata
--
-- The 2026 FCC Form 499-A Line 105 is an explicit multi-select (ranked 1-5)
-- across 22 carrier categories. Migration 038 stored `service_categories
-- TEXT[]` and `filer_type TEXT` but the handler treated Line 105 as a
-- single category. This migration replaces that with:
--
-- line_105_primary — single required primary category id
-- line_105_categories — JSONB array of {id, rank, infra_type, is_tdm_service}
--
-- Reseller handling: local_reseller and toll_reseller are NOT standalone
-- categories in our data model. A CLEC or IXC with `infra_type='reseller'`
-- triggers the corresponding Line 105 box being ticked automatically by
-- form_499a.py. Similarly an MVNO is wireless with infra_type='mvno'.
--
-- Category-specific metadata lives in dedicated JSONB columns so we can
-- evolve each without touching the shared table schema.
-- ── Line 105 primary + ranked multi-select ──────────────────────────────
ALTER TABLE telecom_entities ADD COLUMN IF NOT EXISTS line_105_primary TEXT;
ALTER TABLE telecom_entities ADD COLUMN IF NOT EXISTS line_105_categories JSONB NOT NULL DEFAULT '[]'::jsonb;
-- Example shape:
-- [{"id":"clec","rank":1,"infra_type":"reseller","is_tdm_service":false},
-- {"id":"ixc", "rank":2,"infra_type":"facilities"}]
--
-- GIN index for "find every filer that provides wireless service" etc.
CREATE INDEX IF NOT EXISTS idx_telecom_entities_line_105_categories
ON telecom_entities USING gin (line_105_categories jsonb_path_ops);
CREATE INDEX IF NOT EXISTS idx_telecom_entities_line_105_primary
ON telecom_entities(line_105_primary)
WHERE line_105_primary IS NOT NULL;
-- ── Category-specific metadata JSONB columns ────────────────────────────
-- wireless_meta shape:
-- { spectrum_bands: ["Lower 700 MHz", "PCS 1900"], host_mno: null,
-- post_paid_subs: 12000, pre_paid_subs: 3500,
-- cell_site_count: 42, msa_coverage: ["MSA-001","MSA-003"] }
ALTER TABLE telecom_entities ADD COLUMN IF NOT EXISTS wireless_meta JSONB;
-- satellite_meta shape:
-- { earth_station_license_ids: ["E123456"], orbital_slot: "W 73.0",
-- satellite_operator: "Intelsat", service_type: "FSS",
-- mss_us_subscribers: null }
ALTER TABLE telecom_entities ADD COLUMN IF NOT EXISTS satellite_meta JSONB;
-- audio_bridging_meta shape:
-- { platform: "proprietary", toll_free_accessible: true,
-- participant_min_revenue_cents: 1200000,
-- subscription_revenue_cents: 4500000 }
ALTER TABLE telecom_entities ADD COLUMN IF NOT EXISTS audio_bridging_meta JSONB;
-- private_line_circuits: one row per circuit.
-- [{id, bandwidth, endpoint_a:{city,state,country},
-- endpoint_b:{city,state,country}, monthly_revenue_cents}, ...]
ALTER TABLE telecom_entities ADD COLUMN IF NOT EXISTS private_line_circuits JSONB;
-- ── Backfill from the single-valued filer_type/service_categories ───────
-- Existing rows have filer_type populated (e.g., 'interconnected_voip',
-- 'clec'). Seed line_105_primary + line_105_categories from it so we
-- don't break live data. infra_type from 038 is also carried into the
-- JSONB entry.
UPDATE telecom_entities
SET line_105_primary = filer_type,
line_105_categories = jsonb_build_array(
jsonb_build_object(
'id', filer_type,
'rank', 1,
'infra_type', COALESCE(infra_type, 'facilities'),
'is_tdm_service', false
)
)
WHERE line_105_primary IS NULL
AND filer_type IS NOT NULL;